@interfere/next 9.0.2 → 10.0.1-canary.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 (180) hide show
  1. package/README.md +39 -6
  2. package/dist/config.d.mts +25 -5
  3. package/dist/config.d.mts.map +1 -1
  4. package/dist/config.mjs +1 -100
  5. package/dist/config.mjs.map +1 -1
  6. package/dist/instrument-client.d.mts +11 -3
  7. package/dist/instrument-client.d.mts.map +1 -1
  8. package/dist/instrument-client.mjs +1 -11
  9. package/dist/instrument-client.mjs.map +1 -1
  10. package/dist/instrumentation-client.d.mts +1 -0
  11. package/dist/instrumentation-client.mjs +1 -0
  12. package/dist/instrumentation-client.mjs.map +1 -0
  13. package/dist/instrumentation.d.mts +134 -0
  14. package/dist/instrumentation.d.mts.map +1 -0
  15. package/dist/instrumentation.edge.d.mts +35 -0
  16. package/dist/instrumentation.edge.d.mts.map +1 -0
  17. package/dist/instrumentation.edge.mjs +1 -0
  18. package/dist/instrumentation.edge.mjs.map +1 -0
  19. package/dist/instrumentation.mjs +1 -0
  20. package/dist/instrumentation.mjs.map +1 -0
  21. package/dist/internal/build/configure-build.d.mts +3 -2
  22. package/dist/internal/build/configure-build.d.mts.map +1 -1
  23. package/dist/internal/build/configure-build.mjs +1 -87
  24. package/dist/internal/build/configure-build.mjs.map +1 -1
  25. package/dist/internal/build/detect-bundler.d.mts +7 -0
  26. package/dist/internal/build/detect-bundler.d.mts.map +1 -0
  27. package/dist/internal/build/detect-bundler.mjs +1 -0
  28. package/dist/internal/build/detect-bundler.mjs.map +1 -0
  29. package/dist/internal/build/pipeline.d.mts +13 -2
  30. package/dist/internal/build/pipeline.d.mts.map +1 -1
  31. package/dist/internal/build/pipeline.mjs +1 -66
  32. package/dist/internal/build/pipeline.mjs.map +1 -1
  33. package/dist/internal/build/release/destinations/index.d.mts +14 -0
  34. package/dist/internal/build/release/destinations/index.d.mts.map +1 -0
  35. package/dist/internal/build/release/destinations/index.mjs +1 -0
  36. package/dist/internal/build/release/destinations/index.mjs.map +1 -0
  37. package/dist/internal/build/release/destinations/vercel.d.mts.map +1 -1
  38. package/dist/internal/build/release/destinations/vercel.mjs +1 -23
  39. package/dist/internal/build/release/destinations/vercel.mjs.map +1 -1
  40. package/dist/internal/build/release/git.d.mts +13 -0
  41. package/dist/internal/build/release/git.d.mts.map +1 -1
  42. package/dist/internal/build/release/git.mjs +1 -21
  43. package/dist/internal/build/release/git.mjs.map +1 -1
  44. package/dist/internal/build/release/index.d.mts +2 -1
  45. package/dist/internal/build/release/index.d.mts.map +1 -1
  46. package/dist/internal/build/release/index.mjs +1 -19
  47. package/dist/internal/build/release/index.mjs.map +1 -1
  48. package/dist/internal/build/release/sources/github.d.mts.map +1 -1
  49. package/dist/internal/build/release/sources/github.mjs +1 -13
  50. package/dist/internal/build/release/sources/github.mjs.map +1 -1
  51. package/dist/internal/build/release/sources/index.d.mts +21 -0
  52. package/dist/internal/build/release/sources/index.d.mts.map +1 -0
  53. package/dist/internal/build/release/sources/index.mjs +1 -0
  54. package/dist/internal/build/release/sources/index.mjs.map +1 -0
  55. package/dist/internal/build/source-maps/discover-turbopack.d.mts +32 -0
  56. package/dist/internal/build/source-maps/discover-turbopack.d.mts.map +1 -0
  57. package/dist/internal/build/source-maps/discover-turbopack.mjs +1 -0
  58. package/dist/internal/build/source-maps/discover-turbopack.mjs.map +1 -0
  59. package/dist/internal/build/source-maps/discover-webpack.d.mts +53 -0
  60. package/dist/internal/build/source-maps/discover-webpack.d.mts.map +1 -0
  61. package/dist/internal/build/source-maps/discover-webpack.mjs +1 -0
  62. package/dist/internal/build/source-maps/discover-webpack.mjs.map +1 -0
  63. package/dist/internal/build/source-maps/discover.d.mts +28 -10
  64. package/dist/internal/build/source-maps/discover.d.mts.map +1 -1
  65. package/dist/internal/build/source-maps/discover.mjs +1 -87
  66. package/dist/internal/build/source-maps/discover.mjs.map +1 -1
  67. package/dist/internal/build/source-maps/index.d.mts +2 -24
  68. package/dist/internal/build/source-maps/index.d.mts.map +1 -1
  69. package/dist/internal/build/source-maps/index.mjs +1 -28
  70. package/dist/internal/build/source-maps/index.mjs.map +1 -1
  71. package/dist/internal/build/source-maps/paths.d.mts +28 -0
  72. package/dist/internal/build/source-maps/paths.d.mts.map +1 -0
  73. package/dist/internal/build/source-maps/paths.mjs +1 -0
  74. package/dist/internal/build/source-maps/paths.mjs.map +1 -0
  75. package/dist/internal/build/source-maps/upload.d.mts +46 -0
  76. package/dist/internal/build/source-maps/upload.d.mts.map +1 -0
  77. package/dist/internal/build/source-maps/upload.mjs +1 -0
  78. package/dist/internal/build/source-maps/upload.mjs.map +1 -0
  79. package/dist/internal/build/value-injection-loader.d.mts.map +1 -1
  80. package/dist/internal/build/value-injection-loader.mjs +2 -24
  81. package/dist/internal/build/value-injection-loader.mjs.map +1 -1
  82. package/dist/internal/env.d.mts +13 -3
  83. package/dist/internal/env.d.mts.map +1 -1
  84. package/dist/internal/env.mjs +1 -23
  85. package/dist/internal/env.mjs.map +1 -1
  86. package/dist/internal/logger.d.mts +9 -1
  87. package/dist/internal/logger.d.mts.map +1 -1
  88. package/dist/internal/logger.mjs +1 -60
  89. package/dist/internal/logger.mjs.map +1 -1
  90. package/dist/internal/release-slug.d.mts +25 -0
  91. package/dist/internal/release-slug.d.mts.map +1 -0
  92. package/dist/internal/release-slug.mjs +1 -0
  93. package/dist/internal/release-slug.mjs.map +1 -0
  94. package/dist/internal/route/handle-get.d.mts +14 -1
  95. package/dist/internal/route/handle-get.d.mts.map +1 -1
  96. package/dist/internal/route/handle-get.mjs +1 -22
  97. package/dist/internal/route/handle-get.mjs.map +1 -1
  98. package/dist/internal/route/handle-post.d.mts +11 -0
  99. package/dist/internal/route/handle-post.d.mts.map +1 -1
  100. package/dist/internal/route/handle-post.mjs +1 -70
  101. package/dist/internal/route/handle-post.mjs.map +1 -1
  102. package/dist/internal/route/proxy.d.mts +26 -4
  103. package/dist/internal/route/proxy.d.mts.map +1 -1
  104. package/dist/internal/route/proxy.mjs +1 -89
  105. package/dist/internal/route/proxy.mjs.map +1 -1
  106. package/dist/internal/server/capture.d.mts +2 -2
  107. package/dist/internal/server/capture.d.mts.map +1 -1
  108. package/dist/internal/server/capture.mjs +1 -55
  109. package/dist/internal/server/capture.mjs.map +1 -1
  110. package/dist/internal/server/console-bridge.d.mts +19 -0
  111. package/dist/internal/server/console-bridge.d.mts.map +1 -0
  112. package/dist/internal/server/console-bridge.mjs +1 -0
  113. package/dist/internal/server/console-bridge.mjs.map +1 -0
  114. package/dist/internal/server/id-generator.d.mts +38 -0
  115. package/dist/internal/server/id-generator.d.mts.map +1 -0
  116. package/dist/internal/server/id-generator.mjs +1 -0
  117. package/dist/internal/server/id-generator.mjs.map +1 -0
  118. package/dist/internal/server/instrumentation-options.d.mts +86 -0
  119. package/dist/internal/server/instrumentation-options.d.mts.map +1 -0
  120. package/dist/internal/server/instrumentation-options.mjs +1 -0
  121. package/dist/internal/server/remote-config.d.mts.map +1 -1
  122. package/dist/internal/server/remote-config.mjs +1 -29
  123. package/dist/internal/server/remote-config.mjs.map +1 -1
  124. package/dist/internal/server/trace-meta.d.mts +32 -0
  125. package/dist/internal/server/trace-meta.d.mts.map +1 -0
  126. package/dist/internal/server/trace-meta.mjs +1 -0
  127. package/dist/internal/server/trace-meta.mjs.map +1 -0
  128. package/dist/internal/server/traceparent.d.mts +16 -0
  129. package/dist/internal/server/traceparent.d.mts.map +1 -0
  130. package/dist/internal/server/traceparent.mjs +1 -0
  131. package/dist/internal/server/traceparent.mjs.map +1 -0
  132. package/dist/internal/server/types.d.mts +1 -7
  133. package/dist/internal/server/types.d.mts.map +1 -1
  134. package/dist/internal/server/types.mjs +1 -1
  135. package/dist/internal/setup-warnings.d.mts +17 -0
  136. package/dist/internal/setup-warnings.d.mts.map +1 -0
  137. package/dist/internal/setup-warnings.mjs +1 -0
  138. package/dist/internal/setup-warnings.mjs.map +1 -0
  139. package/dist/internal/url.d.mts +4 -0
  140. package/dist/internal/url.d.mts.map +1 -0
  141. package/dist/internal/url.mjs +1 -0
  142. package/dist/internal/url.mjs.map +1 -0
  143. package/dist/internal/version.mjs +1 -5
  144. package/dist/internal/version.mjs.map +1 -1
  145. package/dist/package.mjs +1 -5
  146. package/dist/provider.d.mts +23 -2
  147. package/dist/provider.d.mts.map +1 -0
  148. package/dist/provider.mjs +1 -3
  149. package/dist/provider.mjs.map +1 -0
  150. package/dist/route-handler.d.mts +7 -2
  151. package/dist/route-handler.d.mts.map +1 -1
  152. package/dist/route-handler.mjs +1 -31
  153. package/dist/route-handler.mjs.map +1 -1
  154. package/dist/server.d.mts +2 -2
  155. package/dist/server.mjs +1 -3
  156. package/package.json +78 -26
  157. package/dist/internal/route/sw-script.d.mts +0 -4
  158. package/dist/internal/route/sw-script.d.mts.map +0 -1
  159. package/dist/internal/route/sw-script.mjs +0 -38
  160. package/dist/internal/route/sw-script.mjs.map +0 -1
  161. package/dist/internal/server/dedupe.d.mts +0 -5
  162. package/dist/internal/server/dedupe.d.mts.map +0 -1
  163. package/dist/internal/server/dedupe.mjs +0 -11
  164. package/dist/internal/server/dedupe.mjs.map +0 -1
  165. package/dist/internal/server/envelope.d.mts +0 -14
  166. package/dist/internal/server/envelope.d.mts.map +0 -1
  167. package/dist/internal/server/envelope.mjs +0 -59
  168. package/dist/internal/server/envelope.mjs.map +0 -1
  169. package/dist/internal/server/normalize-request.d.mts +0 -7
  170. package/dist/internal/server/normalize-request.d.mts.map +0 -1
  171. package/dist/internal/server/normalize-request.mjs +0 -50
  172. package/dist/internal/server/normalize-request.mjs.map +0 -1
  173. package/dist/internal/server/runtime.d.mts +0 -14
  174. package/dist/internal/server/runtime.d.mts.map +0 -1
  175. package/dist/internal/server/runtime.mjs +0 -18
  176. package/dist/internal/server/runtime.mjs.map +0 -1
  177. package/dist/internal/server/transport.d.mts +0 -12
  178. package/dist/internal/server/transport.d.mts.map +0 -1
  179. package/dist/internal/server/transport.mjs +0 -26
  180. package/dist/internal/server/transport.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-turbopack.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover-turbopack.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\n\nimport type { SourceMapFile } from \"./discover.js\";\nimport { resolveDistDir, toPublicPath, walkDistTrees } from \"./paths.js\";\n\nconst DEBUG_ID_RE = /\\/\\/[#@]\\s*debugId=([0-9a-f-]+)\\s*$/m;\n\n/**\n * Turbopack-mode discovery.\n *\n * Turbopack hashes the JS chunk and its source map independently, so the\n * `//# sourceMappingURL=…` URL embedded in the chunk never matches the\n * on-disk `.js.map` filename. When `experimental.turbo.debugIds` is on\n * (we set it for the user in `configure-build.ts`), turbopack natively\n * injects matching `debugId` values into both the chunk\n * (`//# debugId=…`) and the source map (`\"debugId\": \"…\"`).\n *\n * We pair JS chunks ↔ source maps by `debugId` (turbopack's natural key)\n * and additionally record each chunk's public URL as `chunkUrl` so the\n * server-side suffix-match resolver has a uniform field to look up by\n * `frame.fileName` regardless of bundler. The webpack discoverer\n * populates the same field directly from the chunk's URL; the turbopack\n * discoverer derives it from the JS chunk's on-disk path.\n *\n * Maps without a debugId, or whose debugId never appears in any chunk,\n * are silently skipped — they have no way to resolve at runtime.\n */\nexport async function discoverTurbopack(opts: {\n projectDir: string;\n distDir: string;\n}): Promise<{ files: SourceMapFile[]; sourceFileCount: number }> {\n const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);\n const relDistDir = relative(opts.projectDir, absDistDir);\n\n const [mapPaths, jsPaths] = await Promise.all([\n walkDistTrees(absDistDir, \".js.map\"),\n walkDistTrees(absDistDir, \".js\"),\n ]);\n\n // Walk JS chunks once and build `debugId → publicUrl` so a single\n // pass over the maps can attach `chunkUrl` per entry.\n const debugIdToChunkUrl = new Map<string, string>();\n await Promise.all(\n jsPaths.map(async (jsAbs) => {\n const content = await readFile(jsAbs, \"utf8\").catch(() => null);\n if (content === null) {\n return;\n }\n const match = DEBUG_ID_RE.exec(content);\n const debugId = match?.[1];\n if (!debugId) {\n return;\n }\n const chunkUrl = toPublicPath(\n relative(opts.projectDir, jsAbs),\n relDistDir\n );\n // First write wins — collisions across .js shouldn't happen with\n // content-hashed chunk filenames, but if they do, the first walked\n // entry is the deterministic choice.\n if (!debugIdToChunkUrl.has(debugId)) {\n debugIdToChunkUrl.set(debugId, chunkUrl);\n }\n })\n );\n\n const files = await Promise.all(\n mapPaths.map(async (mapAbs): Promise<SourceMapFile | null> => {\n const content = await readFile(mapAbs, \"utf8\").catch(() => null);\n if (content === null) {\n return null;\n }\n\n let debugId: string | undefined;\n try {\n const parsed = JSON.parse(content) as { debugId?: unknown };\n if (typeof parsed.debugId === \"string\" && parsed.debugId.length > 0) {\n debugId = parsed.debugId;\n }\n } catch {\n return null;\n }\n\n if (!debugId) {\n return null;\n }\n\n const chunkUrl = debugIdToChunkUrl.get(debugId);\n if (!chunkUrl) {\n // No JS chunk in the dist tree carries this debugId — the map\n // can't pair to a runtime URL, so it's unresolvable. Drop it\n // rather than emitting an unusable manifest entry.\n return null;\n }\n\n return {\n absolute: mapAbs,\n path: toPublicPath(relative(opts.projectDir, mapAbs), relDistDir),\n content,\n hash: createHash(\"sha256\").update(content).digest(\"hex\"),\n debugId,\n chunkUrl,\n } satisfies SourceMapFile;\n })\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n return {\n files: loaded,\n sourceFileCount: loaded.length,\n };\n}\n"],"mappings":"8KAOA,MAAM,YAAc,uCAsBpB,eAAsB,kBAAkB,KAGyB,CAC/D,IAAM,WAAa,eAAe,KAAK,WAAY,KAAK,OAAO,EACzD,WAAa,SAAS,KAAK,WAAY,UAAU,EAEjD,CAAC,SAAU,SAAW,MAAM,QAAQ,IAAI,CAC5C,cAAc,WAAY,SAAS,EACnC,cAAc,WAAY,KAAK,CACjC,CAAC,EAIK,kBAAoB,IAAI,IAC9B,MAAM,QAAQ,IACZ,QAAQ,IAAI,KAAO,QAAU,CAC3B,IAAM,QAAU,MAAM,SAAS,MAAO,MAAM,EAAE,UAAY,IAAI,EAC9D,GAAI,UAAY,KACd,OAGF,IAAM,QADQ,YAAY,KAAK,OACX,IAAI,GACxB,GAAI,CAAC,QACH,OAEF,IAAM,SAAW,aACf,SAAS,KAAK,WAAY,KAAK,EAC/B,UACF,EAIK,kBAAkB,IAAI,OAAO,GAChC,kBAAkB,IAAI,QAAS,QAAQ,CAE3C,CAAC,CACH,EA0CA,IAAM,QAAS,MAxCK,QAAQ,IAC1B,SAAS,IAAI,KAAO,SAA0C,CAC5D,IAAM,QAAU,MAAM,SAAS,OAAQ,MAAM,EAAE,UAAY,IAAI,EAC/D,GAAI,UAAY,KACd,OAAO,KAGT,IAAI,QACJ,GAAI,CACF,IAAM,OAAS,KAAK,MAAM,OAAO,EAC7B,OAAO,OAAO,SAAY,UAAY,OAAO,QAAQ,OAAS,IAChE,QAAU,OAAO,QAErB,MAAQ,CACN,OAAO,IACT,CAEA,GAAI,CAAC,QACH,OAAO,KAGT,IAAM,SAAW,kBAAkB,IAAI,OAAO,EAQ9C,OAPK,SAOE,CACL,SAAU,OACV,KAAM,aAAa,SAAS,KAAK,WAAY,MAAM,EAAG,UAAU,EAChE,QACA,KAAM,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK,EACvD,QACA,QACF,EAVS,IAWX,CAAC,CACH,GAEqB,OAAQ,GAA0B,IAAM,IAAI,EAEjE,MAAO,CACL,MAAO,OACP,gBAAiB,OAAO,MAC1B,CACF"}
@@ -0,0 +1,53 @@
1
+ import { SourceMapFile } from "./discover.mjs";
2
+
3
+ //#region src/internal/build/source-maps/discover-webpack.d.ts
4
+ /**
5
+ * Reads an existing `//# debugId=…` comment from the bundle source.
6
+ * Returns `null` when no debug ID comment is present — the caller is
7
+ * expected to generate and inject one.
8
+ */
9
+ declare function readDebugIdFromJs(content: string): string | null;
10
+ /**
11
+ * Inserts a `//# debugId=…` comment into the chunk. Idempotent: if a
12
+ * spec-compliant comment is already present (e.g. webpack 5.104+ with
13
+ * `SourceMapDevToolPlugin({ debugIds: true })`, turbopack with
14
+ * `experimental.turbopack.debugIds`, or any other tool) it's
15
+ * overwritten with the supplied debugId — callers that read the
16
+ * existing id via `readDebugIdFromJs` first get an idempotent no-op.
17
+ *
18
+ * Otherwise the comment is appended just before the existing
19
+ * `//# sourceMappingURL=…` line so the browser still resolves the map.
20
+ */
21
+ declare function injectDebugIdIntoJs(content: string, debugId: string): string;
22
+ /**
23
+ * Adds `debugId` to the source-map JSON. Idempotent: writes both
24
+ * `debugId` (TC39 spec field) and `debug_id` (legacy variant some
25
+ * older Sentry tooling emits) so manifests stay readable across the
26
+ * ecosystem. Re-running with the same id produces identical output.
27
+ */
28
+ declare function injectDebugIdIntoMap(content: string, debugId: string): string;
29
+ /**
30
+ * Webpack-mode discovery: walks the dist tree, parses each `.js`
31
+ * chunk's `//# sourceMappingURL=…` comment to find its paired `.map`,
32
+ * and ensures both carry the same `debugId`.
33
+ *
34
+ * Idempotent w.r.t. debug-id state on disk:
35
+ * - If the chunk already carries a `//# debugId=…` comment (webpack
36
+ * 5.104+ with `SourceMapDevToolPlugin({ debugIds: true })`, or a
37
+ * third-party tool that already injected one) we reuse it.
38
+ * - Otherwise we generate a fresh UUID and inject it into both files.
39
+ *
40
+ * The "reuse if present" branch matches the strategy in Sentry's
41
+ * webpack plugin (`addDebugIdToBundleSource` in
42
+ * `bundler-plugin-core/src/debug-id-upload.ts`) and means our
43
+ * discovery works transparently when bundlers natively emit debugIds.
44
+ */
45
+ declare function discoverWebpack(opts: {
46
+ projectDir: string;
47
+ distDir: string;
48
+ }): Promise<{
49
+ files: SourceMapFile[];
50
+ sourceFileCount: number;
51
+ }>;
52
+ //#endregion
53
+ export { discoverWebpack, injectDebugIdIntoJs, injectDebugIdIntoMap, readDebugIdFromJs };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-webpack.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover-webpack.ts"],"mappings":";;;;;AAwBA;;;iBAAgB,iBAAA,CAAkB,OAAe;AAAA;AAgBjD;;;;AAAoE;AAuBpE;;;;AAAqE;AAvCpB,iBAgBjC,mBAAA,CAAoB,OAAA,UAAiB,OAAe;;;;;;;iBAuBpD,oBAAA,CAAqB,OAAA,UAAiB,OAAe;;;;;AAyBhB;;;;;;;;;;;;iBAH/B,eAAA,CAAgB,IAAA;EACpC,UAAA;EACA,OAAA;AAAA,IACE,OAAO;EAAG,KAAA,EAAO,aAAA;EAAiB,eAAA;AAAA"}
@@ -0,0 +1 @@
1
+ import{resolveDistDir,toPublicPath,walkDistTrees}from"./paths.mjs";import{relative}from"node:path";import{createHash,randomUUID}from"node:crypto";import{readFile,writeFile}from"node:fs/promises";const SOURCEMAPPING_RE=/\/\/[#@]\s*sourceMappingURL=(\S+)\s*$/,SPEC_LAST_DEBUG_ID_RE=/\/\/# debugId=([a-fA-F0-9-]+)(?![\s\S]*\/\/# debugId=)/m;function readDebugIdFromJs(content){return SPEC_LAST_DEBUG_ID_RE.exec(content)?.[1]??null}function injectDebugIdIntoJs(content,debugId){let debugIdComment=`//# debugId=${debugId}`;if(SPEC_LAST_DEBUG_ID_RE.test(content))return content.replace(SPEC_LAST_DEBUG_ID_RE,debugIdComment);let match=SOURCEMAPPING_RE.exec(content);return match?`${content.slice(0,match.index).trimEnd()}\n${debugIdComment}\n${match[0]}`:`${content}\n${debugIdComment}`}function injectDebugIdIntoMap(content,debugId){let json=JSON.parse(content);return json.debugId=debugId,JSON.stringify(json)}async function discoverWebpack(opts){let absDistDir=resolveDistDir(opts.projectDir,opts.distDir),relDistDir=relative(opts.projectDir,absDistDir),jsPaths=await walkDistTrees(absDistDir,`.js`),pairs=new Map;for(let jsAbs of jsPaths){let content=await readFile(jsAbs,`utf8`),match=SOURCEMAPPING_RE.exec(content);if(!match?.[1])continue;let mapAbs=`${jsAbs.slice(0,jsAbs.lastIndexOf(`/`)+1)}${decodeURIComponent(match[1])}`,jsPublic=toPublicPath(relative(opts.projectDir,jsAbs),relDistDir),mapPublic=toPublicPath(relative(opts.projectDir,mapAbs),relDistDir);pairs.set(mapPublic,{mapAbs,jsAbs,jsPublic,jsContent:content,existingDebugId:readDebugIdFromJs(content)})}return{files:(await Promise.all(Array.from(pairs.entries(),async([mapPublic,pair])=>{let mapContent=await readFile(pair.mapAbs,`utf8`).catch(()=>null);if(mapContent===null)return null;let debugId=pair.existingDebugId??randomUUID();if(!pair.existingDebugId){let injectedJs=injectDebugIdIntoJs(pair.jsContent,debugId);await writeFile(pair.jsAbs,injectedJs,`utf8`)}let finalMap=JSON.parse(mapContent).debugId===debugId?mapContent:injectDebugIdIntoMap(mapContent,debugId);return finalMap!==mapContent&&await writeFile(pair.mapAbs,finalMap,`utf8`),{absolute:pair.mapAbs,path:mapPublic,content:finalMap,hash:createHash(`sha256`).update(finalMap).digest(`hex`),debugId,chunkUrl:pair.jsPublic}}))).filter(f=>f!==null),sourceFileCount:pairs.size}}export{discoverWebpack,injectDebugIdIntoJs,injectDebugIdIntoMap,readDebugIdFromJs};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-webpack.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover-webpack.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\n\nimport type { SourceMapFile } from \"./discover.js\";\nimport { resolveDistDir, toPublicPath, walkDistTrees } from \"./paths.js\";\n\nconst SOURCEMAPPING_RE = /\\/\\/[#@]\\s*sourceMappingURL=(\\S+)\\s*$/;\n\n/**\n * Per the TC39 sourcemap-debug-id proposal, the LAST `//# debugId=…`\n * comment in the bundle is the canonical one. Same regex Sentry uses\n * to detect spec-compliant debug IDs already injected by another tool\n * (webpack 5.104+ `SourceMapDevToolPlugin({ debugIds: true })`,\n * turbopack `experimental.turbopack.debugIds`, rollup, vite, etc.).\n */\nconst SPEC_LAST_DEBUG_ID_RE =\n /\\/\\/# debugId=([a-fA-F0-9-]+)(?![\\s\\S]*\\/\\/# debugId=)/m;\n\n/**\n * Reads an existing `//# debugId=…` comment from the bundle source.\n * Returns `null` when no debug ID comment is present — the caller is\n * expected to generate and inject one.\n */\nexport function readDebugIdFromJs(content: string): string | null {\n const match = SPEC_LAST_DEBUG_ID_RE.exec(content);\n return match?.[1] ?? null;\n}\n\n/**\n * Inserts a `//# debugId=…` comment into the chunk. Idempotent: if a\n * spec-compliant comment is already present (e.g. webpack 5.104+ with\n * `SourceMapDevToolPlugin({ debugIds: true })`, turbopack with\n * `experimental.turbopack.debugIds`, or any other tool) it's\n * overwritten with the supplied debugId — callers that read the\n * existing id via `readDebugIdFromJs` first get an idempotent no-op.\n *\n * Otherwise the comment is appended just before the existing\n * `//# sourceMappingURL=…` line so the browser still resolves the map.\n */\nexport function injectDebugIdIntoJs(content: string, debugId: string): string {\n const debugIdComment = `//# debugId=${debugId}`;\n\n if (SPEC_LAST_DEBUG_ID_RE.test(content)) {\n return content.replace(SPEC_LAST_DEBUG_ID_RE, debugIdComment);\n }\n\n const match = SOURCEMAPPING_RE.exec(content);\n if (match) {\n const before = content.slice(0, match.index).trimEnd();\n const sourceMappingLine = match[0];\n return `${before}\\n${debugIdComment}\\n${sourceMappingLine}`;\n }\n\n return `${content}\\n${debugIdComment}`;\n}\n\n/**\n * Adds `debugId` to the source-map JSON. Idempotent: writes both\n * `debugId` (TC39 spec field) and `debug_id` (legacy variant some\n * older Sentry tooling emits) so manifests stay readable across the\n * ecosystem. Re-running with the same id produces identical output.\n */\nexport function injectDebugIdIntoMap(content: string, debugId: string): string {\n const json = JSON.parse(content) as Record<string, unknown>;\n json[\"debugId\"] = debugId;\n return JSON.stringify(json);\n}\n\n/**\n * Webpack-mode discovery: walks the dist tree, parses each `.js`\n * chunk's `//# sourceMappingURL=…` comment to find its paired `.map`,\n * and ensures both carry the same `debugId`.\n *\n * Idempotent w.r.t. debug-id state on disk:\n * - If the chunk already carries a `//# debugId=…` comment (webpack\n * 5.104+ with `SourceMapDevToolPlugin({ debugIds: true })`, or a\n * third-party tool that already injected one) we reuse it.\n * - Otherwise we generate a fresh UUID and inject it into both files.\n *\n * The \"reuse if present\" branch matches the strategy in Sentry's\n * webpack plugin (`addDebugIdToBundleSource` in\n * `bundler-plugin-core/src/debug-id-upload.ts`) and means our\n * discovery works transparently when bundlers natively emit debugIds.\n */\nexport async function discoverWebpack(opts: {\n projectDir: string;\n distDir: string;\n}): Promise<{ files: SourceMapFile[]; sourceFileCount: number }> {\n const absDistDir = resolveDistDir(opts.projectDir, opts.distDir);\n const relDistDir = relative(opts.projectDir, absDistDir);\n\n const jsPaths = await walkDistTrees(absDistDir, \".js\");\n\n const pairs = new Map<\n string,\n {\n mapAbs: string;\n jsAbs: string;\n jsPublic: string;\n jsContent: string;\n existingDebugId: string | null;\n }\n >();\n\n for (const jsAbs of jsPaths) {\n const content = await readFile(jsAbs, \"utf8\");\n const match = SOURCEMAPPING_RE.exec(content);\n if (!match?.[1]) {\n continue;\n }\n\n const jsDir = jsAbs.slice(0, jsAbs.lastIndexOf(\"/\") + 1);\n const mapRef = decodeURIComponent(match[1]);\n const mapAbs = `${jsDir}${mapRef}`;\n const jsPublic = toPublicPath(relative(opts.projectDir, jsAbs), relDistDir);\n const mapPublic = toPublicPath(\n relative(opts.projectDir, mapAbs),\n relDistDir\n );\n\n pairs.set(mapPublic, {\n mapAbs,\n jsAbs,\n jsPublic,\n jsContent: content,\n existingDebugId: readDebugIdFromJs(content),\n });\n }\n\n const files = await Promise.all(\n Array.from(\n pairs.entries(),\n async ([mapPublic, pair]): Promise<SourceMapFile | null> => {\n const mapContent = await readFile(pair.mapAbs, \"utf8\").catch(\n () => null\n );\n if (mapContent === null) {\n return null;\n }\n\n const debugId = pair.existingDebugId ?? randomUUID();\n\n // Skip the rewrite when the bundler already injected the\n // canonical debug-id comment + source-map field (webpack\n // native debugIds, turbopack, etc.). Re-running with the\n // same id is a no-op anyway, but skipping the I/O is faster\n // and keeps file mtimes stable for incremental builds.\n if (!pair.existingDebugId) {\n const injectedJs = injectDebugIdIntoJs(pair.jsContent, debugId);\n await writeFile(pair.jsAbs, injectedJs, \"utf8\");\n }\n\n const mapJson = JSON.parse(mapContent) as Record<string, unknown>;\n const finalMap =\n mapJson[\"debugId\"] === debugId\n ? mapContent\n : injectDebugIdIntoMap(mapContent, debugId);\n if (finalMap !== mapContent) {\n await writeFile(pair.mapAbs, finalMap, \"utf8\");\n }\n\n return {\n absolute: pair.mapAbs,\n path: mapPublic,\n content: finalMap,\n hash: createHash(\"sha256\").update(finalMap).digest(\"hex\"),\n debugId,\n chunkUrl: pair.jsPublic,\n };\n }\n )\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n return {\n files: loaded,\n sourceFileCount: pairs.size,\n };\n}\n"],"mappings":"mMAOA,MAAM,iBAAmB,wCASnB,sBACJ,0DAOF,SAAgB,kBAAkB,QAAgC,CAEhE,OADc,sBAAsB,KAAK,OAC9B,IAAI,IAAM,IACvB,CAaA,SAAgB,oBAAoB,QAAiB,QAAyB,CAC5E,IAAM,eAAiB,eAAe,UAEtC,GAAI,sBAAsB,KAAK,OAAO,EACpC,OAAO,QAAQ,QAAQ,sBAAuB,cAAc,EAG9D,IAAM,MAAQ,iBAAiB,KAAK,OAAO,EAO3C,OANI,MAGK,GAFQ,QAAQ,MAAM,EAAG,MAAM,KAAK,EAAE,QAE9B,EAAE,IAAI,eAAe,IADV,MAAM,KAI3B,GAAG,QAAQ,IAAI,gBACxB,CAQA,SAAgB,qBAAqB,QAAiB,QAAyB,CAC7E,IAAM,KAAO,KAAK,MAAM,OAAO,EAE/B,MADA,MAAK,QAAa,QACX,KAAK,UAAU,IAAI,CAC5B,CAkBA,eAAsB,gBAAgB,KAG2B,CAC/D,IAAM,WAAa,eAAe,KAAK,WAAY,KAAK,OAAO,EACzD,WAAa,SAAS,KAAK,WAAY,UAAU,EAEjD,QAAU,MAAM,cAAc,WAAY,KAAK,EAE/C,MAAQ,IAAI,IAWlB,IAAK,IAAM,SAAS,QAAS,CAC3B,IAAM,QAAU,MAAM,SAAS,MAAO,MAAM,EACtC,MAAQ,iBAAiB,KAAK,OAAO,EAC3C,GAAI,CAAC,QAAQ,GACX,SAKF,IAAM,OAAS,GAFD,MAAM,MAAM,EAAG,MAAM,YAAY,GAAG,EAAI,CAEhC,IADP,mBAAmB,MAAM,EACT,IACzB,SAAW,aAAa,SAAS,KAAK,WAAY,KAAK,EAAG,UAAU,EACpE,UAAY,aAChB,SAAS,KAAK,WAAY,MAAM,EAChC,UACF,EAEA,MAAM,IAAI,UAAW,CACnB,OACA,MACA,SACA,UAAW,QACX,gBAAiB,kBAAkB,OAAO,CAC5C,CAAC,CACH,CAgDA,MAAO,CACL,OAHa,MA5CK,QAAQ,IAC1B,MAAM,KACJ,MAAM,QAAQ,EACd,MAAO,CAAC,UAAW,QAAyC,CAC1D,IAAM,WAAa,MAAM,SAAS,KAAK,OAAQ,MAAM,EAAE,UAC/C,IACR,EACA,GAAI,aAAe,KACjB,OAAO,KAGT,IAAM,QAAU,KAAK,iBAAmB,WAAW,EAOnD,GAAI,CAAC,KAAK,gBAAiB,CACzB,IAAM,WAAa,oBAAoB,KAAK,UAAW,OAAO,EAC9D,MAAM,UAAU,KAAK,MAAO,WAAY,MAAM,CAChD,CAGA,IAAM,SADU,KAAK,MAAM,UAEnB,EAAE,UAAe,QACnB,WACA,qBAAqB,WAAY,OAAO,EAK9C,OAJI,WAAa,YACf,MAAM,UAAU,KAAK,OAAQ,SAAU,MAAM,EAGxC,CACL,SAAU,KAAK,OACf,KAAM,UACN,QAAS,SACT,KAAM,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK,EACxD,QACA,SAAU,KAAK,QACjB,CACF,CACF,CACF,GAEqB,OAAQ,GAA0B,IAAM,IAG/C,EACZ,gBAAiB,MAAM,IACzB,CACF"}
@@ -1,19 +1,37 @@
1
+ import { NextBuildBundler } from "../detect-bundler.mjs";
2
+ import { injectDebugIdIntoJs, injectDebugIdIntoMap } from "./discover-webpack.mjs";
3
+
1
4
  //#region src/internal/build/source-maps/discover.d.ts
2
5
  interface SourceMapFile {
3
6
  readonly absolute: string;
7
+ /**
8
+ * Public URL the runtime will load this chunk from. ALWAYS populated
9
+ * for both bundlers — turbopack discovery walks JS chunks (in addition
10
+ * to .map files) so it can record this. Lifted onto the manifest as
11
+ * `chunkUrl`; server-side suffix-matching pairs `frame.fileName` to
12
+ * this field by content-hashed filename.
13
+ */
14
+ readonly chunkUrl: string;
4
15
  readonly content: string;
5
16
  readonly debugId: string;
6
17
  readonly hash: string;
7
18
  readonly path: string;
8
19
  }
9
- declare function buildDebugIdSnippet(debugId: string): string;
10
- declare function injectDebugIdIntoJs(content: string, debugId: string): string;
11
- declare function injectDebugIdIntoMap(content: string, debugId: string): string;
12
- declare function discover(projectDir: string, distDir: string): Promise<{
13
- files: SourceMapFile[];
14
- mapping: Record<string, string>;
15
- sourceFileCount: number;
16
- }>;
17
- declare function normalizeDistDir(distDir?: string): string;
20
+ interface DiscoveryResult {
21
+ readonly files: SourceMapFile[];
22
+ readonly sourceFileCount: number;
23
+ }
24
+ /**
25
+ * Single entry point for source-map discovery. The pipeline calls this
26
+ * with the active bundler from `detectActiveBundler()`; new bundlers (e.g.
27
+ * rspack) drop in here as additional cases without touching the pipeline.
28
+ * Other manifest bundlers (for Vite, CLI, etc.) live outside the Next
29
+ * build pipeline and should use their own discovery implementation.
30
+ */
31
+ declare function discoverSourceMaps(opts: {
32
+ bundler: NextBuildBundler;
33
+ projectDir: string;
34
+ distDir: string;
35
+ }): Promise<DiscoveryResult>;
18
36
  //#endregion
19
- export { SourceMapFile, buildDebugIdSnippet, discover, injectDebugIdIntoJs, injectDebugIdIntoMap, normalizeDistDir };
37
+ export { DiscoveryResult, SourceMapFile, discoverSourceMaps, injectDebugIdIntoJs, injectDebugIdIntoMap };
@@ -1 +1 @@
1
- {"version":3,"file":"discover.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"mappings":";UAMiB,aAAA;EAAA,SACN,QAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA;AAAA;AAAA,iBAgBK,mBAAA,CAAoB,OAAA;AAAA,iBAIpB,mBAAA,CAAoB,OAAA,UAAiB,OAAA;AAAA,iBAcrC,oBAAA,CAAqB,OAAA,UAAiB,OAAA;AAAA,iBAShC,QAAA,CAAS,UAAA,UAAoB,OAAA,WAAe,OAAA;;;;;iBAiFlD,gBAAA,CAAiB,OAAA"}
1
+ {"version":3,"file":"discover.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"mappings":";;;;UAKiB,aAAA;EAAA,SACN,QAAA;;AADX;;;;;;WASW,QAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA;EAAA,SACA,IAAA;AAAA;AAAA,UAGM,eAAA;EAAA,SACN,KAAA,EAAO,aAAa;EAAA,SACpB,eAAA;AAAA;;;;;AAAe;AAU1B;;iBAAsB,kBAAA,CAAmB,IAAA;EACvC,OAAA,EAAS,gBAAA;EACT,UAAA;EACA,OAAA;AAAA,IACE,OAAA,CAAQ,eAAA"}
@@ -1,87 +1 @@
1
- import { isAbsolute, join, relative, resolve } from "node:path";
2
- import { createHash, randomUUID } from "node:crypto";
3
- import { readFile, readdir, writeFile } from "node:fs/promises";
4
- //#region src/internal/build/source-maps/discover.ts
5
- const SOURCEMAPPING_RE = /\/\/[#@]\s*sourceMappingURL=(\S+)\s*$/;
6
- function resolveDistDir(projectDir, distDir) {
7
- return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);
8
- }
9
- async function findJsFiles(dir) {
10
- return (await readdir(dir, { recursive: true }).catch(() => [])).filter((entry) => entry.endsWith(".js")).map((entry) => join(dir, entry));
11
- }
12
- function buildDebugIdSnippet(debugId) {
13
- return `!function(){try{var s=(new Error).stack;s&&(globalThis._debugIds=globalThis._debugIds||{},globalThis._debugIds[s]="${debugId}")}catch(e){}}();`;
14
- }
15
- function injectDebugIdIntoJs(content, debugId) {
16
- const snippet = buildDebugIdSnippet(debugId);
17
- const debugIdComment = `//# debugId=${debugId}`;
18
- const match = SOURCEMAPPING_RE.exec(content);
19
- if (match) return `${snippet}\n${content.slice(0, match.index).trimEnd()}\n${debugIdComment}\n${match[0]}`;
20
- return `${snippet}\n${content}\n${debugIdComment}`;
21
- }
22
- function injectDebugIdIntoMap(content, debugId) {
23
- const json = JSON.parse(content);
24
- json["debugId"] = debugId;
25
- if (typeof json["mappings"] === "string") json["mappings"] = `;${json["mappings"]}`;
26
- return JSON.stringify(json);
27
- }
28
- async function discover(projectDir, distDir) {
29
- const absDistDir = resolveDistDir(projectDir, distDir);
30
- const relDistDir = relative(projectDir, absDistDir);
31
- const [staticFiles, serverFiles] = await Promise.all([findJsFiles(join(absDistDir, "static")), findJsFiles(join(absDistDir, "server"))]);
32
- const jsPaths = [...staticFiles, ...serverFiles];
33
- const mapping = {};
34
- const mapAbsolutes = /* @__PURE__ */ new Map();
35
- const jsAbsolutes = /* @__PURE__ */ new Map();
36
- for (const jsAbs of jsPaths) {
37
- const content = await readFile(jsAbs, "utf8");
38
- const match = SOURCEMAPPING_RE.exec(content);
39
- if (!match?.[1]) continue;
40
- const mapAbs = `${jsAbs.slice(0, jsAbs.lastIndexOf("/") + 1)}${decodeURIComponent(match[1])}`;
41
- const jsPublic = toPublicPath(relative(projectDir, jsAbs), relDistDir);
42
- const mapPublic = toPublicPath(relative(projectDir, mapAbs), relDistDir);
43
- mapping[mapPublic] = jsPublic;
44
- mapAbsolutes.set(mapPublic, mapAbs);
45
- jsAbsolutes.set(mapPublic, jsAbs);
46
- }
47
- const loaded = (await Promise.all(mapAbsolutes.entries().map(async ([mapPublic, mapAbs]) => {
48
- const mapContent = await readFile(mapAbs, "utf8").catch(() => null);
49
- if (mapContent === null) return null;
50
- const jsAbs = jsAbsolutes.get(mapPublic);
51
- if (!jsAbs) return null;
52
- const debugId = randomUUID();
53
- await writeFile(jsAbs, injectDebugIdIntoJs(await readFile(jsAbs, "utf8"), debugId), "utf8");
54
- const injectedMap = injectDebugIdIntoMap(mapContent, debugId);
55
- await writeFile(mapAbs, injectedMap, "utf8");
56
- return {
57
- absolute: mapAbs,
58
- path: mapPublic,
59
- content: injectedMap,
60
- hash: createHash("sha256").update(injectedMap).digest("hex"),
61
- debugId
62
- };
63
- }))).filter((f) => f !== null);
64
- const validMapping = {};
65
- for (const file of loaded) {
66
- const js = mapping[file.path];
67
- if (js) validMapping[file.path] = js;
68
- }
69
- return {
70
- files: loaded,
71
- mapping: validMapping,
72
- sourceFileCount: mapAbsolutes.size
73
- };
74
- }
75
- function normalizeDistDir(distDir = ".next") {
76
- let d = distDir.split("\\").join("/");
77
- while (d.startsWith("./")) d = d.slice(2);
78
- return d;
79
- }
80
- function toPublicPath(rel, distDir) {
81
- const p = rel.split("\\").join("/");
82
- if (p.startsWith(`${distDir}/`)) return `_next/${p.slice(distDir.length + 1)}`;
83
- if (p.startsWith(".next/")) return `_next/${p.slice(6)}`;
84
- return p;
85
- }
86
- //#endregion
87
- export { buildDebugIdSnippet, discover, injectDebugIdIntoJs, injectDebugIdIntoMap, normalizeDistDir };
1
+ import{normalizeDistDir}from"./paths.mjs";import{discoverTurbopack}from"./discover-turbopack.mjs";import{discoverWebpack,injectDebugIdIntoJs,injectDebugIdIntoMap}from"./discover-webpack.mjs";async function discoverSourceMaps(opts){let distDir=normalizeDistDir(opts.distDir);switch(opts.bundler){case`webpack`:return discoverWebpack({projectDir:opts.projectDir,distDir});case`turbopack`:return discoverTurbopack({projectDir:opts.projectDir,distDir})}}export{discoverSourceMaps,injectDebugIdIntoJs,injectDebugIdIntoMap};
@@ -1 +1 @@
1
- {"version":3,"file":"discover.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve } from \"node:path\";\n\nconst SOURCEMAPPING_RE = /\\/\\/[#@]\\s*sourceMappingURL=(\\S+)\\s*$/;\n\nexport interface SourceMapFile {\n readonly absolute: string;\n readonly content: string;\n readonly debugId: string;\n readonly hash: string;\n readonly path: string;\n}\n\nfunction resolveDistDir(projectDir: string, distDir: string) {\n return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);\n}\n\nasync function findJsFiles(dir: string) {\n const entries = await readdir(dir, { recursive: true }).catch(\n () => [] as string[]\n );\n return entries\n .filter((entry) => entry.endsWith(\".js\"))\n .map((entry) => join(dir, entry));\n}\n\nexport function buildDebugIdSnippet(debugId: string) {\n return `!function(){try{var s=(new Error).stack;s&&(globalThis._debugIds=globalThis._debugIds||{},globalThis._debugIds[s]=\"${debugId}\")}catch(e){}}();`;\n}\n\nexport function injectDebugIdIntoJs(content: string, debugId: string) {\n const snippet = buildDebugIdSnippet(debugId);\n const debugIdComment = `//# debugId=${debugId}`;\n\n const match = SOURCEMAPPING_RE.exec(content);\n if (match) {\n const before = content.slice(0, match.index).trimEnd();\n const sourceMappingLine = match[0];\n return `${snippet}\\n${before}\\n${debugIdComment}\\n${sourceMappingLine}`;\n }\n\n return `${snippet}\\n${content}\\n${debugIdComment}`;\n}\n\nexport function injectDebugIdIntoMap(content: string, debugId: string) {\n const json = JSON.parse(content) as Record<string, unknown>;\n json[\"debugId\"] = debugId;\n if (typeof json[\"mappings\"] === \"string\") {\n json[\"mappings\"] = `;${json[\"mappings\"]}`;\n }\n return JSON.stringify(json);\n}\n\nexport async function discover(projectDir: string, distDir: string) {\n const absDistDir = resolveDistDir(projectDir, distDir);\n const relDistDir = relative(projectDir, absDistDir);\n\n const [staticFiles, serverFiles] = await Promise.all([\n findJsFiles(join(absDistDir, \"static\")),\n findJsFiles(join(absDistDir, \"server\")),\n ]);\n\n const jsPaths = [...staticFiles, ...serverFiles];\n\n const mapping: Record<string, string> = {};\n const mapAbsolutes = new Map<string, string>();\n const jsAbsolutes = new Map<string, string>();\n\n for (const jsAbs of jsPaths) {\n const content = await readFile(jsAbs, \"utf8\");\n const match = SOURCEMAPPING_RE.exec(content);\n if (!match?.[1]) {\n continue;\n }\n\n const jsDir = jsAbs.slice(0, jsAbs.lastIndexOf(\"/\") + 1);\n const mapRef = decodeURIComponent(match[1]);\n const mapAbs = `${jsDir}${mapRef}`;\n const jsPublic = toPublicPath(relative(projectDir, jsAbs), relDistDir);\n const mapPublic = toPublicPath(relative(projectDir, mapAbs), relDistDir);\n\n mapping[mapPublic] = jsPublic;\n mapAbsolutes.set(mapPublic, mapAbs);\n jsAbsolutes.set(mapPublic, jsAbs);\n }\n\n const files = await Promise.all(\n mapAbsolutes.entries().map(async ([mapPublic, mapAbs]) => {\n const mapContent = await readFile(mapAbs, \"utf8\").catch(() => null);\n if (mapContent === null) {\n return null;\n }\n\n const jsAbs = jsAbsolutes.get(mapPublic);\n if (!jsAbs) {\n return null;\n }\n\n const debugId: string = randomUUID();\n\n const jsContent = await readFile(jsAbs, \"utf8\");\n const injectedJs = injectDebugIdIntoJs(jsContent, debugId);\n await writeFile(jsAbs, injectedJs, \"utf8\");\n\n const injectedMap = injectDebugIdIntoMap(mapContent, debugId);\n await writeFile(mapAbs, injectedMap, \"utf8\");\n\n return {\n absolute: mapAbs,\n path: mapPublic,\n content: injectedMap,\n hash: createHash(\"sha256\").update(injectedMap).digest(\"hex\"),\n debugId,\n };\n })\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n const validMapping: Record<string, string> = {};\n for (const file of loaded) {\n const js = mapping[file.path];\n if (js) {\n validMapping[file.path] = js;\n }\n }\n\n return {\n files: loaded,\n mapping: validMapping,\n sourceFileCount: mapAbsolutes.size,\n };\n}\n\nexport function normalizeDistDir(distDir = \".next\") {\n let d = distDir.split(\"\\\\\").join(\"/\");\n while (d.startsWith(\"./\")) {\n d = d.slice(2);\n }\n return d;\n}\n\nfunction toPublicPath(rel: string, distDir: string) {\n const p = rel.split(\"\\\\\").join(\"/\");\n if (p.startsWith(`${distDir}/`)) {\n return `_next/${p.slice(distDir.length + 1)}`;\n }\n if (p.startsWith(\".next/\")) {\n return `_next/${p.slice(6)}`;\n }\n return p;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"discover.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"sourcesContent":["import type { NextBuildBundler } from \"../detect-bundler.js\";\nimport { discoverTurbopack } from \"./discover-turbopack.js\";\nimport { discoverWebpack } from \"./discover-webpack.js\";\nimport { normalizeDistDir } from \"./paths.js\";\n\nexport interface SourceMapFile {\n readonly absolute: string;\n /**\n * Public URL the runtime will load this chunk from. ALWAYS populated\n * for both bundlers turbopack discovery walks JS chunks (in addition\n * to .map files) so it can record this. Lifted onto the manifest as\n * `chunkUrl`; server-side suffix-matching pairs `frame.fileName` to\n * this field by content-hashed filename.\n */\n readonly chunkUrl: string;\n readonly content: string;\n readonly debugId: string;\n readonly hash: string;\n readonly path: string;\n}\n\nexport interface DiscoveryResult {\n readonly files: SourceMapFile[];\n readonly sourceFileCount: number;\n}\n\n/**\n * Single entry point for source-map discovery. The pipeline calls this\n * with the active bundler from `detectActiveBundler()`; new bundlers (e.g.\n * rspack) drop in here as additional cases without touching the pipeline.\n * Other manifest bundlers (for Vite, CLI, etc.) live outside the Next\n * build pipeline and should use their own discovery implementation.\n */\nexport async function discoverSourceMaps(opts: {\n bundler: NextBuildBundler;\n projectDir: string;\n distDir: string;\n}): Promise<DiscoveryResult> {\n const distDir = normalizeDistDir(opts.distDir);\n switch (opts.bundler) {\n case \"webpack\":\n return discoverWebpack({ projectDir: opts.projectDir, distDir });\n case \"turbopack\":\n return discoverTurbopack({ projectDir: opts.projectDir, distDir });\n }\n}\n\nexport {\n injectDebugIdIntoJs,\n injectDebugIdIntoMap,\n} from \"./discover-webpack.js\";\n"],"mappings":"+LAiCA,eAAsB,mBAAmB,KAIZ,CAC3B,IAAM,QAAU,iBAAiB,KAAK,OAAO,EAC7C,OAAQ,KAAK,QAAb,CACE,IAAK,UACH,OAAO,gBAAgB,CAAE,WAAY,KAAK,WAAY,OAAQ,CAAC,EACjE,IAAK,YACH,OAAO,kBAAkB,CAAE,WAAY,KAAK,WAAY,OAAQ,CAAC,CACrE,CACF"}
@@ -1,29 +1,7 @@
1
1
  import { SourceMapFile } from "./discover.mjs";
2
+ import { uploadSourceMaps } from "./upload.mjs";
2
3
 
3
4
  //#region src/internal/build/source-maps/index.d.ts
4
- declare function buildUploadBody(discovered: {
5
- files: SourceMapFile[];
6
- mapping: Record<string, string>;
7
- sourceFileCount: number;
8
- }): {
9
- body: {
10
- files: {
11
- fileName: string;
12
- content: Blob;
13
- }[];
14
- metadata: {
15
- sourceMapToGenerated: Record<string, string>;
16
- hashes: {
17
- [k: string]: string;
18
- };
19
- debugIds: {
20
- [k: string]: string;
21
- };
22
- sourceFileCount: number;
23
- };
24
- };
25
- totalBytes: number;
26
- };
27
5
  declare function cleanupSourceMaps(files: SourceMapFile[]): Promise<void>;
28
6
  //#endregion
29
- export { buildUploadBody, cleanupSourceMaps };
7
+ export { cleanupSourceMaps, uploadSourceMaps };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"mappings":";;;iBAIgB,eAAA,CAAgB,UAAA;EAC9B,KAAA,EAAO,aAAA;EACP,OAAA,EAAS,MAAA;EACT,eAAA;AAAA;;;;;;;;;;;;;;;;;;;iBAwBoB,iBAAA,CAAkB,KAAA,EAAO,aAAA,KAAe,OAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"mappings":";;;;iBAKsB,iBAAA,CAAkB,KAAA,EAAO,aAAA,KAAkB,OAAO"}
@@ -1,28 +1 @@
1
- import { unlink } from "node:fs/promises";
2
- //#region src/internal/build/source-maps/index.ts
3
- function buildUploadBody(discovered) {
4
- let totalBytes = 0;
5
- return {
6
- body: {
7
- files: discovered.files.map((file) => {
8
- totalBytes += file.content.length;
9
- return {
10
- fileName: file.path,
11
- content: new Blob([file.content], { type: "application/json" })
12
- };
13
- }),
14
- metadata: {
15
- sourceMapToGenerated: discovered.mapping,
16
- hashes: Object.fromEntries(discovered.files.map((f) => [f.path, f.hash])),
17
- debugIds: Object.fromEntries(discovered.files.map((f) => [f.path, f.debugId])),
18
- sourceFileCount: discovered.sourceFileCount
19
- }
20
- },
21
- totalBytes
22
- };
23
- }
24
- async function cleanupSourceMaps(files) {
25
- await Promise.all(files.map((f) => unlink(f.absolute).catch(() => void 0)));
26
- }
27
- //#endregion
28
- export { buildUploadBody, cleanupSourceMaps };
1
+ import{log}from"../../logger.mjs";import{uploadSourceMaps}from"./upload.mjs";import{unlink}from"node:fs/promises";async function cleanupSourceMaps(files){let results=await Promise.allSettled(files.map(f=>unlink(f.absolute))),failures=[];for(let[i,r]of results.entries()){if(r.status!==`rejected`)continue;let err=r.reason;if(err.code===`ENOENT`)continue;let file=files[i];failures.push(`${file?.absolute??`<unknown>`}: ${err.code??err.message??String(err)}`)}failures.length>0&&log.warn(`Source-map cleanup left files on disk`,failures)}export{cleanupSourceMaps,uploadSourceMaps};
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"sourcesContent":["import { unlink } from \"node:fs/promises\";\n\nimport type { SourceMapFile } from \"./discover.js\";\n\nexport function buildUploadBody(discovered: {\n files: SourceMapFile[];\n mapping: Record<string, string>;\n sourceFileCount: number;\n}) {\n let totalBytes = 0;\n\n const files = discovered.files.map((file) => {\n totalBytes += file.content.length;\n return {\n fileName: file.path,\n content: new Blob([file.content], { type: \"application/json\" }),\n };\n });\n\n const metadata = {\n sourceMapToGenerated: discovered.mapping,\n hashes: Object.fromEntries(discovered.files.map((f) => [f.path, f.hash])),\n debugIds: Object.fromEntries(\n discovered.files.map((f) => [f.path, f.debugId])\n ),\n sourceFileCount: discovered.sourceFileCount,\n };\n\n return { body: { files, metadata }, totalBytes };\n}\n\nexport async function cleanupSourceMaps(files: SourceMapFile[]) {\n await Promise.all(\n files.map((f) => unlink(f.absolute).catch(() => undefined))\n );\n}\n"],"mappings":";;AAIA,SAAgB,gBAAgB,YAI7B;CACD,IAAI,aAAa;AAmBjB,QAAO;EAAE,MAAM;GAAE,OAjBH,WAAW,MAAM,KAAK,SAAS;AAC3C,kBAAc,KAAK,QAAQ;AAC3B,WAAO;KACL,UAAU,KAAK;KACf,SAAS,IAAI,KAAK,CAAC,KAAK,QAAQ,EAAE,EAAE,MAAM,oBAAoB,CAAC;KAChE;KAYmB;GAAE,UAAA;IARtB,sBAAsB,WAAW;IACjC,QAAQ,OAAO,YAAY,WAAW,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACzE,UAAU,OAAO,YACf,WAAW,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CACjD;IACD,iBAAiB,WAAW;IAGE;GAAE;EAAE;EAAY;;AAGlD,eAAsB,kBAAkB,OAAwB;AAC9D,OAAM,QAAQ,IACZ,MAAM,KAAK,MAAM,OAAO,EAAE,SAAS,CAAC,YAAY,KAAA,EAAU,CAAC,CAC5D"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"sourcesContent":["import { unlink } from \"node:fs/promises\";\n\nimport { log } from \"../../logger.js\";\nimport type { SourceMapFile } from \"./discover.js\";\n\nexport async function cleanupSourceMaps(files: SourceMapFile[]): Promise<void> {\n // ENOENT is the only failure we silently absorb — a missing file just\n // means the upload-then-cleanup race lost. Anything else (perm, IO,\n // EBUSY) is a real signal: the source map is now stranded on the\n // customer's CDN and we surface it via a single aggregated warning so\n // an operator can investigate without the build failing outright.\n const results = await Promise.allSettled(files.map((f) => unlink(f.absolute)));\n const failures: string[] = [];\n for (const [i, r] of results.entries()) {\n if (r.status !== \"rejected\") {\n continue;\n }\n const err = r.reason as NodeJS.ErrnoException;\n if (err.code === \"ENOENT\") {\n continue;\n }\n const file = files[i];\n failures.push(\n `${file?.absolute ?? \"<unknown>\"}: ${err.code ?? err.message ?? String(err)}`\n );\n }\n if (failures.length > 0) {\n log.warn(\"Source-map cleanup left files on disk\", failures);\n }\n}\n\nexport { uploadSourceMaps } from \"./upload.js\";\n"],"mappings":"kHAKA,eAAsB,kBAAkB,MAAuC,CAM7E,IAAM,QAAU,MAAM,QAAQ,WAAW,MAAM,IAAK,GAAM,OAAO,EAAE,QAAQ,CAAC,CAAC,EACvE,SAAqB,CAAC,EAC5B,IAAK,GAAM,CAAC,EAAG,KAAM,QAAQ,QAAQ,EAAG,CACtC,GAAI,EAAE,SAAW,WACf,SAEF,IAAM,IAAM,EAAE,OACd,GAAI,IAAI,OAAS,SACf,SAEF,IAAM,KAAO,MAAM,GACnB,SAAS,KACP,GAAG,MAAM,UAAY,YAAY,IAAI,IAAI,MAAQ,IAAI,SAAW,OAAO,GAAG,GAC5E,CACF,CACI,SAAS,OAAS,GACpB,IAAI,KAAK,wCAAyC,QAAQ,CAE9D"}
@@ -0,0 +1,28 @@
1
+ //#region src/internal/build/source-maps/paths.d.ts
2
+ /**
3
+ * Strips Windows path separators and leading `./` segments so the rest of
4
+ * the discovery code can assume POSIX-style paths relative to `projectDir`.
5
+ */
6
+ declare function normalizeDistDir(distDir?: string): string;
7
+ /**
8
+ * Resolves an absolute filesystem path for the build's `distDir`. Accepts
9
+ * either an absolute path (passed through) or a path relative to
10
+ * `projectDir`.
11
+ */
12
+ declare function resolveDistDir(projectDir: string, distDir: string): string;
13
+ /**
14
+ * Maps an on-disk path (relative to `projectDir`) to the URL path Next.js
15
+ * will serve it at. Both `_next/` and `.next/` shapes resolve to the public
16
+ * `_next/` prefix the browser sees in `//# sourceMappingURL=...` comments.
17
+ */
18
+ declare function toPublicPath(rel: string, distDir: string): string;
19
+ /**
20
+ * Recursively collects files under `<absDistDir>/static` and
21
+ * `<absDistDir>/server` matching the given suffix. Both subtrees are
22
+ * optional — partial builds (e.g. server-only chunks during ISR) commonly
23
+ * leave one missing, so a missing directory is treated as empty rather
24
+ * than fatal.
25
+ */
26
+ declare function walkDistTrees(absDistDir: string, suffix: ".js" | ".js.map"): Promise<string[]>;
27
+ //#endregion
28
+ export { normalizeDistDir, resolveDistDir, toPublicPath, walkDistTrees };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/paths.ts"],"mappings":";;AAUA;;;iBAAgB,gBAAA,CAAiB,OAAiB;AAAA;AASlD;;;;AATkD,iBASlC,cAAA,CAAe,UAAA,UAAoB,OAAe;AASlE;;;;AAAyD;AAAzD,iBAAgB,YAAA,CAAa,GAAA,UAAa,OAAe;;;;;;;;iBAkBnC,aAAA,CACpB,UAAA,UACA,MAAA,sBACC,OAAO"}
@@ -0,0 +1 @@
1
+ import{isAbsolute,join,resolve}from"node:path";import{readdir}from"node:fs/promises";const NEXT_PUBLIC_PREFIX=`_next/`;function normalizeDistDir(distDir=`.next`){return distDir.replaceAll(`\\`,`/`).replace(/^(\.\/)+/,``)}function resolveDistDir(projectDir,distDir){return isAbsolute(distDir)?distDir:resolve(projectDir,distDir)}function toPublicPath(rel,distDir){let p=rel.replaceAll(`\\`,`/`);return p.startsWith(`${distDir}/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length+1)}`:p.startsWith(`.next/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(6)}`:p}async function walkDistTrees(absDistDir,suffix){return(await Promise.all([`static`,`server`].map(async subtree=>{let root=join(absDistDir,subtree),entries=await readdir(root,{recursive:!0}).catch(()=>[]),out=[];for(let entry of entries)typeof entry==`string`&&entry.endsWith(suffix)&&out.push(join(root,entry));return out}))).flat()}export{normalizeDistDir,resolveDistDir,toPublicPath,walkDistTrees};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/paths.ts"],"sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nconst NEXT_PUBLIC_PREFIX = \"_next/\";\nconst NEXT_DIST_PREFIX = \".next/\";\n\n/**\n * Strips Windows path separators and leading `./` segments so the rest of\n * the discovery code can assume POSIX-style paths relative to `projectDir`.\n */\nexport function normalizeDistDir(distDir = \".next\"): string {\n return distDir.replaceAll(\"\\\\\", \"/\").replace(/^(\\.\\/)+/, \"\");\n}\n\n/**\n * Resolves an absolute filesystem path for the build's `distDir`. Accepts\n * either an absolute path (passed through) or a path relative to\n * `projectDir`.\n */\nexport function resolveDistDir(projectDir: string, distDir: string): string {\n return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);\n}\n\n/**\n * Maps an on-disk path (relative to `projectDir`) to the URL path Next.js\n * will serve it at. Both `_next/` and `.next/` shapes resolve to the public\n * `_next/` prefix the browser sees in `//# sourceMappingURL=...` comments.\n */\nexport function toPublicPath(rel: string, distDir: string): string {\n const p = rel.replaceAll(\"\\\\\", \"/\");\n if (p.startsWith(`${distDir}/`)) {\n return `${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length + 1)}`;\n }\n if (p.startsWith(NEXT_DIST_PREFIX)) {\n return `${NEXT_PUBLIC_PREFIX}${p.slice(NEXT_DIST_PREFIX.length)}`;\n }\n return p;\n}\n\n/**\n * Recursively collects files under `<absDistDir>/static` and\n * `<absDistDir>/server` matching the given suffix. Both subtrees are\n * optional — partial builds (e.g. server-only chunks during ISR) commonly\n * leave one missing, so a missing directory is treated as empty rather\n * than fatal.\n */\nexport async function walkDistTrees(\n absDistDir: string,\n suffix: \".js\" | \".js.map\"\n): Promise<string[]> {\n const subtrees = [\"static\", \"server\"] as const;\n\n const results = await Promise.all(\n subtrees.map(async (subtree) => {\n const root = join(absDistDir, subtree);\n const entries = await readdir(root, { recursive: true }).catch(\n () => [] as string[]\n );\n const out: string[] = [];\n for (const entry of entries) {\n if (typeof entry === \"string\" && entry.endsWith(suffix)) {\n out.push(join(root, entry));\n }\n }\n return out;\n })\n );\n\n return results.flat();\n}\n"],"mappings":"qFAGA,MAAM,mBAAqB,SAO3B,SAAgB,iBAAiB,QAAU,QAAiB,CAC1D,OAAO,QAAQ,WAAW,KAAM,GAAG,EAAE,QAAQ,WAAY,EAAE,CAC7D,CAOA,SAAgB,eAAe,WAAoB,QAAyB,CAC1E,OAAO,WAAW,OAAO,EAAI,QAAU,QAAQ,WAAY,OAAO,CACpE,CAOA,SAAgB,aAAa,IAAa,QAAyB,CACjE,IAAM,EAAI,IAAI,WAAW,KAAM,GAAG,EAOlC,OANI,EAAE,WAAW,GAAG,QAAQ,EAAE,EACrB,GAAG,qBAAqB,EAAE,MAAM,QAAQ,OAAS,CAAC,IAEvD,EAAE,WAAW,QAAgB,EACxB,GAAG,qBAAqB,EAAE,MAAM,CAAuB,IAEzD,CACT,CASA,eAAsB,cACpB,WACA,OACmB,CAmBnB,OAAO,MAhBe,QAAQ,IAC5B,CAHgB,SAAU,QAGnB,EAAE,IAAI,KAAO,UAAY,CAC9B,IAAM,KAAO,KAAK,WAAY,OAAO,EAC/B,QAAU,MAAM,QAAQ,KAAM,CAAE,UAAW,EAAK,CAAC,EAAE,UACjD,CAAC,CACT,EACM,IAAgB,CAAC,EACvB,IAAK,IAAM,SAAS,QACd,OAAO,OAAU,UAAY,MAAM,SAAS,MAAM,GACpD,IAAI,KAAK,KAAK,KAAM,KAAK,CAAC,EAG9B,OAAO,GACT,CAAC,CACH,GAEe,KAAK,CACtB"}
@@ -0,0 +1,46 @@
1
+ import { DiscoveryResult } from "./discover.mjs";
2
+ import { ReleaseSlug } from "@interfere/types/releases/slug";
3
+ import { HTTPClient } from "@interfere/sdk";
4
+ import { ManifestBundler } from "@interfere/types/data/source-maps";
5
+
6
+ //#region src/internal/build/source-maps/upload.d.ts
7
+ interface UploadResult {
8
+ fileCount: number;
9
+ totalBytes: number;
10
+ }
11
+ interface UploadParams {
12
+ apiUrl: string;
13
+ bundler: ManifestBundler;
14
+ discovered: DiscoveryResult;
15
+ httpClient: HTTPClient;
16
+ releaseSlug: ReleaseSlug;
17
+ }
18
+ /**
19
+ * Drives the three-step presigned-URL flow:
20
+ *
21
+ * 1. POST `/v1/releases/:slug/source-maps/sign` with per-file metadata.
22
+ * 2. PUT each file's content directly to R2 in parallel (concurrency
23
+ * bounded so a build with 1000+ chunks doesn't open 1000 sockets).
24
+ * 3. POST `/v1/releases/:slug/source-maps/complete` to materialize the
25
+ * manifest and update the release row.
26
+ *
27
+ * The collector never sees source-map bytes — uploads scale with R2
28
+ * limits, not Cloudflare worker / load-balancer body-size caps. The
29
+ * legacy multipart endpoint is still wired for older SDKs.
30
+ */
31
+ declare function uploadSourceMaps({
32
+ apiUrl,
33
+ bundler,
34
+ discovered,
35
+ httpClient,
36
+ releaseSlug
37
+ }: UploadParams): Promise<UploadResult>;
38
+ interface SourceMapRichness {
39
+ hasSourcesContent: boolean;
40
+ hasNames: boolean;
41
+ hasFile: boolean;
42
+ mappingsPresent: boolean;
43
+ }
44
+ declare function extractRichness(content: string): SourceMapRichness;
45
+ //#endregion
46
+ export { UploadResult, extractRichness, uploadSourceMaps };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/upload.ts"],"mappings":";;;;;;UAciB,YAAA;EACf,SAAA;EACA,UAAU;AAAA;AAAA,UAGF,YAAA;EACR,MAAA;EACA,OAAA,EAAS,eAAA;EACT,UAAA,EAAY,eAAA;EACZ,UAAA,EAAY,UAAA;EACZ,WAAA,EAAa,WAAA;AAAA;;;;;;;;;;;;;;iBAgBO,gBAAA,CAAA;EACpB,MAAA;EACA,OAAA;EACA,UAAA;EACA,UAAA;EACA;AAAA,GACC,YAAA,GAAe,OAAA,CAAQ,YAAA;AAAA,UAoEhB,iBAAA;EACR,iBAAA;EACA,QAAA;EACA,OAAA;EACA,eAAA;AAAA;AAAA,iBAyBc,eAAA,CAAgB,OAAA,WAAkB,iBAAiB"}
@@ -0,0 +1 @@
1
+ async function uploadSourceMaps({apiUrl,bundler,discovered,httpClient,releaseSlug}){let filesByPath=new Map(discovered.files.map(f=>[f.path,f])),signRequest={files:discovered.files.map(file=>({path:file.path,sizeBytes:byteLengthOf(file.content),...extractRichness(file.content)}))},signResponse=await postJson(httpClient,new URL(`/v1/releases/${encodeURIComponent(releaseSlug)}/source-maps/sign`,apiUrl),signRequest),totalBytes=0;await mapWithConcurrency(signResponse.uploads,12,async upload=>{let file=filesByPath.get(upload.path);if(!file)throw Error(`Sign response referenced unknown path "${upload.path}"`);totalBytes+=byteLengthOf(file.content),await putToR2(upload.presignedUrl,file.content)});let completeRequest={files:discovered.files.map(file=>({path:file.path,hash:file.hash,debugId:file.debugId,chunkUrl:file.chunkUrl})),sourceFileCount:discovered.sourceFileCount,bundler};return{fileCount:(await postJson(httpClient,new URL(`/v1/releases/${encodeURIComponent(releaseSlug)}/source-maps/complete`,apiUrl),completeRequest)).fileCount,totalBytes}}function byteLengthOf(content){return new TextEncoder().encode(content).byteLength}const EMPTY_RICHNESS={hasSourcesContent:!1,hasNames:!1,hasFile:!1,mappingsPresent:!1};function leafRichness(map){let sourcesContent=map.sourcesContent,names=map.names,file=map.file,mappings=map.mappings;return{hasSourcesContent:Array.isArray(sourcesContent)&&sourcesContent.length>0,hasNames:Array.isArray(names)&&names.length>0,hasFile:typeof file==`string`&&file.length>0,mappingsPresent:typeof mappings==`string`&&mappings.length>0}}function extractRichness(content){let parsed;try{parsed=JSON.parse(content)}catch{return EMPTY_RICHNESS}if(!(parsed&&typeof parsed==`object`))return EMPTY_RICHNESS;let top=parsed,sections=top.sections;if(!Array.isArray(sections))return leafRichness(top);let merged={hasSourcesContent:!1,hasNames:!1,hasFile:typeof top.file==`string`&&top.file.length>0,mappingsPresent:!1};for(let section of sections){let inner=section?.map;if(!(inner&&typeof inner==`object`))continue;let r=leafRichness(inner);merged.hasSourcesContent||=r.hasSourcesContent,merged.hasNames||=r.hasNames,merged.mappingsPresent||=r.mappingsPresent}return merged}async function postJson(httpClient,url,body){let response=await httpClient.request(new Request(url,{method:`POST`,headers:{"content-type":`application/json`,accept:`application/json`},body:JSON.stringify(body)}));if(!response.ok){let detail=await response.text().catch(()=>``);throw Error(`Source-map API request failed: POST ${url.pathname} -> ${response.status} ${detail}`)}return await response.json()}async function putToR2(presignedUrl,content){let response=await fetch(presignedUrl,{method:`PUT`,headers:{"content-type":`application/json`},body:content});if(!response.ok){let detail=await response.text().catch(()=>``);throw Error(`Release metadata file upload failed: ${response.status} ${detail}`)}}async function mapWithConcurrency(items,concurrency,fn){let cursor=0;async function worker(){for(;;){let i=cursor++;if(i>=items.length)return;let item=items[i];if(item===void 0)return;await fn(item,i)}}await Promise.all(Array.from({length:Math.min(concurrency,items.length)},()=>worker()))}export{extractRichness,uploadSourceMaps};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/upload.ts"],"sourcesContent":["import type { HTTPClient } from \"@interfere/sdk\";\nimport type { ReleaseSlug } from \"@interfere/types/releases/slug\";\nimport type {\n CompleteSourceMapsRequest,\n CompleteSourceMapsResponse,\n ManifestBundler,\n SignSourceMapsRequest,\n SignSourceMapsResponse,\n} from \"@interfere/types/data/source-maps\";\n\nimport type { DiscoveryResult } from \"./discover.js\";\n\nconst PUT_CONCURRENCY = 12;\n\nexport interface UploadResult {\n fileCount: number;\n totalBytes: number;\n}\n\ninterface UploadParams {\n apiUrl: string;\n bundler: ManifestBundler;\n discovered: DiscoveryResult;\n httpClient: HTTPClient;\n releaseSlug: ReleaseSlug;\n}\n\n/**\n * Drives the three-step presigned-URL flow:\n *\n * 1. POST `/v1/releases/:slug/source-maps/sign` with per-file metadata.\n * 2. PUT each file's content directly to R2 in parallel (concurrency\n * bounded so a build with 1000+ chunks doesn't open 1000 sockets).\n * 3. POST `/v1/releases/:slug/source-maps/complete` to materialize the\n * manifest and update the release row.\n *\n * The collector never sees source-map bytes — uploads scale with R2\n * limits, not Cloudflare worker / load-balancer body-size caps. The\n * legacy multipart endpoint is still wired for older SDKs.\n */\nexport async function uploadSourceMaps({\n apiUrl,\n bundler,\n discovered,\n httpClient,\n releaseSlug,\n}: UploadParams): Promise<UploadResult> {\n const filesByPath = new Map(discovered.files.map((f) => [f.path, f]));\n\n const signRequest = {\n files: discovered.files.map((file) => ({\n path: file.path,\n sizeBytes: byteLengthOf(file.content),\n ...extractRichness(file.content),\n })),\n } satisfies SignSourceMapsRequest;\n\n const signResponse = await postJson<SignSourceMapsResponse>(\n httpClient,\n new URL(\n `/v1/releases/${encodeURIComponent(releaseSlug)}/source-maps/sign`,\n apiUrl\n ),\n signRequest\n );\n\n let totalBytes = 0;\n\n await mapWithConcurrency(\n signResponse.uploads,\n PUT_CONCURRENCY,\n async (upload) => {\n const file = filesByPath.get(upload.path);\n if (!file) {\n throw new Error(\n `Sign response referenced unknown path \"${upload.path}\"`\n );\n }\n\n totalBytes += byteLengthOf(file.content);\n await putToR2(upload.presignedUrl, file.content);\n }\n );\n\n const completeRequest = {\n files: discovered.files.map((file) => ({\n path: file.path,\n hash: file.hash,\n debugId: file.debugId,\n chunkUrl: file.chunkUrl,\n })),\n sourceFileCount: discovered.sourceFileCount,\n bundler,\n } satisfies CompleteSourceMapsRequest;\n\n const completeResponse = await postJson<CompleteSourceMapsResponse>(\n httpClient,\n new URL(\n `/v1/releases/${encodeURIComponent(releaseSlug)}/source-maps/complete`,\n apiUrl\n ),\n completeRequest\n );\n\n return {\n fileCount: completeResponse.fileCount,\n totalBytes,\n };\n}\n\nfunction byteLengthOf(content: string) {\n return new TextEncoder().encode(content).byteLength;\n}\n\ninterface SourceMapRichness {\n hasSourcesContent: boolean;\n hasNames: boolean;\n hasFile: boolean;\n mappingsPresent: boolean;\n}\n\nconst EMPTY_RICHNESS: SourceMapRichness = {\n hasSourcesContent: false,\n hasNames: false,\n hasFile: false,\n mappingsPresent: false,\n};\n\nfunction leafRichness(map: Record<string, unknown>): SourceMapRichness {\n const sourcesContent = map[\"sourcesContent\"];\n const names = map[\"names\"];\n const file = map[\"file\"];\n const mappings = map[\"mappings\"];\n\n return {\n hasSourcesContent:\n Array.isArray(sourcesContent) && sourcesContent.length > 0,\n hasNames: Array.isArray(names) && names.length > 0,\n hasFile: typeof file === \"string\" && file.length > 0,\n mappingsPresent: typeof mappings === \"string\" && mappings.length > 0,\n };\n}\n\nexport function extractRichness(content: string): SourceMapRichness {\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return EMPTY_RICHNESS;\n }\n\n if (!(parsed && typeof parsed === \"object\")) {\n return EMPTY_RICHNESS;\n }\n\n const top = parsed as Record<string, unknown>;\n const sections = top[\"sections\"];\n\n if (!Array.isArray(sections)) {\n return leafRichness(top);\n }\n\n const merged: SourceMapRichness = {\n hasSourcesContent: false,\n hasNames: false,\n hasFile: typeof top[\"file\"] === \"string\" && (top[\"file\"] as string).length > 0,\n mappingsPresent: false,\n };\n\n for (const section of sections) {\n const inner = (section as { map?: unknown } | null)?.map;\n if (!(inner && typeof inner === \"object\")) {\n continue;\n }\n const r = leafRichness(inner as Record<string, unknown>);\n merged.hasSourcesContent ||= r.hasSourcesContent;\n merged.hasNames ||= r.hasNames;\n merged.mappingsPresent ||= r.mappingsPresent;\n }\n\n return merged;\n}\n\nasync function postJson<T>(\n httpClient: HTTPClient,\n url: URL,\n body: unknown\n): Promise<T> {\n const response = await httpClient.request(\n new Request(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n },\n body: JSON.stringify(body),\n })\n );\n\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw new Error(\n `Source-map API request failed: POST ${url.pathname} -> ${response.status} ${detail}`\n );\n }\n\n return (await response.json()) as T;\n}\n\nasync function putToR2(presignedUrl: string, content: string) {\n const response = await fetch(presignedUrl, {\n method: \"PUT\",\n headers: { \"content-type\": \"application/json\" },\n body: content,\n });\n\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw new Error(\n `Release metadata file upload failed: ${response.status} ${detail}`\n );\n }\n}\n\nasync function mapWithConcurrency<T>(\n items: T[],\n concurrency: number,\n fn: (item: T, index: number) => Promise<void>\n): Promise<void> {\n let cursor = 0;\n\n async function worker() {\n while (true) {\n const i = cursor++;\n if (i >= items.length) {\n return;\n }\n const item = items[i];\n // Index is bounded by `items.length` above; the assertion is\n // narrowing for noUncheckedIndexedAccess, not a runtime check.\n if (item === undefined) {\n return;\n }\n await fn(item, i);\n }\n }\n\n await Promise.all(\n Array.from({ length: Math.min(concurrency, items.length) }, () => worker())\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"value-injection-loader.d.mts","names":[],"sources":["../../../src/internal/build/value-injection-loader.ts"],"mappings":";;;UAEiB,2BAAA;EAAA,SACN,gBAAA;EAAA,SACA,MAAA,GAAS,OAAA,CAAQ,uBAAA;AAAA;AAAA,UAGlB,UAAA;EACR,UAAA,IAAc,CAAA;AAAA;AAAA,iBAGQ,oBAAA,CACtB,IAAA,EAAM,UAAA,CAAW,2BAAA,GACjB,QAAA"}
1
+ {"version":3,"file":"value-injection-loader.d.mts","names":[],"sources":["../../../src/internal/build/value-injection-loader.ts"],"mappings":";;;UAEiB,2BAAA;EAAA,SACN,gBAAA;EAAA,SACA,MAAA,GAAS,OAAO,CAAC,uBAAA;AAAA;AAAA,UAGlB,UAAA;EACR,UAAA,IAAc,CAAC;AAAA;AAAA,iBAGO,oBAAA,CACtB,IAAA,EAAM,UAAU,CAAC,2BAAA,GACjB,QAAA"}
@@ -1,24 +1,2 @@
1
- //#region src/internal/build/value-injection-loader.ts
2
- function valueInjectionLoader(userCode) {
3
- const values = resolveValues(this.getOptions());
4
- const lines = Object.entries(values).filter(([, value]) => value !== void 0).map(([key, value]) => {
5
- return `globalThis["${key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"] = ${JSON.stringify(value)};`;
6
- });
7
- if (lines.length === 0) return userCode;
8
- return `${lines.join("\n")}\n${userCode}`;
9
- }
10
- function resolveValues(options) {
11
- if (typeof options.serializedValues === "string") try {
12
- const parsed = JSON.parse(options.serializedValues);
13
- if (isRecord(parsed)) return parsed;
14
- return {};
15
- } catch {
16
- return {};
17
- }
18
- return options.values ?? {};
19
- }
20
- function isRecord(value) {
21
- return typeof value === "object" && value !== null && !Array.isArray(value);
22
- }
23
- //#endregion
24
- export { valueInjectionLoader as default };
1
+ function valueInjectionLoader(userCode){let values=resolveValues(this.getOptions()),lines=Object.entries(values).filter(([,value])=>value!==void 0).map(([key,value])=>`globalThis["${key.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"] = ${JSON.stringify(value)};`);return lines.length===0?userCode:`${lines.join(`
2
+ `)}\n${userCode}`}function resolveValues(options){if(typeof options.serializedValues==`string`)try{let parsed=JSON.parse(options.serializedValues);return isRecord(parsed)?parsed:{}}catch{return{}}return options.values??{}}function isRecord(value){return typeof value==`object`&&!!value&&!Array.isArray(value)}export{valueInjectionLoader as default};
@@ -1 +1 @@
1
- {"version":3,"file":"value-injection-loader.mjs","names":[],"sources":["../../../src/internal/build/value-injection-loader.ts"],"sourcesContent":["import type { InterfereInjectedValues } from \"./configure-build.js\";\n\nexport interface ValueInjectionLoaderOptions {\n readonly serializedValues?: string;\n readonly values?: Partial<InterfereInjectedValues>;\n}\n\ninterface LoaderThis<T> {\n getOptions(): T;\n}\n\nexport default function valueInjectionLoader(\n this: LoaderThis<ValueInjectionLoaderOptions>,\n userCode: string\n): string {\n const values = resolveValues(this.getOptions());\n const lines = Object.entries(values)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => {\n const escapedKey = key.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n return `globalThis[\"${escapedKey}\"] = ${JSON.stringify(value)};`;\n });\n\n if (lines.length === 0) {\n return userCode;\n }\n\n return `${lines.join(\"\\n\")}\\n${userCode}`;\n}\n\nfunction resolveValues(\n options: ValueInjectionLoaderOptions\n): Record<string, unknown> {\n if (typeof options.serializedValues === \"string\") {\n try {\n const parsed = JSON.parse(options.serializedValues);\n if (isRecord(parsed)) {\n return parsed;\n }\n return {};\n } catch {\n return {};\n }\n }\n\n return options.values ?? {};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":";AAWA,SAAwB,qBAEtB,UACQ;CACR,MAAM,SAAS,cAAc,KAAK,YAAY,CAAC;CAC/C,MAAM,QAAQ,OAAO,QAAQ,OAAO,CACjC,QAAQ,GAAG,WAAW,UAAU,KAAA,EAAU,CAC1C,KAAK,CAAC,KAAK,WAAW;AAErB,SAAO,eADY,IAAI,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,OAC5B,CAAC,OAAO,KAAK,UAAU,MAAM,CAAC;GAC9D;AAEJ,KAAI,MAAM,WAAW,EACnB,QAAO;AAGT,QAAO,GAAG,MAAM,KAAK,KAAK,CAAC,IAAI;;AAGjC,SAAS,cACP,SACyB;AACzB,KAAI,OAAO,QAAQ,qBAAqB,SACtC,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,QAAQ,iBAAiB;AACnD,MAAI,SAAS,OAAO,CAClB,QAAO;AAET,SAAO,EAAE;SACH;AACN,SAAO,EAAE;;AAIb,QAAO,QAAQ,UAAU,EAAE;;AAG7B,SAAS,SAAS,OAAkD;AAClE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM"}
1
+ {"version":3,"file":"value-injection-loader.mjs","names":[],"sources":["../../../src/internal/build/value-injection-loader.ts"],"sourcesContent":["import type { InterfereInjectedValues } from \"./configure-build.js\";\n\nexport interface ValueInjectionLoaderOptions {\n readonly serializedValues?: string;\n readonly values?: Partial<InterfereInjectedValues>;\n}\n\ninterface LoaderThis<T> {\n getOptions(): T;\n}\n\nexport default function valueInjectionLoader(\n this: LoaderThis<ValueInjectionLoaderOptions>,\n userCode: string\n): string {\n const values = resolveValues(this.getOptions());\n const lines = Object.entries(values)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => {\n const escapedKey = key.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n return `globalThis[\"${escapedKey}\"] = ${JSON.stringify(value)};`;\n });\n\n if (lines.length === 0) {\n return userCode;\n }\n\n return `${lines.join(\"\\n\")}\\n${userCode}`;\n}\n\nfunction resolveValues(\n options: ValueInjectionLoaderOptions\n): Record<string, unknown> {\n if (typeof options.serializedValues === \"string\") {\n try {\n const parsed = JSON.parse(options.serializedValues);\n if (isRecord(parsed)) {\n return parsed;\n }\n return {};\n } catch {\n return {};\n }\n }\n\n return options.values ?? {};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"AAWA,SAAwB,qBAEtB,SACQ,CACR,IAAM,OAAS,cAAc,KAAK,WAAW,CAAC,EACxC,MAAQ,OAAO,QAAQ,MAAM,EAChC,QAAQ,EAAG,SAAW,QAAU,IAAA,EAAS,EACzC,KAAK,CAAC,IAAK,SAEH,eADY,IAAI,QAAQ,MAAO,MAAM,EAAE,QAAQ,KAAM,KAC7B,EAAE,OAAO,KAAK,UAAU,KAAK,EAAE,EAC/D,EAMH,OAJI,MAAM,SAAW,EACZ,SAGF,GAAG,MAAM,KAAK;CAAI,EAAE,IAAI,UACjC,CAEA,SAAS,cACP,QACyB,CACzB,GAAI,OAAO,QAAQ,kBAAqB,SACtC,GAAI,CACF,IAAM,OAAS,KAAK,MAAM,QAAQ,gBAAgB,EAIlD,OAHI,SAAS,MAAM,EACV,OAEF,CAAC,CACV,MAAQ,CACN,MAAO,CAAC,CACV,CAGF,OAAO,QAAQ,QAAU,CAAC,CAC5B,CAEA,SAAS,SAAS,MAAkD,CAClE,OAAO,OAAO,OAAU,YAAY,OAAkB,CAAC,MAAM,QAAQ,KAAK,CAC5E"}
@@ -5,13 +5,23 @@ interface InterfereEnv {
5
5
  readonly apiKey: string | null;
6
6
  readonly apiUrl: string;
7
7
  readonly nextRuntime: string | null;
8
- readonly nodeEnvironment: Exclude<Env, null>;
8
+ readonly nodeEnvironment: Env;
9
+ readonly publicKey: string | null;
9
10
  readonly release: {
10
11
  readonly sourceId: string | null;
11
12
  readonly destinationId: string | null;
12
13
  };
13
14
  }
14
- declare function isEnabledInEnvironment(): boolean;
15
+ /**
16
+ * Server-side gate for the proxy route handler, the `captureError` /
17
+ * `onRequestError` helpers, and the remote-config fetcher. Distinct
18
+ * from the browser-side `isEnabledByEnvironment` (in
19
+ * `@interfere/react/internal/kernel`) because the server has different
20
+ * env conventions: `NEXT_PUBLIC_INTERFERE_FORCE_ENABLE` is the dev
21
+ * opt-in, and there's no "unknown runtime, default enabled" case the
22
+ * way the browser SDK has for plain-browser / Vite hosts.
23
+ */
24
+ declare function isEnabledOnServer(): boolean;
15
25
  declare function readInterfereEnv(): InterfereEnv;
16
26
  //#endregion
17
- export { InterfereEnv, isEnabledInEnvironment, readInterfereEnv };
27
+ export { InterfereEnv, isEnabledOnServer, readInterfereEnv };
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.mts","names":[],"sources":["../../src/internal/env.ts"],"mappings":";;;UAKiB,YAAA;EAAA,SACN,MAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,eAAA,EAAiB,OAAA,CAAQ,GAAA;EAAA,SACzB,OAAA;IAAA,SACE,QAAA;IAAA,SACA,aAAA;EAAA;AAAA;AAAA,iBAIG,sBAAA,CAAA;AAAA,iBAOA,gBAAA,CAAA,GAAoB,YAAA"}
1
+ {"version":3,"file":"env.d.mts","names":[],"sources":["../../src/internal/env.ts"],"mappings":";;;UAKiB,YAAA;EAAA,SACN,MAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,eAAA,EAAiB,GAAG;EAAA,SACpB,SAAA;EAAA,SACA,OAAA;IAAA,SACE,QAAA;IAAA,SACA,aAAA;EAAA;AAAA;;;;;;AAAa;AAa1B;;;iBAAgB,iBAAA,CAAA;AAAA,iBAOA,gBAAA,CAAA,GAAoB,YAAY"}