@sentry/bundler-plugins 10.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +31 -0
  3. package/build/cjs/babel-plugin/constants.js +126 -0
  4. package/build/cjs/babel-plugin/constants.js.map +1 -0
  5. package/build/cjs/babel-plugin/experimental.js +334 -0
  6. package/build/cjs/babel-plugin/experimental.js.map +1 -0
  7. package/build/cjs/babel-plugin/index.js +508 -0
  8. package/build/cjs/babel-plugin/index.js.map +1 -0
  9. package/build/cjs/core/build-plugin-manager.js +583 -0
  10. package/build/cjs/core/build-plugin-manager.js.map +1 -0
  11. package/build/cjs/core/debug-id-upload.js +184 -0
  12. package/build/cjs/core/debug-id-upload.js.map +1 -0
  13. package/build/cjs/core/glob.js +10 -0
  14. package/build/cjs/core/glob.js.map +1 -0
  15. package/build/cjs/core/index.js +113 -0
  16. package/build/cjs/core/index.js.map +1 -0
  17. package/build/cjs/core/logger.js +29 -0
  18. package/build/cjs/core/logger.js.map +1 -0
  19. package/build/cjs/core/options-mapping.js +115 -0
  20. package/build/cjs/core/options-mapping.js.map +1 -0
  21. package/build/cjs/core/sentry/telemetry.js +127 -0
  22. package/build/cjs/core/sentry/telemetry.js.map +1 -0
  23. package/build/cjs/core/sentry/transports.js +108 -0
  24. package/build/cjs/core/sentry/transports.js.map +1 -0
  25. package/build/cjs/core/utils.js +298 -0
  26. package/build/cjs/core/utils.js.map +1 -0
  27. package/build/cjs/core/version.js +6 -0
  28. package/build/cjs/core/version.js.map +1 -0
  29. package/build/cjs/esbuild/index.js +208 -0
  30. package/build/cjs/esbuild/index.js.map +1 -0
  31. package/build/cjs/rollup/index.js +193 -0
  32. package/build/cjs/rollup/index.js.map +1 -0
  33. package/build/cjs/vite/index.js +28 -0
  34. package/build/cjs/vite/index.js.map +1 -0
  35. package/build/cjs/webpack/component-annotation-transform.js +29 -0
  36. package/build/cjs/webpack/component-annotation-transform.js.map +1 -0
  37. package/build/cjs/webpack/index.js +25 -0
  38. package/build/cjs/webpack/index.js.map +1 -0
  39. package/build/cjs/webpack/webpack4and5.js +185 -0
  40. package/build/cjs/webpack/webpack4and5.js.map +1 -0
  41. package/build/cjs/webpack/webpack5.js +11 -0
  42. package/build/cjs/webpack/webpack5.js.map +1 -0
  43. package/build/esm/babel-plugin/constants.js +123 -0
  44. package/build/esm/babel-plugin/constants.js.map +1 -0
  45. package/build/esm/babel-plugin/experimental.js +332 -0
  46. package/build/esm/babel-plugin/experimental.js.map +1 -0
  47. package/build/esm/babel-plugin/index.js +505 -0
  48. package/build/esm/babel-plugin/index.js.map +1 -0
  49. package/build/esm/core/build-plugin-manager.js +561 -0
  50. package/build/esm/core/build-plugin-manager.js.map +1 -0
  51. package/build/esm/core/debug-id-upload.js +161 -0
  52. package/build/esm/core/debug-id-upload.js.map +1 -0
  53. package/build/esm/core/glob.js +8 -0
  54. package/build/esm/core/glob.js.map +1 -0
  55. package/build/esm/core/index.js +82 -0
  56. package/build/esm/core/index.js.map +1 -0
  57. package/build/esm/core/logger.js +27 -0
  58. package/build/esm/core/logger.js.map +1 -0
  59. package/build/esm/core/options-mapping.js +111 -0
  60. package/build/esm/core/options-mapping.js.map +1 -0
  61. package/build/esm/core/sentry/telemetry.js +118 -0
  62. package/build/esm/core/sentry/telemetry.js.map +1 -0
  63. package/build/esm/core/sentry/transports.js +92 -0
  64. package/build/esm/core/sentry/transports.js.map +1 -0
  65. package/build/esm/core/utils.js +271 -0
  66. package/build/esm/core/utils.js.map +1 -0
  67. package/build/esm/core/version.js +4 -0
  68. package/build/esm/core/version.js.map +1 -0
  69. package/build/esm/esbuild/index.js +190 -0
  70. package/build/esm/esbuild/index.js.map +1 -0
  71. package/build/esm/package.json +1 -0
  72. package/build/esm/rollup/index.js +172 -0
  73. package/build/esm/rollup/index.js.map +1 -0
  74. package/build/esm/vite/index.js +24 -0
  75. package/build/esm/vite/index.js.map +1 -0
  76. package/build/esm/webpack/component-annotation-transform.js +27 -0
  77. package/build/esm/webpack/component-annotation-transform.js.map +1 -0
  78. package/build/esm/webpack/index.js +21 -0
  79. package/build/esm/webpack/index.js.map +1 -0
  80. package/build/esm/webpack/webpack4and5.js +168 -0
  81. package/build/esm/webpack/webpack4and5.js.map +1 -0
  82. package/build/esm/webpack/webpack5.js +8 -0
  83. package/build/esm/webpack/webpack5.js.map +1 -0
  84. package/build/types/babel-plugin/constants.d.ts +27 -0
  85. package/build/types/babel-plugin/constants.d.ts.map +1 -0
  86. package/build/types/babel-plugin/experimental.d.ts +51 -0
  87. package/build/types/babel-plugin/experimental.d.ts.map +1 -0
  88. package/build/types/babel-plugin/index.d.ts +56 -0
  89. package/build/types/babel-plugin/index.d.ts.map +1 -0
  90. package/build/types/core/build-plugin-manager.d.ts +82 -0
  91. package/build/types/core/build-plugin-manager.d.ts.map +1 -0
  92. package/build/types/core/debug-id-upload.d.ts +17 -0
  93. package/build/types/core/debug-id-upload.d.ts.map +1 -0
  94. package/build/types/core/glob.d.ts +5 -0
  95. package/build/types/core/glob.d.ts.map +1 -0
  96. package/build/types/core/index.d.ts +53 -0
  97. package/build/types/core/index.d.ts.map +1 -0
  98. package/build/types/core/logger.d.ts +14 -0
  99. package/build/types/core/logger.d.ts.map +1 -0
  100. package/build/types/core/options-mapping.d.ts +82 -0
  101. package/build/types/core/options-mapping.d.ts.map +1 -0
  102. package/build/types/core/sentry/telemetry.d.ts +14 -0
  103. package/build/types/core/sentry/telemetry.d.ts.map +1 -0
  104. package/build/types/core/sentry/transports.d.ts +5 -0
  105. package/build/types/core/sentry/transports.d.ts.map +1 -0
  106. package/build/types/core/types.d.ts +570 -0
  107. package/build/types/core/types.d.ts.map +1 -0
  108. package/build/types/core/utils.d.ts +87 -0
  109. package/build/types/core/utils.d.ts.map +1 -0
  110. package/build/types/core/version.d.ts +2 -0
  111. package/build/types/core/version.d.ts.map +1 -0
  112. package/build/types/esbuild/index.d.ts +6 -0
  113. package/build/types/esbuild/index.d.ts.map +1 -0
  114. package/build/types/rollup/index.d.ts +56 -0
  115. package/build/types/rollup/index.d.ts.map +1 -0
  116. package/build/types/vite/index.d.ts +9 -0
  117. package/build/types/vite/index.d.ts.map +1 -0
  118. package/build/types/webpack/component-annotation-transform.d.ts +11 -0
  119. package/build/types/webpack/component-annotation-transform.d.ts.map +1 -0
  120. package/build/types/webpack/index.d.ts +5 -0
  121. package/build/types/webpack/index.d.ts.map +1 -0
  122. package/build/types/webpack/webpack4and5.d.ts +99 -0
  123. package/build/types/webpack/webpack4and5.d.ts.map +1 -0
  124. package/build/types/webpack/webpack5.d.ts +5 -0
  125. package/build/types/webpack/webpack5.d.ts.map +1 -0
  126. package/build/types-ts3.8/babel-plugin/constants.d.ts +27 -0
  127. package/build/types-ts3.8/babel-plugin/experimental.d.ts +51 -0
  128. package/build/types-ts3.8/babel-plugin/index.d.ts +56 -0
  129. package/build/types-ts3.8/core/build-plugin-manager.d.ts +82 -0
  130. package/build/types-ts3.8/core/debug-id-upload.d.ts +17 -0
  131. package/build/types-ts3.8/core/glob.d.ts +5 -0
  132. package/build/types-ts3.8/core/index.d.ts +53 -0
  133. package/build/types-ts3.8/core/logger.d.ts +14 -0
  134. package/build/types-ts3.8/core/options-mapping.d.ts +82 -0
  135. package/build/types-ts3.8/core/sentry/telemetry.d.ts +14 -0
  136. package/build/types-ts3.8/core/sentry/transports.d.ts +5 -0
  137. package/build/types-ts3.8/core/types.d.ts +570 -0
  138. package/build/types-ts3.8/core/utils.d.ts +87 -0
  139. package/build/types-ts3.8/core/version.d.ts +2 -0
  140. package/build/types-ts3.8/esbuild/index.d.ts +6 -0
  141. package/build/types-ts3.8/rollup/index.d.ts +56 -0
  142. package/build/types-ts3.8/vite/index.d.ts +9 -0
  143. package/build/types-ts3.8/webpack/component-annotation-transform.d.ts +11 -0
  144. package/build/types-ts3.8/webpack/index.d.ts +5 -0
  145. package/build/types-ts3.8/webpack/webpack4and5.d.ts +99 -0
  146. package/build/types-ts3.8/webpack/webpack5.d.ts +5 -0
  147. package/package.json +153 -0
  148. package/sentry-esbuild-debugid-injection-file.js +20 -0
  149. package/sentry-release-injection-file.js +4 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-plugin-manager.js","sources":["../../../src/core/build-plugin-manager.ts"],"sourcesContent":["/* oxlint-disable max-lines */\nimport SentryCli from '@sentry/cli';\nimport { closeSession, DEFAULT_ENVIRONMENT, getTraceData, makeSession, setMeasurement, startSpan } from '@sentry/core';\nimport * as dotenv from 'dotenv';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\nimport type { NormalizedOptions } from './options-mapping';\nimport { normalizeUserOptions, validateOptions } from './options-mapping';\nimport type { Logger } from './logger';\nimport { createLogger } from './logger';\nimport { allowedToSendTelemetry, createSentryInstance, safeFlushTelemetry } from './sentry/telemetry';\nimport type { Options, SentrySDKBuildFlags } from './types';\nimport {\n arrayify,\n getProjects,\n getTurborepoEnvPassthroughWarning,\n serializeIgnoreOptions,\n stripQueryAndHashFromPath,\n} from './utils';\nimport { defaultRewriteSourcesHook, prepareBundleForDebugIdUpload } from './debug-id-upload';\nimport { globFiles } from './glob';\nimport { LIB_VERSION } from './version';\n\n// Module-level guard to prevent duplicate deploy records when multiple bundler plugin\n// instances run in the same process (e.g. Next.js creates separate webpack compilers\n// for client, server, and edge). Keyed by release name.\nconst _deployedReleases = new Set<string>();\n\n/** @internal Exported for testing only. */\nexport function _resetDeployedReleasesForTesting(): void {\n _deployedReleases.clear();\n}\n\nexport type SentryBuildPluginManager = {\n /**\n * A logger instance that takes the options passed to the build plugin manager into account. (for silencing and log level etc.)\n */\n logger: Logger;\n\n /**\n * Options after normalization. Includes things like the inferred release name.\n */\n normalizedOptions: NormalizedOptions;\n /**\n * Magic strings and their replacement values that can be used for bundle size optimizations. This already takes\n * into account the options passed to the build plugin manager.\n */\n bundleSizeOptimizationReplacementValues: SentrySDKBuildFlags;\n /**\n * Metadata that should be injected into bundles if possible. Takes into account options passed to the build plugin manager.\n */\n // See `generateModuleMetadataInjectorCode` for how this should be used exactly\n bundleMetadata: Record<string, unknown>;\n\n /**\n * Contains utility functions for emitting telemetry via the build plugin manager.\n */\n telemetry: {\n /**\n * Emits a `Sentry Bundler Plugin execution` signal.\n */\n emitBundlerPluginExecutionSignal(): Promise<void>;\n };\n\n /**\n * Will potentially create a release based on the build plugin manager options.\n *\n * Also\n * - finalizes the release\n * - sets commits\n * - uploads legacy sourcemaps\n * - adds deploy information\n */\n createRelease(): Promise<void>;\n\n /**\n * Injects debug IDs into the build artifacts.\n *\n * This is a separate function from `uploadSourcemaps` because that needs to run before the sourcemaps are uploaded.\n * Usually the respective bundler-plugin will take care of this before the sourcemaps are uploaded.\n * Only use this if you need to manually inject debug IDs into the build artifacts.\n */\n injectDebugIds(buildArtifactPaths: string[]): Promise<void>;\n\n /**\n * Uploads sourcemaps using the \"Debug ID\" method. This function takes a list of build artifact paths that will be uploaded\n */\n uploadSourcemaps(buildArtifactPaths: string[], opts?: { prepareArtifacts?: boolean }): Promise<void>;\n\n /**\n * Will delete artifacts based on the passed `sourcemaps.filesToDeleteAfterUpload` option.\n */\n deleteArtifacts(): Promise<void>;\n\n createDependencyOnBuildArtifacts: () => () => void;\n};\n\nfunction createCliInstance(options: NormalizedOptions): SentryCli {\n return new SentryCli(null, {\n authToken: options.authToken,\n org: options.org,\n // Default to the first project if multiple projects are specified\n project: getProjects(options.project)?.[0],\n silent: options.silent,\n url: options.url,\n vcsRemote: options.release.vcsRemote,\n headers: {\n ...(options.telemetry ? getTraceData() : {}),\n ...options.headers,\n },\n });\n}\n\n/**\n * Creates a build plugin manager that exposes primitives for everything that a Sentry JavaScript SDK or build tooling may do during a build.\n *\n * The build plugin manager's behavior strongly depends on the options that are passed in.\n */\nexport function createSentryBuildPluginManager(\n userOptions: Options,\n bundlerPluginMetaContext: {\n /**\n * E.g. `webpack` or `nextjs` or `turbopack`\n */\n buildTool: string;\n /**\n * E.g. `5` for webpack v5 or `4` for Rollup v4\n */\n buildToolMajorVersion?: string;\n /**\n * E.g. `[sentry-webpack-plugin]` or `[@sentry/nextjs]`\n */\n loggerPrefix: string;\n },\n): SentryBuildPluginManager {\n const logger = createLogger({\n prefix: bundlerPluginMetaContext.loggerPrefix,\n silent: userOptions.silent ?? false,\n debug: userOptions.debug ?? false,\n });\n\n try {\n const dotenvFile = fs.readFileSync(path.join(process.cwd(), '.env.sentry-build-plugin'), 'utf-8');\n // NOTE: Do not use the dotenv.config API directly to read the dotenv file! For some ungodly reason, it falls back to reading `${process.cwd()}/.env` which is absolutely not what we want.\n const dotenvResult = dotenv.parse(dotenvFile);\n\n // Vite has a bug/behaviour where spreading into process.env will cause it to crash\n // https://github.com/vitest-dev/vitest/issues/1870#issuecomment-1501140251\n Object.assign(process.env, dotenvResult);\n\n logger.info('Using environment variables configured in \".env.sentry-build-plugin\".');\n } catch (e: unknown) {\n // Ignore \"file not found\" errors but throw all others\n if (typeof e === 'object' && e && 'code' in e && e.code !== 'ENOENT') {\n throw e;\n }\n }\n\n const options = normalizeUserOptions(userOptions);\n\n if (options.disable) {\n // Early-return a noop build plugin manager instance so that we\n // don't continue validating options, setting up Sentry, etc.\n // Otherwise we might create side-effects or log messages that\n // users don't expect from a disabled plugin.\n return {\n normalizedOptions: options,\n logger,\n bundleSizeOptimizationReplacementValues: {},\n telemetry: {\n emitBundlerPluginExecutionSignal: async () => {\n /* noop */\n },\n },\n bundleMetadata: {},\n createRelease: async () => {\n /* noop */\n },\n uploadSourcemaps: async () => {\n /* noop */\n },\n deleteArtifacts: async () => {\n /* noop */\n },\n createDependencyOnBuildArtifacts: () => () => {\n /* noop */\n },\n injectDebugIds: async () => {\n /* noop */\n },\n };\n }\n\n const shouldSendTelemetry = allowedToSendTelemetry(options);\n const { sentryScope, sentryClient } = createSentryInstance(\n options,\n shouldSendTelemetry,\n bundlerPluginMetaContext.buildTool,\n bundlerPluginMetaContext.buildToolMajorVersion,\n );\n\n const { release, environment = DEFAULT_ENVIRONMENT } = sentryClient.getOptions();\n\n const sentrySession = makeSession({ release, environment });\n sentryScope.setSession(sentrySession);\n // Send the start of the session\n sentryClient.captureSession(sentrySession);\n\n let sessionHasEnded = false; // Just to prevent infinite loops with beforeExit, which is called whenever the event loop empties out\n\n function endSession(): void {\n if (sessionHasEnded) {\n return;\n }\n\n closeSession(sentrySession);\n sentryClient.captureSession(sentrySession);\n sessionHasEnded = true;\n }\n\n // We also need to manually end sessions on errors because beforeExit is not called on crashes\n process.on('beforeExit', () => {\n endSession();\n });\n\n // Set the User-Agent that Sentry CLI will use when interacting with Sentry\n process.env['SENTRY_PIPELINE'] = `${bundlerPluginMetaContext.buildTool}-plugin/${LIB_VERSION}`;\n\n // Propagate debug flag to Sentry CLI via environment variable\n // Only set if not already defined to respect user's explicit configuration\n if (options.debug && !process.env['SENTRY_LOG_LEVEL']) {\n process.env['SENTRY_LOG_LEVEL'] = 'debug';\n }\n\n // Not a bulletproof check but should be good enough to at least sometimes determine\n // if the plugin is called in dev/watch mode or for a prod build. The important part\n // here is to avoid a false positive. False negatives are okay.\n const isDevMode = process.env['NODE_ENV'] === 'development';\n\n /**\n * Handles errors caught and emitted in various areas of the plugin.\n *\n * Also sets the sentry session status according to the error handling.\n *\n * If users specify their custom `errorHandler` we'll leave the decision to throw\n * or continue up to them. By default, @param throwByDefault controls if the plugin\n * should throw an error (which causes a build fail in most bundlers) or continue.\n */\n function handleRecoverableError(unknownError: unknown, throwByDefault: boolean): void {\n sentrySession.status = 'abnormal';\n try {\n if (options.errorHandler) {\n try {\n if (unknownError instanceof Error) {\n options.errorHandler(unknownError);\n } else {\n options.errorHandler(new Error('An unknown error occurred'));\n }\n } catch (e) {\n sentrySession.status = 'crashed';\n throw e;\n }\n } else {\n // setting the session to \"crashed\" b/c from a plugin perspective this run failed.\n // However, we're intentionally not rethrowing the error to avoid breaking the user build.\n sentrySession.status = 'crashed';\n if (throwByDefault) {\n throw unknownError;\n }\n logger.error(\"An error occurred. Couldn't finish all operations:\", unknownError);\n }\n } finally {\n endSession();\n }\n }\n\n if (!validateOptions(options, logger)) {\n // Throwing by default to avoid a misconfigured plugin going unnoticed.\n handleRecoverableError(new Error('Options were not set correctly. See output above for more details.'), true);\n }\n\n // We have multiple plugins depending on generated source map files. (debug ID upload, legacy upload)\n // Additionally, we also want to have the functionality to delete files after uploading sourcemaps.\n // All of these plugins and the delete functionality need to run in the same hook (`writeBundle`).\n // Since the plugins among themselves are not aware of when they run and finish, we need a system to\n // track their dependencies on the generated files, so that we can initiate the file deletion only after\n // nothing depends on the files anymore.\n const dependenciesOnBuildArtifacts = new Set<symbol>();\n const buildArtifactsDependencySubscribers: (() => void)[] = [];\n\n function notifyBuildArtifactDependencySubscribers(): void {\n buildArtifactsDependencySubscribers.forEach(subscriber => {\n subscriber();\n });\n }\n\n function createDependencyOnBuildArtifacts(): () => void {\n const dependencyIdentifier = Symbol();\n dependenciesOnBuildArtifacts.add(dependencyIdentifier);\n\n return function freeDependencyOnBuildArtifacts() {\n dependenciesOnBuildArtifacts.delete(dependencyIdentifier);\n notifyBuildArtifactDependencySubscribers();\n };\n }\n\n /**\n * Returns a Promise that resolves when all the currently active dependencies are freed again.\n *\n * It is very important that this function is called as late as possible before wanting to await the Promise to give\n * the dependency producers as much time as possible to register themselves.\n */\n function waitUntilBuildArtifactDependenciesAreFreed(): Promise<void> {\n return new Promise<void>(resolve => {\n buildArtifactsDependencySubscribers.push(() => {\n if (dependenciesOnBuildArtifacts.size === 0) {\n resolve();\n }\n });\n\n if (dependenciesOnBuildArtifacts.size === 0) {\n resolve();\n }\n });\n }\n\n const bundleSizeOptimizationReplacementValues: SentrySDKBuildFlags = {};\n if (options.bundleSizeOptimizations) {\n const { bundleSizeOptimizations } = options;\n\n if (bundleSizeOptimizations.excludeDebugStatements) {\n bundleSizeOptimizationReplacementValues['__SENTRY_DEBUG__'] = false;\n }\n if (bundleSizeOptimizations.excludeTracing) {\n bundleSizeOptimizationReplacementValues['__SENTRY_TRACING__'] = false;\n }\n if (bundleSizeOptimizations.excludeReplayCanvas) {\n bundleSizeOptimizationReplacementValues['__RRWEB_EXCLUDE_CANVAS__'] = true;\n }\n if (bundleSizeOptimizations.excludeReplayIframe) {\n bundleSizeOptimizationReplacementValues['__RRWEB_EXCLUDE_IFRAME__'] = true;\n }\n if (bundleSizeOptimizations.excludeReplayShadowDom) {\n bundleSizeOptimizationReplacementValues['__RRWEB_EXCLUDE_SHADOW_DOM__'] = true;\n }\n if (bundleSizeOptimizations.excludeReplayWorker) {\n bundleSizeOptimizationReplacementValues['__SENTRY_EXCLUDE_REPLAY_WORKER__'] = true;\n }\n }\n\n let bundleMetadata: Record<string, unknown> = {};\n if (options.moduleMetadata || options.applicationKey) {\n if (options.applicationKey) {\n // We use different keys so that if user-code receives multiple bundling passes, we will store the application keys of all the passes.\n // It is a bit unfortunate that we have to inject the metadata snippet at the top, because after multiple\n // injections, the first injection will always \"win\" because it comes last in the code. We would generally be\n // fine with making the last bundling pass win. But because it cannot win, we have to use a workaround of storing\n // the app keys in different object keys.\n // We can simply use the `_sentryBundlerPluginAppKey:` to filter for app keys in the SDK.\n bundleMetadata[`_sentryBundlerPluginAppKey:${options.applicationKey}`] = true;\n }\n\n if (typeof options.moduleMetadata === 'function') {\n const args = {\n org: options.org,\n project: getProjects(options.project)?.[0],\n projects: getProjects(options.project),\n release: options.release.name,\n };\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n bundleMetadata = { ...bundleMetadata, ...options.moduleMetadata(args) };\n } else {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n bundleMetadata = { ...bundleMetadata, ...options.moduleMetadata };\n }\n }\n\n return {\n /**\n * A logger instance that takes the options passed to the build plugin manager into account. (for silencing and log level etc.)\n */\n logger,\n\n /**\n * Options after normalization. Includes things like the inferred release name.\n */\n normalizedOptions: options,\n\n /**\n * Magic strings and their replacement values that can be used for bundle size optimizations. This already takes\n * into account the options passed to the build plugin manager.\n */\n bundleSizeOptimizationReplacementValues,\n\n /**\n * Metadata that should be injected into bundles if possible. Takes into account options passed to the build plugin manager.\n */\n // See `generateModuleMetadataInjectorCode` for how this should be used exactly\n bundleMetadata,\n\n /**\n * Contains utility functions for emitting telemetry via the build plugin manager.\n */\n telemetry: {\n /**\n * Emits a `Sentry Bundler Plugin execution` signal.\n */\n async emitBundlerPluginExecutionSignal() {\n if (await shouldSendTelemetry) {\n logger.info(\n 'Sending telemetry data on issues and performance to Sentry. To disable telemetry, set `options.telemetry` to `false`.',\n );\n startSpan({ name: 'Sentry Bundler Plugin execution', scope: sentryScope }, () => {\n //\n });\n await safeFlushTelemetry(sentryClient);\n }\n },\n },\n\n /**\n * Will potentially create a release based on the build plugin manager options.\n *\n * Also\n * - finalizes the release\n * - sets commits\n * - uploads legacy sourcemaps\n * - adds deploy information\n */\n async createRelease() {\n if (!options.release.name) {\n logger.debug(\n 'No release name provided. Will not create release. Please set the `release.name` option to identify your release.',\n );\n return;\n } else if (isDevMode) {\n logger.debug('Running in development mode. Will not create release.');\n return;\n } else if (!options.authToken) {\n logger.warn(\n `No auth token provided. Will not create release. Please set the \\`authToken\\` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/${getTurborepoEnvPassthroughWarning('SENTRY_AUTH_TOKEN')}`,\n );\n return;\n } else if (!options.org && !options.authToken.startsWith('sntrys_')) {\n logger.warn(\n `No organization slug provided. Will not create release. Please set the \\`org\\` option to your Sentry organization slug.${getTurborepoEnvPassthroughWarning('SENTRY_ORG')}`,\n );\n return;\n } else if (!options.project || (Array.isArray(options.project) && options.project.length === 0)) {\n logger.warn(\n `No project provided. Will not create release. Please set the \\`project\\` option to your Sentry project slug.${getTurborepoEnvPassthroughWarning('SENTRY_PROJECT')}`,\n );\n return;\n }\n\n // It is possible that this writeBundle hook is called multiple times in one build (for example when reusing the plugin, or when using build tooling like `@vitejs/plugin-legacy`)\n // Therefore we need to actually register the execution of this hook as dependency on the sourcemap files.\n const freeWriteBundleInvocationDependencyOnSourcemapFiles = createDependencyOnBuildArtifacts();\n\n try {\n const cliInstance = createCliInstance(options);\n\n if (options.release.create) {\n const releaseOutput = await cliInstance.releases.new(options.release.name);\n logger.debug('Release created:', releaseOutput);\n }\n\n if (options.release.uploadLegacySourcemaps) {\n const normalizedInclude = arrayify(options.release.uploadLegacySourcemaps)\n .map(includeItem => (typeof includeItem === 'string' ? { paths: [includeItem] } : includeItem))\n .map(includeEntry => ({\n ...includeEntry,\n validate: includeEntry.validate ?? false,\n ext: includeEntry.ext\n ? includeEntry.ext.map(extension => `.${extension.replace(/^\\./, '')}`)\n : ['.js', '.map', '.jsbundle', '.bundle'],\n ignore: includeEntry.ignore ? arrayify(includeEntry.ignore) : undefined,\n }));\n\n await cliInstance.releases.uploadSourceMaps(options.release.name, {\n include: normalizedInclude,\n dist: options.release.dist,\n projects: getProjects(options.project),\n // We want this promise to throw if the sourcemaps fail to upload so that we know about it.\n // see: https://github.com/getsentry/sentry-cli/pull/2605\n live: 'rejectOnError',\n });\n }\n\n if (options.release.setCommits !== false) {\n try {\n await cliInstance.releases.setCommits(\n options.release.name,\n // set commits always exists due to the normalize function\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n options.release.setCommits!,\n );\n } catch (e) {\n // shouldNotThrowOnFailure being present means that the plugin defaulted to `{ auto: true }` for the setCommitsOptions, meaning that wee should not throw when CLI throws because there is no repo\n if (\n options.release.setCommits &&\n 'shouldNotThrowOnFailure' in options.release.setCommits &&\n options.release.setCommits.shouldNotThrowOnFailure\n ) {\n logger.debug(\n 'An error occurred setting commits on release (this message can be ignored unless you commits on release are desired):',\n e,\n );\n } else {\n throw e;\n }\n }\n }\n\n if (options.release.finalize) {\n await cliInstance.releases.finalize(options.release.name);\n }\n\n if (options.release.deploy && !_deployedReleases.has(options.release.name)) {\n await cliInstance.releases.newDeploy(options.release.name, options.release.deploy);\n _deployedReleases.add(options.release.name);\n }\n } catch (e) {\n sentryScope.captureException('Error in \"releaseManagementPlugin\" writeBundle hook');\n await safeFlushTelemetry(sentryClient);\n handleRecoverableError(e, false);\n } finally {\n freeWriteBundleInvocationDependencyOnSourcemapFiles();\n }\n },\n\n /*\n Injects debug IDs into the build artifacts.\n\n This is a separate function from `uploadSourcemaps` because that needs to run before the sourcemaps are uploaded.\n Usually the respective bundler-plugin will take care of this before the sourcemaps are uploaded.\n Only use this if you need to manually inject debug IDs into the build artifacts.\n */\n async injectDebugIds(buildArtifactPaths: string[]) {\n await startSpan({ name: 'inject-debug-ids', scope: sentryScope, forceTransaction: true }, async () => {\n try {\n const cliInstance = createCliInstance(options);\n await cliInstance.execute(\n ['sourcemaps', 'inject', ...serializeIgnoreOptions(options.sourcemaps?.ignore), ...buildArtifactPaths],\n options.debug ? 'rejectOnError' : false,\n );\n } catch (e) {\n sentryScope.captureException('Error in \"debugIdInjectionPlugin\" writeBundle hook');\n handleRecoverableError(e, false);\n } finally {\n await safeFlushTelemetry(sentryClient);\n }\n });\n },\n\n /**\n * Uploads sourcemaps using the \"Debug ID\" method.\n *\n * By default, this prepares bundles in a temporary folder before uploading. You can opt into an\n * in-place, direct upload path by setting `prepareArtifacts` to `false`. If `prepareArtifacts` is set to\n * `false`, no preparation (e.g. adding `//# debugId=...` and writing adjusted source maps) is performed and no temp folder is used.\n *\n * @param buildArtifactPaths - The paths of the build artifacts to upload\n * @param opts - Optional flags to control temp folder usage and preparation\n */\n async uploadSourcemaps(buildArtifactPaths: string[], opts?: { prepareArtifacts?: boolean }) {\n if (!canUploadSourceMaps(options, logger, isDevMode)) {\n return;\n }\n\n // Early exit if assets is explicitly set to an empty array\n const assets = options.sourcemaps?.assets;\n if (Array.isArray(assets) && assets.length === 0) {\n logger.debug('Empty `sourcemaps.assets` option provided. Will not upload sourcemaps with debug ID.');\n return;\n }\n\n await startSpan(\n // This is `forceTransaction`ed because this span is used in dashboards in the form of indexed transactions.\n { name: 'debug-id-sourcemap-upload', scope: sentryScope, forceTransaction: true },\n async () => {\n // If we're not using a temp folder, we must not prepare artifacts in-place (to avoid mutating user files)\n const shouldPrepare = opts?.prepareArtifacts ?? true;\n\n let folderToCleanUp: string | undefined;\n\n // It is possible that this writeBundle hook (which calls this function) is called multiple times in one build (for example when reusing the plugin, or when using build tooling like `@vitejs/plugin-legacy`)\n // Therefore we need to actually register the execution of this hook as dependency on the sourcemap files.\n const freeUploadDependencyOnBuildArtifacts = createDependencyOnBuildArtifacts();\n\n try {\n if (!shouldPrepare) {\n // Direct CLI upload from existing artifact paths (no globbing, no preparation)\n let pathsToUpload: string[];\n\n if (assets) {\n pathsToUpload = Array.isArray(assets) ? assets : [assets];\n logger.debug(\n `Direct upload mode: passing user-provided assets directly to CLI: ${pathsToUpload.join(', ')}`,\n );\n } else {\n // Use original paths e.g. like ['.next/server'] directly –> preferred way when no globbing is done\n pathsToUpload = buildArtifactPaths;\n }\n\n const ignorePaths = options.sourcemaps?.ignore\n ? Array.isArray(options.sourcemaps?.ignore)\n ? options.sourcemaps?.ignore\n : [options.sourcemaps?.ignore]\n : [];\n await startSpan({ name: 'upload', scope: sentryScope }, async () => {\n const cliInstance = createCliInstance(options);\n await cliInstance.releases.uploadSourceMaps(options.release.name ?? 'undefined', {\n include: [\n {\n paths: pathsToUpload,\n rewrite: true,\n dist: options.release.dist,\n },\n ],\n ignore: ignorePaths,\n projects: getProjects(options.project),\n live: 'rejectOnError',\n });\n });\n\n logger.info('Successfully uploaded source maps to Sentry');\n } else {\n // Prepare artifacts in temp folder before uploading\n let globAssets: string | string[];\n if (assets) {\n globAssets = assets;\n } else {\n logger.debug(\n 'No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts.',\n );\n globAssets = buildArtifactPaths;\n }\n\n const globResult = await startSpan(\n { name: 'glob', scope: sentryScope },\n async () => await globFiles(globAssets, { ignore: options.sourcemaps?.ignore }),\n );\n\n const debugIdChunkFilePaths = globResult.filter(debugIdChunkFilePath => {\n return !!stripQueryAndHashFromPath(debugIdChunkFilePath).match(/\\.(js|mjs|cjs)$/);\n });\n\n // The order of the files output by glob() is not deterministic\n // Ensure order within the files so that {debug-id}-{chunkIndex} coupling is consistent\n debugIdChunkFilePaths.sort();\n\n if (debugIdChunkFilePaths.length === 0) {\n logger.warn(\n \"Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option.\",\n );\n } else {\n const tmpUploadFolder = await startSpan({ name: 'mkdtemp', scope: sentryScope }, async () => {\n return (\n process.env?.['SENTRY_TEST_OVERRIDE_TEMP_DIR'] ||\n (await fs.promises.mkdtemp(path.join(os.tmpdir(), 'sentry-bundler-plugin-upload-')))\n );\n });\n folderToCleanUp = tmpUploadFolder;\n\n // Prepare into temp folder, then upload\n await startSpan({ name: 'prepare-bundles', scope: sentryScope }, async prepBundlesSpan => {\n // Preparing the bundles can be a lot of work and doing it all at once has the potential of nuking the heap so\n // instead we do it with a maximum of 16 concurrent workers\n const preparationTasks = debugIdChunkFilePaths.map((chunkFilePath, chunkIndex) => async () => {\n await prepareBundleForDebugIdUpload(\n chunkFilePath,\n tmpUploadFolder,\n chunkIndex,\n logger,\n options.sourcemaps?.rewriteSources ?? defaultRewriteSourcesHook,\n options.sourcemaps?.resolveSourceMap,\n );\n });\n const workers: Promise<void>[] = [];\n const worker = async (): Promise<void> => {\n while (preparationTasks.length > 0) {\n const task = preparationTasks.shift();\n if (task) {\n await task();\n }\n }\n };\n for (let workerIndex = 0; workerIndex < 16; workerIndex++) {\n workers.push(worker());\n }\n\n await Promise.all(workers);\n\n const files = await fs.promises.readdir(tmpUploadFolder);\n const stats = files.map(file => fs.promises.stat(path.join(tmpUploadFolder, file)));\n const uploadSize = (await Promise.all(stats)).reduce(\n (accumulator, { size }) => accumulator + size,\n 0,\n );\n\n setMeasurement('files', files.length, 'none', prepBundlesSpan);\n setMeasurement('upload_size', uploadSize, 'byte', prepBundlesSpan);\n\n await startSpan({ name: 'upload', scope: sentryScope }, async () => {\n const cliInstance = createCliInstance(options);\n await cliInstance.releases.uploadSourceMaps(options.release.name ?? 'undefined', {\n include: [\n {\n paths: [tmpUploadFolder],\n rewrite: false,\n dist: options.release.dist,\n },\n ],\n projects: getProjects(options.project),\n live: 'rejectOnError',\n });\n });\n });\n\n logger.info('Successfully uploaded source maps to Sentry');\n }\n }\n } catch (e) {\n sentryScope.captureException('Error in \"debugIdUploadPlugin\" writeBundle hook');\n handleRecoverableError(e, false);\n } finally {\n if (folderToCleanUp && !process.env?.['SENTRY_TEST_OVERRIDE_TEMP_DIR']) {\n logger.debug('Cleaning up temporary files...');\n try {\n await startSpan({ name: 'cleanup', scope: sentryScope }, async () => {\n if (folderToCleanUp) {\n await fs.promises.rm(folderToCleanUp, { recursive: true, force: true });\n logger.debug(`Temporary folder deleted: ${folderToCleanUp}`);\n }\n });\n } catch (e) {\n // A failed cleanup must not skip the teardown steps below (freeing upload\n // dependencies, flushing telemetry), so swallow and log instead of rethrowing.\n logger.debug('Failed to clean up temporary folder:', e);\n }\n }\n logger.debug('Freeing upload dependencies...');\n freeUploadDependencyOnBuildArtifacts();\n logger.debug('Flushing telemetry data...');\n await safeFlushTelemetry(sentryClient);\n logger.debug('Telemetry flushed. Plugin upload process complete.');\n }\n },\n );\n },\n\n /**\n * Will delete artifacts based on the passed `sourcemaps.filesToDeleteAfterUpload` option.\n */\n async deleteArtifacts() {\n try {\n const filesToDelete = await options.sourcemaps?.filesToDeleteAfterUpload;\n if (filesToDelete !== undefined) {\n const filePathsToDelete = await globFiles(filesToDelete);\n\n logger.debug('Waiting for dependencies on generated files to be freed before deleting...');\n\n await waitUntilBuildArtifactDependenciesAreFreed();\n\n filePathsToDelete.forEach(filePathToDelete => {\n logger.debug(`Deleting asset after upload: ${filePathToDelete}`);\n });\n\n await Promise.all(\n filePathsToDelete.map(filePathToDelete =>\n fs.promises.rm(filePathToDelete, { force: true }).catch(e => {\n // This is allowed to fail - we just don't do anything\n logger.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);\n }),\n ),\n );\n }\n } catch (e) {\n sentryScope.captureException('Error in \"sentry-file-deletion-plugin\" buildEnd hook');\n await safeFlushTelemetry(sentryClient);\n // We throw by default if we get here b/c not being able to delete\n // source maps could leak them to production\n handleRecoverableError(e, true);\n }\n },\n createDependencyOnBuildArtifacts,\n };\n}\n\nfunction canUploadSourceMaps(options: NormalizedOptions, logger: Logger, isDevMode: boolean): boolean {\n if (options.sourcemaps?.disable) {\n logger.debug('Source map upload was disabled. Will not upload sourcemaps using debug ID process.');\n return false;\n }\n if (isDevMode) {\n logger.debug('Running in development mode. Will not upload sourcemaps.');\n return false;\n }\n if (!options.authToken) {\n logger.warn(\n `No auth token provided. Will not upload source maps. Please set the \\`authToken\\` option. You can find information on how to generate a Sentry auth token here: https://docs.sentry.io/api/auth/${getTurborepoEnvPassthroughWarning('SENTRY_AUTH_TOKEN')}`,\n );\n return false;\n }\n if (!options.org && !options.authToken.startsWith('sntrys_')) {\n logger.warn(\n `No org provided. Will not upload source maps. Please set the \\`org\\` option to your Sentry organization slug.${getTurborepoEnvPassthroughWarning('SENTRY_ORG')}`,\n );\n return false;\n }\n if (!getProjects(options.project)?.[0]) {\n logger.warn(\n `No project provided. Will not upload source maps. Please set the \\`project\\` option to your Sentry project slug.${getTurborepoEnvPassthroughWarning('SENTRY_PROJECT')}`,\n );\n return false;\n }\n\n return true;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,161 @@
1
+ import fs__default from 'fs';
2
+ import path__default from 'path';
3
+ import * as url from 'url';
4
+ import * as util from 'util';
5
+ import { promisify } from 'util';
6
+ import { stripQueryAndHashFromPath } from './utils.js';
7
+
8
+ function createDebugIdUploadFunction({ sentryBuildPluginManager }) {
9
+ return async (buildArtifactPaths) => {
10
+ const cleanedPaths = buildArtifactPaths.map(stripQueryAndHashFromPath);
11
+ await sentryBuildPluginManager.uploadSourcemaps(cleanedPaths);
12
+ };
13
+ }
14
+ async function prepareBundleForDebugIdUpload(bundleFilePath, uploadFolder, chunkIndex, logger, rewriteSourcesHook, resolveSourceMapHook) {
15
+ let bundleContent;
16
+ try {
17
+ bundleContent = await promisify(fs__default.readFile)(bundleFilePath, "utf8");
18
+ } catch (e) {
19
+ logger.error(`Could not read bundle to determine debug ID and source map: ${bundleFilePath}`, e);
20
+ return;
21
+ }
22
+ const debugId = determineDebugIdFromBundleSource(bundleContent);
23
+ if (debugId === void 0) {
24
+ logger.debug(
25
+ `Could not determine debug ID from bundle. This can happen if you did not clean your output folder before installing the Sentry plugin. File will not be source mapped: ${bundleFilePath}`
26
+ );
27
+ return;
28
+ }
29
+ const uniqueUploadName = `${debugId}-${chunkIndex}`;
30
+ bundleContent = addDebugIdToBundleSource(bundleContent, debugId);
31
+ const writeSourceFilePromise = fs__default.promises.writeFile(
32
+ path__default.join(uploadFolder, `${uniqueUploadName}.js`),
33
+ bundleContent,
34
+ "utf-8"
35
+ );
36
+ const writeSourceMapFilePromise = determineSourceMapPathFromBundle(
37
+ bundleFilePath,
38
+ bundleContent,
39
+ logger,
40
+ resolveSourceMapHook
41
+ ).then(async (sourceMapPath) => {
42
+ if (sourceMapPath) {
43
+ await prepareSourceMapForDebugIdUpload(
44
+ sourceMapPath,
45
+ path__default.join(uploadFolder, `${uniqueUploadName}.js.map`),
46
+ debugId,
47
+ rewriteSourcesHook,
48
+ logger
49
+ );
50
+ }
51
+ });
52
+ await writeSourceFilePromise;
53
+ await writeSourceMapFilePromise;
54
+ }
55
+ function determineDebugIdFromBundleSource(code) {
56
+ const match = code.match(
57
+ /sentry-dbid-([0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12})/
58
+ );
59
+ if (match) {
60
+ return match[1];
61
+ } else {
62
+ return void 0;
63
+ }
64
+ }
65
+ const SPEC_LAST_DEBUG_ID_REGEX = /\/\/# debugId=([a-fA-F0-9-]+)(?![\s\S]*\/\/# debugId=)/m;
66
+ function hasSpecCompliantDebugId(bundleSource) {
67
+ return SPEC_LAST_DEBUG_ID_REGEX.test(bundleSource);
68
+ }
69
+ function addDebugIdToBundleSource(bundleSource, debugId) {
70
+ if (hasSpecCompliantDebugId(bundleSource)) {
71
+ return bundleSource.replace(SPEC_LAST_DEBUG_ID_REGEX, `//# debugId=${debugId}`);
72
+ } else {
73
+ return `${bundleSource}
74
+ //# debugId=${debugId}`;
75
+ }
76
+ }
77
+ async function determineSourceMapPathFromBundle(bundlePath, bundleSource, logger, resolveSourceMapHook) {
78
+ const sourceMappingUrlMatch = bundleSource.match(/^\s*\/\/# sourceMappingURL=(.*)$/m);
79
+ const sourceMappingUrl = sourceMappingUrlMatch ? sourceMappingUrlMatch[1] : void 0;
80
+ const searchLocations = [];
81
+ if (resolveSourceMapHook) {
82
+ logger.debug(
83
+ `Calling sourcemaps.resolveSourceMap(${JSON.stringify(bundlePath)}, ${JSON.stringify(sourceMappingUrl)})`
84
+ );
85
+ const customPath = await resolveSourceMapHook(bundlePath, sourceMappingUrl);
86
+ logger.debug(`resolveSourceMap hook returned: ${JSON.stringify(customPath)}`);
87
+ if (customPath) {
88
+ searchLocations.push(customPath);
89
+ }
90
+ }
91
+ if (sourceMappingUrl) {
92
+ let parsedUrl;
93
+ try {
94
+ parsedUrl = new URL(sourceMappingUrl);
95
+ } catch {
96
+ }
97
+ if (parsedUrl?.protocol === "file:") {
98
+ searchLocations.push(url.fileURLToPath(sourceMappingUrl));
99
+ } else if (parsedUrl) ; else if (path__default.isAbsolute(sourceMappingUrl)) {
100
+ searchLocations.push(path__default.normalize(sourceMappingUrl));
101
+ } else {
102
+ searchLocations.push(path__default.normalize(path__default.join(path__default.dirname(bundlePath), sourceMappingUrl)));
103
+ }
104
+ }
105
+ searchLocations.push(`${bundlePath}.map`);
106
+ for (const searchLocation of searchLocations) {
107
+ try {
108
+ await util.promisify(fs__default.access)(searchLocation);
109
+ logger.debug(`Source map found for bundle \`${bundlePath}\`: \`${searchLocation}\``);
110
+ return searchLocation;
111
+ } catch {
112
+ }
113
+ }
114
+ logger.debug(
115
+ `Could not determine source map path for bundle \`${bundlePath}\` with sourceMappingURL=${sourceMappingUrl === void 0 ? "undefined" : `\`${sourceMappingUrl}\``} - Did you turn on source map generation in your bundler? (Attempted paths: ${searchLocations.map((e) => `\`${e}\``).join(", ")})`
116
+ );
117
+ return void 0;
118
+ }
119
+ async function prepareSourceMapForDebugIdUpload(sourceMapPath, targetPath, debugId, rewriteSourcesHook, logger) {
120
+ let sourceMapFileContent;
121
+ try {
122
+ sourceMapFileContent = await util.promisify(fs__default.readFile)(sourceMapPath, {
123
+ encoding: "utf8"
124
+ });
125
+ } catch (e) {
126
+ logger.error(`Failed to read source map for debug ID upload: ${sourceMapPath}`, e);
127
+ return;
128
+ }
129
+ let map;
130
+ try {
131
+ map = JSON.parse(sourceMapFileContent);
132
+ map["debug_id"] = debugId;
133
+ map["debugId"] = debugId;
134
+ } catch {
135
+ logger.error(`Failed to parse source map for debug ID upload: ${sourceMapPath}`);
136
+ return;
137
+ }
138
+ if (map["sources"] && Array.isArray(map["sources"])) {
139
+ const mapDir = path__default.dirname(sourceMapPath);
140
+ map["sources"] = map["sources"].map((source) => rewriteSourcesHook(source, map, { mapDir }));
141
+ }
142
+ try {
143
+ await util.promisify(fs__default.writeFile)(targetPath, JSON.stringify(map), {
144
+ encoding: "utf8"
145
+ });
146
+ } catch (e) {
147
+ logger.error(`Failed to prepare source map for debug ID upload: ${sourceMapPath}`, e);
148
+ return;
149
+ }
150
+ }
151
+ const PROTOCOL_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:\/\//;
152
+ function defaultRewriteSourcesHook(source) {
153
+ if (source.match(PROTOCOL_REGEX)) {
154
+ return source.replace(PROTOCOL_REGEX, "");
155
+ } else {
156
+ return path__default.relative(process.cwd(), path__default.normalize(source));
157
+ }
158
+ }
159
+
160
+ export { createDebugIdUploadFunction, defaultRewriteSourcesHook, determineSourceMapPathFromBundle, prepareBundleForDebugIdUpload };
161
+ //# sourceMappingURL=debug-id-upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-id-upload.js","sources":["../../../src/core/debug-id-upload.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport * as url from 'url';\nimport * as util from 'util';\nimport { promisify } from 'util';\nimport type { SentryBuildPluginManager } from './build-plugin-manager';\nimport type { Logger } from './logger';\nimport type { ResolveSourceMapHook, RewriteSourcesHook } from './types';\nimport { stripQueryAndHashFromPath } from './utils';\n\ninterface DebugIdUploadPluginOptions {\n sentryBuildPluginManager: SentryBuildPluginManager;\n}\n\nexport function createDebugIdUploadFunction({ sentryBuildPluginManager }: DebugIdUploadPluginOptions) {\n return async (buildArtifactPaths: string[]) => {\n // Webpack and perhaps other bundlers allow you to append query strings to\n // filenames for cache busting purposes. We should strip these before upload.\n const cleanedPaths = buildArtifactPaths.map(stripQueryAndHashFromPath);\n await sentryBuildPluginManager.uploadSourcemaps(cleanedPaths);\n };\n}\n\nexport async function prepareBundleForDebugIdUpload(\n bundleFilePath: string,\n uploadFolder: string,\n chunkIndex: number,\n logger: Logger,\n rewriteSourcesHook: RewriteSourcesHook,\n resolveSourceMapHook: ResolveSourceMapHook | undefined,\n): Promise<void> {\n let bundleContent;\n try {\n bundleContent = await promisify(fs.readFile)(bundleFilePath, 'utf8');\n } catch (e) {\n logger.error(`Could not read bundle to determine debug ID and source map: ${bundleFilePath}`, e);\n return;\n }\n\n const debugId = determineDebugIdFromBundleSource(bundleContent);\n if (debugId === undefined) {\n logger.debug(\n `Could not determine debug ID from bundle. This can happen if you did not clean your output folder before installing the Sentry plugin. File will not be source mapped: ${bundleFilePath}`,\n );\n return;\n }\n\n const uniqueUploadName = `${debugId}-${chunkIndex}`;\n\n bundleContent = addDebugIdToBundleSource(bundleContent, debugId);\n const writeSourceFilePromise = fs.promises.writeFile(\n path.join(uploadFolder, `${uniqueUploadName}.js`),\n bundleContent,\n 'utf-8',\n );\n\n const writeSourceMapFilePromise = determineSourceMapPathFromBundle(\n bundleFilePath,\n bundleContent,\n logger,\n resolveSourceMapHook,\n ).then(async sourceMapPath => {\n if (sourceMapPath) {\n await prepareSourceMapForDebugIdUpload(\n sourceMapPath,\n path.join(uploadFolder, `${uniqueUploadName}.js.map`),\n debugId,\n rewriteSourcesHook,\n logger,\n );\n }\n });\n\n await writeSourceFilePromise;\n await writeSourceMapFilePromise;\n}\n\n/**\n * Looks for a particular string pattern (`sdbid-[debug ID]`) in the bundle\n * source and extracts the bundle's debug ID from it.\n *\n * The string pattern is injected via the debug ID injection snipped.\n */\nfunction determineDebugIdFromBundleSource(code: string): string | undefined {\n const match = code.match(\n /sentry-dbid-([0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12})/,\n );\n\n if (match) {\n return match[1];\n } else {\n return undefined;\n }\n}\n\nconst SPEC_LAST_DEBUG_ID_REGEX = /\\/\\/# debugId=([a-fA-F0-9-]+)(?![\\s\\S]*\\/\\/# debugId=)/m;\n\nfunction hasSpecCompliantDebugId(bundleSource: string): boolean {\n return SPEC_LAST_DEBUG_ID_REGEX.test(bundleSource);\n}\n\nfunction addDebugIdToBundleSource(bundleSource: string, debugId: string): string {\n if (hasSpecCompliantDebugId(bundleSource)) {\n return bundleSource.replace(SPEC_LAST_DEBUG_ID_REGEX, `//# debugId=${debugId}`);\n } else {\n return `${bundleSource}\\n//# debugId=${debugId}`;\n }\n}\n\n/**\n * Applies a set of heuristics to find the source map for a particular bundle.\n *\n * @returns the path to the bundle's source map or `undefined` if none could be found.\n */\nexport async function determineSourceMapPathFromBundle(\n bundlePath: string,\n bundleSource: string,\n logger: Logger,\n resolveSourceMapHook: ResolveSourceMapHook | undefined,\n): Promise<string | undefined> {\n const sourceMappingUrlMatch = bundleSource.match(/^\\s*\\/\\/# sourceMappingURL=(.*)$/m);\n const sourceMappingUrl = sourceMappingUrlMatch ? (sourceMappingUrlMatch[1] as string) : undefined;\n\n const searchLocations: string[] = [];\n\n if (resolveSourceMapHook) {\n logger.debug(\n `Calling sourcemaps.resolveSourceMap(${JSON.stringify(bundlePath)}, ${JSON.stringify(sourceMappingUrl)})`,\n );\n const customPath = await resolveSourceMapHook(bundlePath, sourceMappingUrl);\n logger.debug(`resolveSourceMap hook returned: ${JSON.stringify(customPath)}`);\n\n if (customPath) {\n searchLocations.push(customPath);\n }\n }\n\n // 1. try to find source map at `sourceMappingURL` location\n if (sourceMappingUrl) {\n let parsedUrl: URL | undefined;\n try {\n parsedUrl = new URL(sourceMappingUrl);\n } catch {\n // noop\n }\n\n if (parsedUrl?.protocol === 'file:') {\n searchLocations.push(url.fileURLToPath(sourceMappingUrl));\n } else if (parsedUrl) {\n // noop, non-file urls don't translate to a local sourcemap file\n } else if (path.isAbsolute(sourceMappingUrl)) {\n searchLocations.push(path.normalize(sourceMappingUrl));\n } else {\n searchLocations.push(path.normalize(path.join(path.dirname(bundlePath), sourceMappingUrl)));\n }\n }\n\n // 2. try to find source map at path adjacent to chunk source, but with `.map` appended\n searchLocations.push(`${bundlePath}.map`);\n\n for (const searchLocation of searchLocations) {\n try {\n await util.promisify(fs.access)(searchLocation);\n logger.debug(`Source map found for bundle \\`${bundlePath}\\`: \\`${searchLocation}\\``);\n return searchLocation;\n } catch {\n // noop\n }\n }\n\n // This is just a debug message because it can be quite spammy for some frameworks\n logger.debug(\n `Could not determine source map path for bundle \\`${bundlePath}\\`` +\n ` with sourceMappingURL=${sourceMappingUrl === undefined ? 'undefined' : `\\`${sourceMappingUrl}\\``}` +\n ` - Did you turn on source map generation in your bundler?` +\n ` (Attempted paths: ${searchLocations.map(e => `\\`${e}\\``).join(', ')})`,\n );\n return undefined;\n}\n\n/**\n * Reads a source map, injects debug ID fields, and writes the source map to the target path.\n */\nasync function prepareSourceMapForDebugIdUpload(\n sourceMapPath: string,\n targetPath: string,\n debugId: string,\n rewriteSourcesHook: RewriteSourcesHook,\n logger: Logger,\n): Promise<void> {\n let sourceMapFileContent: string;\n try {\n sourceMapFileContent = await util.promisify(fs.readFile)(sourceMapPath, {\n encoding: 'utf8',\n });\n } catch (e) {\n logger.error(`Failed to read source map for debug ID upload: ${sourceMapPath}`, e);\n return;\n }\n\n let map: Record<string, unknown>;\n try {\n map = JSON.parse(sourceMapFileContent) as { sources: unknown; [key: string]: unknown };\n // For now we write both fields until we know what will become the standard - if ever.\n map['debug_id'] = debugId;\n map['debugId'] = debugId;\n } catch {\n logger.error(`Failed to parse source map for debug ID upload: ${sourceMapPath}`);\n return;\n }\n\n if (map['sources'] && Array.isArray(map['sources'])) {\n const mapDir = path.dirname(sourceMapPath);\n map['sources'] = map['sources'].map((source: string) => rewriteSourcesHook(source, map, { mapDir }));\n }\n\n try {\n await util.promisify(fs.writeFile)(targetPath, JSON.stringify(map), {\n encoding: 'utf8',\n });\n } catch (e) {\n logger.error(`Failed to prepare source map for debug ID upload: ${sourceMapPath}`, e);\n return;\n }\n}\n\nconst PROTOCOL_REGEX = /^[a-zA-Z][a-zA-Z0-9+\\-.]*:\\/\\//;\nexport function defaultRewriteSourcesHook(source: string): string {\n if (source.match(PROTOCOL_REGEX)) {\n return source.replace(PROTOCOL_REGEX, '');\n } else {\n return path.relative(process.cwd(), path.normalize(source));\n }\n}\n"],"names":["fs","path"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { glob } from 'glob';
2
+
3
+ function globFiles(patterns, options) {
4
+ return glob(patterns, { absolute: true, nodir: true, ...options });
5
+ }
6
+
7
+ export { globFiles };
8
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sources":["../../../src/core/glob.ts"],"sourcesContent":["import { glob } from 'glob';\n\nexport function globFiles(\n patterns: string | string[],\n options?: { root?: string; ignore?: string | string[] },\n): Promise<string[]> {\n return glob(patterns, { absolute: true, nodir: true, ...options });\n}\n"],"names":[],"mappings":";;AAEO,SAAS,SAAA,CACd,UACA,OAAA,EACmB;AACnB,EAAA,OAAO,IAAA,CAAK,UAAU,EAAE,QAAA,EAAU,MAAM,KAAA,EAAO,IAAA,EAAM,GAAG,OAAA,EAAS,CAAA;AACnE;;;;"}
@@ -0,0 +1,82 @@
1
+ import { transformAsync } from '@babel/core';
2
+ import componentNameAnnotatePlugin from '../babel-plugin/index.js';
3
+ import SentryCli from '@sentry/cli';
4
+ import { debug } from '@sentry/core';
5
+ import * as fs from 'fs';
6
+ import { stripQueryAndHashFromPath, CodeInjection, containsOnlyImports } from './utils.js';
7
+ export { generateModuleMetadataInjectorCode, generateReleaseInjectorCode, replaceBooleanFlagsInCode, stringToUUID } from './utils.js';
8
+ export { globFiles } from './glob.js';
9
+ export { createSentryBuildPluginManager } from './build-plugin-manager.js';
10
+ export { createDebugIdUploadFunction } from './debug-id-upload.js';
11
+ import { experimentalComponentNameAnnotatePlugin } from '../babel-plugin/experimental.js';
12
+
13
+ function sentryCliBinaryExists() {
14
+ return fs.existsSync(SentryCli.getPath());
15
+ }
16
+ const COMMENT_USE_STRICT_REGEX = (
17
+ // Note: CodeQL complains that this regex potentially has n^2 runtime. This likely won't affect realistic files.
18
+ /^(?:\s*|\/\*(?:.|\r|\n)*?\*\/|\/\/.*[\n\r])*(?:"[^"]*";|'[^']*';)?/
19
+ );
20
+ function isJsFile(fileName) {
21
+ const cleanFileName = stripQueryAndHashFromPath(fileName);
22
+ return [".js", ".mjs", ".cjs"].some((ext) => cleanFileName.endsWith(ext));
23
+ }
24
+ function shouldSkipCodeInjection(code, facadeModuleId) {
25
+ if (code.trim().length === 0) {
26
+ return true;
27
+ }
28
+ if (facadeModuleId && stripQueryAndHashFromPath(facadeModuleId).endsWith(".html")) {
29
+ return containsOnlyImports(code);
30
+ }
31
+ return false;
32
+ }
33
+ function createComponentNameAnnotateHooks(ignoredComponents, injectIntoHtml) {
34
+ return {
35
+ async transform(code, id) {
36
+ const idWithoutQueryAndHash = stripQueryAndHashFromPath(id);
37
+ if (idWithoutQueryAndHash.match(/\\node_modules\\|\/node_modules\//)) {
38
+ return null;
39
+ }
40
+ if (![".jsx", ".tsx"].some((ending) => idWithoutQueryAndHash.endsWith(ending))) {
41
+ return null;
42
+ }
43
+ const parserPlugins = [];
44
+ if (idWithoutQueryAndHash.endsWith(".jsx")) {
45
+ parserPlugins.push("jsx");
46
+ } else if (idWithoutQueryAndHash.endsWith(".tsx")) {
47
+ parserPlugins.push("jsx", "typescript");
48
+ }
49
+ const plugin = injectIntoHtml ? experimentalComponentNameAnnotatePlugin : componentNameAnnotatePlugin;
50
+ try {
51
+ const result = await transformAsync(code, {
52
+ plugins: [[plugin, { ignoredComponents }]],
53
+ filename: id,
54
+ parserOpts: {
55
+ sourceType: "module",
56
+ allowAwaitOutsideFunction: true,
57
+ plugins: parserPlugins
58
+ },
59
+ generatorOpts: {
60
+ decoratorsBeforeExport: true
61
+ },
62
+ sourceMaps: true
63
+ });
64
+ return {
65
+ code: result?.code ?? code,
66
+ map: result?.map
67
+ };
68
+ } catch (e) {
69
+ debug.error(`Failed to apply react annotate plugin`, e);
70
+ }
71
+ return { code };
72
+ }
73
+ };
74
+ }
75
+ function getDebugIdSnippet(debugId) {
76
+ return new CodeInjection(
77
+ `var n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}");`
78
+ );
79
+ }
80
+
81
+ export { COMMENT_USE_STRICT_REGEX, CodeInjection, createComponentNameAnnotateHooks, getDebugIdSnippet, isJsFile, sentryCliBinaryExists, shouldSkipCodeInjection };
82
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/core/index.ts"],"sourcesContent":["import { transformAsync } from '@babel/core';\nimport componentNameAnnotatePlugin, { experimentalComponentNameAnnotatePlugin } from '../babel-plugin';\nimport SentryCli from '@sentry/cli';\nimport { debug } from '@sentry/core';\nimport * as fs from 'fs';\nimport { CodeInjection, containsOnlyImports, stripQueryAndHashFromPath } from './utils';\n\n/**\n * Determines whether the Sentry CLI binary is in its expected location.\n * This function is useful since `@sentry/cli` installs the binary via a post-install\n * script and post-install scripts may not always run. E.g. with `npm i --ignore-scripts`.\n */\nexport function sentryCliBinaryExists(): boolean {\n return fs.existsSync(SentryCli.getPath());\n}\n\n// We need to be careful not to inject the snippet before any `\"use strict\";`s.\n// As an additional complication `\"use strict\";`s may come after any number of comments.\nexport const COMMENT_USE_STRICT_REGEX =\n // Note: CodeQL complains that this regex potentially has n^2 runtime. This likely won't affect realistic files.\n /^(?:\\s*|\\/\\*(?:.|\\r|\\n)*?\\*\\/|\\/\\/.*[\\n\\r])*(?:\"[^\"]*\";|'[^']*';)?/;\n\n/**\n * Checks if a file is a JavaScript file based on its extension.\n * Handles query strings and hashes in the filename.\n */\nexport function isJsFile(fileName: string): boolean {\n const cleanFileName = stripQueryAndHashFromPath(fileName);\n return ['.js', '.mjs', '.cjs'].some(ext => cleanFileName.endsWith(ext));\n}\n\n/**\n * Checks if a chunk should be skipped for code injection\n *\n * This is necessary to handle Vite's MPA (multi-page application) mode where\n * HTML entry points create \"facade\" chunks that should not contain injected code.\n * See: https://github.com/getsentry/sentry-javascript-bundler-plugins/issues/829\n *\n * However, in SPA mode, the main bundle also has an HTML facade but contains\n * substantial application code. We should NOT skip injection for these bundles.\n *\n * @param code - The chunk's code content\n * @param facadeModuleId - The facade module ID (if any) - HTML files create facade chunks\n * @returns true if the chunk should be skipped\n */\nexport function shouldSkipCodeInjection(code: string, facadeModuleId: string | null | undefined): boolean {\n // Skip empty chunks - these are placeholder chunks that should be optimized away\n if (code.trim().length === 0) {\n return true;\n }\n\n // For HTML facade chunks, only skip if they contain only import statements\n if (facadeModuleId && stripQueryAndHashFromPath(facadeModuleId).endsWith('.html')) {\n return containsOnlyImports(code);\n }\n\n return false;\n}\n\nexport { globFiles } from './glob';\n\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nexport function createComponentNameAnnotateHooks(ignoredComponents: string[], injectIntoHtml: boolean) {\n type ParserPlugins = NonNullable<NonNullable<Parameters<typeof transformAsync>[1]>['parserOpts']>['plugins'];\n\n return {\n async transform(this: void, code: string, id: string) {\n // id may contain query and hash which will trip up our file extension logic below\n const idWithoutQueryAndHash = stripQueryAndHashFromPath(id);\n\n if (idWithoutQueryAndHash.match(/\\\\node_modules\\\\|\\/node_modules\\//)) {\n return null;\n }\n\n // We will only apply this plugin on jsx and tsx files\n if (!['.jsx', '.tsx'].some(ending => idWithoutQueryAndHash.endsWith(ending))) {\n return null;\n }\n\n const parserPlugins: ParserPlugins = [];\n if (idWithoutQueryAndHash.endsWith('.jsx')) {\n parserPlugins.push('jsx');\n } else if (idWithoutQueryAndHash.endsWith('.tsx')) {\n parserPlugins.push('jsx', 'typescript');\n }\n\n const plugin = injectIntoHtml ? experimentalComponentNameAnnotatePlugin : componentNameAnnotatePlugin;\n\n try {\n const result = await transformAsync(code, {\n plugins: [[plugin, { ignoredComponents }]],\n filename: id,\n parserOpts: {\n sourceType: 'module',\n allowAwaitOutsideFunction: true,\n plugins: parserPlugins,\n },\n generatorOpts: {\n decoratorsBeforeExport: true,\n },\n sourceMaps: true,\n });\n\n return {\n code: result?.code ?? code,\n map: result?.map,\n };\n } catch (e) {\n debug.error(`Failed to apply react annotate plugin`, e);\n }\n\n return { code };\n },\n };\n}\n\nexport function getDebugIdSnippet(debugId: string): CodeInjection {\n return new CodeInjection(\n `var n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]=\"${debugId}\",e._sentryDebugIdIdentifier=\"sentry-dbid-${debugId}\");`,\n );\n}\n\nexport type { Logger } from './logger';\nexport type { Options, SentrySDKBuildFlags } from './types';\nexport {\n CodeInjection,\n replaceBooleanFlagsInCode,\n stringToUUID,\n generateReleaseInjectorCode,\n generateModuleMetadataInjectorCode,\n} from './utils';\nexport { createSentryBuildPluginManager } from './build-plugin-manager';\nexport { createDebugIdUploadFunction } from './debug-id-upload';\n"],"names":[],"mappings":";;;;;;;;;;;;AAYO,SAAS,qBAAA,GAAiC;AAC/C,EAAA,OAAO,EAAA,CAAG,UAAA,CAAW,SAAA,CAAU,OAAA,EAAS,CAAA;AAC1C;AAIO,MAAM,wBAAA;AAAA;AAAA,EAEX;AAAA;AAMK,SAAS,SAAS,QAAA,EAA2B;AAClD,EAAA,MAAM,aAAA,GAAgB,0BAA0B,QAAQ,CAAA;AACxD,EAAA,OAAO,CAAC,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAA,CAAE,KAAK,CAAA,GAAA,KAAO,aAAA,CAAc,QAAA,CAAS,GAAG,CAAC,CAAA;AACxE;AAgBO,SAAS,uBAAA,CAAwB,MAAc,cAAA,EAAoD;AAExG,EAAA,IAAI,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,EAAG;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,kBAAkB,yBAAA,CAA0B,cAAc,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG;AACjF,IAAA,OAAO,oBAAoB,IAAI,CAAA;AAAA,EACjC;AAEA,EAAA,OAAO,KAAA;AACT;AAKO,SAAS,gCAAA,CAAiC,mBAA6B,cAAA,EAAyB;AAGrG,EAAA,OAAO;AAAA,IACL,MAAM,SAAA,CAAsB,IAAA,EAAc,EAAA,EAAY;AAEpD,MAAA,MAAM,qBAAA,GAAwB,0BAA0B,EAAE,CAAA;AAE1D,MAAA,IAAI,qBAAA,CAAsB,KAAA,CAAM,mCAAmC,CAAA,EAAG;AACpE,QAAA,OAAO,IAAA;AAAA,MACT;AAGA,MAAA,IAAI,CAAC,CAAC,MAAA,EAAQ,MAAM,CAAA,CAAE,IAAA,CAAK,CAAA,MAAA,KAAU,qBAAA,CAAsB,QAAA,CAAS,MAAM,CAAC,CAAA,EAAG;AAC5E,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,MAAM,gBAA+B,EAAC;AACtC,MAAA,IAAI,qBAAA,CAAsB,QAAA,CAAS,MAAM,CAAA,EAAG;AAC1C,QAAA,aAAA,CAAc,KAAK,KAAK,CAAA;AAAA,MAC1B,CAAA,MAAA,IAAW,qBAAA,CAAsB,QAAA,CAAS,MAAM,CAAA,EAAG;AACjD,QAAA,aAAA,CAAc,IAAA,CAAK,OAAO,YAAY,CAAA;AAAA,MACxC;AAEA,MAAA,MAAM,MAAA,GAAS,iBAAiB,uCAAA,GAA0C,2BAAA;AAE1E,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,IAAA,EAAM;AAAA,UACxC,SAAS,CAAC,CAAC,QAAQ,EAAE,iBAAA,EAAmB,CAAC,CAAA;AAAA,UACzC,QAAA,EAAU,EAAA;AAAA,UACV,UAAA,EAAY;AAAA,YACV,UAAA,EAAY,QAAA;AAAA,YACZ,yBAAA,EAA2B,IAAA;AAAA,YAC3B,OAAA,EAAS;AAAA,WACX;AAAA,UACA,aAAA,EAAe;AAAA,YACb,sBAAA,EAAwB;AAAA,WAC1B;AAAA,UACA,UAAA,EAAY;AAAA,SACb,CAAA;AAED,QAAA,OAAO;AAAA,UACL,IAAA,EAAM,QAAQ,IAAA,IAAQ,IAAA;AAAA,UACtB,KAAK,MAAA,EAAQ;AAAA,SACf;AAAA,MACF,SAAS,CAAA,EAAG;AACV,QAAA,KAAA,CAAM,KAAA,CAAM,yCAAyC,CAAC,CAAA;AAAA,MACxD;AAEA,MAAA,OAAO,EAAE,IAAA,EAAK;AAAA,IAChB;AAAA,GACF;AACF;AAEO,SAAS,kBAAkB,OAAA,EAAgC;AAChE,EAAA,OAAO,IAAI,aAAA;AAAA,IACT,CAAA,4FAAA,EAA+F,OAAO,CAAA,0CAAA,EAA6C,OAAO,CAAA,GAAA;AAAA,GAC5J;AACF;;;;"}
@@ -0,0 +1,27 @@
1
+ function createLogger(options) {
2
+ return {
3
+ info(message, ...params) {
4
+ if (!options.silent) {
5
+ console.info(`${options.prefix} Info: ${message}`, ...params);
6
+ }
7
+ },
8
+ warn(message, ...params) {
9
+ if (!options.silent) {
10
+ console.warn(`${options.prefix} Warning: ${message}`, ...params);
11
+ }
12
+ },
13
+ error(message, ...params) {
14
+ if (!options.silent) {
15
+ console.error(`${options.prefix} Error: ${message}`, ...params);
16
+ }
17
+ },
18
+ debug(message, ...params) {
19
+ if (!options.silent && options.debug) {
20
+ console.debug(`${options.prefix} Debug: ${message}`, ...params);
21
+ }
22
+ }
23
+ };
24
+ }
25
+
26
+ export { createLogger };
27
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sources":["../../../src/core/logger.ts"],"sourcesContent":["interface LoggerOptions {\n silent: boolean;\n debug: boolean;\n prefix: string;\n}\n\nexport type Logger = {\n info(message: string, ...params: unknown[]): void;\n warn(message: string, ...params: unknown[]): void;\n error(message: string, ...params: unknown[]): void;\n debug(message: string, ...params: unknown[]): void;\n};\n\n// Logging everything to stderr not to interfere with stdout\nexport function createLogger(options: LoggerOptions): Logger {\n return {\n info(message: string, ...params: unknown[]) {\n if (!options.silent) {\n // eslint-disable-next-line no-console\n console.info(`${options.prefix} Info: ${message}`, ...params);\n }\n },\n warn(message: string, ...params: unknown[]) {\n if (!options.silent) {\n // eslint-disable-next-line no-console\n console.warn(`${options.prefix} Warning: ${message}`, ...params);\n }\n },\n error(message: string, ...params: unknown[]) {\n if (!options.silent) {\n // eslint-disable-next-line no-console\n console.error(`${options.prefix} Error: ${message}`, ...params);\n }\n },\n debug(message: string, ...params: unknown[]) {\n if (!options.silent && options.debug) {\n // eslint-disable-next-line no-console\n console.debug(`${options.prefix} Debug: ${message}`, ...params);\n }\n },\n };\n}\n"],"names":[],"mappings":"AAcO,SAAS,aAAa,OAAA,EAAgC;AAC3D,EAAA,OAAO;AAAA,IACL,IAAA,CAAK,YAAoB,MAAA,EAAmB;AAC1C,MAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AAEnB,QAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,OAAA,CAAQ,MAAM,UAAU,OAAO,CAAA,CAAA,EAAI,GAAG,MAAM,CAAA;AAAA,MAC9D;AAAA,IACF,CAAA;AAAA,IACA,IAAA,CAAK,YAAoB,MAAA,EAAmB;AAC1C,MAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AAEnB,QAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,OAAA,CAAQ,MAAM,aAAa,OAAO,CAAA,CAAA,EAAI,GAAG,MAAM,CAAA;AAAA,MACjE;AAAA,IACF,CAAA;AAAA,IACA,KAAA,CAAM,YAAoB,MAAA,EAAmB;AAC3C,MAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AAEnB,QAAA,OAAA,CAAQ,KAAA,CAAM,GAAG,OAAA,CAAQ,MAAM,WAAW,OAAO,CAAA,CAAA,EAAI,GAAG,MAAM,CAAA;AAAA,MAChE;AAAA,IACF,CAAA;AAAA,IACA,KAAA,CAAM,YAAoB,MAAA,EAAmB;AAC3C,MAAA,IAAI,CAAC,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,KAAA,EAAO;AAEpC,QAAA,OAAA,CAAQ,KAAA,CAAM,GAAG,OAAA,CAAQ,MAAM,WAAW,OAAO,CAAA,CAAA,EAAI,GAAG,MAAM,CAAA;AAAA,MAChE;AAAA,IACF;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,111 @@
1
+ import { determineReleaseName } from './utils.js';
2
+
3
+ const SENTRY_SAAS_URL = "https://sentry.io";
4
+ function normalizeUserOptions(userOptions) {
5
+ const options = {
6
+ org: userOptions.org ?? process.env["SENTRY_ORG"],
7
+ project: userOptions.project ?? (process.env["SENTRY_PROJECT"]?.includes(",") ? process.env["SENTRY_PROJECT"].split(",").map((p) => p.trim()) : process.env["SENTRY_PROJECT"]),
8
+ authToken: userOptions.authToken ?? process.env["SENTRY_AUTH_TOKEN"],
9
+ url: userOptions.url ?? process.env["SENTRY_URL"] ?? SENTRY_SAAS_URL,
10
+ headers: userOptions.headers,
11
+ debug: userOptions.debug ?? false,
12
+ silent: userOptions.silent ?? false,
13
+ errorHandler: userOptions.errorHandler,
14
+ telemetry: userOptions.telemetry ?? true,
15
+ disable: userOptions.disable ?? false,
16
+ sourcemaps: userOptions.sourcemaps,
17
+ release: {
18
+ ...userOptions.release,
19
+ name: userOptions.release?.name ?? process.env["SENTRY_RELEASE"] ?? determineReleaseName(),
20
+ inject: userOptions.release?.inject ?? true,
21
+ create: userOptions.release?.create ?? true,
22
+ finalize: userOptions.release?.finalize ?? true,
23
+ vcsRemote: userOptions.release?.vcsRemote ?? process.env["SENTRY_VSC_REMOTE"] ?? "origin",
24
+ setCommits: userOptions.release?.setCommits
25
+ },
26
+ bundleSizeOptimizations: userOptions.bundleSizeOptimizations,
27
+ reactComponentAnnotation: userOptions.reactComponentAnnotation,
28
+ _metaOptions: {
29
+ telemetry: {
30
+ metaFramework: userOptions._metaOptions?.telemetry?.metaFramework,
31
+ bundlerMajorVersion: userOptions._metaOptions?.telemetry?.bundlerMajorVersion
32
+ }
33
+ },
34
+ applicationKey: userOptions.applicationKey,
35
+ moduleMetadata: userOptions.moduleMetadata,
36
+ _experiments: userOptions._experiments ?? {}
37
+ };
38
+ if (options.release.setCommits === void 0) {
39
+ if (process.env["VERCEL"] && process.env["VERCEL_GIT_COMMIT_SHA"] && process.env["VERCEL_GIT_REPO_SLUG"] && process.env["VERCEL_GIT_REPO_OWNER"] && // We only want to set commits for the production env because Sentry becomes extremely noisy (eg on slack) for
40
+ // preview environments because the previous commit is always the "stem" commit of the preview/PR causing Sentry
41
+ // to notify you for other people creating PRs.
42
+ process.env["VERCEL_TARGET_ENV"] === "production") {
43
+ options.release.setCommits = {
44
+ shouldNotThrowOnFailure: true,
45
+ commit: process.env["VERCEL_GIT_COMMIT_SHA"],
46
+ previousCommit: process.env["VERCEL_GIT_PREVIOUS_SHA"],
47
+ repo: `${process.env["VERCEL_GIT_REPO_OWNER"]}/${process.env["VERCEL_GIT_REPO_SLUG"]}`,
48
+ ignoreEmpty: true,
49
+ ignoreMissing: true
50
+ };
51
+ } else {
52
+ options.release.setCommits = {
53
+ shouldNotThrowOnFailure: true,
54
+ auto: true,
55
+ ignoreEmpty: true,
56
+ ignoreMissing: true
57
+ };
58
+ }
59
+ }
60
+ if (options.release.deploy === void 0 && process.env["VERCEL"] && process.env["VERCEL_TARGET_ENV"]) {
61
+ options.release.deploy = {
62
+ env: `vercel-${process.env["VERCEL_TARGET_ENV"]}`,
63
+ url: process.env["VERCEL_URL"] ? `https://${process.env["VERCEL_URL"]}` : void 0
64
+ };
65
+ }
66
+ return options;
67
+ }
68
+ function validateOptions(options, logger) {
69
+ const setCommits = options.release?.setCommits;
70
+ if (setCommits) {
71
+ if (!setCommits.auto && !(setCommits.repo && setCommits.commit)) {
72
+ logger.error(
73
+ "The `setCommits` option was specified but is missing required properties.",
74
+ "Please set either `auto` or both, `repo` and `commit`."
75
+ );
76
+ return false;
77
+ }
78
+ if (setCommits.auto && setCommits.repo && setCommits) {
79
+ logger.warn(
80
+ "The `setCommits` options includes `auto` but also `repo` and `commit`.",
81
+ "Ignoring `repo` and `commit`.",
82
+ "Please only set either `auto` or both, `repo` and `commit`."
83
+ );
84
+ }
85
+ }
86
+ if (options.release?.deploy && typeof options.release.deploy === "object" && !options.release.deploy.env) {
87
+ logger.error(
88
+ "The `deploy` option was specified but is missing the required `env` property.",
89
+ "Please set the `env` property."
90
+ );
91
+ return false;
92
+ }
93
+ if (options.project && Array.isArray(options.project)) {
94
+ if (options.project.length === 0) {
95
+ logger.error(
96
+ "The `project` option was specified as an array but is empty.",
97
+ "Please provide at least one project slug."
98
+ );
99
+ return false;
100
+ }
101
+ const invalidProjects = options.project.filter((p) => typeof p !== "string" || p.trim() === "");
102
+ if (invalidProjects.length > 0) {
103
+ logger.error("The `project` option contains invalid project slugs.", "All projects must be non-empty strings.");
104
+ return false;
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+
110
+ export { SENTRY_SAAS_URL, normalizeUserOptions, validateOptions };
111
+ //# sourceMappingURL=options-mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options-mapping.js","sources":["../../../src/core/options-mapping.ts"],"sourcesContent":["import type { Logger } from './logger';\nimport type {\n Options as UserOptions,\n SetCommitsOptions,\n RewriteSourcesHook,\n ResolveSourceMapHook,\n IncludeEntry,\n ModuleMetadata,\n ModuleMetadataCallback,\n} from './types';\nimport { determineReleaseName } from './utils';\n\nexport type NormalizedOptions = {\n org: string | undefined;\n project: string | string[] | undefined;\n authToken: string | undefined;\n url: string;\n headers: Record<string, string> | undefined;\n debug: boolean;\n silent: boolean;\n errorHandler: ((err: Error) => void) | undefined;\n telemetry: boolean;\n disable: boolean;\n sourcemaps:\n | {\n disable?: boolean | 'disable-upload';\n assets?: string | string[];\n ignore?: string | string[];\n rewriteSources?: RewriteSourcesHook;\n resolveSourceMap?: ResolveSourceMapHook;\n filesToDeleteAfterUpload?: string | string[] | Promise<string | string[] | undefined>;\n }\n | undefined;\n release: {\n name: string | undefined;\n inject: boolean;\n create: boolean;\n finalize: boolean;\n vcsRemote: string;\n setCommits:\n | (SetCommitsOptions & {\n shouldNotThrowOnFailure?: boolean;\n })\n | false\n | undefined;\n dist?: string;\n deploy?:\n | {\n env: string;\n started?: number | string;\n finished?: number | string;\n time?: number;\n name?: string;\n url?: string;\n }\n | false;\n uploadLegacySourcemaps?: string | IncludeEntry | Array<string | IncludeEntry>;\n };\n bundleSizeOptimizations:\n | {\n excludeDebugStatements?: boolean;\n excludeTracing?: boolean;\n excludeReplayCanvas?: boolean;\n excludeReplayShadowDom?: boolean;\n excludeReplayIframe?: boolean;\n excludeReplayWorker?: boolean;\n }\n | undefined;\n reactComponentAnnotation:\n | {\n enabled?: boolean;\n ignoredComponents?: string[];\n _experimentalInjectIntoHtml?: boolean;\n }\n | undefined;\n _metaOptions: {\n telemetry: {\n metaFramework: string | undefined;\n bundlerMajorVersion: string | undefined;\n };\n };\n applicationKey: string | undefined;\n moduleMetadata: ModuleMetadata | ModuleMetadataCallback | undefined;\n _experiments: {\n injectBuildInformation?: boolean;\n } & Record<string, unknown>;\n};\n\nexport const SENTRY_SAAS_URL = 'https://sentry.io';\n\n// oxlint-disable-next-line complexity\nexport function normalizeUserOptions(userOptions: UserOptions): NormalizedOptions {\n const options = {\n org: userOptions.org ?? process.env['SENTRY_ORG'],\n project:\n userOptions.project ??\n (process.env['SENTRY_PROJECT']?.includes(',')\n ? process.env['SENTRY_PROJECT'].split(',').map(p => p.trim())\n : process.env['SENTRY_PROJECT']),\n authToken: userOptions.authToken ?? process.env['SENTRY_AUTH_TOKEN'],\n url: userOptions.url ?? process.env['SENTRY_URL'] ?? SENTRY_SAAS_URL,\n headers: userOptions.headers,\n debug: userOptions.debug ?? false,\n silent: userOptions.silent ?? false,\n errorHandler: userOptions.errorHandler,\n telemetry: userOptions.telemetry ?? true,\n disable: userOptions.disable ?? false,\n sourcemaps: userOptions.sourcemaps,\n release: {\n ...userOptions.release,\n name: userOptions.release?.name ?? process.env['SENTRY_RELEASE'] ?? determineReleaseName(),\n inject: userOptions.release?.inject ?? true,\n create: userOptions.release?.create ?? true,\n finalize: userOptions.release?.finalize ?? true,\n vcsRemote: userOptions.release?.vcsRemote ?? process.env['SENTRY_VSC_REMOTE'] ?? 'origin',\n setCommits: userOptions.release?.setCommits as\n | (SetCommitsOptions & { shouldNotThrowOnFailure?: boolean })\n | false\n | undefined,\n },\n bundleSizeOptimizations: userOptions.bundleSizeOptimizations,\n reactComponentAnnotation: userOptions.reactComponentAnnotation,\n _metaOptions: {\n telemetry: {\n metaFramework: userOptions._metaOptions?.telemetry?.metaFramework,\n bundlerMajorVersion: userOptions._metaOptions?.telemetry?.bundlerMajorVersion,\n },\n },\n applicationKey: userOptions.applicationKey,\n moduleMetadata: userOptions.moduleMetadata,\n _experiments: userOptions._experiments ?? {},\n };\n\n if (options.release.setCommits === undefined) {\n if (\n process.env['VERCEL'] &&\n process.env['VERCEL_GIT_COMMIT_SHA'] &&\n process.env['VERCEL_GIT_REPO_SLUG'] &&\n process.env['VERCEL_GIT_REPO_OWNER'] &&\n // We only want to set commits for the production env because Sentry becomes extremely noisy (eg on slack) for\n // preview environments because the previous commit is always the \"stem\" commit of the preview/PR causing Sentry\n // to notify you for other people creating PRs.\n process.env['VERCEL_TARGET_ENV'] === 'production'\n ) {\n options.release.setCommits = {\n shouldNotThrowOnFailure: true,\n commit: process.env['VERCEL_GIT_COMMIT_SHA'],\n previousCommit: process.env['VERCEL_GIT_PREVIOUS_SHA'],\n repo: `${process.env['VERCEL_GIT_REPO_OWNER']}/${process.env['VERCEL_GIT_REPO_SLUG']}`,\n ignoreEmpty: true,\n ignoreMissing: true,\n };\n } else {\n options.release.setCommits = {\n shouldNotThrowOnFailure: true,\n auto: true,\n ignoreEmpty: true,\n ignoreMissing: true,\n };\n }\n }\n\n if (options.release.deploy === undefined && process.env['VERCEL'] && process.env['VERCEL_TARGET_ENV']) {\n options.release.deploy = {\n env: `vercel-${process.env['VERCEL_TARGET_ENV']}`,\n url: process.env['VERCEL_URL'] ? `https://${process.env['VERCEL_URL']}` : undefined,\n };\n }\n\n return options;\n}\n\n/**\n * Validates a few combinations of options that are not checked by Sentry CLI.\n *\n * For all other options, we can rely on Sentry CLI to validate them. In fact,\n * we can't validate them in the plugin because Sentry CLI might pick up options from\n * its config file.\n *\n * @param options the internal options\n * @param logger the logger\n *\n * @returns `true` if the options are valid, `false` otherwise\n */\nexport function validateOptions(options: NormalizedOptions, logger: Logger): boolean {\n const setCommits = options.release?.setCommits;\n if (setCommits) {\n if (!setCommits.auto && !(setCommits.repo && setCommits.commit)) {\n logger.error(\n 'The `setCommits` option was specified but is missing required properties.',\n 'Please set either `auto` or both, `repo` and `commit`.',\n );\n return false;\n }\n if (setCommits.auto && setCommits.repo && setCommits) {\n logger.warn(\n 'The `setCommits` options includes `auto` but also `repo` and `commit`.',\n 'Ignoring `repo` and `commit`.',\n 'Please only set either `auto` or both, `repo` and `commit`.',\n );\n }\n }\n\n if (options.release?.deploy && typeof options.release.deploy === 'object' && !options.release.deploy.env) {\n logger.error(\n 'The `deploy` option was specified but is missing the required `env` property.',\n 'Please set the `env` property.',\n );\n return false;\n }\n\n if (options.project && Array.isArray(options.project)) {\n if (options.project.length === 0) {\n logger.error(\n 'The `project` option was specified as an array but is empty.',\n 'Please provide at least one project slug.',\n );\n return false;\n }\n // Check each project is a non-empty string\n const invalidProjects = options.project.filter(p => typeof p !== 'string' || p.trim() === '');\n if (invalidProjects.length > 0) {\n logger.error('The `project` option contains invalid project slugs.', 'All projects must be non-empty strings.');\n return false;\n }\n }\n\n return true;\n}\n"],"names":[],"mappings":"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"}