diff --git a/.eslintrc.js b/.eslintrc.js index 53944e16d9dc..64452fdd7c15 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,7 +38,7 @@ module.exports = { }, }, { - files: ['jest/**/*.ts', 'scripts/**/*.ts'], + files: ['scripts/**/*.ts'], parserOptions: { project: ['tsconfig.dev.json'], }, diff --git a/.gitignore b/.gitignore index be853254d612..f784704ac31a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,8 +17,6 @@ scratch/ # side effects of running AWS lambda layer zip action locally dist-serverless/ sentry-node-serverless-*.zip -# transpiled transformers -jest/transformers/*.js # node tarballs packages/*/sentry-*.tgz .nxcache diff --git a/.vscode/launch.json b/.vscode/launch.json index 409d7264a7e0..87d8002f6e7b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -52,35 +52,6 @@ "internalConsoleOptions": "openOnSessionStart", "outputCapture": "std" }, - // Run a specific test file in watch mode (must have file in currently active tab when hitting the play button). - // NOTE: If you try to run this and VSCode complains that the command `shellCommand.execute` can't be found, go - // install the recommended extension Tasks Shell Input. - { - "name": "Debug unit tests - just open file", - "type": "node", - "cwd": "${workspaceFolder}/packages/${input:getPackageName}", - "request": "launch", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": [ - "--watch", - // this runs one test at a time, rather than running them in parallel (necessary for debugging so that you know - // you're hitting a single test's breakpoints, in order) - "--runInBand", - // coverage messes up the source maps - "--coverage", - "false", - // remove this to run all package tests - "${relativeFile}" - ], - "sourceMaps": true, - "smartStep": true, - // otherwise it goes to the VSCode debug terminal, which prints the test output or console logs (depending on - // "outputCapture" option here; default is to show console logs), but not both - "console": "integratedTerminal", - // since we're not using it, don't automatically switch to it - "internalConsoleOptions": "neverOpen" - }, - // Run a specific test file in watch mode (must have file in currently active tab when hitting the play button). // NOTE: If you try to run this and VSCode complains that the command `shellCommand.execute` can't be found, go // install the recommended extension Tasks Shell Input. diff --git a/CHANGELOG.md b/CHANGELOG.md index 7adb951938a1..38a12489d36e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,87 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +## 9.10.0 + +### Important Changes + +- **feat: Add support for logs** + + - feat(node): Add logging public APIs to Node SDKs ([#15764](https://github.com/getsentry/sentry-javascript/pull/15764)) + - feat(core): Add support for `beforeSendLog` ([#15814](https://github.com/getsentry/sentry-javascript/pull/15814)) + - feat(core): Add support for parameterizing logs ([#15812](https://github.com/getsentry/sentry-javascript/pull/15812)) + - fix: Remove critical log severity level ([#15824](https://github.com/getsentry/sentry-javascript/pull/15824)) + + All JavaScript SDKs other than `@sentry/cloudflare` and `@sentry/deno` now support sending logs via dedicated methods as part of Sentry's [upcoming logging product](https://github.com/getsentry/sentry/discussions/86804). + + Logging is gated by an experimental option, `_experiments.enableLogs`. + + ```js + Sentry.init({ + dsn: 'PUBLIC_DSN', + // `enableLogs` must be set to true to use the logging features + _experiments: { enableLogs: true }, + }); + + const { trace, debug, info, warn, error, fatal, fmt } = Sentry.logger; + + trace('Starting database connection', { database: 'users' }); + debug('Cache miss for user', { userId: 123 }); + error('Failed to process payment', { orderId: 'order_123', amount: 99.99 }); + fatal('Database connection pool exhausted', { database: 'users', activeConnections: 100 }); + + // Structured logging via the `fmt` helper function. When you use `fmt`, the string template and parameters are sent separately so they can be queried independently in Sentry. + + info(fmt(`Updated profile for user ${userId}`)); + warn(fmt(`Rate limit approaching for endpoint ${endpoint}. Requests: ${requests}, Limit: ${limit}`)); + ``` + + With server-side SDKs like `@sentry/node`, `@sentry/bun` or server-side of `@sentry/nextjs` or `@sentry/sveltekit`, you can do structured logging without needing the `fmt` helper function. + + ```js + const { info, warn } = Sentry.logger; + + info('User %s logged in successfully', [123]); + warn('Failed to load user %s data', [123], { errorCode: 404 }); + ``` + + To filter logs, or update them before they are sent to Sentry, you can use the `_experiments.beforeSendLog` option. + +- **feat(browser): Add `diagnoseSdkConnectivity()` function to programmatically detect possible connectivity issues ([#15821](https://github.com/getsentry/sentry-javascript/pull/15821))** + + The `diagnoseSdkConnectivity()` function can be used to programmatically detect possible connectivity issues with the Sentry SDK. + + ```js + const result = await Sentry.diagnoseSdkConnectivity(); + ``` + + The result will be an object with the following properties: + + - `"no-client-active"`: There was no active client when the function was called. This possibly means that the SDK was not initialized yet. + - `"sentry-unreachable"`: The Sentry SaaS servers were not reachable. This likely means that there is an ad blocker active on the page or that there are other connection issues. + - `undefined`: The SDK is working as expected. + +- **SDK Tracing Performance Improvements for Node SDKs** + + - feat: Stop using `dropUndefinedKeys` ([#15796](https://github.com/getsentry/sentry-javascript/pull/15796)) + - feat(node): Only add span listeners for instrumentation when used ([#15802](https://github.com/getsentry/sentry-javascript/pull/15802)) + - ref: Avoid `dropUndefinedKeys` for `spanToJSON` calls ([#15792](https://github.com/getsentry/sentry-javascript/pull/15792)) + - ref: Avoid using `SentryError` for PromiseBuffer control flow ([#15822](https://github.com/getsentry/sentry-javascript/pull/15822)) + - ref: Stop using `dropUndefinedKeys` in SpanExporter ([#15794](https://github.com/getsentry/sentry-javascript/pull/15794)) + - ref(core): Avoid using `SentryError` for event processing control flow ([#15823](https://github.com/getsentry/sentry-javascript/pull/15823)) + - ref(node): Avoid `dropUndefinedKeys` in Node SDK init ([#15797](https://github.com/getsentry/sentry-javascript/pull/15797)) + - ref(opentelemetry): Avoid sampling work for non-root spans ([#15820](https://github.com/getsentry/sentry-javascript/pull/15820)) + + We've been hard at work making performance improvements to the Sentry Node SDKs (`@sentry/node`, `@sentry/aws-serverless`, `@sentry/nestjs`, etc.). We've seen that upgrading from `9.7.0` to `9.10.0` leads to 30-40% improvement in request latency for HTTP web-server applications that use tracing with high sample rates. Non web-server applications and non-tracing applications will see smaller improvements. + +### Other Changes + +- chore(deps): Bump `rrweb` to `2.35.0` ([#15825](https://github.com/getsentry/sentry-javascript/pull/15825)) +- deps: Bump bundler plugins to `3.2.3` ([#15829](https://github.com/getsentry/sentry-javascript/pull/15829)) +- feat: Always truncate stored breadcrumb messages to 2kb ([#15819](https://github.com/getsentry/sentry-javascript/pull/15819)) +- feat(nextjs): Disable server webpack-handling for static builds ([#15751](https://github.com/getsentry/sentry-javascript/pull/15751)) +- fix(nuxt): Don't override Nuxt options if undefined ([#15795](https://github.com/getsentry/sentry-javascript/pull/15795)) + ## 9.9.0 ### Important Changes @@ -42,7 +123,7 @@ - **feat(browser): Add `logger.X` methods to browser SDK ([#15763](https://github.com/getsentry/sentry-javascript/pull/15763))** - For Sentry's [upcoming logging product](https://github.com/getsentry/sentry/discussions/86804), the SDK now supports sending logs via dedicated + For Sentry's [upcoming logging product](https://github.com/getsentry/sentry/discussions/86804), the SDK now supports sending logs via dedicated methods. ```js Sentry.init({ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b74d59693a18..8d486d6718c1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,23 +73,6 @@ the tests in each location. Check out the `scripts` entry of the corresponding ` Note: you must run `yarn build` before `yarn test` will work. -## Debugging Tests - -If you run into trouble writing tests and need to debug one of them, you can do so using VSCode's debugger. - -0. If you don't already have it installed, install the Tasks Shell Input extension, which you'll find in the Extensions - tab in the sidebar as one of the recommended workspace extensions. - -1. Place breakpoints or `debugger` statements in the test or the underlying code wherever you'd like `jest` to pause. -2. Open the file containing the test in question, and make sure its tab is active (so you can see the file's contents). -3. Switch to the debugger in the sidebar and choose `Debug unit tests - just open file` from the dropdown. -4. Click the green "play" button to run the tests in the open file in watch mode. - -Pro tip: If any of your breakpoints are in code run by multiple tests, and you run the whole test file, you'll land on -those breakpoints over and over again, in the middle of tests you don't care about. To avoid this, replace the test's -initial `it` or `test` with `it.only` or `test.only`. That way, when you hit a breakpoint, you'll know you got there are -part of the buggy test. - ## Debug Build Flags Throughout the codebase, you will find a `__DEBUG_BUILD__` constant. This flag serves two purposes: diff --git a/dev-packages/browser-integration-tests/suites/public-api/captureException/aggregateError/subject.js b/dev-packages/browser-integration-tests/suites/public-api/captureException/aggregateError/subject.js new file mode 100644 index 000000000000..fb5bf2f2100e --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/captureException/aggregateError/subject.js @@ -0,0 +1,13 @@ +try { + // Create an AggregateError with multiple error objects + const error1 = new Error('First error message'); + const error2 = new TypeError('Second error message'); + const error3 = new RangeError('Third error message'); + + // Create the AggregateError with these errors and a message + const aggregateError = new AggregateError([error1, error2, error3], 'Multiple errors occurred'); + + throw aggregateError; +} catch (err) { + Sentry.captureException(err); +} diff --git a/dev-packages/browser-integration-tests/suites/public-api/captureException/aggregateError/test.ts b/dev-packages/browser-integration-tests/suites/public-api/captureException/aggregateError/test.ts new file mode 100644 index 000000000000..41b1a09c74f3 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/captureException/aggregateError/test.ts @@ -0,0 +1,69 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../../utils/fixtures'; +import { envelopeRequestParser, waitForErrorRequestOnUrl } from '../../../../utils/helpers'; + +sentryTest('should capture an AggregateError with embedded errors', async ({ getLocalTestUrl, page }) => { + const url = await getLocalTestUrl({ testDir: __dirname }); + const req = await waitForErrorRequestOnUrl(page, url); + const eventData = envelopeRequestParser(req); + + expect(eventData.exception?.values).toHaveLength(4); // AggregateError + 3 embedded errors + + // Verify the embedded errors come first + expect(eventData.exception?.values?.[0]).toMatchObject({ + type: 'RangeError', + value: 'Third error message', + mechanism: { + type: 'chained', + handled: true, + source: expect.stringMatching(/^errors\[\d+\]$/), + exception_id: expect.any(Number), + }, + }); + + expect(eventData.exception?.values?.[1]).toMatchObject({ + type: 'TypeError', + value: 'Second error message', + mechanism: { + type: 'chained', + handled: true, + source: expect.stringMatching(/^errors\[\d+\]$/), + exception_id: expect.any(Number), + }, + }); + + expect(eventData.exception?.values?.[2]).toMatchObject({ + type: 'Error', + value: 'First error message', + mechanism: { + type: 'chained', + handled: true, + source: expect.stringMatching(/^errors\[\d+\]$/), + exception_id: expect.any(Number), + }, + }); + + // Verify the AggregateError comes last + expect(eventData.exception?.values?.[3]).toMatchObject({ + type: 'AggregateError', + value: 'Multiple errors occurred', + mechanism: { + type: 'generic', + handled: true, + is_exception_group: true, + exception_id: expect.any(Number), + }, + stacktrace: { + frames: expect.any(Array), + }, + }); + + // Get parent exception ID for reference checks + const parentId = eventData.exception?.values?.[3].mechanism?.exception_id; + + // Verify parent_id references match for all child errors + for (let i = 0; i < 3; i++) { + expect(eventData.exception?.values?.[i].mechanism?.parent_id).toBe(parentId); + } +}); diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/init.js b/dev-packages/browser-integration-tests/suites/public-api/logger/init.js new file mode 100644 index 000000000000..27397e0f90ce --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/init.js @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + _experiments: { + enableLogs: true, + }, +}); diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/subject.js b/dev-packages/browser-integration-tests/suites/public-api/logger/subject.js new file mode 100644 index 000000000000..e175ee4c9e27 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/subject.js @@ -0,0 +1,19 @@ +Sentry.logger.trace('test trace'); +Sentry.logger.debug('test debug'); +Sentry.logger.info('test info'); +Sentry.logger.warn('test warn'); +Sentry.logger.error('test error'); +Sentry.logger.fatal('test fatal'); + +const formattedMessage = (message, stringArg, boolArg, numberArg) => { + return Sentry.logger.fmt`test ${message} ${stringArg} ${boolArg} ${numberArg}`; +}; + +Sentry.logger.trace(formattedMessage('trace', 'stringArg', false, 123)); +Sentry.logger.debug(formattedMessage('debug', 'stringArg', false, 123)); +Sentry.logger.info(formattedMessage('info', 'stringArg', false, 123)); +Sentry.logger.warn(formattedMessage('warn', 'stringArg', false, 123)); +Sentry.logger.error(formattedMessage('error', 'stringArg', false, 123)); +Sentry.logger.fatal(formattedMessage('fatal', 'stringArg', false, 123)); + +Sentry.flush(); diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/test.ts new file mode 100644 index 000000000000..53a5f31ffcbb --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/test.ts @@ -0,0 +1,372 @@ +import { expect } from '@playwright/test'; +import type { OtelLogEnvelope } from '@sentry/core'; + +import { sentryTest } from '../../../utils/fixtures'; +import { getFirstSentryEnvelopeRequest, properFullEnvelopeRequestParser } from '../../../utils/helpers'; + +sentryTest('should capture all logging methods', async ({ getLocalTestUrl, page }) => { + const bundle = process.env.PW_BUNDLE || ''; + // Only run this for npm package exports + if (bundle.startsWith('bundle') || bundle.startsWith('loader')) { + sentryTest.skip(); + } + + const url = await getLocalTestUrl({ testDir: __dirname }); + + const event = await getFirstSentryEnvelopeRequest(page, url, properFullEnvelopeRequestParser); + const envelopeItems = event[1]; + + expect(envelopeItems[0]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'trace', + body: { stringValue: 'test trace' }, + attributes: [], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 1, + }, + ]); + + expect(envelopeItems[1]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'debug', + body: { stringValue: 'test debug' }, + attributes: [], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 5, + }, + ]); + + expect(envelopeItems[2]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'info', + body: { stringValue: 'test info' }, + attributes: [], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 9, + }, + ]); + + expect(envelopeItems[3]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'warn', + body: { stringValue: 'test warn' }, + attributes: [], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 13, + }, + ]); + + expect(envelopeItems[4]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'error', + body: { stringValue: 'test error' }, + attributes: [], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 17, + }, + ]); + + expect(envelopeItems[5]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'fatal', + body: { stringValue: 'test fatal' }, + attributes: [], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 21, + }, + ]); + + expect(envelopeItems[6]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'trace', + body: { stringValue: 'test trace stringArg false 123' }, + attributes: [ + { + key: 'sentry.message.template', + value: { + stringValue: 'test %s %s %s %s', + }, + }, + { + key: 'sentry.message.param.0', + value: { + stringValue: 'trace', + }, + }, + { + key: 'sentry.message.param.1', + value: { + stringValue: 'stringArg', + }, + }, + { + key: 'sentry.message.param.2', + value: { + boolValue: false, + }, + }, + { + key: 'sentry.message.param.3', + value: { + doubleValue: 123, + }, + }, + ], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 1, + }, + ]); + + expect(envelopeItems[7]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'debug', + body: { stringValue: 'test debug stringArg false 123' }, + attributes: [ + { + key: 'sentry.message.template', + value: { + stringValue: 'test %s %s %s %s', + }, + }, + { + key: 'sentry.message.param.0', + value: { + stringValue: 'debug', + }, + }, + { + key: 'sentry.message.param.1', + value: { + stringValue: 'stringArg', + }, + }, + { + key: 'sentry.message.param.2', + value: { + boolValue: false, + }, + }, + { + key: 'sentry.message.param.3', + value: { + doubleValue: 123, + }, + }, + ], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 5, + }, + ]); + + expect(envelopeItems[8]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'info', + body: { stringValue: 'test info stringArg false 123' }, + attributes: [ + { + key: 'sentry.message.template', + value: { + stringValue: 'test %s %s %s %s', + }, + }, + { + key: 'sentry.message.param.0', + value: { + stringValue: 'info', + }, + }, + { + key: 'sentry.message.param.1', + value: { + stringValue: 'stringArg', + }, + }, + { + key: 'sentry.message.param.2', + value: { + boolValue: false, + }, + }, + { + key: 'sentry.message.param.3', + value: { + doubleValue: 123, + }, + }, + ], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 9, + }, + ]); + + expect(envelopeItems[9]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'warn', + body: { stringValue: 'test warn stringArg false 123' }, + attributes: [ + { + key: 'sentry.message.template', + value: { + stringValue: 'test %s %s %s %s', + }, + }, + { + key: 'sentry.message.param.0', + value: { + stringValue: 'warn', + }, + }, + { + key: 'sentry.message.param.1', + value: { + stringValue: 'stringArg', + }, + }, + { + key: 'sentry.message.param.2', + value: { + boolValue: false, + }, + }, + { + key: 'sentry.message.param.3', + value: { + doubleValue: 123, + }, + }, + ], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 13, + }, + ]); + + expect(envelopeItems[10]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'error', + body: { stringValue: 'test error stringArg false 123' }, + attributes: [ + { + key: 'sentry.message.template', + value: { + stringValue: 'test %s %s %s %s', + }, + }, + { + key: 'sentry.message.param.0', + value: { + stringValue: 'error', + }, + }, + { + key: 'sentry.message.param.1', + value: { + stringValue: 'stringArg', + }, + }, + { + key: 'sentry.message.param.2', + value: { + boolValue: false, + }, + }, + { + key: 'sentry.message.param.3', + value: { + doubleValue: 123, + }, + }, + ], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 17, + }, + ]); + + expect(envelopeItems[11]).toEqual([ + { + type: 'otel_log', + }, + { + severityText: 'fatal', + body: { stringValue: 'test fatal stringArg false 123' }, + attributes: [ + { + key: 'sentry.message.template', + value: { + stringValue: 'test %s %s %s %s', + }, + }, + { + key: 'sentry.message.param.0', + value: { + stringValue: 'fatal', + }, + }, + { + key: 'sentry.message.param.1', + value: { + stringValue: 'stringArg', + }, + }, + { + key: 'sentry.message.param.2', + value: { + boolValue: false, + }, + }, + { + key: 'sentry.message.param.3', + value: { + doubleValue: 123, + }, + }, + ], + timeUnixNano: expect.any(String), + traceId: expect.any(String), + severityNumber: 21, + }, + ]); +}); diff --git a/dev-packages/browser-integration-tests/utils/helpers.ts b/dev-packages/browser-integration-tests/utils/helpers.ts index 0d2b17cc0db9..d08ffccd7831 100644 --- a/dev-packages/browser-integration-tests/utils/helpers.ts +++ b/dev-packages/browser-integration-tests/utils/helpers.ts @@ -135,10 +135,13 @@ export const countEnvelopes = async ( page.on('request', requestHandler); - setTimeout(() => { - page.off('request', requestHandler); - resolve(reqCount); - }, options?.timeout || 1000); + setTimeout( + () => { + page.off('request', requestHandler); + resolve(reqCount); + }, + options?.timeout || 1000, + ); }); if (options?.url) { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json index f779d9ece306..f02e3c0138da 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json @@ -19,7 +19,7 @@ "@types/node": "^18.19.1", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", - "next": "14.0.2", + "next": "14.2.25", "react": "18.2.0", "react-dom": "18.2.0", "typescript": "~5.0.0" diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/server/plugins/customNitroErrorHandler.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/server/plugins/customNitroErrorHandler.ts index 2d9258936169..9ca836610f2f 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/server/plugins/customNitroErrorHandler.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/server/plugins/customNitroErrorHandler.ts @@ -1,4 +1,4 @@ -import { Context, GLOBAL_OBJ, dropUndefinedKeys, flush, logger, vercelWaitUntil } from '@sentry/core'; +import { Context, GLOBAL_OBJ, flush, logger, vercelWaitUntil } from '@sentry/core'; import * as SentryNode from '@sentry/node'; import { H3Error } from 'h3'; import type { CapturedErrorContext } from 'nitropack'; @@ -36,24 +36,22 @@ export default defineNitroPlugin(nitroApp => { }); function extractErrorContext(errorContext: CapturedErrorContext): Context { - const structuredContext: Context = { - method: undefined, - path: undefined, - tags: undefined, - }; + const ctx: Context = {}; - if (errorContext) { - if (errorContext.event) { - structuredContext.method = errorContext.event._method || undefined; - structuredContext.path = errorContext.event._path || undefined; - } + if (!errorContext) { + return ctx; + } - if (Array.isArray(errorContext.tags)) { - structuredContext.tags = errorContext.tags || undefined; - } + if (errorContext.event) { + ctx.method = errorContext.event._method; + ctx.path = errorContext.event._path; + } + + if (Array.isArray(errorContext.tags)) { + ctx.tags = errorContext.tags; } - return dropUndefinedKeys(structuredContext); + return ctx; } async function flushIfServerless(): Promise { diff --git a/dev-packages/node-integration-tests/.eslintrc.js b/dev-packages/node-integration-tests/.eslintrc.js index 51b7dfbb7ed3..8d5573907fb9 100644 --- a/dev-packages/node-integration-tests/.eslintrc.js +++ b/dev-packages/node-integration-tests/.eslintrc.js @@ -1,7 +1,6 @@ module.exports = { env: { node: true, - jest: true, }, extends: ['../../.eslintrc.js'], overrides: [ diff --git a/dev-packages/node-integration-tests/README.md b/dev-packages/node-integration-tests/README.md index 3f7abd7b5727..c920f05d5e31 100644 --- a/dev-packages/node-integration-tests/README.md +++ b/dev-packages/node-integration-tests/README.md @@ -23,7 +23,7 @@ folders containing test scenarios and assertions. `runServer` also accepts an optional `scenarioPath` argument for non-standard usage. `test.ts` is required for each test case, and contains the server runner logic, request interceptors for Sentry -requests, and assertions. Test server, interceptors and assertions are all run on the same Jest thread. +requests, and assertions. Test server, interceptors and assertions are all run on the same Vitest thread. ### Utilities @@ -40,12 +40,10 @@ Tests can be run locally with: `yarn test` -To run tests with Jest's watch mode: +To run tests with Vitest's watch mode: `yarn test:watch` To filter tests by their title: `yarn test -t "set different properties of a scope"` - -You can refer to [Jest documentation](https://jestjs.io/docs/cli) for other CLI options. diff --git a/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts b/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts index 797ede718b39..9a9fa28b1022 100644 --- a/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/tedious/test.ts @@ -1,7 +1,8 @@ import { afterAll, describe, expect, test } from 'vitest'; import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; -describe('tedious auto instrumentation', {timeout: 75_000}, () => { +// eslint-disable-next-line @sentry-internal/sdk/no-skipped-tests +describe.skip('tedious auto instrumentation', { timeout: 75_000 }, () => { afterAll(() => { cleanupChildProcesses(); }); diff --git a/dev-packages/node-integration-tests/tsconfig.json b/dev-packages/node-integration-tests/tsconfig.json index 9ef29d983a08..1cd6c0aec734 100644 --- a/dev-packages/node-integration-tests/tsconfig.json +++ b/dev-packages/node-integration-tests/tsconfig.json @@ -9,6 +9,6 @@ "lib": ["DOM", "ES2018"], // package-specific options "esModuleInterop": true, - "types": ["node", "jest"] + "types": ["node"] } } diff --git a/dev-packages/node-integration-tests/utils/assertions.ts b/dev-packages/node-integration-tests/utils/assertions.ts index 4197c4a70844..f3925dfd493e 100644 --- a/dev-packages/node-integration-tests/utils/assertions.ts +++ b/dev-packages/node-integration-tests/utils/assertions.ts @@ -4,6 +4,7 @@ import type { Envelope, Event, SerializedCheckIn, + SerializedOtelLog, SerializedSession, SessionAggregates, TransactionEvent, @@ -66,6 +67,12 @@ export function assertSentryClientReport(actual: ClientReport, expected: Partial }); } +export function assertSentryOtelLog(actual: SerializedOtelLog, expected: Partial): void { + expect(actual).toMatchObject({ + ...expected, + }); +} + export function assertEnvelopeHeader(actual: Envelope[0], expected: Partial): void { expect(actual).toEqual({ event_id: expect.any(String), diff --git a/dev-packages/node-integration-tests/utils/runner.ts b/dev-packages/node-integration-tests/utils/runner.ts index 1d77e80bf55c..436e03a4c330 100644 --- a/dev-packages/node-integration-tests/utils/runner.ts +++ b/dev-packages/node-integration-tests/utils/runner.ts @@ -10,6 +10,7 @@ import type { Event, EventEnvelope, SerializedCheckIn, + SerializedOtelLog, SerializedSession, SessionAggregates, TransactionEvent, @@ -20,6 +21,7 @@ import { assertSentryCheckIn, assertSentryClientReport, assertSentryEvent, + assertSentryOtelLog, assertSentrySession, assertSentrySessions, assertSentryTransaction, @@ -119,6 +121,7 @@ type ExpectedSession = Partial | ((event: SerializedSession) type ExpectedSessions = Partial | ((event: SessionAggregates) => void); type ExpectedCheckIn = Partial | ((event: SerializedCheckIn) => void); type ExpectedClientReport = Partial | ((event: ClientReport) => void); +type ExpectedOtelLog = Partial | ((event: SerializedOtelLog) => void); type Expected = | { @@ -138,13 +141,17 @@ type Expected = } | { client_report: ExpectedClientReport; + } + | { + otel_log: ExpectedOtelLog; }; type ExpectedEnvelopeHeader = | { event: Partial } | { transaction: Partial } | { session: Partial } - | { sessions: Partial }; + | { sessions: Partial } + | { otel_log: Partial }; type StartResult = { completed(): Promise; @@ -325,6 +332,9 @@ export function createRunner(...paths: string[]) { } else if ('client_report' in expected) { expectClientReport(item[1] as ClientReport, expected.client_report); expectCallbackCalled(); + } else if ('otel_log' in expected) { + expectOtelLog(item[1] as SerializedOtelLog, expected.otel_log); + expectCallbackCalled(); } else { throw new Error( `Unhandled expected envelope item type: ${JSON.stringify(expected)}\nItem: ${JSON.stringify(item)}`, @@ -547,3 +557,11 @@ function expectClientReport(item: ClientReport, expected: ExpectedClientReport): assertSentryClientReport(item, expected); } } + +function expectOtelLog(item: SerializedOtelLog, expected: ExpectedOtelLog): void { + if (typeof expected === 'function') { + expected(item); + } else { + assertSentryOtelLog(item, expected); + } +} diff --git a/jest/jest.config.js b/jest/jest.config.js deleted file mode 100644 index 804519918182..000000000000 --- a/jest/jest.config.js +++ /dev/null @@ -1,43 +0,0 @@ -module.exports = { - // this is the package root, even when tests are being run at the repo level - rootDir: process.cwd(), - collectCoverage: true, - transform: { - '^.+\\.(ts|tsx)$': 'ts-jest', - }, - coverageDirectory: '/coverage', - moduleFileExtensions: ['js', 'ts', 'tsx'], - testMatch: ['/**/*.test.ts', '/**/*.test.tsx'], - moduleNameMapper: { - '^axios$': require.resolve('axios'), - '@opentelemetry/semantic-conventions/incubating': require.resolve('@opentelemetry/semantic-conventions/incubating'), - }, - globals: { - 'ts-jest': { - tsconfig: '/tsconfig.test.json', - diagnostics: { - // Ignore this warning for tests, we do not care about this - ignoreCodes: ['TS151001'], - }, - }, - __DEBUG_BUILD__: true, - }, - testPathIgnorePatterns: ['/build/', '/node_modules/'], - - // On CI, we do not need the pretty CLI output, as it makes logs harder to parse - ...(process.env.CI - ? { - coverageReporters: ['json', 'lcov', 'clover'], - reporters: [ - 'default', - [ - 'jest-junit', - { - outputName: 'jest.junit.xml', - classNameTemplate: '{filepath}', - }, - ], - ], - } - : {}), -}; diff --git a/package.json b/package.json index 138ed7d787de..8985b40af8d0 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "circularDepCheck": "lerna run circularDepCheck", "clean": "run-s clean:build clean:caches", "clean:build": "lerna run clean", - "clean:caches": "yarn rimraf eslintcache .nxcache .nx && yarn jest --clearCache", + "clean:caches": "yarn rimraf eslintcache .nxcache .nx", "clean:deps": "lerna clean --yes && rm -rf node_modules && yarn", "clean:tarballs": "rimraf {packages,dev-packages}/*/*.tgz", "clean:watchman": "watchman watch-del \".\"", @@ -110,7 +110,6 @@ "@rollup/pluginutils": "^5.1.0", "@size-limit/file": "~11.1.6", "@size-limit/webpack": "~11.1.6", - "@types/jest": "^27.4.1", "@types/jsdom": "^21.1.6", "@types/node": "^18.19.1", "@vitest/coverage-v8": "^2.1.8", @@ -118,9 +117,6 @@ "downlevel-dts": "~0.11.0", "es-check": "^7.2.1", "eslint": "7.32.0", - "jest": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-junit": "^16.0.0", "jsdom": "^21.1.2", "lerna": "7.1.1", "madge": "7.0.0", @@ -133,7 +129,6 @@ "rollup-plugin-license": "^3.3.1", "size-limit": "~11.1.6", "sucrase": "^3.35.0", - "ts-jest": "^27.1.4", "ts-node": "10.9.1", "typescript": "~5.0.0", "vitest": "^2.1.8", diff --git a/packages/astro/src/index.server.ts b/packages/astro/src/index.server.ts index 6f9647d0134e..6467affd841c 100644 --- a/packages/astro/src/index.server.ts +++ b/packages/astro/src/index.server.ts @@ -127,6 +127,7 @@ export { withScope, zodErrorsIntegration, profiler, + logger, } from '@sentry/node'; export { init } from './server/sdk'; diff --git a/packages/astro/src/index.types.ts b/packages/astro/src/index.types.ts index eeadf11fa3d5..ec6713098f11 100644 --- a/packages/astro/src/index.types.ts +++ b/packages/astro/src/index.types.ts @@ -10,6 +10,7 @@ import type { NodeOptions } from '@sentry/node'; import type { Client, Integration, Options, StackParser } from '@sentry/core'; import type * as clientSdk from './index.client'; +import type * as serverSdk from './index.server'; import sentryAstro from './index.server'; /** Initializes Sentry Astro SDK */ @@ -26,4 +27,6 @@ export declare function flush(timeout?: number | undefined): PromiseLike { + const client = getClient(); + + if (!client) { + return 'no-client-active'; + } + + if (!client.getDsn()) { + return 'no-dsn-configured'; + } + + try { + // If fetch throws, there is likely an ad blocker active or there are other connective issues. + await fetch( + // We want this to be as close as possible to an actual ingest URL so that ad blockers will actually block the request + // We are using the "sentry-sdks" org with id 447951 not to pollute any actual organizations. + 'https://o447951.ingest.sentry.io/api/1337/envelope/?sentry_version=7&sentry_key=1337&sentry_client=sentry.javascript.browser%2F1.33.7', + { + body: '{}', + method: 'POST', + mode: 'cors', + credentials: 'omit', + }, + ); + } catch { + return 'sentry-unreachable'; + } +} diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 47bef0cd6dae..9103bbab99b5 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -71,3 +71,4 @@ export { launchDarklyIntegration, buildLaunchDarklyFlagUsedHandler } from './int export { openFeatureIntegration, OpenFeatureIntegrationHook } from './integrations/featureFlags/openfeature'; export { unleashIntegration } from './integrations/featureFlags/unleash'; export { statsigIntegration } from './integrations/featureFlags/statsig'; +export { diagnoseSdkConnectivity } from './diagnose-sdk'; diff --git a/packages/browser/src/log.ts b/packages/browser/src/log.ts index 4ae97fd27a94..23322c168a67 100644 --- a/packages/browser/src/log.ts +++ b/packages/browser/src/log.ts @@ -1,4 +1,4 @@ -import type { LogSeverityLevel, Log, Client } from '@sentry/core'; +import type { LogSeverityLevel, Log, Client, ParameterizedString } from '@sentry/core'; import { getClient, _INTERNAL_captureLog, _INTERNAL_flushLogsBuffer } from '@sentry/core'; import { WINDOW } from './helpers'; @@ -59,7 +59,7 @@ function addFlushingListeners(client: Client): void { */ function captureLog( level: LogSeverityLevel, - message: string, + message: ParameterizedString, attributes?: Log['attributes'], severityNumber?: Log['severityNumber'], ): void { @@ -77,15 +77,28 @@ function captureLog( * @summary Capture a log with the `trace` level. Requires `_experiments.enableLogs` to be enabled. * * @param message - The message to log. - * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. + * @param attributes - Arbitrary structured data that stores information about the log - e.g., { userId: 100, route: '/dashboard' }. * * @example * * ``` - * Sentry.logger.trace('Hello world', { userId: 100 }); + * Sentry.logger.trace('User clicked submit button', { + * buttonId: 'submit-form', + * formId: 'user-profile', + * timestamp: Date.now() + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.trace(Sentry.logger.fmt`User ${user} navigated to ${page}`, { + * userId: '123', + * sessionId: 'abc-xyz' + * }); * ``` */ -export function trace(message: string, attributes?: Log['attributes']): void { +export function trace(message: ParameterizedString, attributes?: Log['attributes']): void { captureLog('trace', message, attributes); } @@ -93,15 +106,29 @@ export function trace(message: string, attributes?: Log['attributes']): void { * @summary Capture a log with the `debug` level. Requires `_experiments.enableLogs` to be enabled. * * @param message - The message to log. - * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. + * @param attributes - Arbitrary structured data that stores information about the log - e.g., { component: 'Header', state: 'loading' }. * * @example * * ``` - * Sentry.logger.debug('Hello world', { userId: 100 }); + * Sentry.logger.debug('Component mounted', { + * component: 'UserProfile', + * props: { userId: 123 }, + * renderTime: 150 + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.debug(Sentry.logger.fmt`API request to ${endpoint} failed`, { + * statusCode: 404, + * requestId: 'req-123', + * duration: 250 + * }); * ``` */ -export function debug(message: string, attributes?: Log['attributes']): void { +export function debug(message: ParameterizedString, attributes?: Log['attributes']): void { captureLog('debug', message, attributes); } @@ -109,15 +136,29 @@ export function debug(message: string, attributes?: Log['attributes']): void { * @summary Capture a log with the `info` level. Requires `_experiments.enableLogs` to be enabled. * * @param message - The message to log. - * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. + * @param attributes - Arbitrary structured data that stores information about the log - e.g., { feature: 'checkout', status: 'completed' }. * * @example * * ``` - * Sentry.logger.info('Hello world', { userId: 100 }); + * Sentry.logger.info('User completed checkout', { + * orderId: 'order-123', + * amount: 99.99, + * paymentMethod: 'credit_card' + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.info(Sentry.logger.fmt`User ${user} updated profile picture`, { + * userId: 'user-123', + * imageSize: '2.5MB', + * timestamp: Date.now() + * }); * ``` */ -export function info(message: string, attributes?: Log['attributes']): void { +export function info(message: ParameterizedString, attributes?: Log['attributes']): void { captureLog('info', message, attributes); } @@ -125,15 +166,30 @@ export function info(message: string, attributes?: Log['attributes']): void { * @summary Capture a log with the `warn` level. Requires `_experiments.enableLogs` to be enabled. * * @param message - The message to log. - * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. + * @param attributes - Arbitrary structured data that stores information about the log - e.g., { browser: 'Chrome', version: '91.0' }. * * @example * * ``` - * Sentry.logger.warn('Hello world', { userId: 100 }); + * Sentry.logger.warn('Browser compatibility issue detected', { + * browser: 'Safari', + * version: '14.0', + * feature: 'WebRTC', + * fallback: 'enabled' + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.warn(Sentry.logger.fmt`API endpoint ${endpoint} is deprecated`, { + * recommendedEndpoint: '/api/v2/users', + * sunsetDate: '2024-12-31', + * clientVersion: '1.2.3' + * }); * ``` */ -export function warn(message: string, attributes?: Log['attributes']): void { +export function warn(message: ParameterizedString, attributes?: Log['attributes']): void { captureLog('warn', message, attributes); } @@ -141,15 +197,31 @@ export function warn(message: string, attributes?: Log['attributes']): void { * @summary Capture a log with the `error` level. Requires `_experiments.enableLogs` to be enabled. * * @param message - The message to log. - * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. + * @param attributes - Arbitrary structured data that stores information about the log - e.g., { error: 'NetworkError', url: '/api/data' }. * * @example * * ``` - * Sentry.logger.error('Hello world', { userId: 100 }); + * Sentry.logger.error('Failed to load user data', { + * error: 'NetworkError', + * url: '/api/users/123', + * statusCode: 500, + * retryCount: 3 + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.error(Sentry.logger.fmt`Payment processing failed for order ${orderId}`, { + * error: 'InsufficientFunds', + * amount: 100.00, + * currency: 'USD', + * userId: 'user-456' + * }); * ``` */ -export function error(message: string, attributes?: Log['attributes']): void { +export function error(message: ParameterizedString, attributes?: Log['attributes']): void { captureLog('error', message, attributes); } @@ -157,30 +229,32 @@ export function error(message: string, attributes?: Log['attributes']): void { * @summary Capture a log with the `fatal` level. Requires `_experiments.enableLogs` to be enabled. * * @param message - The message to log. - * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. + * @param attributes - Arbitrary structured data that stores information about the log - e.g., { appState: 'corrupted', sessionId: 'abc-123' }. * * @example * * ``` - * Sentry.logger.fatal('Hello world', { userId: 100 }); + * Sentry.logger.fatal('Application state corrupted', { + * lastKnownState: 'authenticated', + * sessionId: 'session-123', + * timestamp: Date.now(), + * recoveryAttempted: true + * }); * ``` - */ -export function fatal(message: string, attributes?: Log['attributes']): void { - captureLog('fatal', message, attributes); -} - -/** - * @summary Capture a log with the `critical` level. Requires `_experiments.enableLogs` to be enabled. * - * @param message - The message to log. - * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. - * - * @example + * @example With template strings * * ``` - * Sentry.logger.critical('Hello world', { userId: 100 }); + * Sentry.logger.fatal(Sentry.logger.fmt`Critical system failure in ${service}`, { + * service: 'payment-processor', + * errorCode: 'CRITICAL_FAILURE', + * affectedUsers: 150, + * timestamp: Date.now() + * }); * ``` */ -export function critical(message: string, attributes?: Log['attributes']): void { - captureLog('critical', message, attributes); +export function fatal(message: ParameterizedString, attributes?: Log['attributes']): void { + captureLog('fatal', message, attributes); } + +export { fmt } from '@sentry/core'; diff --git a/packages/browser/test/index.test.ts b/packages/browser/test/index.test.ts index f6f66184509f..ad4d47b1bf04 100644 --- a/packages/browser/test/index.test.ts +++ b/packages/browser/test/index.test.ts @@ -334,7 +334,6 @@ describe('SentryBrowser', () => { expect(logger.warn).toBeDefined(); expect(logger.error).toBeDefined(); expect(logger.fatal).toBeDefined(); - expect(logger.critical).toBeDefined(); }); }); }); diff --git a/packages/browser/test/log.test.ts b/packages/browser/test/log.test.ts index 582cc3b45d20..9cddc3ecfc71 100644 --- a/packages/browser/test/log.test.ts +++ b/packages/browser/test/log.test.ts @@ -64,7 +64,6 @@ describe('Logger', () => { expect(logger.warn).toBeTypeOf('function'); expect(logger.error).toBeTypeOf('function'); expect(logger.fatal).toBeTypeOf('function'); - expect(logger.critical).toBeTypeOf('function'); }); it('should call _INTERNAL_captureLog with trace level', () => { @@ -150,20 +149,6 @@ describe('Logger', () => { undefined, ); }); - - it('should call _INTERNAL_captureLog with critical level', () => { - logger.critical('Test critical message', { key: 'value' }); - expect(mockCaptureLog).toHaveBeenCalledWith( - { - level: 'critical', - message: 'Test critical message', - attributes: { key: 'value' }, - severityNumber: undefined, - }, - expect.any(Object), - undefined, - ); - }); }); describe('Automatic flushing', () => { @@ -196,5 +181,38 @@ describe('Logger', () => { vi.advanceTimersByTime(2000); expect(mockFlushLogsBuffer).toHaveBeenCalledTimes(1); }); + + it('should handle parameterized strings with parameters', () => { + logger.info(logger.fmt`Hello ${'John'}, your balance is ${100}`, { userId: 123 }); + expect(mockCaptureLog).toHaveBeenCalledWith( + { + level: 'info', + message: expect.objectContaining({ + __sentry_template_string__: 'Hello %s, your balance is %s', + __sentry_template_values__: ['John', 100], + }), + attributes: { + userId: 123, + }, + }, + expect.any(Object), + undefined, + ); + }); + + it('should handle parameterized strings without additional attributes', () => { + logger.debug(logger.fmt`User ${'Alice'} logged in from ${'mobile'}`); + expect(mockCaptureLog).toHaveBeenCalledWith( + { + level: 'debug', + message: expect.objectContaining({ + __sentry_template_string__: 'User %s logged in from %s', + __sentry_template_values__: ['Alice', 'mobile'], + }), + }, + expect.any(Object), + undefined, + ); + }); }); }); diff --git a/packages/browser/test/tracing/browserTracingIntegration.test.ts b/packages/browser/test/tracing/browserTracingIntegration.test.ts index ee43935cd531..fe9005d47215 100644 --- a/packages/browser/test/tracing/browserTracingIntegration.test.ts +++ b/packages/browser/test/tracing/browserTracingIntegration.test.ts @@ -728,6 +728,7 @@ describe('browserTracingIntegration', () => { sampled: true, sampleRand: expect.any(Number), dsc: { + release: undefined, environment: 'production', public_key: 'examplePublicKey', sample_rate: '1', @@ -768,6 +769,7 @@ describe('browserTracingIntegration', () => { sampled: false, sampleRand: expect.any(Number), dsc: { + release: undefined, environment: 'production', public_key: 'examplePublicKey', sample_rate: '0', @@ -892,6 +894,7 @@ describe('browserTracingIntegration', () => { expect(dynamicSamplingContext).toBeDefined(); expect(dynamicSamplingContext).toStrictEqual({ + release: undefined, environment: 'production', public_key: 'examplePublicKey', sample_rate: '1', diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 52b3d9fa4c42..c2aff0f1ca52 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -132,6 +132,7 @@ export { profiler, amqplibIntegration, vercelAIIntegration, + logger, } from '@sentry/node'; export { diff --git a/packages/cloudflare/src/transport.ts b/packages/cloudflare/src/transport.ts index 40b8549df9cd..108a0e915656 100644 --- a/packages/cloudflare/src/transport.ts +++ b/packages/cloudflare/src/transport.ts @@ -1,5 +1,5 @@ import type { BaseTransportOptions, Transport, TransportMakeRequestResponse, TransportRequest } from '@sentry/core'; -import { SentryError, createTransport, suppressTracing } from '@sentry/core'; +import { SENTRY_BUFFER_FULL_ERROR, createTransport, suppressTracing } from '@sentry/core'; export interface CloudflareTransportOptions extends BaseTransportOptions { /** Fetch API init parameters. */ @@ -38,7 +38,7 @@ export class IsolatedPromiseBuffer { */ public add(taskProducer: () => PromiseLike): PromiseLike { if (this._taskProducers.length >= this._bufferSize) { - return Promise.reject(new SentryError('Not adding Promise because buffer limit was reached.')); + return Promise.reject(SENTRY_BUFFER_FULL_ERROR); } this._taskProducers.push(taskProducer); diff --git a/packages/cloudflare/test/transport.test.ts b/packages/cloudflare/test/transport.test.ts index d3aca638eba1..d02ef18079be 100644 --- a/packages/cloudflare/test/transport.test.ts +++ b/packages/cloudflare/test/transport.test.ts @@ -1,4 +1,4 @@ -import { createEnvelope, serializeEnvelope } from '@sentry/core'; +import { SENTRY_BUFFER_FULL_ERROR, createEnvelope, serializeEnvelope } from '@sentry/core'; import type { EventEnvelope, EventItem } from '@sentry/core'; import { afterAll, describe, expect, it, vi } from 'vitest'; @@ -140,7 +140,12 @@ describe('IsolatedPromiseBuffer', () => { await ipb.add(task2); await ipb.add(task3); - await expect(ipb.add(task4)).rejects.toThrowError('Not adding Promise because buffer limit was reached.'); + try { + await ipb.add(task4); + throw new Error('Should not be called'); + } catch (error) { + expect(error).toBe(SENTRY_BUFFER_FULL_ERROR); + } }); it('should not throw when one of the tasks throws when drained', async () => { diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts index af13ea2d691f..6deea6ac38ce 100644 --- a/packages/core/src/client.ts +++ b/packages/core/src/client.ts @@ -16,6 +16,7 @@ import type { FeedbackEvent, FetchBreadcrumbHint, Integration, + Log, MonitorConfig, Outcome, ParameterizedString, @@ -52,7 +53,6 @@ import { import { createClientReportEnvelope } from './utils-hoist/clientreport'; import { dsnToString, makeDsn } from './utils-hoist/dsn'; import { addItemToEnvelope, createAttachmentEnvelopeItem } from './utils-hoist/envelope'; -import { SentryError } from './utils-hoist/error'; import { isParameterizedString, isPlainObject, isPrimitive, isThenable } from './utils-hoist/is'; import { logger } from './utils-hoist/logger'; import { checkOrSetAlreadyCaught, uuid4 } from './utils-hoist/misc'; @@ -68,6 +68,41 @@ import { _getSpanForScope } from './utils/spanOnScope'; const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured."; const MISSING_RELEASE_FOR_SESSION_ERROR = 'Discarded session because of missing or non-string release'; +const INTERNAL_ERROR_SYMBOL = Symbol.for('SentryInternalError'); +const DO_NOT_SEND_EVENT_SYMBOL = Symbol.for('SentryDoNotSendEventError'); + +interface InternalError { + message: string; + [INTERNAL_ERROR_SYMBOL]: true; +} + +interface DoNotSendEventError { + message: string; + [DO_NOT_SEND_EVENT_SYMBOL]: true; +} + +function _makeInternalError(message: string): InternalError { + return { + message, + [INTERNAL_ERROR_SYMBOL]: true, + }; +} + +function _makeDoNotSendEventError(message: string): DoNotSendEventError { + return { + message, + [DO_NOT_SEND_EVENT_SYMBOL]: true, + }; +} + +function _isInternalError(error: unknown): error is InternalError { + return !!error && typeof error === 'object' && INTERNAL_ERROR_SYMBOL in error; +} + +function _isDoNotSendEventError(error: unknown): error is DoNotSendEventError { + return !!error && typeof error === 'object' && DO_NOT_SEND_EVENT_SYMBOL in error; +} + /** * Base implementation for all JavaScript SDK clients. * @@ -621,6 +656,20 @@ export abstract class Client { */ public on(hook: 'close', callback: () => void): () => void; + /** + * A hook that is called before a log is captured. This hooks runs before `beforeSendLog` is fired. + * + * @returns {() => void} A function that, when executed, removes the registered callback. + */ + public on(hook: 'beforeCaptureLog', callback: (log: Log) => void): () => void; + + /** + * A hook that is called after a log is captured + * + * @returns {() => void} A function that, when executed, removes the registered callback. + */ + public on(hook: 'afterCaptureLog', callback: (log: Log) => void): () => void; + /** * Register a hook on this client. */ @@ -768,6 +817,16 @@ export abstract class Client { */ public emit(hook: 'close'): void; + /** + * Emit a hook event for client before capturing a log. This hooks runs before `beforeSendLog` is fired. + */ + public emit(hook: 'beforeCaptureLog', log: Log): void; + + /** + * Emit a hook event for client after capturing a log. + */ + public emit(hook: 'afterCaptureLog', log: Log): void; + /** * Emit a hook that was previously registered via `on()`. */ @@ -950,10 +1009,10 @@ export abstract class Client { }, reason => { if (DEBUG_BUILD) { - // If something's gone wrong, log the error as a warning. If it's just us having used a `SentryError` for - // control flow, log just the message (no stack) as a log-level log. - if (reason instanceof SentryError && reason.logLevel === 'log') { + if (_isDoNotSendEventError(reason)) { logger.log(reason.message); + } else if (_isInternalError(reason)) { + logger.warn(reason.message); } else { logger.warn(reason); } @@ -997,9 +1056,8 @@ export abstract class Client { if (isError && typeof parsedSampleRate === 'number' && Math.random() > parsedSampleRate) { this.recordDroppedEvent('sample_rate', 'error'); return rejectedSyncPromise( - new SentryError( + _makeDoNotSendEventError( `Discarding event because it's not included in the random sample (sampling rate = ${sampleRate})`, - 'log', ), ); } @@ -1010,7 +1068,7 @@ export abstract class Client { .then(prepared => { if (prepared === null) { this.recordDroppedEvent('event_processor', dataCategory); - throw new SentryError('An event processor returned `null`, will not send event.', 'log'); + throw _makeDoNotSendEventError('An event processor returned `null`, will not send event.'); } const isInternalException = hint.data && (hint.data as { __sentry__: boolean }).__sentry__ === true; @@ -1030,7 +1088,7 @@ export abstract class Client { const spanCount = 1 + spans.length; this.recordDroppedEvent('before_send', 'span', spanCount); } - throw new SentryError(`${beforeSendLabel} returned \`null\`, will not send event.`, 'log'); + throw _makeDoNotSendEventError(`${beforeSendLabel} returned \`null\`, will not send event.`); } const session = currentScope.getSession() || isolationScope.getSession(); @@ -1064,7 +1122,7 @@ export abstract class Client { return processedEvent; }) .then(null, reason => { - if (reason instanceof SentryError) { + if (_isDoNotSendEventError(reason) || _isInternalError(reason)) { throw reason; } @@ -1074,7 +1132,7 @@ export abstract class Client { }, originalException: reason, }); - throw new SentryError( + throw _makeInternalError( `Event processing pipeline threw an error, original event will not be sent. Details have been sent as a new event.\nReason: ${reason}`, ); }); @@ -1180,16 +1238,16 @@ function _validateBeforeSendResult( return beforeSendResult.then( event => { if (!isPlainObject(event) && event !== null) { - throw new SentryError(invalidValueError); + throw _makeInternalError(invalidValueError); } return event; }, e => { - throw new SentryError(`${beforeSendLabel} rejected with ${e}`); + throw _makeInternalError(`${beforeSendLabel} rejected with ${e}`); }, ); } else if (!isPlainObject(beforeSendResult) && beforeSendResult !== null) { - throw new SentryError(invalidValueError); + throw _makeInternalError(invalidValueError); } return beforeSendResult; } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 292a9d5d9f6d..800df99e1c0e 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -66,7 +66,7 @@ export { hasTracingEnabled } from './utils/hasSpansEnabled'; export { hasSpansEnabled } from './utils/hasSpansEnabled'; export { isSentryRequestUrl } from './utils/isSentryRequestUrl'; export { handleCallbackErrors } from './utils/handleCallbackErrors'; -export { parameterize } from './utils/parameterize'; +export { parameterize, fmt } from './utils/parameterize'; export { addAutoIpAddressToSession, addAutoIpAddressToUser } from './utils/ipAddress'; export { convertSpanLinksForEnvelope, diff --git a/packages/core/src/integrations/eventFilters.ts b/packages/core/src/integrations/eventFilters.ts index 95bce0d758c8..8b571b19fb75 100644 --- a/packages/core/src/integrations/eventFilters.ts +++ b/packages/core/src/integrations/eventFilters.ts @@ -102,19 +102,12 @@ function _mergeOptions( ...(internalOptions.disableErrorDefaults ? [] : DEFAULT_IGNORE_ERRORS), ], ignoreTransactions: [...(internalOptions.ignoreTransactions || []), ...(clientOptions.ignoreTransactions || [])], - ignoreInternal: internalOptions.ignoreInternal !== undefined ? internalOptions.ignoreInternal : true, }; } function _shouldDropEvent(event: Event, options: Partial): boolean { if (!event.type) { // Filter errors - - if (options.ignoreInternal && _isSentryError(event)) { - DEBUG_BUILD && - logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`); - return true; - } if (_isIgnoredError(event, options.ignoreErrors)) { DEBUG_BUILD && logger.warn( @@ -196,16 +189,6 @@ function _isAllowedUrl(event: Event, allowUrls?: Array): boolea return !url ? true : stringMatchesSomePattern(url, allowUrls); } -function _isSentryError(event: Event): boolean { - try { - // @ts-expect-error can't be a sentry error if undefined - return event.exception.values[0].type === 'SentryError'; - } catch (e) { - // ignore - } - return false; -} - function _getLastValidUrl(frames: StackFrame[] = []): string | null { for (let i = frames.length - 1; i >= 0; i--) { const frame = frames[i]; diff --git a/packages/core/src/logs/index.ts b/packages/core/src/logs/index.ts index 6c6c9b580ee9..fbe1b40493c3 100644 --- a/packages/core/src/logs/index.ts +++ b/packages/core/src/logs/index.ts @@ -5,7 +5,7 @@ import { DEBUG_BUILD } from '../debug-build'; import { SEVERITY_TEXT_TO_SEVERITY_NUMBER } from './constants'; import type { SerializedLogAttribute, SerializedOtelLog } from '../types-hoist'; import type { Log } from '../types-hoist/log'; -import { logger } from '../utils-hoist'; +import { isParameterizedString, logger } from '../utils-hoist'; import { _getSpanForScope } from '../utils/spanOnScope'; import { createOtelLogEnvelope } from './envelope'; @@ -62,18 +62,28 @@ export function logAttributeToSerializedLogAttribute(key: string, value: unknown * @experimental This method will experience breaking changes. This is not yet part of * the stable Sentry SDK API and can be changed or removed without warning. */ -export function _INTERNAL_captureLog(log: Log, client = getClient(), scope = getCurrentScope()): void { +export function _INTERNAL_captureLog(beforeLog: Log, client = getClient(), scope = getCurrentScope()): void { if (!client) { DEBUG_BUILD && logger.warn('No client available to capture log.'); return; } const { _experiments, release, environment } = client.getOptions(); - if (!_experiments?.enableLogs) { + const { enableLogs = false, beforeSendLog } = _experiments ?? {}; + if (!enableLogs) { DEBUG_BUILD && logger.warn('logging option not enabled, log will not be captured.'); return; } + client.emit('beforeCaptureLog', beforeLog); + + const log = beforeSendLog ? beforeSendLog(beforeLog) : beforeLog; + if (!log) { + client.recordDroppedEvent('before_send', 'log_item', 1); + DEBUG_BUILD && logger.warn('beforeSendLog returned null, log will not be captured.'); + return; + } + const [, traceContext] = _getTraceInfoFromScope(client, scope); const { level, message, attributes, severityNumber } = log; @@ -90,6 +100,14 @@ export function _INTERNAL_captureLog(log: Log, client = getClient(), scope = get logAttributes.environment = environment; } + if (isParameterizedString(message)) { + const { __sentry_template_string__, __sentry_template_values__ = [] } = message; + logAttributes['sentry.message.template'] = __sentry_template_string__; + __sentry_template_values__.forEach((param, index) => { + logAttributes[`sentry.message.param.${index}`] = param; + }); + } + const span = _getSpanForScope(scope); if (span) { // Add the parent span ID to the log attributes for trace context @@ -110,14 +128,14 @@ export function _INTERNAL_captureLog(log: Log, client = getClient(), scope = get const logBuffer = CLIENT_TO_LOG_BUFFER_MAP.get(client); if (logBuffer === undefined) { CLIENT_TO_LOG_BUFFER_MAP.set(client, [serializedLog]); - // Every time we initialize a new log buffer, we start a new interval to flush the buffer - return; + } else { + logBuffer.push(serializedLog); + if (logBuffer.length > MAX_LOG_BUFFER_SIZE) { + _INTERNAL_flushLogsBuffer(client, logBuffer); + } } - logBuffer.push(serializedLog); - if (logBuffer.length > MAX_LOG_BUFFER_SIZE) { - _INTERNAL_flushLogsBuffer(client, logBuffer); - } + client.emit('afterCaptureLog', log); } /** diff --git a/packages/core/src/scope.ts b/packages/core/src/scope.ts index a302e5a14c34..d10b9dea08d6 100644 --- a/packages/core/src/scope.ts +++ b/packages/core/src/scope.ts @@ -24,6 +24,7 @@ import { isPlainObject } from './utils-hoist/is'; import { logger } from './utils-hoist/logger'; import { uuid4 } from './utils-hoist/misc'; import { generateTraceId } from './utils-hoist/propagationContext'; +import { truncate } from './utils-hoist/string'; import { dateTimestampInSeconds } from './utils-hoist/time'; import { merge } from './utils/merge'; import { _getSpanForScope, _setSpanForScope } from './utils/spanOnScope'; @@ -474,9 +475,11 @@ export class Scope { return this; } - const mergedBreadcrumb = { + const mergedBreadcrumb: Breadcrumb = { timestamp: dateTimestampInSeconds(), ...breadcrumb, + // Breadcrumb messages can theoretically be infinitely large and they're held in memory so we truncate them not to leak (too much) memory + message: breadcrumb.message ? truncate(breadcrumb.message, 2048) : breadcrumb.message, }; this._breadcrumbs.push(mergedBreadcrumb); diff --git a/packages/core/src/server-runtime-client.ts b/packages/core/src/server-runtime-client.ts index 61db792b901e..16af7b57f7c4 100644 --- a/packages/core/src/server-runtime-client.ts +++ b/packages/core/src/server-runtime-client.ts @@ -4,8 +4,10 @@ import type { ClientOptions, Event, EventHint, + Log, MonitorConfig, ParameterizedString, + Primitive, SerializedCheckIn, SeverityLevel, } from './types-hoist'; @@ -20,6 +22,8 @@ import { eventFromMessage, eventFromUnknownInput } from './utils-hoist/eventbuil import { logger } from './utils-hoist/logger'; import { uuid4 } from './utils-hoist/misc'; import { resolvedSyncPromise } from './utils-hoist/syncpromise'; +import { _INTERNAL_flushLogsBuffer } from './logs'; +import { isPrimitive } from './utils-hoist'; export interface ServerRuntimeClientOptions extends ClientOptions { platform?: string; @@ -33,6 +37,8 @@ export interface ServerRuntimeClientOptions extends ClientOptions extends Client { + private _logWeight: number; + /** * Creates a new Edge SDK instance. * @param options Configuration options for this SDK. @@ -42,6 +48,26 @@ export class ServerRuntimeClient< registerSpanErrorInstrumentation(); super(options); + + this._logWeight = 0; + + // eslint-disable-next-line @typescript-eslint/no-this-alias + const client = this; + this.on('flush', () => { + _INTERNAL_flushLogsBuffer(client); + }); + + this.on('afterCaptureLog', log => { + client._logWeight += estimateLogSizeInBytes(log); + + // We flush the logs buffer if it exceeds 0.8 MB + // The log weight is a rough estimate, so we flush way before + // the payload gets too big. + if (client._logWeight > 800_000) { + _INTERNAL_flushLogsBuffer(client); + client._logWeight = 0; + } + }); } /** @@ -196,3 +222,45 @@ function setCurrentRequestSessionErroredOrCrashed(eventHint?: EventHint): void { } } } + +/** + * Estimate the size of a log in bytes. + * + * @param log - The log to estimate the size of. + * @returns The estimated size of the log in bytes. + */ +function estimateLogSizeInBytes(log: Log): number { + let weight = 0; + + // Estimate byte size of 2 bytes per character. This is a rough estimate JS strings are stored as UTF-16. + if (log.message) { + weight += log.message.length * 2; + } + + if (log.attributes) { + Object.values(log.attributes).forEach(value => { + if (Array.isArray(value)) { + weight += value.length * estimatePrimitiveSizeInBytes(value[0]); + } else if (isPrimitive(value)) { + weight += estimatePrimitiveSizeInBytes(value); + } else { + // For objects values, we estimate the size of the object as 100 bytes + weight += 100; + } + }); + } + + return weight; +} + +function estimatePrimitiveSizeInBytes(value: Primitive): number { + if (typeof value === 'string') { + return value.length * 2; + } else if (typeof value === 'number') { + return 8; + } else if (typeof value === 'boolean') { + return 4; + } + + return 0; +} diff --git a/packages/core/src/tracing/dynamicSamplingContext.ts b/packages/core/src/tracing/dynamicSamplingContext.ts index 706684ffecab..12cf4ca11ca6 100644 --- a/packages/core/src/tracing/dynamicSamplingContext.ts +++ b/packages/core/src/tracing/dynamicSamplingContext.ts @@ -8,7 +8,7 @@ import { baggageHeaderToDynamicSamplingContext, dynamicSamplingContextToSentryBaggageHeader, } from '../utils-hoist/baggage'; -import { addNonEnumerableProperty, dropUndefinedKeys } from '../utils-hoist/object'; +import { addNonEnumerableProperty } from '../utils-hoist/object'; import { hasSpansEnabled } from '../utils/hasSpansEnabled'; import { getRootSpan, spanIsSampled, spanToJSON } from '../utils/spanUtils'; import { getCapturedScopesOnSpan } from './utils'; @@ -41,12 +41,14 @@ export function getDynamicSamplingContextFromClient(trace_id: string, client: Cl const { publicKey: public_key } = client.getDsn() || {}; - const dsc = dropUndefinedKeys({ + // Instead of conditionally adding non-undefined values, we add them and then remove them if needed + // otherwise, the order of baggage entries changes, which "breaks" a bunch of tests etc. + const dsc: DynamicSamplingContext = { environment: options.environment || DEFAULT_ENVIRONMENT, release: options.release, public_key, trace_id, - }) satisfies DynamicSamplingContext; + }; client.emit('createDsc', dsc); diff --git a/packages/core/src/tracing/sentrySpan.ts b/packages/core/src/tracing/sentrySpan.ts index 6641e1e87296..f08d906dc1e0 100644 --- a/packages/core/src/tracing/sentrySpan.ts +++ b/packages/core/src/tracing/sentrySpan.ts @@ -26,7 +26,6 @@ import type { } from '../types-hoist'; import type { SpanLink } from '../types-hoist/link'; import { logger } from '../utils-hoist/logger'; -import { dropUndefinedKeys } from '../utils-hoist/object'; import { generateSpanId, generateTraceId } from '../utils-hoist/propagationContext'; import { timestampInSeconds } from '../utils-hoist/time'; import { @@ -223,7 +222,7 @@ export class SentrySpan implements Span { * use `spanToJSON(span)` instead. */ public getSpanJSON(): SpanJSON { - return dropUndefinedKeys({ + return { data: this._attributes, description: this._name, op: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP], @@ -240,7 +239,7 @@ export class SentrySpan implements Span { is_segment: (this._isStandaloneSpan && getRootSpan(this) === this) || undefined, segment_id: this._isStandaloneSpan ? getRootSpan(this).spanContext().spanId : undefined, links: convertSpanLinksForEnvelope(this._links), - }); + }; } /** @inheritdoc */ diff --git a/packages/core/src/transports/base.ts b/packages/core/src/transports/base.ts index 9296095428cf..2b7de82ba4e1 100644 --- a/packages/core/src/transports/base.ts +++ b/packages/core/src/transports/base.ts @@ -14,9 +14,8 @@ import { forEachEnvelopeItem, serializeEnvelope, } from '../utils-hoist/envelope'; -import { SentryError } from '../utils-hoist/error'; import { logger } from '../utils-hoist/logger'; -import { type PromiseBuffer, makePromiseBuffer } from '../utils-hoist/promisebuffer'; +import { type PromiseBuffer, makePromiseBuffer, SENTRY_BUFFER_FULL_ERROR } from '../utils-hoist/promisebuffer'; import { type RateLimits, isRateLimited, updateRateLimits } from '../utils-hoist/ratelimit'; import { resolvedSyncPromise } from '../utils-hoist/syncpromise'; @@ -85,7 +84,7 @@ export function createTransport( return buffer.add(requestTask).then( result => result, error => { - if (error instanceof SentryError) { + if (error === SENTRY_BUFFER_FULL_ERROR) { DEBUG_BUILD && logger.error('Skipped sending event because buffer is full.'); recordEnvelopeLoss('queue_overflow'); return resolvedSyncPromise({}); diff --git a/packages/core/src/types-hoist/event.ts b/packages/core/src/types-hoist/event.ts index 5b4d87337236..a042edad2cda 100644 --- a/packages/core/src/types-hoist/event.ts +++ b/packages/core/src/types-hoist/event.ts @@ -22,7 +22,7 @@ export interface Event { message?: string; logentry?: { message?: string; - params?: string[]; + params?: unknown[]; }; timestamp?: number; start_timestamp?: number; diff --git a/packages/core/src/types-hoist/index.ts b/packages/core/src/types-hoist/index.ts index 1ca827f225a5..1659aeda9bc0 100644 --- a/packages/core/src/types-hoist/index.ts +++ b/packages/core/src/types-hoist/index.ts @@ -49,6 +49,8 @@ export type { ProfileChunkItem, SpanEnvelope, SpanItem, + OtelLogEnvelope, + OtelLogItem, } from './envelope'; export type { ExtendedError } from './error'; export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent } from './event'; diff --git a/packages/core/src/types-hoist/log.ts b/packages/core/src/types-hoist/log.ts index a313b493306c..35e30ce42b65 100644 --- a/packages/core/src/types-hoist/log.ts +++ b/packages/core/src/types-hoist/log.ts @@ -1,4 +1,6 @@ -export type LogSeverityLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'critical'; +import type { ParameterizedString } from './parameterize'; + +export type LogSeverityLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; export type SerializedLogAttributeValueType = | { @@ -36,12 +38,12 @@ export interface Log { /** * The message to be logged - for example, 'hello world' would become a log like '[INFO] hello world' */ - message: string; + message: ParameterizedString; /** * Arbitrary structured data that stores information about the log - e.g., userId: 100. */ - attributes?: Record>; + attributes?: Record; /** * The severity number - generally higher severity are levels like 'error' and lower are levels like 'debug' diff --git a/packages/core/src/types-hoist/options.ts b/packages/core/src/types-hoist/options.ts index d0474b959fa9..51ccc7cdab79 100644 --- a/packages/core/src/types-hoist/options.ts +++ b/packages/core/src/types-hoist/options.ts @@ -2,6 +2,7 @@ import type { CaptureContext } from '../scope'; import type { Breadcrumb, BreadcrumbHint } from './breadcrumb'; import type { ErrorEvent, EventHint, TransactionEvent } from './event'; import type { Integration } from './integration'; +import type { Log } from './log'; import type { TracesSamplerSamplingContext } from './samplingcontext'; import type { SdkMetadata } from './sdkmetadata'; import type { SpanJSON } from './span'; @@ -188,6 +189,17 @@ export interface ClientOptions Log | null; }; /** diff --git a/packages/core/src/types-hoist/parameterize.ts b/packages/core/src/types-hoist/parameterize.ts index a94daa3684db..8b62bfd483e9 100644 --- a/packages/core/src/types-hoist/parameterize.ts +++ b/packages/core/src/types-hoist/parameterize.ts @@ -1,4 +1,4 @@ export type ParameterizedString = string & { __sentry_template_string__?: string; - __sentry_template_values__?: string[]; + __sentry_template_values__?: unknown[]; }; diff --git a/packages/core/src/utils-hoist/anr.ts b/packages/core/src/utils-hoist/anr.ts index 0602321117bf..84cce09bb030 100644 --- a/packages/core/src/utils-hoist/anr.ts +++ b/packages/core/src/utils-hoist/anr.ts @@ -1,6 +1,5 @@ import type { StackFrame } from '../types-hoist'; import { filenameIsInApp } from './node-stack-trace'; -import { dropUndefinedKeys } from './object'; import { UNKNOWN_FUNCTION } from './stacktrace'; type WatchdogReturn = { @@ -81,12 +80,12 @@ export function callFrameToStackFrame( const colno = frame.location.columnNumber ? frame.location.columnNumber + 1 : undefined; const lineno = frame.location.lineNumber ? frame.location.lineNumber + 1 : undefined; - return dropUndefinedKeys({ + return { filename, module: getModuleFromFilename(filename), function: frame.functionName || UNKNOWN_FUNCTION, colno, lineno, in_app: filename ? filenameIsInApp(filename) : undefined, - }); + }; } diff --git a/packages/core/src/utils-hoist/envelope.ts b/packages/core/src/utils-hoist/envelope.ts index 2593079d5db6..450706fb9c2e 100644 --- a/packages/core/src/utils-hoist/envelope.ts +++ b/packages/core/src/utils-hoist/envelope.ts @@ -18,7 +18,6 @@ import type { import { dsnToString } from './dsn'; import { normalize } from './normalize'; -import { dropUndefinedKeys } from './object'; import { GLOBAL_OBJ } from './worldwide'; /** @@ -196,13 +195,13 @@ export function createAttachmentEnvelopeItem(attachment: Attachment): Attachment const buffer = typeof attachment.data === 'string' ? encodeUTF8(attachment.data) : attachment.data; return [ - dropUndefinedKeys({ + { type: 'attachment', length: buffer.length, filename: attachment.filename, content_type: attachment.contentType, attachment_type: attachment.attachmentType, - }), + }, buffer, ]; } diff --git a/packages/core/src/utils-hoist/error.ts b/packages/core/src/utils-hoist/error.ts index 5ae28093a8bf..e15a52dcfc83 100644 --- a/packages/core/src/utils-hoist/error.ts +++ b/packages/core/src/utils-hoist/error.ts @@ -1,6 +1,9 @@ import type { ConsoleLevel } from '../types-hoist'; -/** An error emitted by Sentry SDKs and related utilities. */ +/** + * An error emitted by Sentry SDKs and related utilities. + * @deprecated This class is no longer used and will be removed in a future version. Use `Error` instead. + */ export class SentryError extends Error { public logLevel: ConsoleLevel; diff --git a/packages/core/src/utils-hoist/index.ts b/packages/core/src/utils-hoist/index.ts index 4f22928eff86..990ad55fcc8e 100644 --- a/packages/core/src/utils-hoist/index.ts +++ b/packages/core/src/utils-hoist/index.ts @@ -2,6 +2,7 @@ export { applyAggregateErrorsToEvent } from './aggregate-errors'; export { getBreadcrumbLogLevelFromHttpStatusCode } from './breadcrumb-log-level'; export { getComponentName, getLocationHref, htmlTreeAsString } from './browser'; export { dsnFromString, dsnToString, makeDsn } from './dsn'; +// eslint-disable-next-line deprecation/deprecation export { SentryError } from './error'; export { GLOBAL_OBJ } from './worldwide'; export type { InternalGlobal } from './worldwide'; @@ -45,6 +46,7 @@ export { normalize, normalizeToSize, normalizeUrlToBase } from './normalize'; export { addNonEnumerableProperty, convertToPlainObject, + // eslint-disable-next-line deprecation/deprecation dropUndefinedKeys, extractExceptionKeysForMessage, fill, @@ -53,7 +55,7 @@ export { objectify, } from './object'; export { basename, dirname, isAbsolute, join, normalizePath, relative, resolve } from './path'; -export { makePromiseBuffer } from './promisebuffer'; +export { makePromiseBuffer, SENTRY_BUFFER_FULL_ERROR } from './promisebuffer'; export type { PromiseBuffer } from './promisebuffer'; export { severityLevelFromString } from './severity'; diff --git a/packages/core/src/utils-hoist/object.ts b/packages/core/src/utils-hoist/object.ts index 7826e960d982..d1a1ba82aa99 100644 --- a/packages/core/src/utils-hoist/object.ts +++ b/packages/core/src/utils-hoist/object.ts @@ -210,6 +210,8 @@ export function extractExceptionKeysForMessage(exception: Record(inputValue: T): T { // This map keeps track of what already visited nodes map to. diff --git a/packages/core/src/utils-hoist/promisebuffer.ts b/packages/core/src/utils-hoist/promisebuffer.ts index 32b90e4d8519..d7eb82443fda 100644 --- a/packages/core/src/utils-hoist/promisebuffer.ts +++ b/packages/core/src/utils-hoist/promisebuffer.ts @@ -1,4 +1,3 @@ -import { SentryError } from './error'; import { SyncPromise, rejectedSyncPromise, resolvedSyncPromise } from './syncpromise'; export interface PromiseBuffer { @@ -9,6 +8,8 @@ export interface PromiseBuffer { drain(timeout?: number): PromiseLike; } +export const SENTRY_BUFFER_FULL_ERROR = Symbol.for('SentryBufferFullError'); + /** * Creates an new PromiseBuffer object with the specified limit * @param limit max number of promises that can be stored in the buffer @@ -42,7 +43,7 @@ export function makePromiseBuffer(limit?: number): PromiseBuffer { */ function add(taskProducer: () => PromiseLike): PromiseLike { if (!isReady()) { - return rejectedSyncPromise(new SentryError('Not adding Promise because buffer limit was reached.')); + return rejectedSyncPromise(SENTRY_BUFFER_FULL_ERROR); } // start the task and add its promise to the queue diff --git a/packages/core/src/utils/parameterize.ts b/packages/core/src/utils/parameterize.ts index 392f4b70b444..2ada1f4ec2d9 100644 --- a/packages/core/src/utils/parameterize.ts +++ b/packages/core/src/utils/parameterize.ts @@ -5,13 +5,24 @@ import type { ParameterizedString } from '../types-hoist'; * For example: parameterize`This is a log statement with ${x} and ${y} params`, would return: * "__sentry_template_string__": 'This is a log statement with %s and %s params', * "__sentry_template_values__": ['first', 'second'] + * * @param strings An array of string values splitted between expressions * @param values Expressions extracted from template string - * @returns String with template information in __sentry_template_string__ and __sentry_template_values__ properties + * + * @returns A `ParameterizedString` object that can be passed into `captureMessage` or Sentry.logger.X methods. */ -export function parameterize(strings: TemplateStringsArray, ...values: string[]): ParameterizedString { +export function parameterize(strings: TemplateStringsArray, ...values: unknown[]): ParameterizedString { const formatted = new String(String.raw(strings, ...values)) as ParameterizedString; formatted.__sentry_template_string__ = strings.join('\x00').replace(/%/g, '%%').replace(/\0/g, '%s'); formatted.__sentry_template_values__ = values; return formatted; } + +/** + * Tagged template function which returns parameterized representation of the message. + * + * @param strings An array of string values splitted between expressions + * @param values Expressions extracted from template string + * @returns A `ParameterizedString` object that can be passed into `captureMessage` or Sentry.logger.X methods. + */ +export const fmt = parameterize; diff --git a/packages/core/src/utils/request.ts b/packages/core/src/utils/request.ts index 07907d8b9b4f..91a965484d8c 100644 --- a/packages/core/src/utils/request.ts +++ b/packages/core/src/utils/request.ts @@ -1,6 +1,5 @@ import type { PolymorphicRequest, RequestEventData } from '../types-hoist'; import type { WebFetchHeaders, WebFetchRequest } from '../types-hoist/webfetchapi'; -import { dropUndefinedKeys } from '../utils-hoist/object'; /** * Transforms a `Headers` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into a simple key-value dict. @@ -91,14 +90,14 @@ export function httpRequestToRequestData(request: { // This is non-standard, but may be set on e.g. Next.js or Express requests const cookies = (request as PolymorphicRequest).cookies; - return dropUndefinedKeys({ + return { url: absoluteUrl, method: request.method, query_string: extractQueryParamsFromUrl(url), headers: headersToDict(headers), cookies, data, - }); + }; } function getAbsoluteUrl({ diff --git a/packages/core/src/utils/spanUtils.ts b/packages/core/src/utils/spanUtils.ts index 7cb19fbacf3c..cbfcde2a2576 100644 --- a/packages/core/src/utils/spanUtils.ts +++ b/packages/core/src/utils/spanUtils.ts @@ -21,7 +21,7 @@ import type { } from '../types-hoist'; import type { SpanLink, SpanLinkJSON } from '../types-hoist/link'; import { consoleSandbox } from '../utils-hoist/logger'; -import { addNonEnumerableProperty, dropUndefinedKeys } from '../utils-hoist/object'; +import { addNonEnumerableProperty } from '../utils-hoist/object'; import { generateSpanId } from '../utils-hoist/propagationContext'; import { timestampInSeconds } from '../utils-hoist/time'; import { generateSentryTraceHeader } from '../utils-hoist/tracing'; @@ -42,7 +42,7 @@ export function spanToTransactionTraceContext(span: Span): TraceContext { const { spanId: span_id, traceId: trace_id } = span.spanContext(); const { data, op, parent_span_id, status, origin, links } = spanToJSON(span); - return dropUndefinedKeys({ + return { parent_span_id, span_id, trace_id, @@ -51,7 +51,7 @@ export function spanToTransactionTraceContext(span: Span): TraceContext { status, origin, links, - }); + }; } /** @@ -67,11 +67,11 @@ export function spanToTraceContext(span: Span): TraceContext { const span_id = isRemote ? scope?.getPropagationContext().propagationSpanId || generateSpanId() : spanId; - return dropUndefinedKeys({ + return { parent_span_id, span_id, trace_id, - }); + }; } /** @@ -147,7 +147,7 @@ export function spanToJSON(span: Span): SpanJSON { if (spanIsOpenTelemetrySdkTraceBaseSpan(span)) { const { attributes, startTime, name, endTime, parentSpanId, status, links } = span; - return dropUndefinedKeys({ + return { span_id, trace_id, data: attributes, @@ -160,7 +160,7 @@ export function spanToJSON(span: Span): SpanJSON { op: attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP], origin: attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] as SpanOrigin | undefined, links: convertSpanLinksForEnvelope(links), - }); + }; } // Finally, at least we have `spanContext()`.... diff --git a/packages/core/src/utils/transactionEvent.ts b/packages/core/src/utils/transactionEvent.ts index 9ec233b4f078..195c31a66966 100644 --- a/packages/core/src/utils/transactionEvent.ts +++ b/packages/core/src/utils/transactionEvent.ts @@ -1,6 +1,5 @@ import { SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_PROFILE_ID } from '../semanticAttributes'; import type { SpanJSON, TransactionEvent } from '../types-hoist'; -import { dropUndefinedKeys } from '../utils-hoist'; /** * Converts a transaction event to a span JSON object. @@ -8,7 +7,7 @@ import { dropUndefinedKeys } from '../utils-hoist'; export function convertTransactionEventToSpanJson(event: TransactionEvent): SpanJSON { const { trace_id, parent_span_id, span_id, status, origin, data, op } = event.contexts?.trace ?? {}; - return dropUndefinedKeys({ + return { data: data ?? {}, description: event.transaction, op, @@ -23,14 +22,14 @@ export function convertTransactionEventToSpanJson(event: TransactionEvent): Span exclusive_time: data?.[SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME] as number | undefined, measurements: event.measurements, is_segment: true, - }); + }; } /** * Converts a span JSON object to a transaction event. */ export function convertSpanJsonToTransactionEvent(span: SpanJSON): TransactionEvent { - const event: TransactionEvent = { + return { type: 'transaction', timestamp: span.timestamp, start_timestamp: span.start_timestamp, @@ -52,6 +51,4 @@ export function convertSpanJsonToTransactionEvent(span: SpanJSON): TransactionEv }, measurements: span.measurements, }; - - return dropUndefinedKeys(event); } diff --git a/packages/core/test/lib/client.test.ts b/packages/core/test/lib/client.test.ts index 9f60226c0de7..03907285f6cb 100644 --- a/packages/core/test/lib/client.test.ts +++ b/packages/core/test/lib/client.test.ts @@ -1,7 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import { Scope, - SentryError, SyncPromise, addBreadcrumb, dsnToString, @@ -533,7 +532,7 @@ describe('Client', () => { ); }); - test('it adds a trace context to all events xxx', () => { + test('it adds a trace context to all events', () => { expect.assertions(1); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); @@ -1206,7 +1205,7 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); const client = new TestClient(options); const captureExceptionSpy = vi.spyOn(client, 'captureException'); - const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'log'); + const loggerLogSpy = vi.spyOn(loggerModule.logger, 'log'); client.captureEvent({ message: 'hello' }); @@ -1215,7 +1214,7 @@ describe('Client', () => { // This proves that the reason the event didn't send/didn't get set on the test client is not because there was an // error, but because `beforeSend` returned `null` expect(captureExceptionSpy).not.toBeCalled(); - expect(loggerWarnSpy).toBeCalledWith('before send for type `error` returned `null`, will not send event.'); + expect(loggerLogSpy).toBeCalledWith('before send for type `error` returned `null`, will not send event.'); }); test('calls `beforeSendTransaction` and discards the event', () => { @@ -1225,7 +1224,7 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); const client = new TestClient(options); const captureExceptionSpy = vi.spyOn(client, 'captureException'); - const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'log'); + const loggerLogSpy = vi.spyOn(loggerModule.logger, 'log'); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); @@ -1234,7 +1233,7 @@ describe('Client', () => { // This proves that the reason the event didn't send/didn't get set on the test client is not because there was an // error, but because `beforeSendTransaction` returned `null` expect(captureExceptionSpy).not.toBeCalled(); - expect(loggerWarnSpy).toBeCalledWith('before send for type `transaction` returned `null`, will not send event.'); + expect(loggerLogSpy).toBeCalledWith('before send for type `transaction` returned `null`, will not send event.'); }); test('does not discard span and warn when returning null from `beforeSendSpan', () => { @@ -1293,9 +1292,7 @@ describe('Client', () => { expect(beforeSend).toHaveBeenCalled(); expect(TestClient.instance!.event).toBeUndefined(); - expect(loggerWarnSpy).toBeCalledWith( - new SentryError('before send for type `error` must return `null` or a valid event.'), - ); + expect(loggerWarnSpy).toBeCalledWith('before send for type `error` must return `null` or a valid event.'); } }); @@ -1314,9 +1311,7 @@ describe('Client', () => { expect(beforeSendTransaction).toHaveBeenCalled(); expect(TestClient.instance!.event).toBeUndefined(); - expect(loggerWarnSpy).toBeCalledWith( - new SentryError('before send for type `transaction` must return `null` or a valid event.'), - ); + expect(loggerWarnSpy).toBeCalledWith('before send for type `transaction` must return `null` or a valid event.'); } }); @@ -1688,9 +1683,7 @@ describe('Client', () => { originalException: exception, }); expect(loggerWarnSpy).toBeCalledWith( - new SentryError( - `Event processing pipeline threw an error, original event will not be sent. Details have been sent as a new event.\nReason: ${exception}`, - ), + `Event processing pipeline threw an error, original event will not be sent. Details have been sent as a new event.\nReason: ${exception}`, ); }); diff --git a/packages/core/test/lib/integrations/eventFilters.test.ts b/packages/core/test/lib/integrations/eventFilters.test.ts index 51a15f909f5d..924711ce8662 100644 --- a/packages/core/test/lib/integrations/eventFilters.test.ts +++ b/packages/core/test/lib/integrations/eventFilters.test.ts @@ -311,17 +311,6 @@ const EVENT_WITH_VALUE: Event = { }, }; -const SENTRY_EVENT: Event = { - exception: { - values: [ - { - type: 'SentryError', - value: 'something something server connection', - }, - ], - }, -}; - const SCRIPT_ERROR_EVENT: Event = { exception: { values: [ @@ -425,22 +414,6 @@ describe.each([ ['InboundFilters', inboundFiltersIntegration], ['EventFilters', eventFiltersIntegration], ])('%s', (_, integrationFn) => { - describe('_isSentryError', () => { - it('should work as expected', () => { - const eventProcessor = createEventFiltersEventProcessor(integrationFn); - expect(eventProcessor(MESSAGE_EVENT, {})).toBe(MESSAGE_EVENT); - expect(eventProcessor(EXCEPTION_EVENT, {})).toBe(EXCEPTION_EVENT); - expect(eventProcessor(SENTRY_EVENT, {})).toBe(null); - }); - - it('should be configurable', () => { - const eventProcessor = createEventFiltersEventProcessor(integrationFn, { ignoreInternal: false }); - expect(eventProcessor(MESSAGE_EVENT, {})).toBe(MESSAGE_EVENT); - expect(eventProcessor(EXCEPTION_EVENT, {})).toBe(EXCEPTION_EVENT); - expect(eventProcessor(SENTRY_EVENT, {})).toBe(SENTRY_EVENT); - }); - }); - describe('ignoreErrors', () => { it('string filter with partial match', () => { const eventProcessor = createEventFiltersEventProcessor(integrationFn, { diff --git a/packages/core/test/lib/log/envelope.test.ts b/packages/core/test/lib/logs/envelope.test.ts similarity index 100% rename from packages/core/test/lib/log/envelope.test.ts rename to packages/core/test/lib/logs/envelope.test.ts diff --git a/packages/core/test/lib/log/index.test.ts b/packages/core/test/lib/logs/index.test.ts similarity index 62% rename from packages/core/test/lib/log/index.test.ts rename to packages/core/test/lib/logs/index.test.ts index ab7cfe9bb4b4..e2b7eba781d2 100644 --- a/packages/core/test/lib/log/index.test.ts +++ b/packages/core/test/lib/logs/index.test.ts @@ -7,7 +7,8 @@ import { } from '../../../src/logs'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; import * as loggerModule from '../../../src/utils-hoist/logger'; -import { Scope } from '../../../src'; +import { Scope, fmt } from '../../../src'; +import type { Log } from '../../../src/types-hoist/log'; const PUBLIC_DSN = 'https://username@domain/123'; @@ -116,6 +117,7 @@ describe('_INTERNAL_captureLog', () => { expect(_INTERNAL_getLogBuffer(client)?.[0]).toEqual( expect.objectContaining({ traceId: '3d9355f71e9c444b81161599adac6e29', + severityNumber: 17, // error level maps to 17 }), ); }); @@ -187,4 +189,121 @@ describe('_INTERNAL_captureLog', () => { _INTERNAL_flushLogsBuffer(client); expect(mockSendEnvelope).not.toHaveBeenCalled(); }); + + it('handles parameterized strings correctly', () => { + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, _experiments: { enableLogs: true } }); + const client = new TestClient(options); + + const parameterizedMessage = fmt`Hello ${'John'}, welcome to ${'Sentry'}`; + + _INTERNAL_captureLog({ level: 'info', message: parameterizedMessage }, client, undefined); + + const logAttributes = _INTERNAL_getLogBuffer(client)?.[0]?.attributes; + expect(logAttributes).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + key: 'sentry.message.template', + value: { stringValue: 'Hello %s, welcome to %s' }, + }), + expect.objectContaining({ + key: 'sentry.message.param.0', + value: { stringValue: 'John' }, + }), + expect.objectContaining({ + key: 'sentry.message.param.1', + value: { stringValue: 'Sentry' }, + }), + ]), + ); + }); + + it('processes logs through beforeSendLog when provided', () => { + const beforeSendLog = vi.fn().mockImplementation(log => ({ + ...log, + message: `Modified: ${log.message}`, + attributes: { ...log.attributes, processed: true }, + })); + + const options = getDefaultTestClientOptions({ + dsn: PUBLIC_DSN, + _experiments: { enableLogs: true, beforeSendLog }, + }); + const client = new TestClient(options); + + _INTERNAL_captureLog( + { + level: 'info', + message: 'original message', + attributes: { original: true }, + }, + client, + undefined, + ); + + expect(beforeSendLog).toHaveBeenCalledWith({ + level: 'info', + message: 'original message', + attributes: { original: true }, + }); + + const logBuffer = _INTERNAL_getLogBuffer(client); + expect(logBuffer).toBeDefined(); + expect(logBuffer?.[0]).toEqual( + expect.objectContaining({ + body: { + stringValue: 'Modified: original message', + }, + attributes: expect.arrayContaining([ + expect.objectContaining({ key: 'processed', value: { boolValue: true } }), + expect.objectContaining({ key: 'original', value: { boolValue: true } }), + ]), + }), + ); + }); + + it('drops logs when beforeSendLog returns null', () => { + const beforeSendLog = vi.fn().mockReturnValue(null); + const recordDroppedEventSpy = vi.spyOn(TestClient.prototype, 'recordDroppedEvent'); + const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'warn').mockImplementation(() => undefined); + + const options = getDefaultTestClientOptions({ + dsn: PUBLIC_DSN, + _experiments: { enableLogs: true, beforeSendLog }, + }); + const client = new TestClient(options); + + _INTERNAL_captureLog( + { + level: 'info', + message: 'test message', + }, + client, + undefined, + ); + + expect(beforeSendLog).toHaveBeenCalled(); + expect(recordDroppedEventSpy).toHaveBeenCalledWith('before_send', 'log_item', 1); + expect(loggerWarnSpy).toHaveBeenCalledWith('beforeSendLog returned null, log will not be captured.'); + expect(_INTERNAL_getLogBuffer(client)).toBeUndefined(); + + recordDroppedEventSpy.mockRestore(); + loggerWarnSpy.mockRestore(); + }); + + it('emits beforeCaptureLog and afterCaptureLog events', () => { + const beforeCaptureLogSpy = vi.spyOn(TestClient.prototype, 'emit'); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, _experiments: { enableLogs: true } }); + const client = new TestClient(options); + + const log: Log = { + level: 'info', + message: 'test message', + }; + + _INTERNAL_captureLog(log, client, undefined); + + expect(beforeCaptureLogSpy).toHaveBeenCalledWith('beforeCaptureLog', log); + expect(beforeCaptureLogSpy).toHaveBeenCalledWith('afterCaptureLog', log); + beforeCaptureLogSpy.mockRestore(); + }); }); diff --git a/packages/core/test/lib/scope.test.ts b/packages/core/test/lib/scope.test.ts index 4b27eff42824..87dcf9315ba9 100644 --- a/packages/core/test/lib/scope.test.ts +++ b/packages/core/test/lib/scope.test.ts @@ -186,6 +186,12 @@ describe('Scope', () => { expect(scope['_breadcrumbs']).toHaveLength(111); }); + test('addBreadcrumb will truncate the stored messages', () => { + const scope = new Scope(); + scope.addBreadcrumb({ message: 'A'.repeat(10_000) }); + expect(scope['_breadcrumbs'][0]?.message).toBe(`${'A'.repeat(2048)}...`); + }); + test('setLevel', () => { const scope = new Scope(); scope.setLevel('fatal'); diff --git a/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts b/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts index 23406908037c..2b7a030734bb 100644 --- a/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts +++ b/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts @@ -70,6 +70,7 @@ describe('getDynamicSamplingContextFromSpan', () => { const dynamicSamplingContext = getDynamicSamplingContextFromSpan(rootSpan); expect(dynamicSamplingContext).toStrictEqual({ + public_key: undefined, release: '1.0.1', environment: 'production', sampled: 'true', @@ -88,6 +89,7 @@ describe('getDynamicSamplingContextFromSpan', () => { const dynamicSamplingContext = getDynamicSamplingContextFromSpan(rootSpan); expect(dynamicSamplingContext).toStrictEqual({ + public_key: undefined, release: '1.0.1', environment: 'production', sampled: 'true', @@ -111,6 +113,7 @@ describe('getDynamicSamplingContextFromSpan', () => { const dynamicSamplingContext = getDynamicSamplingContextFromSpan(rootSpan); expect(dynamicSamplingContext).toStrictEqual({ + public_key: undefined, release: '1.0.1', environment: 'production', sampled: 'true', @@ -166,6 +169,7 @@ describe('getDynamicSamplingContextFromSpan', () => { const dynamicSamplingContext = getDynamicSamplingContextFromSpan(rootSpan); expect(dynamicSamplingContext).toStrictEqual({ + public_key: undefined, release: '1.0.1', environment: 'production', trace_id: expect.stringMatching(/^[a-f0-9]{32}$/), diff --git a/packages/core/test/lib/tracing/sentrySpan.test.ts b/packages/core/test/lib/tracing/sentrySpan.test.ts index eda0246bda03..726f30790c5b 100644 --- a/packages/core/test/lib/tracing/sentrySpan.test.ts +++ b/packages/core/test/lib/tracing/sentrySpan.test.ts @@ -75,26 +75,6 @@ describe('SentrySpan', () => { expect(serialized).toHaveProperty('span_id', 'd'); expect(serialized).toHaveProperty('trace_id', 'c'); }); - - test('should drop all `undefined` values', () => { - const spanA = new SentrySpan({ traceId: 'a', spanId: 'b' }); - const spanB = new SentrySpan({ - parentSpanId: spanA.spanContext().spanId, - spanId: 'd', - traceId: 'c', - }); - const serialized = spanToJSON(spanB); - expect(serialized).toStrictEqual({ - start_timestamp: expect.any(Number), - parent_span_id: 'b', - span_id: 'd', - trace_id: 'c', - origin: 'manual', - data: { - 'sentry.origin': 'manual', - }, - }); - }); }); describe('end', () => { diff --git a/packages/core/test/utils-hoist/is.test.ts b/packages/core/test/utils-hoist/is.test.ts index 09fac86fcf12..70a83eee5efd 100644 --- a/packages/core/test/utils-hoist/is.test.ts +++ b/packages/core/test/utils-hoist/is.test.ts @@ -14,16 +14,6 @@ import { supportsDOMError, supportsDOMException, supportsErrorEvent } from '../. import { resolvedSyncPromise } from '../../src/utils-hoist/syncpromise'; import { testOnlyIfNodeVersionAtLeast } from './testutils'; -class SentryError extends Error { - public name: string; - - public constructor(public message: string) { - super(message); - this.name = new.target.prototype.constructor.name; - Object.setPrototypeOf(this, new.target.prototype); - } -} - if (supportsDOMError()) { describe('isDOMError()', () => { test('should work as advertised', () => { @@ -47,7 +37,6 @@ describe('isError()', () => { test('should work as advertised', () => { expect(isError(new Error())).toEqual(true); expect(isError(new ReferenceError())).toEqual(true); - expect(isError(new SentryError('message'))).toEqual(true); expect(isError({})).toEqual(false); expect( isError({ diff --git a/packages/core/test/utils-hoist/misc.test.ts b/packages/core/test/utils-hoist/misc.test.ts index ea2d03992fe8..0bcc317a017c 100644 --- a/packages/core/test/utils-hoist/misc.test.ts +++ b/packages/core/test/utils-hoist/misc.test.ts @@ -291,8 +291,6 @@ describe('checkOrSetAlreadyCaught()', () => { describe('uuid4 generation', () => { const uuid4Regex = /^[0-9A-F]{12}[4][0-9A-F]{3}[89AB][0-9A-F]{15}$/i; - // Jest messes with the global object, so there is no global crypto object in any node version - // For this reason we need to create our own crypto object for each test to cover all the code paths it('returns valid uuid v4 ids via Math.random', () => { for (let index = 0; index < 1_000; index++) { expect(uuid4()).toMatch(uuid4Regex); diff --git a/packages/core/test/utils-hoist/normalize.test.ts b/packages/core/test/utils-hoist/normalize.test.ts index 7fbecd8608e7..e08c7187c839 100644 --- a/packages/core/test/utils-hoist/normalize.test.ts +++ b/packages/core/test/utils-hoist/normalize.test.ts @@ -1,5 +1,5 @@ /** - * @jest-environment jsdom + * @vitest-environment jsdom */ import { describe, expect, test, vi } from 'vitest'; diff --git a/packages/core/test/utils-hoist/object.test.ts b/packages/core/test/utils-hoist/object.test.ts index e1c32f163193..bda0a53e3a5c 100644 --- a/packages/core/test/utils-hoist/object.test.ts +++ b/packages/core/test/utils-hoist/object.test.ts @@ -1,5 +1,5 @@ /** - * @jest-environment jsdom + * @vitest-environment jsdom */ import type { WrappedFunction } from '../../src/types-hoist'; @@ -169,6 +169,7 @@ describe('extractExceptionKeysForMessage()', () => { }); }); +/* eslint-disable deprecation/deprecation */ describe('dropUndefinedKeys()', () => { test('simple case', () => { expect( @@ -314,6 +315,7 @@ describe('dropUndefinedKeys()', () => { expect(droppedChicken.lays[0] === droppedChicken).toBe(true); }); }); +/* eslint-enable deprecation/deprecation */ describe('objectify()', () => { describe('stringifies nullish values', () => { @@ -329,17 +331,10 @@ describe('objectify()', () => { }); describe('wraps other primitives with their respective object wrapper classes', () => { - // TODO: There's currently a bug in Jest - if you give it the `Boolean` class, it runs `typeof received === - // 'boolean'` but not `received instanceof Boolean` (the way it correctly does for other primitive wrappers, like - // `Number` and `String). (See https://github.com/facebook/jest/pull/11976.) Once that is fixed and we upgrade jest, - // we can comment the test below back in. (The tests for symbols and bigints are working only because our current - // version of jest is sufficiently old that they're not even considered in the relevant check and just fall to the - // default `instanceof` check jest uses for all unknown classes.) - it.each([ ['number', Number, 1121], ['string', String, 'Dogs are great!'], - // ["boolean", Boolean, true], + ['boolean', Boolean, true], ['symbol', Symbol, Symbol('Maisey')], ])('%s', (_caseName, wrapperClass, primitive) => { const objectifiedPrimitive = objectify(primitive); diff --git a/packages/eslint-config-sdk/package.json b/packages/eslint-config-sdk/package.json index 32b568606f29..2f0ce2b521e4 100644 --- a/packages/eslint-config-sdk/package.json +++ b/packages/eslint-config-sdk/package.json @@ -29,7 +29,6 @@ "eslint-config-prettier": "^6.11.0", "eslint-plugin-deprecation": "^1.5.0", "eslint-plugin-import": "^2.22.0", - "eslint-plugin-jest": "^27.2.2", "eslint-plugin-jsdoc": "^30.0.3", "eslint-plugin-simple-import-sort": "^5.0.3" }, diff --git a/packages/eslint-config-sdk/src/base.js b/packages/eslint-config-sdk/src/base.js index 8c11f26dd925..10e410aaa592 100644 --- a/packages/eslint-config-sdk/src/base.js +++ b/packages/eslint-config-sdk/src/base.js @@ -154,10 +154,6 @@ module.exports = { }, }, { - // Configuration for files in test directories - env: { - jest: true, - }, files: [ 'test.ts', '*.test.ts', diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 590141d75264..57d49c028d5e 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -47,7 +47,7 @@ "dependencies": { "@sentry/core": "9.9.0", "@sentry/react": "9.9.0", - "@sentry/webpack-plugin": "3.2.2" + "@sentry/webpack-plugin": "3.2.3" }, "peerDependencies": { "gatsby": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", diff --git a/packages/gatsby/tsconfig.plugin.json b/packages/gatsby/tsconfig.plugin.json index 88724d075f48..1eb512a6fa0b 100644 --- a/packages/gatsby/tsconfig.plugin.json +++ b/packages/gatsby/tsconfig.plugin.json @@ -5,7 +5,6 @@ "compilerOptions": { // should include all types from `./tsconfig.json` plus types for all test frameworks used - // "types": ["node", "jest"] "declaration": true, "declarationMap": false, "emitDeclarationOnly": true, diff --git a/packages/google-cloud-serverless/jest.config.js b/packages/google-cloud-serverless/jest.config.js deleted file mode 100644 index 24f49ab59a4c..000000000000 --- a/packages/google-cloud-serverless/jest.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../../jest/jest.config.js'); diff --git a/packages/google-cloud-serverless/package.json b/packages/google-cloud-serverless/package.json index d5c4baddad56..3500292d0ef3 100644 --- a/packages/google-cloud-serverless/package.json +++ b/packages/google-cloud-serverless/package.json @@ -55,10 +55,7 @@ "devDependencies": { "@google-cloud/bigquery": "^5.3.0", "@google-cloud/common": "^3.4.1", - "@google-cloud/functions-framework": "^1.7.1", - "@google-cloud/pubsub": "^2.5.0", "@types/node": "^18.19.1", - "google-gax": "^2.9.0", "nock": "^13.5.5" }, "scripts": { @@ -77,8 +74,8 @@ "clean": "rimraf build coverage sentry-google-cloud-*.tgz", "fix": "eslint . --format stylish --fix", "lint": "eslint . --format stylish", - "test": "jest", - "test:watch": "jest --watch", + "test": "vitest run", + "test:watch": "vitest --watch", "yalc:publish": "yalc publish --push --sig" }, "volta": { diff --git a/packages/google-cloud-serverless/src/index.ts b/packages/google-cloud-serverless/src/index.ts index 9505ef6dd248..83a18f62c6df 100644 --- a/packages/google-cloud-serverless/src/index.ts +++ b/packages/google-cloud-serverless/src/index.ts @@ -113,6 +113,7 @@ export { amqplibIntegration, childProcessIntegration, vercelAIIntegration, + logger, } from '@sentry/node'; export { diff --git a/packages/google-cloud-serverless/src/integrations/google-cloud-grpc.ts b/packages/google-cloud-serverless/src/integrations/google-cloud-grpc.ts index 7d4c49990af6..6261660b5f98 100644 --- a/packages/google-cloud-serverless/src/integrations/google-cloud-grpc.ts +++ b/packages/google-cloud-serverless/src/integrations/google-cloud-grpc.ts @@ -3,11 +3,11 @@ import type { Client, IntegrationFn } from '@sentry/core'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, fill, getClient } from '@sentry/core'; import { startInactiveSpan } from '@sentry/node'; -interface GrpcFunction extends CallableFunction { +export interface GrpcFunction extends CallableFunction { (...args: unknown[]): EventEmitter; } -interface GrpcFunctionObject extends GrpcFunction { +export interface GrpcFunctionObject extends GrpcFunction { requestStream: boolean; responseStream: boolean; originalName: string; @@ -21,7 +21,7 @@ interface CreateStubFunc extends CallableFunction { (createStub: unknown, options: StubOptions): PromiseLike; } -interface Stub { +export interface Stub { [key: string]: GrpcFunctionObject; } @@ -78,7 +78,7 @@ function wrapCreateStub(origCreate: CreateStubFunc): CreateStubFunc { } /** Patches the function in grpc stub to enable tracing */ -function fillGrpcFunction(stub: Stub, serviceIdentifier: string, methodName: string): void { +export function fillGrpcFunction(stub: Stub, serviceIdentifier: string, methodName: string): void { const funcObj = stub[methodName]; if (typeof funcObj !== 'function') { return; diff --git a/packages/google-cloud-serverless/test/__mocks__/dns.ts b/packages/google-cloud-serverless/test/__mocks__/dns.ts deleted file mode 100644 index d03aa8d3f84b..000000000000 --- a/packages/google-cloud-serverless/test/__mocks__/dns.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const lookup = jest.fn(); -export const resolveTxt = jest.fn(); diff --git a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts index 8bbc926643f7..34aad6f13adb 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts @@ -1,22 +1,24 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; +import { describe, vi, beforeEach, test, expect } from 'vitest'; import { wrapCloudEventFunction } from '../../src/gcpfunction/cloud_events'; import type { CloudEventFunction, CloudEventFunctionWithCallback } from '../../src/gcpfunction/general'; -const mockStartSpanManual = jest.fn((...spanArgs) => ({ ...spanArgs })); -const mockFlush = jest.fn((...args) => Promise.resolve(args)); -const mockCaptureException = jest.fn(); +const mockStartSpanManual = vi.fn((...spanArgs) => ({ ...spanArgs })); +const mockFlush = vi.fn((...args) => Promise.resolve(args)); +const mockCaptureException = vi.fn(); const mockScope = { - setContext: jest.fn(), + setContext: vi.fn(), }; const mockSpan = { - end: jest.fn(), + end: vi.fn(), }; -jest.mock('@sentry/node', () => { - const original = jest.requireActual('@sentry/node'); +vi.mock('@sentry/node', async () => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node'); return { ...original, startSpanManual: (...args: unknown[]) => { @@ -38,7 +40,7 @@ jest.mock('@sentry/node', () => { describe('wrapCloudEventFunction', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); function handleCloudEvent(fn: CloudEventFunctionWithCallback): Promise { diff --git a/packages/google-cloud-serverless/test/gcpfunction/events.test.ts b/packages/google-cloud-serverless/test/gcpfunction/events.test.ts index aad3d5ec1645..99274c714637 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/events.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/events.test.ts @@ -1,23 +1,25 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; +import { describe, vi, beforeEach, test, expect } from 'vitest'; import type { Event } from '@sentry/core'; import { wrapEventFunction } from '../../src/gcpfunction/events'; import type { EventFunction, EventFunctionWithCallback } from '../../src/gcpfunction/general'; -const mockStartSpanManual = jest.fn((...spanArgs) => ({ ...spanArgs })); -const mockFlush = jest.fn((...args) => Promise.resolve(args)); -const mockCaptureException = jest.fn(); +const mockStartSpanManual = vi.fn((...spanArgs) => ({ ...spanArgs })); +const mockFlush = vi.fn((...args) => Promise.resolve(args)); +const mockCaptureException = vi.fn(); const mockScope = { - setContext: jest.fn(), + setContext: vi.fn(), }; const mockSpan = { - end: jest.fn(), + end: vi.fn(), }; -jest.mock('@sentry/node', () => { - const original = jest.requireActual('@sentry/node'); +vi.mock('@sentry/node', async () => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node'); return { ...original, startSpanManual: (...args: unknown[]) => { @@ -39,7 +41,7 @@ jest.mock('@sentry/node', () => { describe('wrapEventFunction', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); function handleEvent(fn: EventFunctionWithCallback): Promise { @@ -238,7 +240,7 @@ describe('wrapEventFunction', () => { const scopeFunction = mockCaptureException.mock.calls[0][1]; const event: Event = { exception: { values: [{}] } }; let evtProcessor: ((e: Event) => Event) | undefined = undefined; - scopeFunction({ addEventProcessor: jest.fn().mockImplementation(proc => (evtProcessor = proc)) }); + scopeFunction({ addEventProcessor: vi.fn().mockImplementation(proc => (evtProcessor = proc)) }); expect(evtProcessor).toBeInstanceOf(Function); // @ts-expect-error just mocking around... diff --git a/packages/google-cloud-serverless/test/gcpfunction/http.test.ts b/packages/google-cloud-serverless/test/gcpfunction/http.test.ts index 7f456237ad9c..914c1baffed0 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/http.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/http.test.ts @@ -1,28 +1,27 @@ import type { Integration } from '@sentry/core'; - import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; +import { describe, vi, beforeEach, test, expect, type MockInstance } from 'vitest'; import { wrapHttpFunction } from '../../src/gcpfunction/http'; - import type { HttpFunction, Request, Response } from '../../src/gcpfunction/general'; - import { init } from '../../src/sdk'; -const mockStartSpanManual = jest.fn((...spanArgs) => ({ ...spanArgs })); -const mockFlush = jest.fn((...args) => Promise.resolve(args)); -const mockCaptureException = jest.fn(); -const mockInit = jest.fn(); +const mockStartSpanManual = vi.fn((...spanArgs) => ({ ...spanArgs })); +const mockFlush = vi.fn((...args) => Promise.resolve(args)); +const mockCaptureException = vi.fn(); +const mockInit = vi.fn(); const mockScope = { - setSDKProcessingMetadata: jest.fn(), + setSDKProcessingMetadata: vi.fn(), }; const mockSpan = { - end: jest.fn(), + end: vi.fn(), }; -jest.mock('@sentry/node', () => { - const original = jest.requireActual('@sentry/node'); +vi.mock('@sentry/node', async () => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node'); return { ...original, init: (options: unknown) => { @@ -47,7 +46,7 @@ jest.mock('@sentry/node', () => { describe('GCPFunction', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); async function handleHttp(fn: HttpFunction, trace_headers: { [key: string]: string } | null = null): Promise { @@ -146,7 +145,7 @@ describe('GCPFunction', () => { body: { foo: 'bar' }, } as Request; - const mockEnd = jest.fn(); + const mockEnd = vi.fn(); const response = { end: mockEnd } as unknown as Response; mockFlush.mockImplementationOnce(async () => { @@ -171,8 +170,8 @@ describe('GCPFunction', () => { await handleHttp(wrappedHandler); - const initOptions = (mockInit as unknown as jest.SpyInstance).mock.calls[0]; - const defaultIntegrations = initOptions[0]?.defaultIntegrations.map((i: Integration) => i.name); + const initOptions = (mockInit as unknown as MockInstance).mock.calls[0]; + const defaultIntegrations = initOptions?.[0]?.defaultIntegrations.map((i: Integration) => i.name); expect(defaultIntegrations).toContain('RequestData'); diff --git a/packages/google-cloud-serverless/test/integrations/google-cloud-grpc.test.ts b/packages/google-cloud-serverless/test/integrations/google-cloud-grpc.test.ts index 2e6c9039e075..af37bc71a7c5 100644 --- a/packages/google-cloud-serverless/test/integrations/google-cloud-grpc.test.ts +++ b/packages/google-cloud-serverless/test/integrations/google-cloud-grpc.test.ts @@ -1,25 +1,32 @@ -jest.mock('dns'); +import { vi, describe, beforeEach, test, expect } from 'vitest'; +import { NodeClient } from '@sentry/node'; +import { createTransport } from '@sentry/core'; +import { setCurrentClient, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; +import { googleCloudGrpcIntegration, fillGrpcFunction } from '../../src/integrations/google-cloud-grpc'; +import type { GrpcFunctionObject, Stub, GrpcFunction } from '../../src/integrations/google-cloud-grpc'; -import * as dns from 'dns'; -import { EventEmitter } from 'events'; -import * as fs from 'fs'; -import * as path from 'path'; -import { PubSub } from '@google-cloud/pubsub'; -import * as http2 from 'http2'; -import * as nock from 'nock'; +const mockSpanEnd = vi.fn(); +const mockStartInactiveSpan = vi.fn(); +const mockFill = vi.fn(); -import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; -import { NodeClient, createTransport, setCurrentClient } from '@sentry/node'; -import { googleCloudGrpcIntegration } from '../../src/integrations/google-cloud-grpc'; +let mockClient: NodeClient; -const spyConnect = jest.spyOn(http2, 'connect'); - -const mockSpanEnd = jest.fn(); -const mockStartInactiveSpan = jest.fn(spanArgs => ({ ...spanArgs })); +vi.mock('@sentry/core', async () => { + const original = await vi.importActual('@sentry/core'); + return { + ...original, + fill: (obj: any, name: string, replacement: any) => { + mockFill(obj, name, replacement); + obj[name] = replacement(obj[name]); + }, + getClient: () => mockClient, + }; +}); -jest.mock('@sentry/node', () => { +vi.mock('@sentry/node', async () => { + const original = await vi.importActual('@sentry/node'); return { - ...jest.requireActual('@sentry/node'), + ...original, startInactiveSpan: (ctx: unknown) => { mockStartInactiveSpan(ctx); return { end: mockSpanEnd }; @@ -27,130 +34,177 @@ jest.mock('@sentry/node', () => { }; }); -/** Fake HTTP2 stream */ -class FakeStream extends EventEmitter { - public rstCode: number = 0; - close() { - this.emit('end'); - this.emit('close'); - } - end() {} - pause() {} - resume() {} - write(_data: Buffer, cb: CallableFunction) { - process.nextTick(cb, null); - } -} - -/** Fake HTTP2 session for GRPC */ -class FakeSession extends EventEmitter { - public socket: EventEmitter = new EventEmitter(); - public request: jest.Mock = jest.fn(); - ping() {} - mockRequest(fn: (stream: FakeStream) => void): FakeStream { - const stream = new FakeStream(); - this.request.mockImplementationOnce(() => { - process.nextTick(fn, stream); - return stream; - }); - return stream; - } - mockUnaryRequest(responseData: Buffer) { - this.mockRequest(stream => { - stream.emit( - 'response', - { ':status': 200, 'content-type': 'application/grpc', 'content-disposition': 'attachment' }, - 4, - ); - stream.emit('data', responseData); - stream.emit('trailers', { 'grpc-status': '0', 'content-disposition': 'attachment' }); - }); - } - close() { - this.emit('close'); - this.socket.emit('close'); - } - ref() {} - unref() {} +// Need to override mock because the integration loads google-gax as a CJS file +async function mock(mockedUri: string, stub: any) { + // @ts-expect-error we are using import on purpose + const { Module } = await import('module'); + + // @ts-expect-error test + Module._load_original = Module._load; + // @ts-expect-error test + Module._load = (uri, parent) => { + if (uri === mockedUri) return stub; + // @ts-expect-error test + return Module._load_original(uri, parent); + }; } -function mockHttp2Session(): FakeSession { - const session = new FakeSession(); - spyConnect.mockImplementationOnce(() => { - process.nextTick(() => session.emit('connect')); - return session as unknown as http2.ClientHttp2Session; - }); - return session; -} +vi.hoisted( + () => + void mock('google-gax', { + GrpcClient: { + prototype: { + createStub: vi.fn(), + }, + }, + }), +); describe('GoogleCloudGrpc tracing', () => { - const mockClient = new NodeClient({ - tracesSampleRate: 1.0, - integrations: [], - dsn: 'https://withAWSServices@domain/123', - transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => Promise.resolve({})), - stackParser: () => [], - }); + beforeEach(() => { + mockClient = new NodeClient({ + tracesSampleRate: 1.0, + integrations: [], + dsn: 'https://withAWSServices@domain/123', + transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => Promise.resolve({})), + stackParser: () => [], + }); - const integration = googleCloudGrpcIntegration(); - mockClient.addIntegration(integration); + const integration = googleCloudGrpcIntegration(); + mockClient.addIntegration(integration); + integration.setup?.(mockClient); - beforeEach(() => { - nock('https://www.googleapis.com').post('/oauth2/v4/token').reply(200, []); setCurrentClient(mockClient); mockSpanEnd.mockClear(); mockStartInactiveSpan.mockClear(); + mockFill.mockClear(); }); - afterAll(() => { - nock.restore(); - spyConnect.mockRestore(); - }); - - // We use google cloud pubsub as an example of grpc service for which we can trace requests. - describe('pubsub', () => { - // @ts-expect-error see "Why @ts-expect-error" note - const dnsLookup = dns.lookup as jest.Mock; - // @ts-expect-error see "Why @ts-expect-error" note - const resolveTxt = dns.resolveTxt as jest.Mock; - dnsLookup.mockImplementation((hostname, ...args) => { - expect(hostname).toEqual('pubsub.googleapis.com'); - process.nextTick(args[args.length - 1], null, [{ address: '0.0.0.0', family: 4 }]); - }); - resolveTxt.mockImplementation((hostname, cb) => { - expect(hostname).toEqual('pubsub.googleapis.com'); - process.nextTick(cb, null, []); + describe('setup', () => { + test('integration name is correct', () => { + const integration = googleCloudGrpcIntegration(); + expect(integration.name).toBe('GoogleCloudGrpc'); }); - const pubsub = new PubSub({ - credentials: { - client_email: 'client@email', - private_key: fs.readFileSync(path.resolve(__dirname, 'private.pem')).toString(), - }, - projectId: 'project-id', + test('setupOnce patches GrpcClient.createStub', () => { + const mockCreateStub = vi.fn(); + const mockGrpcClient = { + prototype: { + createStub: mockCreateStub, + }, + }; + + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('google-gax').GrpcClient = mockGrpcClient; + + const integration = googleCloudGrpcIntegration(); + integration.setupOnce?.(); + expect(mockCreateStub).toBeDefined(); }); - afterEach(() => { - dnsLookup.mockReset(); - resolveTxt.mockReset(); + test('setupOnce throws when google-gax is not available and not optional', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('google-gax').GrpcClient = undefined; + + const integration = googleCloudGrpcIntegration(); + expect(() => integration.setupOnce?.()).toThrow(); }); - afterAll(async () => { - await pubsub.close(); + test('setupOnce does not throw when google-gax is not available and optional', () => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('google-gax').GrpcClient = undefined; + + const optionalIntegration = googleCloudGrpcIntegration({ optional: true }); + expect(() => optionalIntegration.setupOnce?.()).not.toThrow(); }); + }); - test('publish', async () => { - mockHttp2Session().mockUnaryRequest(Buffer.from('00000000120a1031363337303834313536363233383630', 'hex')); - const resp = await pubsub.topic('nicetopic').publish(Buffer.from('data')); - expect(resp).toEqual('1637084156623860'); - expect(mockStartInactiveSpan).toBeCalledWith({ - op: 'grpc.pubsub', + describe('fillGrpcFunction', () => { + test('patches unary call methods with tracing', () => { + const mockStub: Stub = { + unaryMethod: Object.assign(vi.fn(), { + requestStream: false, + responseStream: false, + originalName: 'unaryMethod', + } as GrpcFunctionObject), + }; + + const mockEventEmitter = { + on: vi.fn(), + }; + + (mockStub.unaryMethod as any).apply = vi.fn().mockReturnValue(mockEventEmitter); + + fillGrpcFunction(mockStub, 'test-service', 'unaryMethod'); + + const result = (mockStub.unaryMethod as GrpcFunction)(); + expect(result).toBe(mockEventEmitter); + expect(mockEventEmitter.on).toHaveBeenCalledWith('status', expect.any(Function)); + expect(mockStartInactiveSpan).toHaveBeenCalledWith({ + name: 'unary call unaryMethod', + onlyIfParent: true, + op: 'grpc.test-service', attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.grpc.serverless', }, - name: 'unary call publish', - onlyIfParent: true, }); }); + + test('does not patch non-unary call methods', () => { + const mockStub: Stub = { + clientStreamMethod: Object.assign(vi.fn(), { + requestStream: true, + responseStream: false, + originalName: 'clientStreamMethod', + } as GrpcFunctionObject), + serverStreamMethod: Object.assign(vi.fn(), { + requestStream: false, + responseStream: true, + originalName: 'serverStreamMethod', + } as GrpcFunctionObject), + bidiStreamMethod: Object.assign(vi.fn(), { + requestStream: true, + responseStream: true, + originalName: 'bidiStreamMethod', + } as GrpcFunctionObject), + }; + + fillGrpcFunction(mockStub, 'test-service', 'clientStreamMethod'); + fillGrpcFunction(mockStub, 'test-service', 'serverStreamMethod'); + fillGrpcFunction(mockStub, 'test-service', 'bidiStreamMethod'); + + expect(mockStartInactiveSpan).not.toHaveBeenCalled(); + }); + + test('does not patch non-function properties', () => { + const mockStub: Stub = { + nonFunction: Object.assign(vi.fn(), { + requestStream: false, + responseStream: false, + originalName: 'nonFunction', + } as GrpcFunctionObject), + }; + + fillGrpcFunction(mockStub, 'test-service', 'nonFunction'); + expect(mockStartInactiveSpan).not.toHaveBeenCalled(); + }); + + test('does not patch methods when return value is not an EventEmitter', () => { + const mockStub: Stub = { + unaryMethod: Object.assign(vi.fn(), { + requestStream: false, + responseStream: false, + originalName: 'unaryMethod', + } as GrpcFunctionObject), + }; + + (mockStub.unaryMethod as any).apply = vi.fn().mockReturnValue({ notAnEventEmitter: true }); + + fillGrpcFunction(mockStub, 'test-service', 'unaryMethod'); + + const result = (mockStub.unaryMethod as GrpcFunction)(); + expect(result).toEqual({ notAnEventEmitter: true }); + expect(mockStartInactiveSpan).not.toHaveBeenCalled(); + }); }); }); diff --git a/packages/google-cloud-serverless/test/integrations/google-cloud-http.test.ts b/packages/google-cloud-serverless/test/integrations/google-cloud-http.test.ts index ca26d1069379..164d1c10dfc2 100644 --- a/packages/google-cloud-serverless/test/integrations/google-cloud-http.test.ts +++ b/packages/google-cloud-serverless/test/integrations/google-cloud-http.test.ts @@ -1,18 +1,23 @@ import * as fs from 'fs'; import * as path from 'path'; import { BigQuery } from '@google-cloud/bigquery'; -import * as nock from 'nock'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore ESM/CJS interop issue +import nock from 'nock'; +import { describe, vi, beforeEach, test, expect, afterAll } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; import { NodeClient, createTransport, setCurrentClient } from '@sentry/node'; import { googleCloudHttpIntegration } from '../../src/integrations/google-cloud-http'; -const mockSpanEnd = jest.fn(); -const mockStartInactiveSpan = jest.fn(spanArgs => ({ ...spanArgs })); +const mockSpanEnd = vi.fn(); +const mockStartInactiveSpan = vi.fn(spanArgs => ({ ...spanArgs })); -jest.mock('@sentry/node', () => { +vi.mock('@sentry/node', async () => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node'); return { - ...jest.requireActual('@sentry/node'), + ...original, startInactiveSpan: (ctx: unknown) => { mockStartInactiveSpan(ctx); return { end: mockSpanEnd }; diff --git a/packages/google-cloud-serverless/test/sdk.test.ts b/packages/google-cloud-serverless/test/sdk.test.ts index ee4a1fc6fa17..522915116e24 100644 --- a/packages/google-cloud-serverless/test/sdk.test.ts +++ b/packages/google-cloud-serverless/test/sdk.test.ts @@ -1,9 +1,12 @@ +import { vi, describe, beforeEach, test, expect } from 'vitest'; + import { init } from '../src/sdk'; -const mockInit = jest.fn(); +const mockInit = vi.fn(); -jest.mock('@sentry/node', () => { - const original = jest.requireActual('@sentry/node'); +vi.mock('@sentry/node', async () => { + // eslint-disable-next-line @typescript-eslint/consistent-type-imports + const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node'); return { ...original, init: (options: unknown) => { @@ -14,7 +17,7 @@ jest.mock('@sentry/node', () => { describe('init()', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); test('calls Sentry.init with correct sdk info metadata', () => { diff --git a/packages/google-cloud-serverless/tsconfig.test.json b/packages/google-cloud-serverless/tsconfig.test.json index 87f6afa06b86..ca7dbeb3be94 100644 --- a/packages/google-cloud-serverless/tsconfig.test.json +++ b/packages/google-cloud-serverless/tsconfig.test.json @@ -1,11 +1,11 @@ { "extends": "./tsconfig.json", - "include": ["test/**/*"], + "include": ["test/**/*", "vite.config.ts"], "compilerOptions": { // should include all types from `./tsconfig.json` plus types for all test frameworks used - "types": ["node", "jest"] + "types": ["node"] // other package-specific, test-specific options } diff --git a/packages/google-cloud-serverless/vite.config.ts b/packages/google-cloud-serverless/vite.config.ts new file mode 100644 index 000000000000..f18ec92095bc --- /dev/null +++ b/packages/google-cloud-serverless/vite.config.ts @@ -0,0 +1,8 @@ +import baseConfig from '../../vite/vite.config'; + +export default { + ...baseConfig, + test: { + ...baseConfig.test, + }, +}; diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 09904a4611af..d933aec3811d 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -85,7 +85,7 @@ "@sentry/opentelemetry": "9.9.0", "@sentry/react": "9.9.0", "@sentry/vercel-edge": "9.9.0", - "@sentry/webpack-plugin": "3.2.2", + "@sentry/webpack-plugin": "3.2.3", "chalk": "3.0.0", "resolve": "1.22.8", "rollup": "4.35.0", diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index cababfa63002..9155b0cd2b60 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -349,9 +349,11 @@ export function constructWebpackConfigFunction( } } - // We don't want to do any webpack plugin stuff OR any source maps stuff in dev mode. + const isStaticExport = userNextConfig?.output === 'export'; + + // We don't want to do any webpack plugin stuff OR any source maps stuff in dev mode or for the server on static-only builds. // Symbolication for dev-mode errors is done elsewhere. - if (!isDev) { + if (!(isDev || (isStaticExport && isServer))) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const { sentryWebpackPlugin } = loadModule<{ sentryWebpackPlugin: any }>('@sentry/webpack-plugin', module) ?? {}; diff --git a/packages/nextjs/src/index.types.ts b/packages/nextjs/src/index.types.ts index 7b6173f9c8ea..f1b24da081f0 100644 --- a/packages/nextjs/src/index.types.ts +++ b/packages/nextjs/src/index.types.ts @@ -32,6 +32,8 @@ export declare const createReduxEnhancer: typeof clientSdk.createReduxEnhancer; export declare const showReportDialog: typeof clientSdk.showReportDialog; export declare const withErrorBoundary: typeof clientSdk.withErrorBoundary; +export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger; + export { withSentryConfig } from './config'; /** diff --git a/packages/node/jest.config.js b/packages/node/jest.config.js deleted file mode 100644 index 24f49ab59a4c..000000000000 --- a/packages/node/jest.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../../jest/jest.config.js'); diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index bdc8d6405217..decfbd578c68 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -150,3 +150,7 @@ export type { User, Span, } from '@sentry/core'; + +import * as logger from './log'; + +export { logger }; diff --git a/packages/node/src/integrations/console.ts b/packages/node/src/integrations/console.ts index 5e5e6ac414d9..d1bb0463551e 100644 --- a/packages/node/src/integrations/console.ts +++ b/packages/node/src/integrations/console.ts @@ -5,7 +5,6 @@ import { defineIntegration, getClient, severityLevelFromString, - truncate, } from '@sentry/core'; const INTEGRATION_NAME = 'Console'; @@ -26,7 +25,7 @@ export const consoleIntegration = defineIntegration(() => { { category: 'console', level: severityLevelFromString(level), - message: truncate(util.format.apply(undefined, args), 2048), // 2KB + message: util.format.apply(undefined, args), }, { input: [...args], diff --git a/packages/node/src/integrations/tracing/connect.ts b/packages/node/src/integrations/tracing/connect.ts index 8cfe2bb74050..ae7958c7da83 100644 --- a/packages/node/src/integrations/tracing/connect.ts +++ b/packages/node/src/integrations/tracing/connect.ts @@ -104,7 +104,7 @@ function addConnectSpanAttributes(span: Span): void { [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.connect`, }); - // Also update the name, we don't need to "middleware - " prefix + // Also update the name, we don't need the "middleware - " prefix const name = attributes['connect.name']; if (typeof name === 'string') { span.updateName(name); diff --git a/packages/node/src/integrations/tracing/dataloader.ts b/packages/node/src/integrations/tracing/dataloader.ts index 6339515c6f28..3c887bb33fa5 100644 --- a/packages/node/src/integrations/tracing/dataloader.ts +++ b/packages/node/src/integrations/tracing/dataloader.ts @@ -6,7 +6,7 @@ import { spanToJSON, } from '@sentry/core'; import type { IntegrationFn } from '@sentry/core'; -import { generateInstrumentOnce } from '../../otel/instrument'; +import { instrumentWhenWrapped, generateInstrumentOnce } from '../../otel/instrument'; const INTEGRATION_NAME = 'Dataloader'; @@ -19,31 +19,37 @@ export const instrumentDataloader = generateInstrumentOnce( ); const _dataloaderIntegration = (() => { + let instrumentationWrappedCallback: undefined | ((callback: () => void) => void); + return { name: INTEGRATION_NAME, setupOnce() { - instrumentDataloader(); + const instrumentation = instrumentDataloader(); + instrumentationWrappedCallback = instrumentWhenWrapped(instrumentation); }, setup(client) { - client.on('spanStart', span => { - const spanJSON = spanToJSON(span); - if (spanJSON.description?.startsWith('dataloader')) { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.dataloader'); - } + // This is called either immediately or when the instrumentation is wrapped + instrumentationWrappedCallback?.(() => { + client.on('spanStart', span => { + const spanJSON = spanToJSON(span); + if (spanJSON.description?.startsWith('dataloader')) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.dataloader'); + } - // These are all possible dataloader span descriptions - // Still checking for the future versions - // in case they add support for `clear` and `prime` - if ( - spanJSON.description === 'dataloader.load' || - spanJSON.description === 'dataloader.loadMany' || - spanJSON.description === 'dataloader.batch' - ) { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'cache.get'); - // TODO: We can try adding `key` to the `data` attribute upstream. - // Or alternatively, we can add `requestHook` to the dataloader instrumentation. - } + // These are all possible dataloader span descriptions + // Still checking for the future versions + // in case they add support for `clear` and `prime` + if ( + spanJSON.description === 'dataloader.load' || + spanJSON.description === 'dataloader.loadMany' || + spanJSON.description === 'dataloader.batch' + ) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'cache.get'); + // TODO: We can try adding `key` to the `data` attribute upstream. + // Or alternatively, we can add `requestHook` to the dataloader instrumentation. + } + }); }); }, }; diff --git a/packages/node/src/integrations/tracing/genericPool.ts b/packages/node/src/integrations/tracing/genericPool.ts index 6c4169d66b99..d6f736c6f9a5 100644 --- a/packages/node/src/integrations/tracing/genericPool.ts +++ b/packages/node/src/integrations/tracing/genericPool.ts @@ -1,33 +1,38 @@ import { GenericPoolInstrumentation } from '@opentelemetry/instrumentation-generic-pool'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, spanToJSON } from '@sentry/core'; import type { IntegrationFn } from '@sentry/core'; -import { generateInstrumentOnce } from '../../otel/instrument'; +import { generateInstrumentOnce, instrumentWhenWrapped } from '../../otel/instrument'; const INTEGRATION_NAME = 'GenericPool'; export const instrumentGenericPool = generateInstrumentOnce(INTEGRATION_NAME, () => new GenericPoolInstrumentation({})); const _genericPoolIntegration = (() => { + let instrumentationWrappedCallback: undefined | ((callback: () => void) => void); + return { name: INTEGRATION_NAME, setupOnce() { - instrumentGenericPool(); + const instrumentation = instrumentGenericPool(); + instrumentationWrappedCallback = instrumentWhenWrapped(instrumentation); }, setup(client) { - client.on('spanStart', span => { - const spanJSON = spanToJSON(span); + instrumentationWrappedCallback?.(() => + client.on('spanStart', span => { + const spanJSON = spanToJSON(span); - const spanDescription = spanJSON.description; + const spanDescription = spanJSON.description; - // typo in emitted span for version <= 0.38.0 of @opentelemetry/instrumentation-generic-pool - const isGenericPoolSpan = - spanDescription === 'generic-pool.aquire' || spanDescription === 'generic-pool.acquire'; + // typo in emitted span for version <= 0.38.0 of @opentelemetry/instrumentation-generic-pool + const isGenericPoolSpan = + spanDescription === 'generic-pool.aquire' || spanDescription === 'generic-pool.acquire'; - if (isGenericPoolSpan) { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.generic_pool'); - } - }); + if (isGenericPoolSpan) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.generic_pool'); + } + }), + ); }, }; }) satisfies IntegrationFn; diff --git a/packages/node/src/integrations/tracing/knex.ts b/packages/node/src/integrations/tracing/knex.ts index 86c728d115bd..da70d8b3c8b7 100644 --- a/packages/node/src/integrations/tracing/knex.ts +++ b/packages/node/src/integrations/tracing/knex.ts @@ -1,7 +1,7 @@ import { KnexInstrumentation } from '@opentelemetry/instrumentation-knex'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, spanToJSON } from '@sentry/core'; import type { IntegrationFn } from '@sentry/core'; -import { generateInstrumentOnce } from '../../otel/instrument'; +import { generateInstrumentOnce, instrumentWhenWrapped } from '../../otel/instrument'; const INTEGRATION_NAME = 'Knex'; @@ -11,21 +11,26 @@ export const instrumentKnex = generateInstrumentOnce( ); const _knexIntegration = (() => { + let instrumentationWrappedCallback: undefined | ((callback: () => void) => void); + return { name: INTEGRATION_NAME, setupOnce() { - instrumentKnex(); + const instrumentation = instrumentKnex(); + instrumentationWrappedCallback = instrumentWhenWrapped(instrumentation); }, setup(client) { - client.on('spanStart', span => { - const { data } = spanToJSON(span); - // knex.version is always set in the span data - // https://github.com/open-telemetry/opentelemetry-js-contrib/blob/0309caeafc44ac9cb13a3345b790b01b76d0497d/plugins/node/opentelemetry-instrumentation-knex/src/instrumentation.ts#L138 - if ('knex.version' in data) { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.knex'); - } - }); + instrumentationWrappedCallback?.(() => + client.on('spanStart', span => { + const { data } = spanToJSON(span); + // knex.version is always set in the span data + // https://github.com/open-telemetry/opentelemetry-js-contrib/blob/0309caeafc44ac9cb13a3345b790b01b76d0497d/plugins/node/opentelemetry-instrumentation-knex/src/instrumentation.ts#L138 + if ('knex.version' in data) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.knex'); + } + }), + ); }, }; }) satisfies IntegrationFn; diff --git a/packages/node/src/integrations/tracing/prisma.ts b/packages/node/src/integrations/tracing/prisma.ts index 58516671c9a3..06b75f0c707e 100644 --- a/packages/node/src/integrations/tracing/prisma.ts +++ b/packages/node/src/integrations/tracing/prisma.ts @@ -19,6 +19,18 @@ function isPrismaV6TracingHelper(helper: unknown): helper is PrismaV6TracingHelp return !!helper && typeof helper === 'object' && 'dispatchEngineSpans' in helper; } +function getPrismaTracingHelper(): unknown | undefined { + const prismaInstrumentationObject = (globalThis as Record).PRISMA_INSTRUMENTATION; + const prismaTracingHelper = + prismaInstrumentationObject && + typeof prismaInstrumentationObject === 'object' && + 'helper' in prismaInstrumentationObject + ? prismaInstrumentationObject.helper + : undefined; + + return prismaTracingHelper; +} + class SentryPrismaInteropInstrumentation extends EsmInteropPrismaInstrumentation { public constructor() { super(); @@ -30,13 +42,7 @@ class SentryPrismaInteropInstrumentation extends EsmInteropPrismaInstrumentation // The PrismaIntegration (super class) defines a global variable `global["PRISMA_INSTRUMENTATION"]` when `enable()` is called. This global variable holds a "TracingHelper" which Prisma uses internally to create tracing data. It's their way of not depending on OTEL with their main package. The sucky thing is, prisma broke the interface of the tracing helper with the v6 major update. This means that if you use Prisma 5 with the v6 instrumentation (or vice versa) Prisma just blows up, because tries to call methods on the helper that no longer exist. // Because we actually want to use the v6 instrumentation and not blow up in Prisma 5 user's faces, what we're doing here is backfilling the v5 method (`createEngineSpan`) with a noop so that no longer crashes when it attempts to call that function. // We still won't fully emit all the spans, but this could potentially be implemented in the future. - const prismaInstrumentationObject = (globalThis as Record).PRISMA_INSTRUMENTATION; - const prismaTracingHelper = - prismaInstrumentationObject && - typeof prismaInstrumentationObject === 'object' && - 'helper' in prismaInstrumentationObject - ? prismaInstrumentationObject.helper - : undefined; + const prismaTracingHelper = getPrismaTracingHelper(); let emittedWarning = false; @@ -119,6 +125,12 @@ export const prismaIntegration = defineIntegration( instrumentPrisma({ prismaInstrumentation }); }, setup(client) { + // If no tracing helper exists, we skip any work here + // this means that prisma is not being used + if (!getPrismaTracingHelper()) { + return; + } + client.on('spanStart', span => { const spanJSON = spanToJSON(span); if (spanJSON.description?.startsWith('prisma:')) { diff --git a/packages/node/src/integrations/tracing/tedious.ts b/packages/node/src/integrations/tracing/tedious.ts index 644601986a7e..dd74c095a566 100644 --- a/packages/node/src/integrations/tracing/tedious.ts +++ b/packages/node/src/integrations/tracing/tedious.ts @@ -1,7 +1,7 @@ import { TediousInstrumentation } from '@opentelemetry/instrumentation-tedious'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, spanToJSON } from '@sentry/core'; import type { IntegrationFn } from '@sentry/core'; -import { generateInstrumentOnce } from '../../otel/instrument'; +import { generateInstrumentOnce, instrumentWhenWrapped } from '../../otel/instrument'; const TEDIUS_INSTRUMENTED_METHODS = new Set([ 'callProcedure', @@ -17,25 +17,30 @@ const INTEGRATION_NAME = 'Tedious'; export const instrumentTedious = generateInstrumentOnce(INTEGRATION_NAME, () => new TediousInstrumentation({})); const _tediousIntegration = (() => { + let instrumentationWrappedCallback: undefined | ((callback: () => void) => void); + return { name: INTEGRATION_NAME, setupOnce() { - instrumentTedious(); + const instrumentation = instrumentTedious(); + instrumentationWrappedCallback = instrumentWhenWrapped(instrumentation); }, setup(client) { - client.on('spanStart', span => { - const { description, data } = spanToJSON(span); - // Tedius integration always set a span name and `db.system` attribute to `mssql`. - if (!description || data['db.system'] !== 'mssql') { - return; - } - - const operation = description.split(' ')[0] || ''; - if (TEDIUS_INSTRUMENTED_METHODS.has(operation)) { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.tedious'); - } - }); + instrumentationWrappedCallback?.(() => + client.on('spanStart', span => { + const { description, data } = spanToJSON(span); + // Tedius integration always set a span name and `db.system` attribute to `mssql`. + if (!description || data['db.system'] !== 'mssql') { + return; + } + + const operation = description.split(' ')[0] || ''; + if (TEDIUS_INSTRUMENTED_METHODS.has(operation)) { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.db.otel.tedious'); + } + }), + ); }, }; }) satisfies IntegrationFn; diff --git a/packages/node/src/integrations/tracing/vercelai/index.ts b/packages/node/src/integrations/tracing/vercelai/index.ts index a8198a8458ec..26bf57ed38b2 100644 --- a/packages/node/src/integrations/tracing/vercelai/index.ts +++ b/packages/node/src/integrations/tracing/vercelai/index.ts @@ -3,152 +3,153 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_OP, defineIntegration, spanToJSON } from '@se import type { IntegrationFn } from '@sentry/core'; import { generateInstrumentOnce } from '../../../otel/instrument'; import { addOriginToSpan } from '../../../utils/addOriginToSpan'; -import { SentryVercelAiInstrumentation, sentryVercelAiPatched } from './instrumentation'; +import { SentryVercelAiInstrumentation } from './instrumentation'; const INTEGRATION_NAME = 'VercelAI'; export const instrumentVercelAi = generateInstrumentOnce(INTEGRATION_NAME, () => new SentryVercelAiInstrumentation({})); const _vercelAIIntegration = (() => { + let instrumentation: undefined | SentryVercelAiInstrumentation; + return { name: INTEGRATION_NAME, setupOnce() { - instrumentVercelAi(); - }, - processEvent(event) { - if (event.type === 'transaction' && event.spans?.length) { - for (const span of event.spans) { - const { data: attributes, description: name } = span; - - if (!name || span.origin !== 'auto.vercelai.otel') { - continue; - } - - if (attributes['ai.usage.completionTokens'] != undefined) { - attributes['ai.completion_tokens.used'] = attributes['ai.usage.completionTokens']; - } - if (attributes['ai.usage.promptTokens'] != undefined) { - attributes['ai.prompt_tokens.used'] = attributes['ai.usage.promptTokens']; - } - if ( - typeof attributes['ai.usage.completionTokens'] == 'number' && - typeof attributes['ai.usage.promptTokens'] == 'number' - ) { - attributes['ai.total_tokens.used'] = - attributes['ai.usage.completionTokens'] + attributes['ai.usage.promptTokens']; - } - } - } - - return event; + instrumentation = instrumentVercelAi(); }, setup(client) { - client.on('spanStart', span => { - if (!sentryVercelAiPatched) { - return; - } - - const { data: attributes, description: name } = spanToJSON(span); - - if (!name) { - return; - } - - // The id of the model - const aiModelId = attributes['ai.model.id']; - - // the provider of the model - const aiModelProvider = attributes['ai.model.provider']; - - // both of these must be defined for the integration to work - if (typeof aiModelId !== 'string' || typeof aiModelProvider !== 'string' || !aiModelId || !aiModelProvider) { - return; - } - - let isPipelineSpan = false; - - switch (name) { - case 'ai.generateText': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateText'); - isPipelineSpan = true; - break; - } - case 'ai.generateText.doGenerate': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate'); - break; - } - case 'ai.streamText': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamText'); - isPipelineSpan = true; - break; - } - case 'ai.streamText.doStream': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream'); - break; - } - case 'ai.generateObject': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateObject'); - isPipelineSpan = true; - break; - } - case 'ai.generateObject.doGenerate': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate'); - break; - } - case 'ai.streamObject': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamObject'); - isPipelineSpan = true; - break; - } - case 'ai.streamObject.doStream': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream'); - break; - } - case 'ai.embed': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed'); - isPipelineSpan = true; - break; - } - case 'ai.embed.doEmbed': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings'); - break; - } - case 'ai.embedMany': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embedMany'); - isPipelineSpan = true; - break; - } - case 'ai.embedMany.doEmbed': { - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings'); - break; - } - case 'ai.toolCall': - case 'ai.stream.firstChunk': - case 'ai.stream.finish': - span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run'); - break; - } - - addOriginToSpan(span, 'auto.vercelai.otel'); - - const nameWthoutAi = name.replace('ai.', ''); - span.setAttribute('ai.pipeline.name', nameWthoutAi); - span.updateName(nameWthoutAi); - - // If a Telemetry name is set and it is a pipeline span, use that as the operation name - const functionId = attributes['ai.telemetry.functionId']; - if (functionId && typeof functionId === 'string' && isPipelineSpan) { - span.updateName(functionId); - span.setAttribute('ai.pipeline.name', functionId); - } - - if (attributes['ai.prompt']) { - span.setAttribute('ai.input_messages', attributes['ai.prompt']); - } - if (attributes['ai.model.id']) { - span.setAttribute('ai.model_id', attributes['ai.model.id']); - } - span.setAttribute('ai.streaming', name.includes('stream')); + instrumentation?.callWhenPatched(() => { + client.on('spanStart', span => { + const { data: attributes, description: name } = spanToJSON(span); + + if (!name) { + return; + } + + // The id of the model + const aiModelId = attributes['ai.model.id']; + + // the provider of the model + const aiModelProvider = attributes['ai.model.provider']; + + // both of these must be defined for the integration to work + if (typeof aiModelId !== 'string' || typeof aiModelProvider !== 'string' || !aiModelId || !aiModelProvider) { + return; + } + + let isPipelineSpan = false; + + switch (name) { + case 'ai.generateText': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateText'); + isPipelineSpan = true; + break; + } + case 'ai.generateText.doGenerate': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate'); + break; + } + case 'ai.streamText': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamText'); + isPipelineSpan = true; + break; + } + case 'ai.streamText.doStream': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream'); + break; + } + case 'ai.generateObject': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.generateObject'); + isPipelineSpan = true; + break; + } + case 'ai.generateObject.doGenerate': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doGenerate'); + break; + } + case 'ai.streamObject': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.streamObject'); + isPipelineSpan = true; + break; + } + case 'ai.streamObject.doStream': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run.doStream'); + break; + } + case 'ai.embed': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embed'); + isPipelineSpan = true; + break; + } + case 'ai.embed.doEmbed': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings'); + break; + } + case 'ai.embedMany': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.pipeline.embedMany'); + isPipelineSpan = true; + break; + } + case 'ai.embedMany.doEmbed': { + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.embeddings'); + break; + } + case 'ai.toolCall': + case 'ai.stream.firstChunk': + case 'ai.stream.finish': + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'ai.run'); + break; + } + + addOriginToSpan(span, 'auto.vercelai.otel'); + + const nameWthoutAi = name.replace('ai.', ''); + span.setAttribute('ai.pipeline.name', nameWthoutAi); + span.updateName(nameWthoutAi); + + // If a Telemetry name is set and it is a pipeline span, use that as the operation name + const functionId = attributes['ai.telemetry.functionId']; + if (functionId && typeof functionId === 'string' && isPipelineSpan) { + span.updateName(functionId); + span.setAttribute('ai.pipeline.name', functionId); + } + + if (attributes['ai.prompt']) { + span.setAttribute('ai.input_messages', attributes['ai.prompt']); + } + if (attributes['ai.model.id']) { + span.setAttribute('ai.model_id', attributes['ai.model.id']); + } + span.setAttribute('ai.streaming', name.includes('stream')); + }); + + client.addEventProcessor(event => { + if (event.type === 'transaction' && event.spans?.length) { + for (const span of event.spans) { + const { data: attributes, description: name } = span; + + if (!name || span.origin !== 'auto.vercelai.otel') { + continue; + } + + if (attributes['ai.usage.completionTokens'] != undefined) { + attributes['ai.completion_tokens.used'] = attributes['ai.usage.completionTokens']; + } + if (attributes['ai.usage.promptTokens'] != undefined) { + attributes['ai.prompt_tokens.used'] = attributes['ai.usage.promptTokens']; + } + if ( + typeof attributes['ai.usage.completionTokens'] == 'number' && + typeof attributes['ai.usage.promptTokens'] == 'number' + ) { + attributes['ai.total_tokens.used'] = + attributes['ai.usage.completionTokens'] + attributes['ai.usage.promptTokens']; + } + } + } + + return event; + }); }); }, }; diff --git a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts index 97721eaee15d..2cddd175c0d8 100644 --- a/packages/node/src/integrations/tracing/vercelai/instrumentation.ts +++ b/packages/node/src/integrations/tracing/vercelai/instrumentation.ts @@ -23,8 +23,6 @@ type MethodArgs = [MethodFirstArg, ...unknown[]]; type PatchedModuleExports = Record<(typeof INSTRUMENTED_METHODS)[number], (...args: MethodArgs) => unknown> & Record; -export let sentryVercelAiPatched = false; - /** * This detects is added by the Sentry Vercel AI Integration to detect if the integration should * be enabled. @@ -32,6 +30,9 @@ export let sentryVercelAiPatched = false; * It also patches the `ai` module to enable Vercel AI telemetry automatically for all methods. */ export class SentryVercelAiInstrumentation extends InstrumentationBase { + private _isPatched = false; + private _callbacks: (() => void)[] = []; + public constructor(config: InstrumentationConfig = {}) { super('@sentry/instrumentation-vercel-ai', SDK_VERSION, config); } @@ -44,11 +45,26 @@ export class SentryVercelAiInstrumentation extends InstrumentationBase { return module; } + /** + * Call the provided callback when the module is patched. + * If it has already been patched, the callback will be called immediately. + */ + public callWhenPatched(callback: () => void): void { + if (this._isPatched) { + callback(); + } else { + this._callbacks.push(callback); + } + } + /** * Patches module exports to enable Vercel AI telemetry. */ private _patch(moduleExports: PatchedModuleExports): unknown { - sentryVercelAiPatched = true; + this._isPatched = true; + + this._callbacks.forEach(callback => callback()); + this._callbacks = []; function generatePatch(name: string) { return (...args: MethodArgs) => { diff --git a/packages/node/src/log.ts b/packages/node/src/log.ts new file mode 100644 index 000000000000..2523b0f77bf8 --- /dev/null +++ b/packages/node/src/log.ts @@ -0,0 +1,197 @@ +import { format } from 'node:util'; + +import type { LogSeverityLevel, Log, ParameterizedString } from '@sentry/core'; +import { _INTERNAL_captureLog } from '@sentry/core'; + +type CaptureLogArgs = + | [message: ParameterizedString, attributes?: Log['attributes']] + | [messageTemplate: string, messageParams: Array, attributes?: Log['attributes']]; + +/** + * Capture a log with the given level. + * + * @param level - The level of the log. + * @param message - The message to log. + * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100. + */ +function captureLog(level: LogSeverityLevel, ...args: CaptureLogArgs): void { + const [messageOrMessageTemplate, paramsOrAttributes, maybeAttributes] = args; + if (Array.isArray(paramsOrAttributes)) { + const attributes = { ...maybeAttributes }; + attributes['sentry.message.template'] = messageOrMessageTemplate; + paramsOrAttributes.forEach((param, index) => { + attributes[`sentry.message.param.${index}`] = param; + }); + const message = format(messageOrMessageTemplate, ...paramsOrAttributes); + _INTERNAL_captureLog({ level, message, attributes }); + } else { + _INTERNAL_captureLog({ level, message: messageOrMessageTemplate, attributes: paramsOrAttributes }); + } +} + +/** + * @summary Capture a log with the `trace` level. Requires `_experiments.enableLogs` to be enabled. + * + * You can either pass a message and attributes or a message template, params and attributes. + * + * @example + * + * ``` + * Sentry.logger.trace('Starting database connection', { + * database: 'users', + * connectionId: 'conn_123' + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.trace('Database connection %s established for %s', + * ['successful', 'users'], + * { connectionId: 'conn_123' } + * ); + * ``` + */ +export function trace(...args: CaptureLogArgs): void { + captureLog('trace', ...args); +} + +/** + * @summary Capture a log with the `debug` level. Requires `_experiments.enableLogs` to be enabled. + * + * You can either pass a message and attributes or a message template, params and attributes. + * + * @example + * + * ``` + * Sentry.logger.debug('Cache miss for user profile', { + * userId: 'user_123', + * cacheKey: 'profile:user_123' + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.debug('Cache %s for %s: %s', + * ['miss', 'user profile', 'key not found'], + * { userId: 'user_123' } + * ); + * ``` + */ +export function debug(...args: CaptureLogArgs): void { + captureLog('debug', ...args); +} + +/** + * @summary Capture a log with the `info` level. Requires `_experiments.enableLogs` to be enabled. + * + * You can either pass a message and attributes or a message template, params and attributes. + * + * @example + * + * ``` + * Sentry.logger.info('User profile updated', { + * userId: 'user_123', + * updatedFields: ['email', 'preferences'] + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.info('User %s updated their %s', + * ['John Doe', 'profile settings'], + * { userId: 'user_123' } + * ); + * ``` + */ +export function info(...args: CaptureLogArgs): void { + captureLog('info', ...args); +} + +/** + * @summary Capture a log with the `warn` level. Requires `_experiments.enableLogs` to be enabled. + * + * You can either pass a message and attributes or a message template, params and attributes. + * + * @example + * + * ``` + * Sentry.logger.warn('Rate limit approaching', { + * endpoint: '/api/users', + * currentRate: '95/100', + * resetTime: '2024-03-20T10:00:00Z' + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.warn('Rate limit %s for %s: %s', + * ['approaching', '/api/users', '95/100 requests'], + * { resetTime: '2024-03-20T10:00:00Z' } + * ); + * ``` + */ +export function warn(...args: CaptureLogArgs): void { + captureLog('warn', ...args); +} + +/** + * @summary Capture a log with the `error` level. Requires `_experiments.enableLogs` to be enabled. + * + * You can either pass a message and attributes or a message template, params and attributes. + * + * @example + * + * ``` + * Sentry.logger.error('Failed to process payment', { + * orderId: 'order_123', + * errorCode: 'PAYMENT_FAILED', + * amount: 99.99 + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.error('Payment processing failed for order %s: %s', + * ['order_123', 'insufficient funds'], + * { amount: 99.99 } + * ); + * ``` + */ +export function error(...args: CaptureLogArgs): void { + captureLog('error', ...args); +} + +/** + * @summary Capture a log with the `fatal` level. Requires `_experiments.enableLogs` to be enabled. + * + * You can either pass a message and attributes or a message template, params and attributes. + * + * @example + * + * ``` + * Sentry.logger.fatal('Database connection pool exhausted', { + * database: 'users', + * activeConnections: 100, + * maxConnections: 100 + * }); + * ``` + * + * @example With template strings + * + * ``` + * Sentry.logger.fatal('Database %s: %s connections active', + * ['connection pool exhausted', '100/100'], + * { database: 'users' } + * ); + * ``` + */ +export function fatal(...args: CaptureLogArgs): void { + captureLog('fatal', ...args); +} + +export { fmt } from '@sentry/core'; diff --git a/packages/node/src/otel/instrument.ts b/packages/node/src/otel/instrument.ts index c5bd7500a739..6f8b10db2ba7 100644 --- a/packages/node/src/otel/instrument.ts +++ b/packages/node/src/otel/instrument.ts @@ -7,19 +7,22 @@ export const INSTRUMENTED: Record = {}; * Instrument an OpenTelemetry instrumentation once. * This will skip running instrumentation again if it was already instrumented. */ -export function generateInstrumentOnce( +export function generateInstrumentOnce< + Options = unknown, + InstrumentationInstance extends Instrumentation = Instrumentation, +>( name: string, - creator: (options?: Options) => Instrumentation, -): ((options?: Options) => void) & { id: string } { + creator: (options?: Options) => InstrumentationInstance, +): ((options?: Options) => InstrumentationInstance) & { id: string } { return Object.assign( (options?: Options) => { - const instrumented = INSTRUMENTED[name]; + const instrumented = INSTRUMENTED[name] as InstrumentationInstance | undefined; if (instrumented) { // If options are provided, ensure we update them if (options) { instrumented.setConfig(options); } - return; + return instrumented; } const instrumentation = creator(options); @@ -28,7 +31,55 @@ export function generateInstrumentOnce( registerInstrumentations({ instrumentations: [instrumentation], }); + + return instrumentation; }, { id: name }, ); } + +/** + * Ensure a given callback is called when the instrumentation is actually wrapping something. + * This can be used to ensure some logic is only called when the instrumentation is actually active. + * + * This function returns a function that can be invoked with a callback. + * This callback will either be invoked immediately + * (e.g. if the instrumentation was already wrapped, or if _wrap could not be patched), + * or once the instrumentation is actually wrapping something. + * + * Make sure to call this function right after adding the instrumentation, otherwise it may be too late! + * The returned callback can be used any time, and also multiple times. + */ +export function instrumentWhenWrapped(instrumentation: T): (callback: () => void) => void { + let isWrapped = false; + let callbacks: (() => void)[] = []; + + if (!hasWrap(instrumentation)) { + isWrapped = true; + } else { + const originalWrap = instrumentation['_wrap']; + + instrumentation['_wrap'] = (...args: Parameters) => { + isWrapped = true; + callbacks.forEach(callback => callback()); + callbacks = []; + return originalWrap(...args); + }; + } + + const registerCallback = (callback: () => void): void => { + if (isWrapped) { + callback(); + } else { + callbacks.push(callback); + } + }; + + return registerCallback; +} + +function hasWrap( + instrumentation: T, +): instrumentation is T & { _wrap: (...args: unknown[]) => unknown } { + return typeof (instrumentation as T & { _wrap?: (...args: unknown[]) => unknown })['_wrap'] === 'function'; +} diff --git a/packages/node/src/sdk/index.ts b/packages/node/src/sdk/index.ts index 140f99bdd254..d479407a4e67 100644 --- a/packages/node/src/sdk/index.ts +++ b/packages/node/src/sdk/index.ts @@ -1,7 +1,6 @@ import type { Integration, Options } from '@sentry/core'; import { consoleSandbox, - dropUndefinedKeys, functionToStringIntegration, getCurrentScope, getIntegrationsToSetup, @@ -201,50 +200,32 @@ function getClientOptions( getDefaultIntegrationsImpl: (options: Options) => Integration[], ): NodeClientOptions { const release = getRelease(options.release); - - if (options.spotlight == null) { - const spotlightEnv = envToBool(process.env.SENTRY_SPOTLIGHT, { strict: true }); - if (spotlightEnv == null) { - options.spotlight = process.env.SENTRY_SPOTLIGHT; - } else { - options.spotlight = spotlightEnv; - } - } - + const spotlight = + options.spotlight ?? envToBool(process.env.SENTRY_SPOTLIGHT, { strict: true }) ?? process.env.SENTRY_SPOTLIGHT; const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate); - const baseOptions = dropUndefinedKeys({ - dsn: process.env.SENTRY_DSN, - environment: process.env.SENTRY_ENVIRONMENT, - sendClientReports: true, - }); - - const overwriteOptions = dropUndefinedKeys({ - release, - tracesSampleRate, - transport: options.transport || makeNodeTransport, - }); - const mergedOptions = { - ...baseOptions, ...options, - ...overwriteOptions, + dsn: options.dsn ?? process.env.SENTRY_DSN, + environment: options.environment ?? process.env.SENTRY_ENVIRONMENT, + sendClientReports: options.sendClientReports ?? true, + transport: options.transport ?? makeNodeTransport, + stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser), + release, + tracesSampleRate, + spotlight, }; - if (options.defaultIntegrations === undefined) { - options.defaultIntegrations = getDefaultIntegrationsImpl(mergedOptions); - } + const integrations = options.integrations; + const defaultIntegrations = options.defaultIntegrations ?? getDefaultIntegrationsImpl(mergedOptions); - const clientOptions: NodeClientOptions = { + return { ...mergedOptions, - stackParser: stackParserFromStackParserOptions(options.stackParser || defaultStackParser), integrations: getIntegrationsToSetup({ - defaultIntegrations: options.defaultIntegrations, - integrations: options.integrations, + defaultIntegrations, + integrations, }), }; - - return clientOptions; } function getRelease(release: NodeOptions['release']): string | undefined { diff --git a/packages/node/test/helpers/conditional.ts b/packages/node/test/helpers/conditional.ts index 48df7d821da8..ceea11315db4 100644 --- a/packages/node/test/helpers/conditional.ts +++ b/packages/node/test/helpers/conditional.ts @@ -7,7 +7,6 @@ const NODE_VERSION = parseSemver(process.versions.node).major; * Returns`describe` or `describe.skip` depending on allowed major versions of Node. * * @param {{ min?: number; max?: number }} allowedVersion - * @return {*} {jest.Describe} */ export const conditionalTest = (allowedVersion: { min?: number; max?: number }) => { if (!NODE_VERSION) { diff --git a/packages/node/test/integration/console.test.ts b/packages/node/test/integration/console.test.ts index 401dffd34819..691ccd4397ee 100644 --- a/packages/node/test/integration/console.test.ts +++ b/packages/node/test/integration/console.test.ts @@ -36,26 +36,4 @@ describe('Console integration', () => { }, ); }); - - it('should truncate breadcrumbs with more than 2 KB message size', () => { - consoleIntegration().setup?.(getClient() as NodeClient); - - const longMsg = 'A'.repeat(10_000); - - // eslint-disable-next-line no-console - console.log(longMsg); - - expect(addBreadcrumbSpy).toHaveBeenCalledTimes(1); - expect(addBreadcrumbSpy).toHaveBeenCalledWith( - { - category: 'console', - level: 'log', - message: `${'A'.repeat(2048)}...`, - }, - { - input: [longMsg], - level: 'log', - }, - ); - }); }); diff --git a/packages/node/test/log.test.ts b/packages/node/test/log.test.ts new file mode 100644 index 000000000000..bd2e051ddf50 --- /dev/null +++ b/packages/node/test/log.test.ts @@ -0,0 +1,145 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import * as sentryCore from '@sentry/core'; +import * as nodeLogger from '../src/log'; + +// Mock the core functions +vi.mock('@sentry/core', async () => { + const actual = await vi.importActual('@sentry/core'); + return { + ...actual, + _INTERNAL_captureLog: vi.fn(), + }; +}); + +describe('Node Logger', () => { + // Use the mocked function + const mockCaptureLog = vi.mocked(sentryCore._INTERNAL_captureLog); + + beforeEach(() => { + // Reset mocks + mockCaptureLog.mockClear(); + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + describe('Basic logging methods', () => { + it('should export all log methods', () => { + expect(nodeLogger.trace).toBeTypeOf('function'); + expect(nodeLogger.debug).toBeTypeOf('function'); + expect(nodeLogger.info).toBeTypeOf('function'); + expect(nodeLogger.warn).toBeTypeOf('function'); + expect(nodeLogger.error).toBeTypeOf('function'); + expect(nodeLogger.fatal).toBeTypeOf('function'); + }); + + it('should call _INTERNAL_captureLog with trace level', () => { + nodeLogger.trace('Test trace message', { key: 'value' }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'trace', + message: 'Test trace message', + attributes: { key: 'value' }, + }); + }); + + it('should call _INTERNAL_captureLog with debug level', () => { + nodeLogger.debug('Test debug message', { key: 'value' }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'debug', + message: 'Test debug message', + attributes: { key: 'value' }, + }); + }); + + it('should call _INTERNAL_captureLog with info level', () => { + nodeLogger.info('Test info message', { key: 'value' }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'info', + message: 'Test info message', + attributes: { key: 'value' }, + }); + }); + + it('should call _INTERNAL_captureLog with warn level', () => { + nodeLogger.warn('Test warn message', { key: 'value' }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'warn', + message: 'Test warn message', + attributes: { key: 'value' }, + }); + }); + + it('should call _INTERNAL_captureLog with error level', () => { + nodeLogger.error('Test error message', { key: 'value' }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'error', + message: 'Test error message', + attributes: { key: 'value' }, + }); + }); + + it('should call _INTERNAL_captureLog with fatal level', () => { + nodeLogger.fatal('Test fatal message', { key: 'value' }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'fatal', + message: 'Test fatal message', + attributes: { key: 'value' }, + }); + }); + }); + + describe('Template string logging', () => { + it('should handle template strings with parameters', () => { + nodeLogger.info('Hello %s, your balance is %d', ['John', 100], { userId: 123 }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'info', + message: 'Hello John, your balance is 100', + attributes: { + userId: 123, + 'sentry.message.template': 'Hello %s, your balance is %d', + 'sentry.message.param.0': 'John', + 'sentry.message.param.1': 100, + }, + }); + }); + + it('should handle template strings without additional attributes', () => { + nodeLogger.debug('User %s logged in from %s', ['Alice', 'mobile']); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'debug', + message: 'User Alice logged in from mobile', + attributes: { + 'sentry.message.template': 'User %s logged in from %s', + 'sentry.message.param.0': 'Alice', + 'sentry.message.param.1': 'mobile', + }, + }); + }); + + it('should handle parameterized strings with parameters', () => { + nodeLogger.info(nodeLogger.fmt`Hello ${'John'}, your balance is ${100}`, { userId: 123 }); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'info', + message: expect.objectContaining({ + __sentry_template_string__: 'Hello %s, your balance is %s', + __sentry_template_values__: ['John', 100], + }), + attributes: { + userId: 123, + }, + }); + }); + + it('should handle parameterized strings without additional attributes', () => { + nodeLogger.debug(nodeLogger.fmt`User ${'Alice'} logged in from ${'mobile'}`); + expect(mockCaptureLog).toHaveBeenCalledWith({ + level: 'debug', + message: expect.objectContaining({ + __sentry_template_string__: 'User %s logged in from %s', + __sentry_template_values__: ['Alice', 'mobile'], + }), + }); + }); + }); +}); diff --git a/packages/node/test/utils/instrument.test.ts b/packages/node/test/utils/instrument.test.ts new file mode 100644 index 000000000000..3cc7fedb4d22 --- /dev/null +++ b/packages/node/test/utils/instrument.test.ts @@ -0,0 +1,96 @@ +import { describe, test, vi, expect } from 'vitest'; +import { instrumentWhenWrapped } from '../../src/otel/instrument'; + +describe('instrumentWhenWrapped', () => { + test('calls callback immediately when instrumentation has no _wrap method', () => { + const callback = vi.fn(); + const instrumentation = {} as any; + + const registerCallback = instrumentWhenWrapped(instrumentation); + registerCallback(callback); + + expect(callback).toHaveBeenCalledTimes(1); + }); + + test('calls callback when _wrap is called', () => { + const callback = vi.fn(); + const originalWrap = vi.fn(); + const instrumentation = { + _wrap: originalWrap, + } as any; + + const registerCallback = instrumentWhenWrapped(instrumentation); + registerCallback(callback); + + // Callback should not be called yet + expect(callback).not.toHaveBeenCalled(); + + // Call _wrap + instrumentation._wrap(); + + // Callback should be called once + expect(callback).toHaveBeenCalledTimes(1); + expect(originalWrap).toHaveBeenCalled(); + }); + + test('calls multiple callbacks when _wrap is called', () => { + const callback1 = vi.fn(); + const callback2 = vi.fn(); + const originalWrap = vi.fn(); + const instrumentation = { + _wrap: originalWrap, + } as any; + + const registerCallback = instrumentWhenWrapped(instrumentation); + registerCallback(callback1); + registerCallback(callback2); + + // Callbacks should not be called yet + expect(callback1).not.toHaveBeenCalled(); + expect(callback2).not.toHaveBeenCalled(); + + // Call _wrap + instrumentation._wrap(); + + // Both callbacks should be called once + expect(callback1).toHaveBeenCalledTimes(1); + expect(callback2).toHaveBeenCalledTimes(1); + expect(originalWrap).toHaveBeenCalled(); + }); + + test('calls callback immediately if already wrapped', () => { + const callback = vi.fn(); + const originalWrap = vi.fn(); + const instrumentation = { + _wrap: originalWrap, + } as any; + + const registerCallback = instrumentWhenWrapped(instrumentation); + + // Call _wrap first + instrumentation._wrap(); + + registerCallback(callback); + + // Callback should be called immediately + expect(callback).toHaveBeenCalledTimes(1); + expect(originalWrap).toHaveBeenCalled(); + }); + + test('passes through arguments to original _wrap', () => { + const callback = vi.fn(); + const originalWrap = vi.fn(); + const instrumentation = { + _wrap: originalWrap, + } as any; + + const registerCallback = instrumentWhenWrapped(instrumentation); + registerCallback(callback); + + // Call _wrap with arguments + const args = ['arg1', 'arg2']; + instrumentation._wrap(...args); + + expect(originalWrap).toHaveBeenCalledWith(...args); + }); +}); diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index fce211d2d2e4..cda00dd68bbb 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -47,8 +47,8 @@ "@sentry/core": "9.9.0", "@sentry/node": "9.9.0", "@sentry/opentelemetry": "9.9.0", - "@sentry/rollup-plugin": "3.1.2", - "@sentry/vite-plugin": "2.22.6", + "@sentry/rollup-plugin": "3.2.3", + "@sentry/vite-plugin": "3.2.3", "@sentry/vue": "9.9.0" }, "devDependencies": { diff --git a/packages/nuxt/src/index.types.ts b/packages/nuxt/src/index.types.ts index b1393a076029..24b21b8680ae 100644 --- a/packages/nuxt/src/index.types.ts +++ b/packages/nuxt/src/index.types.ts @@ -1,6 +1,7 @@ import type { Client, Integration, Options, StackParser } from '@sentry/core'; import type { SentryNuxtClientOptions, SentryNuxtServerOptions } from './common/types'; import type * as clientSdk from './index.client'; +import type * as serverSdk from './index.server'; // We export everything from both the client part of the SDK and from the server part. Some of the exports collide, // which is not allowed, unless we re-export the colliding exports in this file - which we do below. @@ -13,3 +14,5 @@ export declare const linkedErrorsIntegration: typeof clientSdk.linkedErrorsInteg export declare const contextLinesIntegration: typeof clientSdk.contextLinesIntegration; export declare const getDefaultIntegrations: (options: Options) => Integration[]; export declare const defaultStackParser: StackParser; + +export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger; diff --git a/packages/nuxt/src/runtime/utils.ts b/packages/nuxt/src/runtime/utils.ts index 23bac2486b74..c6eb59807764 100644 --- a/packages/nuxt/src/runtime/utils.ts +++ b/packages/nuxt/src/runtime/utils.ts @@ -1,5 +1,5 @@ import type { ClientOptions, Context } from '@sentry/core'; -import { captureException, dropUndefinedKeys, getClient, getTraceMetaTags } from '@sentry/core'; +import { captureException, getClient, getTraceMetaTags } from '@sentry/core'; import type { VueOptions } from '@sentry/vue/src/types'; import type { CapturedErrorContext } from 'nitropack'; import type { NuxtRenderHTMLContext } from 'nuxt/app'; @@ -9,25 +9,23 @@ import type { ComponentPublicInstance } from 'vue'; * Extracts the relevant context information from the error context (H3Event in Nitro Error) * and created a structured context object. */ -export function extractErrorContext(errorContext: CapturedErrorContext): Context { - const structuredContext: Context = { - method: undefined, - path: undefined, - tags: undefined, - }; +export function extractErrorContext(errorContext: CapturedErrorContext | undefined): Context { + const ctx: Context = {}; - if (errorContext) { - if (errorContext.event) { - structuredContext.method = errorContext.event._method || undefined; - structuredContext.path = errorContext.event._path || undefined; - } + if (!errorContext) { + return ctx; + } - if (Array.isArray(errorContext.tags)) { - structuredContext.tags = errorContext.tags || undefined; - } + if (errorContext.event) { + ctx.method = errorContext.event._method; + ctx.path = errorContext.event._path; + } + + if (Array.isArray(errorContext.tags)) { + ctx.tags = errorContext.tags; } - return dropUndefinedKeys(structuredContext); + return ctx; } /** diff --git a/packages/nuxt/src/vite/sourceMaps.ts b/packages/nuxt/src/vite/sourceMaps.ts index 4f1e1184e637..1372db47889e 100644 --- a/packages/nuxt/src/vite/sourceMaps.ts +++ b/packages/nuxt/src/vite/sourceMaps.ts @@ -142,7 +142,6 @@ export function changeNuxtSourceMapSettings( nuxt: Nuxt, sentryModuleOptions: SentryNuxtModuleOptions, ): { client: UserSourceMapSetting; server: UserSourceMapSetting } { - nuxt.options = nuxt.options || {}; nuxt.options.sourcemap = nuxt.options.sourcemap ?? { server: undefined, client: undefined }; let previousUserSourceMapSetting: { client: UserSourceMapSetting; server: UserSourceMapSetting } = { diff --git a/packages/nuxt/tsconfig.test.json b/packages/nuxt/tsconfig.test.json index 3fbe012384ee..c41efeacd92f 100644 --- a/packages/nuxt/tsconfig.test.json +++ b/packages/nuxt/tsconfig.test.json @@ -5,6 +5,6 @@ "compilerOptions": { // should include all types from `./tsconfig.json` plus types for all test frameworks used - "types": ["node", "vitest/globals"] + "types": ["node"] } } diff --git a/packages/opentelemetry/src/sampler.ts b/packages/opentelemetry/src/sampler.ts index 9c9889e2d2fa..20a04f9cc9e7 100644 --- a/packages/opentelemetry/src/sampler.ts +++ b/packages/opentelemetry/src/sampler.ts @@ -67,6 +67,17 @@ export class SentrySampler implements Sampler { } const parentSampled = parentSpan ? getParentSampled(parentSpan, traceId, spanName) : undefined; + const isRootSpan = !parentSpan || parentContext?.isRemote; + + // We only sample based on parameters (like tracesSampleRate or tracesSampler) for root spans (which is done in sampleSpan). + // Non-root-spans simply inherit the sampling decision from their parent. + if (!isRootSpan) { + return wrapSamplingDecision({ + decision: parentSampled ? SamplingDecision.RECORD_AND_SAMPLED : SamplingDecision.NOT_RECORD, + context, + spanAttributes, + }); + } // We want to pass the inferred name & attributes to the sampler method const { @@ -99,76 +110,60 @@ export class SentrySampler implements Sampler { return wrapSamplingDecision({ decision: undefined, context, spanAttributes }); } - const isRootSpan = !parentSpan || parentContext?.isRemote; + const { isolationScope } = getScopesFromContext(context) ?? {}; - // We only sample based on parameters (like tracesSampleRate or tracesSampler) for root spans (which is done in sampleSpan). - // Non-root-spans simply inherit the sampling decision from their parent. - if (isRootSpan) { - const { isolationScope } = getScopesFromContext(context) ?? {}; - - const dscString = parentContext?.traceState ? parentContext.traceState.get(SENTRY_TRACE_STATE_DSC) : undefined; - const dsc = dscString ? baggageHeaderToDynamicSamplingContext(dscString) : undefined; - - const sampleRand = parseSampleRate(dsc?.sample_rand) ?? Math.random(); - - const [sampled, sampleRate, localSampleRateWasApplied] = sampleSpan( - options, - { - name: inferredSpanName, - attributes: mergedAttributes, - normalizedRequest: isolationScope?.getScopeData().sdkProcessingMetadata.normalizedRequest, - parentSampled, - parentSampleRate: parseSampleRate(dsc?.sample_rate), - }, + const dscString = parentContext?.traceState ? parentContext.traceState.get(SENTRY_TRACE_STATE_DSC) : undefined; + const dsc = dscString ? baggageHeaderToDynamicSamplingContext(dscString) : undefined; + + const sampleRand = parseSampleRate(dsc?.sample_rand) ?? Math.random(); + + const [sampled, sampleRate, localSampleRateWasApplied] = sampleSpan( + options, + { + name: inferredSpanName, + attributes: mergedAttributes, + normalizedRequest: isolationScope?.getScopeData().sdkProcessingMetadata.normalizedRequest, + parentSampled, + parentSampleRate: parseSampleRate(dsc?.sample_rate), + }, + sampleRand, + ); + + const method = `${maybeSpanHttpMethod}`.toUpperCase(); + if (method === 'OPTIONS' || method === 'HEAD') { + DEBUG_BUILD && logger.log(`[Tracing] Not sampling span because HTTP method is '${method}' for ${spanName}`); + + return wrapSamplingDecision({ + decision: SamplingDecision.NOT_RECORD, + context, + spanAttributes, sampleRand, - ); - - const method = `${maybeSpanHttpMethod}`.toUpperCase(); - if (method === 'OPTIONS' || method === 'HEAD') { - DEBUG_BUILD && logger.log(`[Tracing] Not sampling span because HTTP method is '${method}' for ${spanName}`); - - return { - ...wrapSamplingDecision({ - decision: SamplingDecision.NOT_RECORD, - context, - spanAttributes, - sampleRand, - downstreamTraceSampleRate: 0, // we don't want to sample anything in the downstream trace either - }), - }; - } - - if ( - !sampled && - // We check for `parentSampled === undefined` because we only want to record client reports for spans that are trace roots (ie. when there was incoming trace) - parentSampled === undefined - ) { - DEBUG_BUILD && logger.log('[Tracing] Discarding root span because its trace was not chosen to be sampled.'); - this._client.recordDroppedEvent('sample_rate', 'transaction'); - } - - return { - ...wrapSamplingDecision({ - decision: sampled ? SamplingDecision.RECORD_AND_SAMPLED : SamplingDecision.NOT_RECORD, - context, - spanAttributes, - sampleRand, - downstreamTraceSampleRate: localSampleRateWasApplied ? sampleRate : undefined, - }), - attributes: { - // We set the sample rate on the span when a local sample rate was applied to better understand how traces were sampled in Sentry - [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: localSampleRateWasApplied ? sampleRate : undefined, - }, - }; - } else { - return { - ...wrapSamplingDecision({ - decision: parentSampled ? SamplingDecision.RECORD_AND_SAMPLED : SamplingDecision.NOT_RECORD, - context, - spanAttributes, - }), - }; + downstreamTraceSampleRate: 0, // we don't want to sample anything in the downstream trace either + }); + } + + if ( + !sampled && + // We check for `parentSampled === undefined` because we only want to record client reports for spans that are trace roots (ie. when there was incoming trace) + parentSampled === undefined + ) { + DEBUG_BUILD && logger.log('[Tracing] Discarding root span because its trace was not chosen to be sampled.'); + this._client.recordDroppedEvent('sample_rate', 'transaction'); } + + return { + ...wrapSamplingDecision({ + decision: sampled ? SamplingDecision.RECORD_AND_SAMPLED : SamplingDecision.NOT_RECORD, + context, + spanAttributes, + sampleRand, + downstreamTraceSampleRate: localSampleRateWasApplied ? sampleRate : undefined, + }), + attributes: { + // We set the sample rate on the span when a local sample rate was applied to better understand how traces were sampled in Sentry + [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: localSampleRateWasApplied ? sampleRate : undefined, + }, + }; } /** Returns the sampler name or short description with the configuration. */ diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index e095ab60e805..90a3d890a959 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -19,7 +19,6 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, captureEvent, - dropUndefinedKeys, getCapturedScopesOnSpan, getDynamicSamplingContextFromSpan, getStatusMessage, @@ -274,7 +273,7 @@ export function createTransactionForOtelSpan(span: ReadableSpan): TransactionEve const statusCode = attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]; const responseContext = typeof statusCode === 'number' ? { response: { status_code: statusCode } } : undefined; - const transactionEvent: TransactionEvent = dropUndefinedKeys({ + const transactionEvent: TransactionEvent = { contexts: { trace: traceContext, otel: { @@ -298,7 +297,7 @@ export function createTransactionForOtelSpan(span: ReadableSpan): TransactionEve source, }, }), - }); + }; return transactionEvent; } @@ -335,7 +334,7 @@ function createAndFinishSpanForOtelSpan(node: SpanNode, spans: SpanJSON[], sentS const status = mapStatus(span); - const spanJSON: SpanJSON = dropUndefinedKeys({ + const spanJSON: SpanJSON = { span_id, trace_id, data: allData, @@ -349,7 +348,7 @@ function createAndFinishSpanForOtelSpan(node: SpanNode, spans: SpanJSON[], sentS origin, measurements: timedEventsToMeasurements(span.events), links: convertSpanLinksForEnvelope(links), - }); + }; spans.push(spanJSON); diff --git a/packages/opentelemetry/test/utils/mapStatus.test.ts b/packages/opentelemetry/test/utils/mapStatus.test.ts index aa72cfb95b53..a6b5db847652 100644 --- a/packages/opentelemetry/test/utils/mapStatus.test.ts +++ b/packages/opentelemetry/test/utils/mapStatus.test.ts @@ -81,7 +81,7 @@ describe('mapStatus', () => { expect(actual).toEqual(expected); }); - it('works with string SEMATTRS_HTTP_STATUS_CODE xxx', () => { + it('works with string SEMATTRS_HTTP_STATUS_CODE', () => { const span = createSpan('test-span'); span.setStatus({ code: 0 }); // UNSET diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 801c888aaef4..cb31ab4cb32b 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -38,7 +38,7 @@ "@sentry/cli": "^2.42.3", "@sentry/core": "9.9.0", "@sentry/node": "9.9.0", - "@sentry/vite-plugin": "^3.2.0", + "@sentry/vite-plugin": "^3.2.3", "glob": "11.0.1" }, "devDependencies": { diff --git a/packages/react-router/src/index.types.ts b/packages/react-router/src/index.types.ts index 4d7fb425f5ee..cf62bf717794 100644 --- a/packages/react-router/src/index.types.ts +++ b/packages/react-router/src/index.types.ts @@ -15,3 +15,5 @@ export declare const contextLinesIntegration: typeof clientSdk.contextLinesInteg export declare const linkedErrorsIntegration: typeof clientSdk.linkedErrorsIntegration; export declare const defaultStackParser: StackParser; export declare const getDefaultIntegrations: (options: Options) => Integration[]; + +export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger; diff --git a/packages/react-router/tsconfig.test.json b/packages/react-router/tsconfig.test.json index b3625cd0bd3f..65d74ebb843a 100644 --- a/packages/react-router/tsconfig.test.json +++ b/packages/react-router/tsconfig.test.json @@ -4,6 +4,6 @@ "include": ["test/**/*", "vite.config.ts"], "compilerOptions": { - "types": ["node", "vitest/globals"], + "types": ["node"], } } diff --git a/packages/remix/src/index.types.ts b/packages/remix/src/index.types.ts index 763a2747f69e..2d1ae40da8e5 100644 --- a/packages/remix/src/index.types.ts +++ b/packages/remix/src/index.types.ts @@ -21,6 +21,8 @@ export declare const defaultStackParser: StackParser; export declare function captureRemixServerException(err: unknown, name: string, request: Request): Promise; +export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger; + // This variable is not a runtime variable but just a type to tell typescript that the methods below can either come // from the client SDK or from the server SDK. TypeScript is smart enough to understand that these resolve to the same // methods from `@sentry/core`. diff --git a/packages/remix/src/server/index.ts b/packages/remix/src/server/index.ts index 4160a871d165..7809455ce3fa 100644 --- a/packages/remix/src/server/index.ts +++ b/packages/remix/src/server/index.ts @@ -112,6 +112,7 @@ export { withMonitor, withScope, zodErrorsIntegration, + logger, } from '@sentry/node'; // Keeping the `*` exports for backwards compatibility and types diff --git a/packages/remix/test/integration/tsconfig.test.json b/packages/remix/test/integration/tsconfig.test.json index 8ce7525d33fd..0bb16039ac48 100644 --- a/packages/remix/test/integration/tsconfig.test.json +++ b/packages/remix/test/integration/tsconfig.test.json @@ -4,6 +4,6 @@ "include": ["test/**/*"], "compilerOptions": { - "types": ["node", "vitest/globals"] + "types": ["node"] } } diff --git a/packages/replay-canvas/package.json b/packages/replay-canvas/package.json index 261842a70f32..a65c2a2c2bfb 100644 --- a/packages/replay-canvas/package.json +++ b/packages/replay-canvas/package.json @@ -65,7 +65,7 @@ }, "homepage": "https://docs.sentry.io/platforms/javascript/session-replay/", "devDependencies": { - "@sentry-internal/rrweb": "2.34.0" + "@sentry-internal/rrweb": "2.35.0" }, "dependencies": { "@sentry-internal/replay": "9.9.0", diff --git a/packages/replay-internal/package.json b/packages/replay-internal/package.json index 44b7974c8942..aabcaf3c9dde 100644 --- a/packages/replay-internal/package.json +++ b/packages/replay-internal/package.json @@ -71,8 +71,8 @@ "devDependencies": { "@babel/core": "^7.17.5", "@sentry-internal/replay-worker": "9.9.0", - "@sentry-internal/rrweb": "2.34.0", - "@sentry-internal/rrweb-snapshot": "2.34.0", + "@sentry-internal/rrweb": "2.35.0", + "@sentry-internal/rrweb-snapshot": "2.35.0", "fflate": "0.8.2", "jest-matcher-utils": "^29.0.0", "jsdom-worker": "^0.2.1" diff --git a/packages/replay-internal/src/integration.ts b/packages/replay-internal/src/integration.ts index 4ec1a357eac4..bc916ba591a8 100644 --- a/packages/replay-internal/src/integration.ts +++ b/packages/replay-internal/src/integration.ts @@ -1,5 +1,5 @@ import type { BrowserClientReplayOptions, Client, Integration, IntegrationFn, ReplayRecordingMode } from '@sentry/core'; -import { consoleSandbox, dropUndefinedKeys, isBrowser, parseSampleRate } from '@sentry/core'; +import { consoleSandbox, isBrowser, parseSampleRate } from '@sentry/core'; import { DEFAULT_FLUSH_MAX_DELAY, DEFAULT_FLUSH_MIN_DELAY, @@ -356,7 +356,7 @@ function loadReplayOptionsFromClient(initialOptions: InitialReplayPluginOptions, const finalOptions: ReplayPluginOptions = { sessionSampleRate: 0, errorSampleRate: 0, - ...dropUndefinedKeys(initialOptions), + ...initialOptions, }; const replaysSessionSampleRate = parseSampleRate(opt.replaysSessionSampleRate); diff --git a/packages/solidstart/src/index.types.ts b/packages/solidstart/src/index.types.ts index 54a5ec6d6a3c..d243bd371241 100644 --- a/packages/solidstart/src/index.types.ts +++ b/packages/solidstart/src/index.types.ts @@ -22,3 +22,5 @@ export declare const defaultStackParser: StackParser; export declare function close(timeout?: number | undefined): PromiseLike; export declare function flush(timeout?: number | undefined): PromiseLike; export declare function lastEventId(): string | undefined; + +export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger; diff --git a/packages/solidstart/src/server/index.ts b/packages/solidstart/src/server/index.ts index 948c3c746d0c..a36b7fbfaad1 100644 --- a/packages/solidstart/src/server/index.ts +++ b/packages/solidstart/src/server/index.ts @@ -115,6 +115,7 @@ export { withMonitor, withScope, zodErrorsIntegration, + logger, } from '@sentry/node'; // We can still leave this for the carrier init and type exports diff --git a/packages/solidstart/tsconfig.test.json b/packages/solidstart/tsconfig.test.json index 51c6c9c9b8ea..62b0f6844441 100644 --- a/packages/solidstart/tsconfig.test.json +++ b/packages/solidstart/tsconfig.test.json @@ -5,7 +5,7 @@ "compilerOptions": { // should include all types from `./tsconfig.json` plus types for all test frameworks used - "types": ["node", "vitest/globals", "vite/client", "@testing-library/jest-dom"], + "types": ["node", "@testing-library/jest-dom"], // other package-specific, test-specific options "jsx": "preserve", diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json index 9e145941bcbf..1cb03303ff49 100644 --- a/packages/sveltekit/package.json +++ b/packages/sveltekit/package.json @@ -50,7 +50,7 @@ "@sentry/node": "9.9.0", "@sentry/opentelemetry": "9.9.0", "@sentry/svelte": "9.9.0", - "@sentry/vite-plugin": "3.2.0", + "@sentry/vite-plugin": "3.2.3", "magic-string": "0.30.7", "recast": "0.23.11", "sorcery": "1.0.0" diff --git a/packages/sveltekit/src/index.types.ts b/packages/sveltekit/src/index.types.ts index bf2edbfb0a0f..161e7098de11 100644 --- a/packages/sveltekit/src/index.types.ts +++ b/packages/sveltekit/src/index.types.ts @@ -53,3 +53,5 @@ export declare function flush(timeout?: number | undefined): PromiseLike; + +export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger; diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts index f8844c1e264d..9df3ddd688c8 100644 --- a/packages/sveltekit/src/server/index.ts +++ b/packages/sveltekit/src/server/index.ts @@ -117,6 +117,7 @@ export { withMonitor, withScope, zodErrorsIntegration, + logger, } from '@sentry/node'; // We can still leave this for the carrier init and type exports diff --git a/packages/sveltekit/src/vite/sentryVitePlugins.ts b/packages/sveltekit/src/vite/sentryVitePlugins.ts index 60258f653400..4444ba9a6ab7 100644 --- a/packages/sveltekit/src/vite/sentryVitePlugins.ts +++ b/packages/sveltekit/src/vite/sentryVitePlugins.ts @@ -1,4 +1,3 @@ -import { dropUndefinedKeys } from '@sentry/core'; import type { Plugin } from 'vite'; import type { AutoInstrumentSelection } from './autoInstrument'; import { makeAutoInstrumentationPlugin } from './autoInstrument'; @@ -104,5 +103,5 @@ export function generateVitePluginOptions( } } - return dropUndefinedKeys(sentryVitePluginsOptions); + return sentryVitePluginsOptions; } diff --git a/packages/tanstackstart-react/src/index.types.ts b/packages/tanstackstart-react/src/index.types.ts index 84a987788d17..0e3bbca37bf9 100644 --- a/packages/tanstackstart-react/src/index.types.ts +++ b/packages/tanstackstart-react/src/index.types.ts @@ -25,3 +25,5 @@ export declare const ErrorBoundary: typeof clientSdk.ErrorBoundary; export declare const createReduxEnhancer: typeof clientSdk.createReduxEnhancer; export declare const showReportDialog: typeof clientSdk.showReportDialog; export declare const withErrorBoundary: typeof clientSdk.withErrorBoundary; + +export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger; diff --git a/packages/vercel-edge/src/transports/index.ts b/packages/vercel-edge/src/transports/index.ts index e938477b3003..e1ce24c501c7 100644 --- a/packages/vercel-edge/src/transports/index.ts +++ b/packages/vercel-edge/src/transports/index.ts @@ -1,5 +1,5 @@ import type { BaseTransportOptions, Transport, TransportMakeRequestResponse, TransportRequest } from '@sentry/core'; -import { SentryError, createTransport, suppressTracing } from '@sentry/core'; +import { SENTRY_BUFFER_FULL_ERROR, createTransport, suppressTracing } from '@sentry/core'; export interface VercelEdgeTransportOptions extends BaseTransportOptions { /** Fetch API init parameters. */ @@ -38,7 +38,7 @@ export class IsolatedPromiseBuffer { */ public add(taskProducer: () => PromiseLike): PromiseLike { if (this._taskProducers.length >= this._bufferSize) { - return Promise.reject(new SentryError('Not adding Promise because buffer limit was reached.')); + return Promise.reject(SENTRY_BUFFER_FULL_ERROR); } this._taskProducers.push(taskProducer); diff --git a/packages/vercel-edge/test/transports/index.test.ts b/packages/vercel-edge/test/transports/index.test.ts index 4434a177d0f8..a7e6bd342fb5 100644 --- a/packages/vercel-edge/test/transports/index.test.ts +++ b/packages/vercel-edge/test/transports/index.test.ts @@ -1,6 +1,6 @@ import { afterAll, describe, expect, it, vi } from 'vitest'; -import { createEnvelope, serializeEnvelope } from '@sentry/core'; +import { SENTRY_BUFFER_FULL_ERROR, createEnvelope, serializeEnvelope } from '@sentry/core'; import type { EventEnvelope, EventItem } from '@sentry/core'; import type { VercelEdgeTransportOptions } from '../../src/transports'; @@ -139,7 +139,12 @@ describe('IsolatedPromiseBuffer', () => { await ipb.add(task2); await ipb.add(task3); - await expect(ipb.add(task4)).rejects.toThrowError('Not adding Promise because buffer limit was reached.'); + try { + await ipb.add(task4); + throw new Error('Should not be called'); + } catch (error) { + expect(error).toBe(SENTRY_BUFFER_FULL_ERROR); + } }); it('should not throw when one of the tasks throws when drained', async () => { diff --git a/tsconfig-templates/tsconfig.test.json b/tsconfig-templates/tsconfig.test.json index af7e36ec0eda..1141567cdfec 100644 --- a/tsconfig-templates/tsconfig.test.json +++ b/tsconfig-templates/tsconfig.test.json @@ -5,7 +5,7 @@ "compilerOptions": { // should include all types from `./tsconfig.json` plus types for all test frameworks used - "types": ["jest"] + "types": [] // other package-specific, test-specific options } diff --git a/tsconfig.dev.json b/tsconfig.dev.json index 8fa9976f16af..a5728ba2f184 100644 --- a/tsconfig.dev.json +++ b/tsconfig.dev.json @@ -2,9 +2,9 @@ { "extends": "./tsconfig.json", - "include": ["**/scripts/**/*.ts", "jest/**/*.ts", "vite/**/*.ts"], + "include": ["**/scripts/**/*.ts", "vite/**/*.ts"], "compilerOptions": { - "types": ["node", "jest", "vitest/globals"] + "types": ["node"] } } diff --git a/yarn.lock b/yarn.lock index 73b52e4425eb..521c455d0e64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -84,10 +84,10 @@ debug "^4.3.4" safe-buffer "~5.1.2" -"@adobe/css-tools@^4.0.1", "@adobe/css-tools@^4.3.2": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63" - integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ== +"@adobe/css-tools@^4.0.1", "@adobe/css-tools@^4.4.0": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.2.tgz#c836b1bd81e6d62cd6cdf3ee4948bcdce8ea79c8" + integrity sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A== "@ai-sdk/provider-utils@2.0.2": version "2.0.2" @@ -1282,7 +1282,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.4", "@babel/compat-data@^7.26.5": +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.4", "@babel/compat-data@^7.26.8": version "7.26.8" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== @@ -1308,7 +1308,7 @@ json5 "^2.2.1" semver "^6.3.0" -"@babel/core@^7.1.0", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.16.10", "@babel/core@^7.16.7", "@babel/core@^7.17.2", "@babel/core@^7.17.5", "@babel/core@^7.18.5", "@babel/core@^7.21.0", "@babel/core@^7.21.8", "@babel/core@^7.22.10", "@babel/core@^7.23.0", "@babel/core@^7.23.3", "@babel/core@^7.23.7", "@babel/core@^7.24.4", "@babel/core@^7.24.7", "@babel/core@^7.3.4", "@babel/core@^7.7.2", "@babel/core@^7.8.0": +"@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.16.10", "@babel/core@^7.16.7", "@babel/core@^7.17.2", "@babel/core@^7.17.5", "@babel/core@^7.18.5", "@babel/core@^7.21.0", "@babel/core@^7.21.8", "@babel/core@^7.22.10", "@babel/core@^7.23.0", "@babel/core@^7.23.3", "@babel/core@^7.23.7", "@babel/core@^7.24.4", "@babel/core@^7.24.7", "@babel/core@^7.3.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== @@ -1338,7 +1338,7 @@ "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" -"@babel/generator@^7.18.10", "@babel/generator@^7.21.5", "@babel/generator@^7.22.10", "@babel/generator@^7.23.6", "@babel/generator@^7.26.9", "@babel/generator@^7.7.2": +"@babel/generator@^7.18.10", "@babel/generator@^7.21.5", "@babel/generator@^7.22.10", "@babel/generator@^7.23.6", "@babel/generator@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== @@ -1371,11 +1371,11 @@ "@babel/types" "^7.22.15" "@babel/helper-compilation-targets@^7.12.0", "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6", "@babel/helper-compilation-targets@^7.26.5": - version "7.26.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" - integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz#de0c753b1cd1d9ab55d473c5a5cf7170f0a81880" + integrity sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA== dependencies: - "@babel/compat-data" "^7.26.5" + "@babel/compat-data" "^7.26.8" "@babel/helper-validator-option" "^7.25.9" browserslist "^4.24.0" lru-cache "^5.1.1" @@ -1557,12 +1557,12 @@ "@babel/types" "^7.22.19" "@babel/helpers@^7.18.9", "@babel/helpers@^7.26.9": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" - integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.0.tgz#53d156098defa8243eab0f32fa17589075a1b808" + integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg== dependencies: - "@babel/template" "^7.26.9" - "@babel/types" "^7.26.9" + "@babel/template" "^7.27.0" + "@babel/types" "^7.27.0" "@babel/highlight@^7.10.4": version "7.24.7" @@ -1574,13 +1574,20 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@7.26.9", "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.4", "@babel/parser@^7.18.10", "@babel/parser@^7.20.7", "@babel/parser@^7.21.8", "@babel/parser@^7.22.10", "@babel/parser@^7.22.16", "@babel/parser@^7.23.5", "@babel/parser@^7.23.6", "@babel/parser@^7.23.9", "@babel/parser@^7.25.3", "@babel/parser@^7.25.4", "@babel/parser@^7.25.6", "@babel/parser@^7.26.9", "@babel/parser@^7.4.5", "@babel/parser@^7.7.0": +"@babel/parser@7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== dependencies: "@babel/types" "^7.26.9" +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.4", "@babel/parser@^7.18.10", "@babel/parser@^7.20.7", "@babel/parser@^7.21.8", "@babel/parser@^7.22.10", "@babel/parser@^7.22.16", "@babel/parser@^7.23.5", "@babel/parser@^7.23.6", "@babel/parser@^7.23.9", "@babel/parser@^7.25.3", "@babel/parser@^7.25.4", "@babel/parser@^7.25.6", "@babel/parser@^7.26.9", "@babel/parser@^7.27.0", "@babel/parser@^7.4.5", "@babel/parser@^7.7.0": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec" + integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== + dependencies: + "@babel/types" "^7.27.0" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.4": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz#6125f0158543fb4edf1c22f322f3db67f21cb3e1" @@ -1773,14 +1780,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== @@ -1829,7 +1829,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -1850,7 +1850,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -1864,7 +1864,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -1899,14 +1899,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.2.0", "@babel/plugin-syntax-typescript@^7.25.9", "@babel/plugin-syntax-typescript@^7.7.2": +"@babel/plugin-syntax-typescript@^7.2.0", "@babel/plugin-syntax-typescript@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== @@ -2593,7 +2593,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.8.4": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== @@ -2614,16 +2614,16 @@ "@babel/parser" "^7.18.10" "@babel/types" "^7.18.10" -"@babel/template@^7.18.10", "@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.24.0", "@babel/template@^7.24.7", "@babel/template@^7.26.9", "@babel/template@^7.3.3": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" - integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== +"@babel/template@^7.18.10", "@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.24.0", "@babel/template@^7.24.7", "@babel/template@^7.26.9", "@babel/template@^7.27.0": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4" + integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== dependencies: "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.26.9" - "@babel/types" "^7.26.9" + "@babel/parser" "^7.27.0" + "@babel/types" "^7.27.0" -"@babel/traverse@^7.18.10", "@babel/traverse@^7.22.10", "@babel/traverse@^7.23.2", "@babel/traverse@^7.23.7", "@babel/traverse@^7.23.9", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.9", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": +"@babel/traverse@^7.18.10", "@babel/traverse@^7.22.10", "@babel/traverse@^7.23.2", "@babel/traverse@^7.23.7", "@babel/traverse@^7.23.9", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.9", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== @@ -2636,10 +2636,10 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.22.10", "@babel/types@^7.22.15", "@babel/types@^7.22.17", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.24.7", "@babel/types@^7.25.4", "@babel/types@^7.25.6", "@babel/types@^7.25.9", "@babel/types@^7.26.3", "@babel/types@^7.26.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.2": - version "7.26.9" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" - integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== +"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.22.10", "@babel/types@^7.22.15", "@babel/types@^7.22.17", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.24.7", "@babel/types@^7.25.4", "@babel/types@^7.25.6", "@babel/types@^7.25.9", "@babel/types@^7.26.3", "@babel/types@^7.26.9", "@babel/types@^7.27.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.7.2": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559" + integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== dependencies: "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" @@ -3889,7 +3889,7 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b" integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg== -"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== @@ -4065,16 +4065,6 @@ retry-request "^4.1.1" teeny-request "^7.0.0" -"@google-cloud/functions-framework@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@google-cloud/functions-framework/-/functions-framework-1.7.1.tgz#d29a27744a6eb2f95d840b86135b97b0d804a49e" - integrity sha512-jjG7nH94Thij97EPW2oQN28pVPRN3UEGcsCRi6RdaaiSyK32X40LN4WHntKVmQPBhqH+I0magHMk1pSb0McH2g== - dependencies: - body-parser "^1.18.3" - express "^4.16.4" - minimist "^1.2.0" - on-finished "^2.3.0" - "@google-cloud/paginator@^3.0.0": version "3.0.5" resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.5.tgz#9d6b96c421a89bd560c1bc2c197c7611ef21db6c" @@ -4083,11 +4073,6 @@ arrify "^2.0.0" extend "^3.0.2" -"@google-cloud/precise-date@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@google-cloud/precise-date/-/precise-date-2.0.3.tgz#14f6f28ce35dabf3882e7aeab1c9d51bd473faed" - integrity sha512-+SDJ3ZvGkF7hzo6BGa8ZqeK3F6Z4+S+KviC9oOK+XCs3tfMyJCh/4j93XIWINgMMDIh9BgEvlw4306VxlXIlYA== - "@google-cloud/projectify@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-2.0.1.tgz#13350ee609346435c795bbfe133a08dfeab78d65" @@ -4098,27 +4083,6 @@ resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-2.0.3.tgz#f934b5cdc939e3c7039ff62b9caaf59a9d89e3a8" integrity sha512-d4VSA86eL/AFTe5xtyZX+ePUjE8dIFu2T8zmdeNBSa5/kNgXPCx/o/wbFNHAGLJdGnk1vddRuMESD9HbOC8irw== -"@google-cloud/pubsub@^2.5.0": - version "2.10.0" - resolved "https://registry.yarnpkg.com/@google-cloud/pubsub/-/pubsub-2.10.0.tgz#5fbfa59c91b15e880bd0258b907d8f52e0509074" - integrity sha512-XM/Fc6/W/LYzGH2pnhGLDR5E6JNZFMfzyUFP5bWgC4FK1KqIZ4g6hrnCCO38G4JfH2i1IuSQuefPF7FrZZo9tw== - dependencies: - "@google-cloud/paginator" "^3.0.0" - "@google-cloud/precise-date" "^2.0.0" - "@google-cloud/projectify" "^2.0.0" - "@google-cloud/promisify" "^2.0.0" - "@opentelemetry/api" "^0.12.0" - "@opentelemetry/tracing" "^0.12.0" - "@types/duplexify" "^3.6.0" - "@types/long" "^4.0.0" - arrify "^2.0.0" - extend "^3.0.2" - google-auth-library "^7.0.0" - google-gax "^2.9.2" - is-stream-ended "^0.1.4" - lodash.snakecase "^4.1.1" - p-defer "^3.0.0" - "@graphql-tools/merge@8.3.1": version "8.3.1" resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.3.1.tgz#06121942ad28982a14635dbc87b5d488a041d722" @@ -4179,23 +4143,6 @@ dependencies: tslib "^2.4.0" -"@grpc/grpc-js@~1.2.0": - version "1.2.12" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.2.12.tgz#0153f27512acf69184bb52c0a1035ca91d6c14b0" - integrity sha512-+gPCklP1eqIgrNPyzddYQdt9+GvZqPlLpIjIo+TveE+gbtp74VV1A2ju8ExeO8ma8f7MbpaGZx/KJPYVWL9eDw== - dependencies: - "@types/node" ">=12.12.47" - google-auth-library "^6.1.1" - semver "^6.2.0" - -"@grpc/proto-loader@^0.5.1": - version "0.5.6" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.6.tgz#1dea4b8a6412b05e2d58514d507137b63a52a98d" - integrity sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ== - dependencies: - lodash.camelcase "^4.3.0" - protobufjs "^6.8.6" - "@handlebars/parser@~2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@handlebars/parser/-/parser-2.0.0.tgz#5e8b7298f31ff8f7b260e6b7363c7e9ceed7d9c5" @@ -4503,114 +4450,6 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba" - integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg== - dependencies: - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^27.5.1" - jest-util "^27.5.1" - slash "^3.0.0" - -"@jest/core@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626" - integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ== - dependencies: - "@jest/console" "^27.5.1" - "@jest/reporters" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.8.1" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^27.5.1" - jest-config "^27.5.1" - jest-haste-map "^27.5.1" - jest-message-util "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-resolve-dependencies "^27.5.1" - jest-runner "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" - jest-watcher "^27.5.1" - micromatch "^4.0.4" - rimraf "^3.0.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74" - integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== - dependencies: - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - jest-mock "^27.5.1" - -"@jest/fake-timers@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74" - integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== - dependencies: - "@jest/types" "^27.5.1" - "@sinonjs/fake-timers" "^8.0.1" - "@types/node" "*" - jest-message-util "^27.5.1" - jest-mock "^27.5.1" - jest-util "^27.5.1" - -"@jest/globals@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b" - integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/types" "^27.5.1" - expect "^27.5.1" - -"@jest/reporters@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04" - integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-haste-map "^27.5.1" - jest-resolve "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" - slash "^3.0.0" - source-map "^0.6.0" - string-length "^4.0.1" - terminal-link "^2.0.0" - v8-to-istanbul "^8.1.0" - "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -4618,67 +4457,6 @@ dependencies: "@sinclair/typebox" "^0.27.8" -"@jest/source-map@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf" - integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg== - dependencies: - callsites "^3.0.0" - graceful-fs "^4.2.9" - source-map "^0.6.0" - -"@jest/test-result@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb" - integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag== - dependencies: - "@jest/console" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b" - integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ== - dependencies: - "@jest/test-result" "^27.5.1" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-runtime "^27.5.1" - -"@jest/transform@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409" - integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw== - dependencies: - "@babel/core" "^7.1.0" - "@jest/types" "^27.5.1" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^1.4.0" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-regex-util "^27.5.1" - jest-util "^27.5.1" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - source-map "^0.6.1" - write-file-atomic "^3.0.0" - -"@jest/types@^27.5.1": - version "27.5.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" - integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^16.0.0" - chalk "^4.0.0" - "@josephg/resolvable@^1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/@josephg/resolvable/-/resolvable-1.0.1.tgz#69bc4db754d79e1a2f17a650d3466e038d94a5eb" @@ -5661,23 +5439,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== -"@opentelemetry/api@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-0.12.0.tgz#0359c3926e8f16fdcd8c78f196bd1e9fc4e66777" - integrity sha512-Dn4vU5GlaBrIWzLpsM6xbJwKHdlpwBQ4Bd+cL9ofJP3hKT8jBXpBpribmyaqAzrajzzl2Yt8uTa9rFVLfjDAvw== - dependencies: - "@opentelemetry/context-base" "^0.12.0" - "@opentelemetry/context-async-hooks@^1.30.1": version "1.30.1" resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz#4f76280691a742597fd0bf682982126857622948" integrity sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA== -"@opentelemetry/context-base@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.12.0.tgz#4906ae27359d3311e3dea1b63770a16f60848550" - integrity sha512-UXwSsXo3F3yZ1dIBOG9ID8v2r9e+bqLWoizCtTb8rXtwF+N5TM7hzzvQz72o3nBU+zrI/D5e+OqAYK8ZgDd3DA== - "@opentelemetry/core@1.30.1", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.26.0", "@opentelemetry/core@^1.30.1", "@opentelemetry/core@^1.8.0": version "1.30.1" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.30.1.tgz#a0b468bb396358df801881709ea38299fc30ab27" @@ -5685,15 +5451,6 @@ dependencies: "@opentelemetry/semantic-conventions" "1.28.0" -"@opentelemetry/core@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-0.12.0.tgz#a888badc9a408fa1f13976a574e69d14be32488e" - integrity sha512-oLZIkmTNWTJXzo1eA4dGu/S7wOVtylsgnEsCmhSJGhrJVDXm1eW/aGuNs3DVBeuxp0ZvQLAul3/PThsC3YrnzA== - dependencies: - "@opentelemetry/api" "^0.12.0" - "@opentelemetry/context-base" "^0.12.0" - semver "^7.1.3" - "@opentelemetry/instrumentation-amqplib@^0.46.1": version "0.46.1" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.1.tgz#7101678488d0e942162ca85c9ac6e93e1f3e0008" @@ -5963,14 +5720,6 @@ "@opentelemetry/core" "1.30.1" "@opentelemetry/semantic-conventions" "1.28.0" -"@opentelemetry/resources@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-0.12.0.tgz#5eb287c3032a2bebb2bb9f69b44bd160d2a7d591" - integrity sha512-8cYvIKB68cyupc7D6SWzkLtt13mbjgxMahL4JKCM6hWPyiGSJlPFEAey4XFXI5LLpPZRYTPHLVoLqI/xwCFZZA== - dependencies: - "@opentelemetry/api" "^0.12.0" - "@opentelemetry/core" "^0.12.0" - "@opentelemetry/sdk-trace-base@^1.30.1": version "1.30.1" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz#41a42234096dc98e8f454d24551fc80b816feb34" @@ -5985,11 +5734,6 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz#337fb2bca0453d0726696e745f50064411f646d6" integrity sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA== -"@opentelemetry/semantic-conventions@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-0.12.0.tgz#7e392aecdbdbd5d737d3995998b120dc17589ab0" - integrity sha512-BuCcDW0uLNYYTns0/LwXkJ8lp8aDm7kpS+WunEmPAPRSCe6ciOYRvzn5reqJfX93rf+6A3U2SgrBnCTH+0qoQQ== - "@opentelemetry/semantic-conventions@^1.25.1", "@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.28.0", "@opentelemetry/semantic-conventions@^1.30.0": version "1.30.0" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.30.0.tgz#3a42c4c475482f2ec87c12aad98832dc0087dc9a" @@ -6002,17 +5746,6 @@ dependencies: "@opentelemetry/core" "^1.1.0" -"@opentelemetry/tracing@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/tracing/-/tracing-0.12.0.tgz#769927721d417bfac85eef50c2af068bedce8873" - integrity sha512-2TUGhTGkhgnxTciHCNAILPSeyXageJewRqfP9wOrx65sKd/jgvNYoY8nYf4EVWVMirDOxKDsmYgUkjdQrwb2dg== - dependencies: - "@opentelemetry/api" "^0.12.0" - "@opentelemetry/context-base" "^0.12.0" - "@opentelemetry/core" "^0.12.0" - "@opentelemetry/resources" "^0.12.0" - "@opentelemetry/semantic-conventions" "^0.12.0" - "@parcel/watcher-android-arm64@2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz#e32d3dda6647791ee930556aee206fcd5ea0fb7a" @@ -6660,11 +6393,23 @@ dependencies: "@sentry-internal/rrweb-snapshot" "2.34.0" +"@sentry-internal/rrdom@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrdom/-/rrdom-2.35.0.tgz#27dbdfe3249afb65a31f3b680cd0cc92ed2001dd" + integrity sha512-sWZjJpv7/Fu1po5ibzGUojWLMGn/GgqsayE8dqbwI6F2x5gMVYL0/yIk+9Qii0ei3Su3BybWHfftZs+5r2Bong== + dependencies: + "@sentry-internal/rrweb-snapshot" "2.35.0" + "@sentry-internal/rrweb-snapshot@2.34.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-2.34.0.tgz#79c2049b6c887e3c128d5fa80d6f745a61dd0e68" integrity sha512-9Tb8jwVufn5GLV0d/CTuoZWo2O06ZB+xWeTJdEkbtJ6PAmO/Q7GQI3uNIx0pfFEnXP+0Km8CKKxpwkEM0z2m6w== +"@sentry-internal/rrweb-snapshot@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-2.35.0.tgz#656f4716e3bdda151f122868f6f92d5f4224967c" + integrity sha512-CyERHnGWIkuCtw4xYJMoyDUv+5vj38HBd0upeEhKyYzjZ8rOttwsFjfZUBdotsP8O0/RVt9KIPRbSRESC1qSJw== + "@sentry-internal/rrweb-types@2.34.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-types/-/rrweb-types-2.34.0.tgz#32b853d93d1d9a1ae1888b17d84b24e674fadee0" @@ -6673,6 +6418,14 @@ "@sentry-internal/rrweb-snapshot" "2.34.0" "@types/css-font-loading-module" "0.0.7" +"@sentry-internal/rrweb-types@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-types/-/rrweb-types-2.35.0.tgz#b2e63879a23593505fc3e28aa811e718de71f15f" + integrity sha512-D0mu2bgtvYD8MGijZDSD+q3FC8fDVRvNJD4canKvI3Wy9/LHTPbJ6F4U544vp5VrdBGCYIf/cxuJwmyZDfl5RQ== + dependencies: + "@sentry-internal/rrweb-snapshot" "2.35.0" + "@types/css-font-loading-module" "0.0.7" + "@sentry-internal/rrweb@2.34.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-2.34.0.tgz#a32945504f1ba2ba60f2ebd7a17d2df5e1aa010d" @@ -6687,25 +6440,29 @@ fflate "^0.4.4" mitt "^3.0.0" +"@sentry-internal/rrweb@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-2.35.0.tgz#ae10b9aaf3ee379164ec52f1186ee053d369b0a3" + integrity sha512-Zy3bnzL9GY6SFTZ5x5YNxtkmIUiaLSppLA41xn6zc4UWSYI4DcA+M8OGxI4TiHkQVJhhjwBG1CevrLyrBxyEgA== + dependencies: + "@sentry-internal/rrdom" "2.35.0" + "@sentry-internal/rrweb-snapshot" "2.35.0" + "@sentry-internal/rrweb-types" "2.35.0" + "@types/css-font-loading-module" "0.0.7" + "@xstate/fsm" "^1.4.0" + base64-arraybuffer "^1.0.1" + fflate "^0.4.4" + mitt "^3.0.0" + "@sentry/babel-plugin-component-annotate@2.22.6": version "2.22.6" resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.6.tgz#829d6caf2c95c1c46108336de4e1049e6521435e" integrity sha512-V2g1Y1I5eSe7dtUVMBvAJr8BaLRr4CLrgNgtPaZyMT4Rnps82SrZ5zqmEkLXPumlXhLUWR6qzoMNN2u+RXVXfQ== -"@sentry/babel-plugin-component-annotate@3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.1.2.tgz#5497ca5adbe775955e96c566511a0bed3ab0a3ce" - integrity sha512-5h2WXRJ6swKA0TwxHHryC8M2QyOfS9QhTAL6ElPfkEYe9HhJieXmxsDpyspbqAa26ccnCUcmwE5vL34jAjt4sQ== - -"@sentry/babel-plugin-component-annotate@3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.0.tgz#17c000cf6cc315bb620eddbd95c88dfb2471cfb9" - integrity sha512-Sg7nLRP1yiJYl/KdGGxYGbjvLq5rswyeB5yESgfWX34XUNZaFgmNvw4pU/QEKVeYgcPyOulgJ+y80ewujyffTA== - -"@sentry/babel-plugin-component-annotate@3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.2.tgz#0c5f26e417b8f524924fa4531b82ad5603216e90" - integrity sha512-D+SKQ266ra/wo87s9+UI/rKQi3qhGPCR8eSCDe0VJudhjHsqyNU+JJ5lnIGCgmZaWFTXgdBP/gdr1Iz1zqGs4Q== +"@sentry/babel-plugin-component-annotate@3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.3.tgz#2ec2ca459fe4087924dda5c54bd8a734fccba3bf" + integrity sha512-nbFvTHD7wOfxsqsbkyDVxxi1XMv6j54TW6i0vwLnzq3uwsSno/bs2Xzdc+mzXyMmji1b27kpOPiI2fKBi3XXVQ== "@sentry/bundler-plugin-core@2.22.6": version "2.22.6" @@ -6721,41 +6478,13 @@ magic-string "0.30.8" unplugin "1.0.1" -"@sentry/bundler-plugin-core@3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.1.2.tgz#29e4e686c5893b41a0d98a1bef6f0315a610bd59" - integrity sha512-lqOCvmOPzKiQenIMhmm5/mwCntwFy0dPZbVD28Dnr3MXpT1rIBg1HXjfnqQWFlMRbL9haSsWiY/TQyR/6b30YA== - dependencies: - "@babel/core" "^7.18.5" - "@sentry/babel-plugin-component-annotate" "3.1.2" - "@sentry/cli" "2.41.1" - dotenv "^16.3.1" - find-up "^5.0.0" - glob "^9.3.2" - magic-string "0.30.8" - unplugin "1.0.1" - -"@sentry/bundler-plugin-core@3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.0.tgz#023ec92530a35fbec7c7077b7a8be2e79f0f9dd5" - integrity sha512-Q/ogVylue3XaFawyIxzuiic+7Dp4w63eJtRtVH8VBebNURyJ/re4GVoP1QNGccE1R243tXY1y2GiwqiJkAONOg== - dependencies: - "@babel/core" "^7.18.5" - "@sentry/babel-plugin-component-annotate" "3.2.0" - "@sentry/cli" "2.41.1" - dotenv "^16.3.1" - find-up "^5.0.0" - glob "^9.3.2" - magic-string "0.30.8" - unplugin "1.0.1" - -"@sentry/bundler-plugin-core@3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.2.tgz#c9193b0c97acf0097fdb820d86eaaad9c9b6b2c4" - integrity sha512-YGrtmqQ2jMixccX2slVG/Lw7pCGJL3DGB3clmY9mO8QBEBIN3/gEANiHJVWwRidpUOS/0b7yVVGAdwZ87oPwTg== +"@sentry/bundler-plugin-core@3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.3.tgz#2d88a3bcae74299aa9969725fd80484847d2ff02" + integrity sha512-efg4F0ia1eO0GdWF9a/9tyKQaP5eHABBU8v/zFTmdw6WCPozFH+aRvfXOVSLGoII/sduRamW9BiUlE4NxrWPqQ== dependencies: "@babel/core" "^7.18.5" - "@sentry/babel-plugin-component-annotate" "3.2.2" + "@sentry/babel-plugin-component-annotate" "3.2.3" "@sentry/cli" "2.42.2" dotenv "^16.3.1" find-up "^5.0.0" @@ -6763,11 +6492,6 @@ magic-string "0.30.8" unplugin "1.0.1" -"@sentry/cli-darwin@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.41.1.tgz#ca7e12bf1ad59bc2df35868ae98abc8869108efa" - integrity sha512-7pS3pu/SuhE6jOn3wptstAg6B5nUP878O6s+2svT7b5fKNfYUi/6NPK6dAveh2Ca0rwVq40TO4YFJabWMgTpdQ== - "@sentry/cli-darwin@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.42.2.tgz#a32a4f226e717122b37d9969e8d4d0e14779f720" @@ -6778,11 +6502,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.42.3.tgz#34782c2bf889cec99794ec90287fec3836b1a691" integrity sha512-QGNXZ5c2kbjB3O37ep/uVfqTspHaHkH4kmoMPNJ6j21A1oYyJq5t/AX9JWsueysRwvn6Jc0K0+XyzYZ13z0vsQ== -"@sentry/cli-linux-arm64@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.41.1.tgz#948e8af8290418b1562db3531db08e69e39d74bb" - integrity sha512-EzYCEnnENBnS5kpNW+2dBcrPZn1MVfywh2joGVQZTpmgDL5YFJ59VOd+K0XuEwqgFI8BSNI14KXZ75s4DD1/Vw== - "@sentry/cli-linux-arm64@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.2.tgz#1c06c83ff21f51ec23acf5be3b1f8c7553bf86b1" @@ -6793,11 +6512,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.3.tgz#b722270c81fbdd7703a26451f505f82528d97116" integrity sha512-tRqWrmphK82G14KKFEouLdV8BdCpGsTuySZ8nzTqhoAtcjpWFaavX2/1UqKzPVYjkxwXc1npO3Q7qfZYW2HvjQ== -"@sentry/cli-linux-arm@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.41.1.tgz#1e5fa971ae8dfb3ea5564c8503b4e635ae6aed8a" - integrity sha512-wNUvquD6qjOCczvuBGf9OiD29nuQ6yf8zzfyPJa5Bdx1QXuteKsKb6HBrMwuIR3liyuu0duzHd+H/+p1n541Hg== - "@sentry/cli-linux-arm@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.2.tgz#00cadc359ae3c051efb3e63873c033c61dbd1ca1" @@ -6808,11 +6522,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.3.tgz#81373e1dd017a3d265a49172546063ebbcf69098" integrity sha512-tipumegAsKy9KLq6Bk87E8FqkKErReaNzdhoHCb081jkxQxpzKN/MQPMl9mA0XeKc4A7OUBM3vjhIk6uNi1R2g== -"@sentry/cli-linux-i686@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.41.1.tgz#3f01aff314f2ad8fd761f3e6e807a5ec09ae4eb4" - integrity sha512-urpQCWrdYnSAsZY3udttuMV88wTJzKZL10xsrp7sjD/Hd+O6qSLVLkxebIlxts70jMLLFHYrQ2bkRg5kKuX6Fg== - "@sentry/cli-linux-i686@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.2.tgz#3b817b715dd806c20dfbffd539725ad8089c310a" @@ -6823,11 +6532,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.3.tgz#8342a137ea57df0bb0136a57c3a21eddc1e28991" integrity sha512-pc4Kc7xTMNbUPiRLQ2UXcj2V2vbVmST0IyhOlVTmY0L3ZxMdiwTq7qgS/IcxI/CaCPyEZWplXnxlsa//mCMuYw== -"@sentry/cli-linux-x64@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.41.1.tgz#30dbf966a4b4c1721ffccd901dfcb6f967db073d" - integrity sha512-ZqpYwHXAaK4MMEFlyaLYr6mJTmpy9qP6n30jGhLTW7kHKS3s6GPLCSlNmIfeClrInEt0963fM633ZRnXa04VPw== - "@sentry/cli-linux-x64@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.2.tgz#ddf906bc3071cc79ce6e633eddcb76bb9068e688" @@ -6838,11 +6542,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.3.tgz#46c4331a46e9c5cee547dcc6c9e039fb8a45f331" integrity sha512-CZoG2swc38/RruLYtvMJNpcbvzqpcSDl+dUFJ3y6wIvMsE1IQL3zrb4xSh1Acf8Hi+GhlFAtoZpgH1tpWWZ/Zw== -"@sentry/cli-win32-i686@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.41.1.tgz#f88eeb5d2d4ee46c38d8616ae1eb484108ea71c2" - integrity sha512-AuRimCeVsx99DIOr9cwdYBHk39tlmAuPDdy2r16iNzY0InXs4xOys4gGzM7N4vlFQvFkzuc778Su0HkfasgprA== - "@sentry/cli-win32-i686@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.2.tgz#9036085c7c6ce455ad45fda411c55ff39c06eb95" @@ -6853,11 +6552,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.3.tgz#5fc97729eb895707808a757ec6d557fbbf4a44de" integrity sha512-geiPcfeuSj23N346xwrxFAuohIivK48NKQQYllVFAADYoYrSawSznVzRyOIheiOte1AIrDkpqzoT/5igl7ANEQ== -"@sentry/cli-win32-x64@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.41.1.tgz#eefd95a2aa184adb464334e265b55a9142070f6f" - integrity sha512-6JcPvXGye61+wPp0xdzfc2YLE/Dcud8JdaK8VxLM3b/8+Em7E+UyliDu3uF8+YGUqizY5JYTd3fs17DC8DZhLw== - "@sentry/cli-win32-x64@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.2.tgz#7d6464b63f32c9f97fff428f246b1f039b402233" @@ -6868,25 +6562,6 @@ resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.3.tgz#759f320d60dc1d923d8c8edc44945aca77813f67" integrity sha512-sG+phJ+3WUMx6gTrUd7UH+q0L6X1YjS57ovMMf3XYyE/WIF8c+uc+vZC/RB3O5l3vTTCXoePqHf8+9ulgp9dkA== -"@sentry/cli@2.41.1": - version "2.41.1" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.41.1.tgz#a9467ca3ff4acfcdedec1565c9ff726b93758d29" - integrity sha512-0GVmDiTV7R1492wkVY4bGcfC0fSmRmQjuxaaPI8CIV9B2VP9pBVCUizi1mevXaaE4I3fM60LI+XYrKFEneuVog== - dependencies: - https-proxy-agent "^5.0.0" - node-fetch "^2.6.7" - progress "^2.0.3" - proxy-from-env "^1.1.0" - which "^2.0.2" - optionalDependencies: - "@sentry/cli-darwin" "2.41.1" - "@sentry/cli-linux-arm" "2.41.1" - "@sentry/cli-linux-arm64" "2.41.1" - "@sentry/cli-linux-i686" "2.41.1" - "@sentry/cli-linux-x64" "2.41.1" - "@sentry/cli-win32-i686" "2.41.1" - "@sentry/cli-win32-x64" "2.41.1" - "@sentry/cli@2.42.2": version "2.42.2" resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.42.2.tgz#8173df4d057d600a9ef0cf1e9b42b0c6607b46e4" @@ -6925,12 +6600,12 @@ "@sentry/cli-win32-i686" "2.42.3" "@sentry/cli-win32-x64" "2.42.3" -"@sentry/rollup-plugin@3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-3.1.2.tgz#d1ed4eeb558e10260bf0e7f292f9ad6baf22a98c" - integrity sha512-CVUsfQkL8REOGuyaPX7BzccZoq+wce05gQW3dG4PcXNPQeKTPRpC89NLcCDJijJa08yvC0DF0wsWRhlFWM89kQ== +"@sentry/rollup-plugin@3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-3.2.3.tgz#df931a1858d8d4cbdb7714793f76eaf2e7f34b2d" + integrity sha512-00WQUYvJ/X5WlfI+MK/Wf+hXroafFw4kEae0/ToAYTnpOIp7twQ/ULBhsGmyzOLSzxnv3CtkhxbOz7sUPdmWvQ== dependencies: - "@sentry/bundler-plugin-core" "3.1.2" + "@sentry/bundler-plugin-core" "3.2.3" unplugin "1.0.1" "@sentry/vite-plugin@2.22.6", "@sentry/vite-plugin@^2.22.6": @@ -6941,20 +6616,20 @@ "@sentry/bundler-plugin-core" "2.22.6" unplugin "1.0.1" -"@sentry/vite-plugin@3.2.0", "@sentry/vite-plugin@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-3.2.0.tgz#0785b6e04e0aed8a4d6b57a433a2da11c14e6cd0" - integrity sha512-IVBoAzZmpoX9+mnmIMq2ndxlFPoWMuYSE5Mek5zOWpYh+GbPxvkrxvM+vg0HeLH4r5v9Tm0FWcEZDgDIZqtoSg== +"@sentry/vite-plugin@3.2.3", "@sentry/vite-plugin@^3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-3.2.3.tgz#3e51bcd7ee37b5b84177637df4d66dbed953a5f5" + integrity sha512-7znFCOi60tTr5LjVnsP9Bb1kXfYHUz2ylueBT6bY5pu9xO5C3D0wpSodY8X7AiqLKWOc5wPbHMSIxNOWp6in3g== dependencies: - "@sentry/bundler-plugin-core" "3.2.0" + "@sentry/bundler-plugin-core" "3.2.3" unplugin "1.0.1" -"@sentry/webpack-plugin@3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-3.2.2.tgz#716ab462279c25cea17490d02cb1d22b00f3f661" - integrity sha512-6OkVKNOjKk8P9j7oh6svZ+kEP1i9YIHBC2aGWL2XsgeZTIrMBxJAXtOf+qSrfMAxEtibSroGVOMQc/y3WJTQtg== +"@sentry/webpack-plugin@3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-3.2.3.tgz#80fbb39045dc54e81ca8df4aac1d4e61c2b729df" + integrity sha512-uBRJO54wOqZ2csi/JT0kLeNpjClypwYBsyrqKgDSp04N2oEnt1eZr4L4yS4kNShI/ZrkA5Q4VWuFk5cCB2f/ew== dependencies: - "@sentry/bundler-plugin-core" "3.2.2" + "@sentry/bundler-plugin-core" "3.2.3" unplugin "1.0.1" uuid "^9.0.0" @@ -6992,13 +6667,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958" integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg== -"@sinonjs/commons@^1.7.0": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b" - integrity sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw== - dependencies: - type-detect "4.0.8" - "@sinonjs/commons@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" @@ -7013,13 +6681,6 @@ dependencies: "@sinonjs/commons" "^3.0.1" -"@sinonjs/fake-timers@^8.0.1": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7" - integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== - dependencies: - "@sinonjs/commons" "^1.7.0" - "@sinonjs/samsam@^8.0.1": version "8.0.2" resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.2.tgz#e4386bf668ff36c95949e55a38dc5f5892fc2689" @@ -7621,12 +7282,11 @@ pretty-format "^27.0.2" "@testing-library/jest-dom@^6.4.5": - version "6.4.5" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz#badb40296477149136dabef32b572ddd3b56adf1" - integrity sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A== + version "6.6.3" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz#26ba906cf928c0f8172e182c6fe214eb4f9f2bd2" + integrity sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA== dependencies: - "@adobe/css-tools" "^4.3.2" - "@babel/runtime" "^7.9.2" + "@adobe/css-tools" "^4.4.0" aria-query "^5.0.0" chalk "^3.0.0" css.escape "^1.5.1" @@ -7743,7 +7403,7 @@ resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.147.tgz#dc5c89aa32f47a9b35e52c32630545c83afa6f2f" integrity sha512-nD0Z9fNIZcxYX5Mai2CTmFD7wX7UldCkW2ezCF8D1T5hdiLsnTWDGRpfRYntU6VjTdLQjOvyszru7I1c1oCQew== -"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.20.1", "@types/babel__core@^7.20.4": +"@types/babel__core@^7.20.1", "@types/babel__core@^7.20.4": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== @@ -7769,7 +7429,7 @@ "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": +"@types/babel__traverse@*": version "7.14.2" resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== @@ -7864,13 +7524,6 @@ resolved "https://registry.yarnpkg.com/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz#dcef10a69d357fe9d43ac4ff2eca6b85dbf466af" integrity sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg== -"@types/duplexify@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8" - integrity sha512-5zOA53RUlzN74bvrSGwjudssD9F3a797sDZQkiYpUOxW+WHaXTCPz4/d5Dgi6FKnOqZ2CpaTo0DhgIfsXAOE/A== - dependencies: - "@types/node" "*" - "@types/ember-resolver@5.0.13": version "5.0.13" resolved "https://registry.yarnpkg.com/@types/ember-resolver/-/ember-resolver-5.0.13.tgz#db66678076ca625ed80b629c09619ae85c1c1f7a" @@ -8141,13 +7794,6 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/graceful-fs@^4.1.2": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== - dependencies: - "@types/node" "*" - "@types/hast@^2.0.0": version "2.3.6" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.6.tgz#bb8b05602112a26d22868acb70c4b20984ec7086" @@ -8207,33 +7853,6 @@ dependencies: "@types/node" "*" -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== - -"@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" - integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^27.4.1": - version "27.4.1" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d" - integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw== - dependencies: - jest-matcher-utils "^27.0.0" - pretty-format "^27.0.0" - "@types/jquery@*": version "3.5.5" resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.5.tgz#2c63f47c9c8d96693d272f5453602afd8338c903" @@ -8260,7 +7879,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/long@^4.0.0", "@types/long@^4.0.1": +"@types/long@^4.0.0": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== @@ -8358,7 +7977,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18": +"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=18": version "22.10.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== @@ -8422,11 +8041,6 @@ pg-protocol "*" pg-types "^2.2.0" -"@types/prettier@^2.1.5": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17" - integrity sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA== - "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" @@ -8592,11 +8206,6 @@ dependencies: "@types/node" "*" -"@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== - "@types/symlink-or-copy@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz#4151a81b4052c80bc2becbae09f3a9ec010a9c7a" @@ -8648,18 +8257,6 @@ dependencies: "@types/node" "*" -"@types/yargs-parser@*": - version "20.2.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" - integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA== - -"@types/yargs@^16.0.0": - version "16.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" - integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== - dependencies: - "@types/yargs-parser" "*" - "@typescript-eslint/eslint-plugin@^5.48.0": version "5.48.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.0.tgz#54f8368d080eb384a455f60c2ee044e948a8ce67" @@ -8693,14 +8290,6 @@ "@typescript-eslint/types" "5.48.0" "@typescript-eslint/visitor-keys" "5.48.0" -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - "@typescript-eslint/scope-manager@6.7.4": version "6.7.4" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz#a484a17aa219e96044db40813429eb7214d7b386" @@ -8747,19 +8336,6 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@5.62.0", "@typescript-eslint/typescript-estree@^5.62.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== - dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - "@typescript-eslint/typescript-estree@6.7.4": version "6.7.4" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz#f2baece09f7bb1df9296e32638b2e1130014ef1a" @@ -8773,6 +8349,19 @@ semver "^7.5.4" ts-api-utils "^1.0.1" +"@typescript-eslint/typescript-estree@^5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== + dependencies: + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/utils@5.48.0": version "5.48.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.48.0.tgz#eee926af2733f7156ad8d15e51791e42ce300273" @@ -8787,20 +8376,6 @@ eslint-utils "^3.0.0" semver "^7.3.7" -"@typescript-eslint/utils@^5.10.0": - version "5.62.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - "@typescript-eslint/utils@^6.0.0": version "6.7.4" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.4.tgz#2236f72b10e38277ee05ef06142522e1de470ff2" @@ -9600,7 +9175,7 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" -abab@^2.0.3, abab@^2.0.5, abab@^2.0.6: +abab@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== @@ -9625,14 +9200,6 @@ accepts@^1.3.5, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" - integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - acorn-globals@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" @@ -9668,11 +9235,6 @@ acorn-typescript@^1.4.3: resolved "https://registry.yarnpkg.com/acorn-typescript/-/acorn-typescript-1.4.13.tgz#5f851c8bdda0aa716ffdd5f6ac084df8acc6f5ea" integrity sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q== -acorn-walk@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" - integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== - acorn-walk@^8.0.0, acorn-walk@^8.0.2, acorn-walk@^8.1.1, acorn-walk@^8.2.0: version "8.3.3" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" @@ -9690,12 +9252,12 @@ acorn@8.12.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== -acorn@^7.1.1, acorn@^7.4.0: +acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.1.0, acorn@^8.10.0, acorn@^8.11.0, acorn@^8.11.3, acorn@^8.12.1, acorn@^8.14.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.6.0, acorn@^8.7.0, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.10.0, acorn@^8.11.0, acorn@^8.11.3, acorn@^8.12.1, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.6.0, acorn@^8.7.0, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -9940,7 +9502,7 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -anymatch@^3.0.3, anymatch@^3.1.1, anymatch@^3.1.3, anymatch@~3.1.2: +anymatch@^3.1.1, anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -10588,20 +10150,6 @@ babel-import-util@^3.0.0: resolved "https://registry.yarnpkg.com/babel-import-util/-/babel-import-util-3.0.0.tgz#5814c6a58e7b80e64156b48fdfd34d48e6e0b1df" integrity sha512-4YNPkuVsxAW5lnSTa6cn4Wk49RX6GAB6vX+M6LqEtN0YePqoFczv1/x0EyLK/o+4E1j9jEuYj5Su7IEPab5JHQ== -babel-jest@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" - integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg== - dependencies: - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^27.5.1" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - babel-loader@8.2.5, babel-loader@^8.0.6, babel-loader@^8.2.2: version "8.2.5" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" @@ -10677,7 +10225,7 @@ babel-plugin-htmlbars-inline-precompile@^5.2.1, babel-plugin-htmlbars-inline-pre parse-static-imports "^1.1.0" string.prototype.matchall "^4.0.5" -babel-plugin-istanbul@6.1.1, babel-plugin-istanbul@^6.1.1: +babel-plugin-istanbul@6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== @@ -10688,16 +10236,6 @@ babel-plugin-istanbul@6.1.1, babel-plugin-istanbul@^6.1.1: istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e" - integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.0.0" - "@types/babel__traverse" "^7.0.6" - babel-plugin-jsx-dom-expressions@^0.37.20: version "0.37.21" resolved "https://registry.yarnpkg.com/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.37.21.tgz#8d63d09c183485f228a11f13cbdf1ff25e541a8e" @@ -10795,32 +10333,6 @@ babel-plugin-syntax-dynamic-import@^6.18.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" integrity sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo= -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81" - integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag== - dependencies: - babel-plugin-jest-hoist "^27.5.1" - babel-preset-current-node-syntax "^1.0.0" - babel-preset-solid@^1.8.4: version "1.8.17" resolved "https://registry.yarnpkg.com/babel-preset-solid/-/babel-preset-solid-1.8.17.tgz#8d55e8e2ee800be85527425e7943534f984dc815" @@ -11018,7 +10530,7 @@ bluebird@^3.4.6, bluebird@^3.7.2: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -body-parser@1.20.3, body-parser@^1.18.3, body-parser@^1.19.0, body-parser@^1.20.3: +body-parser@1.20.3, body-parser@^1.19.0, body-parser@^1.20.3: version "1.20.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== @@ -11596,11 +11108,6 @@ broccoli@^3.5.2: underscore.string "^3.2.2" watch-detector "^1.0.0" -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== - browserify-zlib@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" @@ -11618,13 +11125,6 @@ browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.20.0, browserslist@^4 node-releases "^2.0.18" update-browserslist-db "^1.1.1" -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -12055,11 +11555,6 @@ chalk@^5.0.0, chalk@^5.2.0, chalk@^5.3.0: resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - character-entities-html4@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" @@ -12153,7 +11648,7 @@ citty@^0.1.2, citty@^0.1.5, citty@^0.1.6: dependencies: consola "^3.2.3" -cjs-module-lexer@^1.0.0, cjs-module-lexer@^1.2.2: +cjs-module-lexer@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== @@ -12343,11 +11838,6 @@ cmd-shim@6.0.1: resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.1.tgz#a65878080548e1dca760b3aea1e21ed05194da9d" integrity sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q== -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - code-red@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/code-red/-/code-red-1.0.4.tgz#59ba5c9d1d320a4ef795bc10a28bd42bfebe3e35" @@ -12359,11 +11849,6 @@ code-red@^1.0.3: estree-walker "^3.0.3" periscopic "^3.1.0" -collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== - collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -12779,7 +12264,7 @@ conventional-recommended-bump@7.0.1: git-semver-tags "^5.0.0" meow "^8.1.2" -convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.5.1, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -13199,23 +12684,6 @@ csso@^5.0.5: dependencies: css-tree "~2.2.0" -cssom@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" - integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== - dependencies: - cssom "~0.3.6" - cssstyle@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-3.0.0.tgz#17ca9c87d26eac764bb8cfd00583cff21ce0277a" @@ -13258,15 +12726,6 @@ data-uri-to-buffer@^3.0.1: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== -data-urls@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" - integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== - dependencies: - abab "^2.0.3" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.0.0" - data-urls@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-4.0.0.tgz#333a454eca6f9a5b7b0f1013ff89074c3f522dd4" @@ -13361,7 +12820,7 @@ decamelize@^1.1.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decimal.js@^10.2.1, decimal.js@^10.4.3: +decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== @@ -13400,7 +12859,7 @@ decorator-transforms@^2.0.0: "@babel/plugin-syntax-decorators" "^7.23.3" babel-import-util "^3.0.0" -dedent@0.7.0, dedent@^0.7.0: +dedent@0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= @@ -13654,7 +13113,7 @@ detect-libc@^2.0.0, detect-libc@^2.0.2: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== -detect-newline@3.1.0, detect-newline@^3.0.0: +detect-newline@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== @@ -13756,11 +13215,6 @@ diff-match-patch@^1.0.5: resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw== -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== - diff-sequences@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" @@ -13874,13 +13328,6 @@ domexception@^1.0.1: dependencies: webidl-conversions "^4.0.2" -domexception@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" - integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== - dependencies: - webidl-conversions "^5.0.0" - domexception@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" @@ -14593,11 +14040,6 @@ ember-template-recast@^6.1.3, ember-template-recast@^6.1.4: tmp "^0.2.1" workerpool "^6.4.0" -emittery@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" - integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== - emoji-regex@^10.2.1: version "10.3.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23" @@ -15377,11 +14819,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -15482,13 +14919,6 @@ eslint-plugin-import@^2.22.0: resolve "^1.17.0" tsconfig-paths "^3.9.0" -eslint-plugin-jest@^27.2.2: - version "27.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz#be4ded5f91905d9ec89aa8968d39c71f3b072c0c" - integrity sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw== - dependencies: - "@typescript-eslint/utils" "^5.10.0" - eslint-plugin-jsdoc@^30.0.3: version "30.7.13" resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.7.13.tgz#52e5c74fb806d3bbeb51d04a0c829508c3c6b563" @@ -15906,22 +15336,12 @@ expect-type@^1.1.0: resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75" integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA== -expect@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74" - integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== - dependencies: - "@jest/types" "^27.5.1" - jest-get-type "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - exponential-backoff@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== -express@4.21.1, express@^4.10.7, express@^4.16.4, express@^4.17.1, express@^4.17.3, express@^4.18.1, express@^4.21.1: +express@4.21.1, express@^4.10.7, express@^4.17.1, express@^4.17.3, express@^4.18.1, express@^4.21.1: version "4.21.1" resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281" integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ== @@ -16055,7 +15475,7 @@ fast-glob@^3.0.3, fast-glob@^3.2.11, fast-glob@^3.2.7, fast-glob@^3.2.9, fast-gl merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -16113,7 +15533,7 @@ fast-sourcemap-concat@^2.1.0: source-map-url "^0.3.0" sourcemap-validator "^1.1.0" -fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: +fast-text-encoding@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53" integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== @@ -16490,15 +15910,6 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -16686,7 +16097,7 @@ fsevents@2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -17080,7 +16491,7 @@ glob@^5.0.10: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.4, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.3, glob@~7.2.0: +glob@^7.0.0, glob@^7.0.4, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.3, glob@~7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -17232,22 +16643,7 @@ gonzales-pe@^4.3.0: dependencies: minimist "^1.2.5" -google-auth-library@^6.1.1: - version "6.1.6" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.6.tgz#deacdcdb883d9ed6bac78bb5d79a078877fdf572" - integrity sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ== - dependencies: - arrify "^2.0.0" - base64-js "^1.3.0" - ecdsa-sig-formatter "^1.0.11" - fast-text-encoding "^1.0.0" - gaxios "^4.0.0" - gcp-metadata "^4.2.0" - gtoken "^5.0.4" - jws "^4.0.0" - lru-cache "^6.0.0" - -google-auth-library@^7.0.0, google-auth-library@^7.0.2: +google-auth-library@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.0.3.tgz#a38e853722ac1a4f14a7ff4d170fd0b0bf37766b" integrity sha512-6wJNYqY1QUr5I2lWaUkkzOT2b9OCNhNQrdFOt/bsBbGb7T7NCdEvrBsXraUm+KTUGk2xGlQ7m9RgUd4Llcw8NQ== @@ -17256,28 +16652,11 @@ google-auth-library@^7.0.0, google-auth-library@^7.0.2: base64-js "^1.3.0" ecdsa-sig-formatter "^1.0.11" fast-text-encoding "^1.0.0" - gaxios "^4.0.0" - gcp-metadata "^4.2.0" - gtoken "^5.0.4" - jws "^4.0.0" - lru-cache "^6.0.0" - -google-gax@^2.9.0, google-gax@^2.9.2: - version "2.11.2" - resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.11.2.tgz#9ef7773b94aaa61c4588fb2408d62e8444995026" - integrity sha512-PNqXv7Oi5XBMgoMWVxLZHUidfMv7cPHrDSDXqLyEd6kY6pqFnVKC8jt2T1df4JPSc2+VLPdeo6L7X9mbdQG8Xw== - dependencies: - "@grpc/grpc-js" "~1.2.0" - "@grpc/proto-loader" "^0.5.1" - "@types/long" "^4.0.0" - abort-controller "^3.0.0" - duplexify "^4.0.0" - fast-text-encoding "^1.0.3" - google-auth-library "^7.0.2" - is-stream-ended "^0.1.4" - node-fetch "^2.6.1" - protobufjs "^6.10.2" - retry-request "^4.0.0" + gaxios "^4.0.0" + gcp-metadata "^4.2.0" + gtoken "^5.0.4" + jws "^4.0.0" + lru-cache "^6.0.0" google-p12-pem@^3.0.3: version "3.1.4" @@ -17883,13 +17262,6 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-encoding-sniffer@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" - integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== - dependencies: - whatwg-encoding "^1.0.5" - html-encoding-sniffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" @@ -18007,7 +17379,7 @@ http-parser-js@>=0.5.1: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== -http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1: +http-proxy-agent@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== @@ -18219,7 +17591,7 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== -import-local@3.1.0, import-local@^3.0.2: +import-local@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== @@ -18669,11 +18041,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - is-generator-function@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" @@ -18891,11 +18258,6 @@ is-ssh@^1.4.0: dependencies: protocols "^2.0.1" -is-stream-ended@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" - integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== - is-stream@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" @@ -19103,7 +18465,7 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0, istanbul-lib-coverag resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: +istanbul-lib-instrument@^5.0.4: version "5.1.0" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== @@ -19123,15 +18485,6 @@ istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: make-dir "^4.0.0" supports-color "^7.1.0" -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - istanbul-lib-source-maps@^5.0.6: version "5.0.6" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" @@ -19141,7 +18494,7 @@ istanbul-lib-source-maps@^5.0.6: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" -istanbul-reports@^3.1.3, istanbul-reports@^3.1.7: +istanbul-reports@^3.1.7: version "3.1.7" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== @@ -19198,88 +18551,6 @@ jake@^10.8.5: filelist "^1.0.1" minimatch "^3.0.4" -jest-changed-files@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" - integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw== - dependencies: - "@jest/types" "^27.5.1" - execa "^5.0.0" - throat "^6.0.1" - -jest-circus@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc" - integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - expect "^27.5.1" - is-generator-fn "^2.0.0" - jest-each "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" - slash "^3.0.0" - stack-utils "^2.0.3" - throat "^6.0.1" - -jest-cli@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145" - integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw== - dependencies: - "@jest/core" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" - prompts "^2.0.1" - yargs "^16.2.0" - -jest-config@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41" - integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA== - dependencies: - "@babel/core" "^7.8.0" - "@jest/test-sequencer" "^27.5.1" - "@jest/types" "^27.5.1" - babel-jest "^27.5.1" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.1" - graceful-fs "^4.2.9" - jest-circus "^27.5.1" - jest-environment-jsdom "^27.5.1" - jest-environment-node "^27.5.1" - jest-get-type "^27.5.1" - jest-jasmine2 "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-runner "^27.5.1" - jest-util "^27.5.1" - jest-validate "^27.5.1" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^27.5.1" - slash "^3.0.0" - strip-json-comments "^3.1.1" - "jest-diff@>=29.4.3 < 30", jest-diff@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" @@ -19290,140 +18561,11 @@ jest-config@^27.5.1: jest-get-type "^29.6.3" pretty-format "^29.7.0" -jest-diff@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== - dependencies: - chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-docblock@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" - integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ== - dependencies: - detect-newline "^3.0.0" - -jest-each@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e" - integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ== - dependencies: - "@jest/types" "^27.5.1" - chalk "^4.0.0" - jest-get-type "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" - -jest-environment-jsdom@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546" - integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - jest-mock "^27.5.1" - jest-util "^27.5.1" - jsdom "^16.6.0" - -jest-environment-node@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e" - integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - jest-mock "^27.5.1" - jest-util "^27.5.1" - -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== - jest-get-type@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== -jest-haste-map@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f" - integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng== - dependencies: - "@jest/types" "^27.5.1" - "@types/graceful-fs" "^4.1.2" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^27.5.1" - jest-serializer "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" - micromatch "^4.0.4" - walker "^1.0.7" - optionalDependencies: - fsevents "^2.3.2" - -jest-jasmine2@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4" - integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/source-map" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - expect "^27.5.1" - is-generator-fn "^2.0.0" - jest-each "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-runtime "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - pretty-format "^27.5.1" - throat "^6.0.1" - -jest-junit@^16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-16.0.0.tgz#d838e8c561cf9fdd7eb54f63020777eee4136785" - integrity sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ== - dependencies: - mkdirp "^1.0.4" - strip-ansi "^6.0.1" - uuid "^8.3.2" - xml "^1.0.1" - -jest-leak-detector@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8" - integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ== - dependencies: - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" - integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== - dependencies: - chalk "^4.0.0" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - jest-matcher-utils@^29.0.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" @@ -19434,193 +18576,7 @@ jest-matcher-utils@^29.0.0: jest-get-type "^29.6.3" pretty-format "^29.7.0" -jest-message-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf" - integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^27.5.1" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^27.5.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" - integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== - dependencies: - "@jest/types" "^27.5.1" - "@types/node" "*" - -jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== - -jest-regex-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" - integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== - -jest-resolve-dependencies@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8" - integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg== - dependencies: - "@jest/types" "^27.5.1" - jest-regex-util "^27.5.1" - jest-snapshot "^27.5.1" - -jest-resolve@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384" - integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw== - dependencies: - "@jest/types" "^27.5.1" - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-pnp-resolver "^1.2.2" - jest-util "^27.5.1" - jest-validate "^27.5.1" - resolve "^1.20.0" - resolve.exports "^1.1.0" - slash "^3.0.0" - -jest-runner@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5" - integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ== - dependencies: - "@jest/console" "^27.5.1" - "@jest/environment" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.8.1" - graceful-fs "^4.2.9" - jest-docblock "^27.5.1" - jest-environment-jsdom "^27.5.1" - jest-environment-node "^27.5.1" - jest-haste-map "^27.5.1" - jest-leak-detector "^27.5.1" - jest-message-util "^27.5.1" - jest-resolve "^27.5.1" - jest-runtime "^27.5.1" - jest-util "^27.5.1" - jest-worker "^27.5.1" - source-map-support "^0.5.6" - throat "^6.0.1" - -jest-runtime@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af" - integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A== - dependencies: - "@jest/environment" "^27.5.1" - "@jest/fake-timers" "^27.5.1" - "@jest/globals" "^27.5.1" - "@jest/source-map" "^27.5.1" - "@jest/test-result" "^27.5.1" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - execa "^5.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^27.5.1" - jest-message-util "^27.5.1" - jest-mock "^27.5.1" - jest-regex-util "^27.5.1" - jest-resolve "^27.5.1" - jest-snapshot "^27.5.1" - jest-util "^27.5.1" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-serializer@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64" - integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w== - dependencies: - "@types/node" "*" - graceful-fs "^4.2.9" - -jest-snapshot@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1" - integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA== - dependencies: - "@babel/core" "^7.7.2" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.0.0" - "@jest/transform" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/babel__traverse" "^7.0.4" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^27.5.1" - graceful-fs "^4.2.9" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - jest-haste-map "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" - jest-util "^27.5.1" - natural-compare "^1.4.0" - pretty-format "^27.5.1" - semver "^7.3.2" - -jest-util@^27.0.0, jest-util@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" - integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== - dependencies: - "@jest/types" "^27.5.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067" - integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ== - dependencies: - "@jest/types" "^27.5.1" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^27.5.1" - leven "^3.1.0" - pretty-format "^27.5.1" - -jest-watcher@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2" - integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw== - dependencies: - "@jest/test-result" "^27.5.1" - "@jest/types" "^27.5.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - jest-util "^27.5.1" - string-length "^4.0.1" - -jest-worker@^27.4.5, jest-worker@^27.5.1: +jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== @@ -19629,15 +18585,6 @@ jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc" - integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ== - dependencies: - "@jest/core" "^27.5.1" - import-local "^3.0.2" - jest-cli "^27.5.1" - jiti@^1.19.3, jiti@^1.21.0, jiti@^1.21.6: version "1.21.6" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" @@ -19710,39 +18657,6 @@ jsdom-worker@^0.2.1: mitt "^1.1.3" uuid-v4 "^0.1.0" -jsdom@^16.6.0: - version "16.7.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" - integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== - dependencies: - abab "^2.0.5" - acorn "^8.2.4" - acorn-globals "^6.0.0" - cssom "^0.4.4" - cssstyle "^2.3.0" - data-urls "^2.0.0" - decimal.js "^10.2.1" - domexception "^2.0.1" - escodegen "^2.0.0" - form-data "^3.0.0" - html-encoding-sniffer "^2.0.1" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" - symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^2.0.0" - webidl-conversions "^6.1.0" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^8.5.0" - ws "^7.4.6" - xml-name-validator "^3.0.0" - jsdom@^21.1.2: version "21.1.2" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.2.tgz#6433f751b8718248d646af1cdf6662dc8a1ca7f9" @@ -19854,11 +18768,6 @@ json-stringify-safe@^5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@2.x, json5@^2.1.2, json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: - version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -19871,6 +18780,11 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +json5@^2.1.2, json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + jsonc-parser@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.1.0.tgz#73b8f0e5c940b83d03476bc2e51a20ef0932615d" @@ -20265,11 +19179,6 @@ leven@2.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" integrity sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA== -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -20547,7 +19456,7 @@ lodash.assign@^3.2.0: lodash._createassigner "^3.0.0" lodash.keys "^3.0.0" -lodash.camelcase@^4.1.1, lodash.camelcase@^4.3.0: +lodash.camelcase@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= @@ -20656,7 +19565,7 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" -lodash.memoize@4.x, lodash.memoize@^4.1.2: +lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= @@ -20681,11 +19590,6 @@ lodash.restparam@^3.0.0: resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= -lodash.snakecase@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" - integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40= - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -20983,7 +19887,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@1.x, make-error@^1.1.1: +make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -23160,7 +22064,7 @@ nuxt@^3.13.2: vue-devtools-stub "^0.1.0" vue-router "^4.4.5" -nwsapi@^2.2.0, nwsapi@^2.2.4: +nwsapi@^2.2.4: version "2.2.9" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.9.tgz#7f3303218372db2e9f27c27766bcfc59ae7e61c6" integrity sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg== @@ -23352,7 +22256,7 @@ ohash@^1.1.3, ohash@^1.1.4: resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.4.tgz#ae8d83014ab81157d2c285abf7792e2995fadd72" integrity sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g== -on-finished@2.4.1, on-finished@^2.3.0: +on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -23885,7 +22789,7 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-json@^5.0.0, parse-json@^5.2.0: +parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -23960,7 +22864,7 @@ parse5-sax-parser@^6.0.1: dependencies: parse5 "^6.0.1" -parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1: +parse5@^6.0.0, parse5@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== @@ -24231,7 +23135,7 @@ picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0, picocolors@^1.1.1: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -24278,7 +23182,7 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -pirates@^4.0.1, pirates@^4.0.4: +pirates@^4.0.1: version "4.0.6" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== @@ -25121,7 +24025,7 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" -pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: +pretty-format@^27.0.2: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== @@ -25244,7 +24148,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prompts@^2.0.1, prompts@^2.4.2: +prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -25287,25 +24191,6 @@ property-information@^6.0.0: resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.3.0.tgz#ba4a06ec6b4e1e90577df9931286953cdf4282c3" integrity sha512-gVNZ74nqhRMiIUYWGQdosYetaKc83x8oT41a0LlV3AAFCAZwCpg4vmGkq8t34+cUhp3cnM4XDiU/7xlgK7HGrg== -protobufjs@^6.10.2, protobufjs@^6.8.6: - version "6.11.4" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" - integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.1" - "@types/node" ">=13.7.0" - long "^4.0.0" - protocols@^2.0.0, protocols@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86" @@ -26312,11 +25197,6 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve.exports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" - integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== - resolve.exports@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" @@ -26423,7 +25303,7 @@ retext@^8.1.0: retext-stringify "^3.0.0" unified "^10.0.0" -retry-request@^4.0.0, retry-request@^4.1.1: +retry-request@^4.1.1: version "4.1.3" resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.1.3.tgz#d5f74daf261372cff58d08b0a1979b4d7cab0fde" integrity sha512-QnRZUpuPNgX0+D1xVxul6DbJ9slvo4Rm6iV/dn63e048MvGbUZiKySVt6Tenp04JqmchxjiLltGerOJys7kJYQ== @@ -26793,13 +25673,6 @@ sax@^1.2.4, sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== - dependencies: - xmlchars "^2.2.0" - saxes@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" @@ -26897,16 +25770,16 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.0, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.2, semver@^7.6.3: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== - semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.0, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.2, semver@^7.6.3: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + send@0.19.0: version "0.19.0" resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" @@ -27488,7 +26361,7 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@0.5.21, source-map-support@^0.5.21, source-map-support@^0.5.5, source-map-support@^0.5.6, source-map-support@~0.5.20: +source-map-support@0.5.21, source-map-support@^0.5.21, source-map-support@^0.5.5, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -27716,13 +26589,6 @@ stack-trace@0.0.x: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== -stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== - dependencies: - escape-string-regexp "^2.0.0" - stackback@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" @@ -27851,14 +26717,6 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - string-similarity@^4.0.1: version "4.0.4" resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" @@ -28153,7 +27011,6 @@ stylus@0.59.0, stylus@^0.59.0: sucrase@^3.27.0, sucrase@^3.35.0, sucrase@getsentry/sucrase#es2020-polyfills: version "3.36.0" - uid fd682f6129e507c00bb4e6319cc5d6b767e36061 resolved "https://codeload.github.com/getsentry/sucrase/tar.gz/fd682f6129e507c00bb4e6319cc5d6b767e36061" dependencies: "@jridgewell/gen-mapping" "^0.3.2" @@ -28190,7 +27047,7 @@ supports-color@^5.3.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: +supports-color@^7.1.0, supports-color@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -28209,14 +27066,6 @@ supports-color@^9.4.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== -supports-hyperlinks@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" - integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -28458,14 +27307,6 @@ temp@0.9.4: mkdirp "^0.5.1" rimraf "~2.6.2" -terminal-link@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" - integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== - dependencies: - ansi-escapes "^4.2.1" - supports-hyperlinks "^2.0.0" - terracotta@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/terracotta/-/terracotta-1.0.5.tgz#633d3aa630f686f383e2577d156c14d261f7eb4c" @@ -28587,11 +27428,6 @@ thenify-all@^1.0.0: dependencies: any-promise "^1.0.0" -throat@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" - integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== - throttleit@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-2.1.0.tgz#a7e4aa0bf4845a5bd10daa39ea0c783f631a07b4" @@ -28791,7 +27627,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@^4.1.2: version "4.1.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== @@ -28894,20 +27730,6 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -ts-jest@^27.1.4: - version "27.1.4" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.4.tgz#84d42cf0f4e7157a52e7c64b1492c46330943e00" - integrity sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^27.0.0" - json5 "2.x" - lodash.memoize "4.x" - make-error "1.x" - semver "7.x" - yargs-parser "20.x" - ts-node@10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -29851,15 +28673,6 @@ v8-compile-cache@2.3.0, v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -v8-to-istanbul@^8.1.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" - integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - source-map "^0.7.3" - valibot@^0.41.0: version "0.41.0" resolved "https://registry.yarnpkg.com/valibot/-/valibot-0.41.0.tgz#5c2efd49c078e455f7862379365f6036f3cd9f96" @@ -30235,20 +29048,6 @@ vue@~3.2.41: "@vue/server-renderer" "3.2.45" "@vue/shared" "3.2.45" -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" - integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" - integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== - dependencies: - xml-name-validator "^3.0.0" - w3c-xmlserializer@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" @@ -30298,7 +29097,7 @@ walkdir@^0.4.1: resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39" integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ== -walker@^1.0.7, walker@~1.0.5: +walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= @@ -30372,11 +29171,6 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webidl-conversions@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" - integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== - webidl-conversions@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" @@ -30565,13 +29359,6 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== -whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== - dependencies: - iconv-lite "0.4.24" - whatwg-encoding@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" @@ -30584,11 +29371,6 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== -whatwg-mimetype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" - integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== - whatwg-mimetype@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" @@ -30618,7 +29400,7 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0: +whatwg-url@^8.4.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== @@ -30915,7 +29697,7 @@ write-pkg@4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" -ws@^7.3.1, ws@^7.4.6: +ws@^7.3.1: version "7.5.10" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== @@ -30935,21 +29717,11 @@ xdg-basedir@^4.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - xml-name-validator@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== -xml@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" - integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw== - xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" @@ -31037,16 +29809,16 @@ yargs-parser@20.2.4: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - yargs-parser@21.1.1, yargs-parser@^21.0.0, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs-parser@^20.2.2, yargs-parser@^20.2.3: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs@16.2.0, yargs@^16.1.1, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"