@interfere/next 11.0.0-canary.2 → 11.0.0-canary.3

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 (120) hide show
  1. package/README.md +3 -2
  2. package/dist/config.mjs +1 -1
  3. package/dist/instrument-client.d.mts +1 -0
  4. package/dist/instrumentation.d.mts +4 -2
  5. package/dist/instrumentation.edge.d.mts +16 -23
  6. package/dist/instrumentation.edge.mjs +1 -1
  7. package/dist/instrumentation.mjs +1 -1
  8. package/dist/internal/build/configure-build.mjs +1 -1
  9. package/dist/internal/build/pipeline.d.mts +1 -14
  10. package/dist/internal/build/release/destinations/cli.d.mts +7 -0
  11. package/dist/internal/build/release/destinations/cli.mjs +1 -0
  12. package/dist/internal/build/release/destinations/cloudflare.d.mts +6 -0
  13. package/dist/internal/build/release/destinations/cloudflare.mjs +1 -0
  14. package/dist/internal/build/release/destinations/index.d.mts +5 -4
  15. package/dist/internal/build/release/destinations/index.mjs +1 -1
  16. package/dist/internal/build/release/index.mjs +1 -1
  17. package/dist/internal/build/source-maps/discover-webpack.d.mts +1 -7
  18. package/dist/internal/build/source-maps/discover-webpack.mjs +1 -1
  19. package/dist/internal/env.mjs +1 -1
  20. package/dist/internal/release-slug.d.mts +1 -17
  21. package/dist/internal/release-slug.mjs +1 -1
  22. package/dist/internal/route/proxy.d.mts +1 -21
  23. package/dist/internal/route/proxy.mjs +1 -1
  24. package/dist/internal/server/capture.d.mts +6 -1
  25. package/dist/internal/server/capture.mjs +1 -1
  26. package/dist/internal/server/edge-exporter.d.mts +14 -0
  27. package/dist/internal/server/edge-exporter.mjs +1 -0
  28. package/dist/internal/server/global-handlers.d.mts +11 -0
  29. package/dist/internal/server/global-handlers.mjs +1 -0
  30. package/dist/internal/server/instrumentation-options.d.mts +15 -1
  31. package/dist/internal/server/server-action-marker.d.mts +9 -0
  32. package/dist/internal/server/server-action-marker.mjs +1 -0
  33. package/dist/internal/server/trace-meta.d.mts +1 -1
  34. package/dist/internal/server/types.d.mts +5 -0
  35. package/dist/internal/server/wrap-proxy.d.mts +22 -0
  36. package/dist/internal/server/wrap-proxy.mjs +1 -0
  37. package/dist/internal/server/wrap-server-action.d.mts +34 -0
  38. package/dist/internal/server/wrap-server-action.mjs +1 -0
  39. package/dist/package.mjs +1 -1
  40. package/dist/server.d.mts +3 -1
  41. package/dist/server.mjs +1 -1
  42. package/package.json +22 -23
  43. package/dist/config.d.mts.map +0 -1
  44. package/dist/config.mjs.map +0 -1
  45. package/dist/instrument-client.d.mts.map +0 -1
  46. package/dist/instrument-client.mjs.map +0 -1
  47. package/dist/instrumentation-client.mjs.map +0 -1
  48. package/dist/instrumentation.d.mts.map +0 -1
  49. package/dist/instrumentation.edge.d.mts.map +0 -1
  50. package/dist/instrumentation.edge.mjs.map +0 -1
  51. package/dist/instrumentation.mjs.map +0 -1
  52. package/dist/internal/build/configure-build.d.mts.map +0 -1
  53. package/dist/internal/build/configure-build.mjs.map +0 -1
  54. package/dist/internal/build/detect-bundler.d.mts.map +0 -1
  55. package/dist/internal/build/detect-bundler.mjs.map +0 -1
  56. package/dist/internal/build/pipeline.d.mts.map +0 -1
  57. package/dist/internal/build/pipeline.mjs.map +0 -1
  58. package/dist/internal/build/release/destinations/index.d.mts.map +0 -1
  59. package/dist/internal/build/release/destinations/index.mjs.map +0 -1
  60. package/dist/internal/build/release/destinations/vercel.d.mts.map +0 -1
  61. package/dist/internal/build/release/destinations/vercel.mjs.map +0 -1
  62. package/dist/internal/build/release/git.d.mts.map +0 -1
  63. package/dist/internal/build/release/git.mjs.map +0 -1
  64. package/dist/internal/build/release/index.d.mts.map +0 -1
  65. package/dist/internal/build/release/index.mjs.map +0 -1
  66. package/dist/internal/build/release/sources/github.d.mts.map +0 -1
  67. package/dist/internal/build/release/sources/github.mjs.map +0 -1
  68. package/dist/internal/build/release/sources/index.d.mts.map +0 -1
  69. package/dist/internal/build/release/sources/index.mjs.map +0 -1
  70. package/dist/internal/build/source-maps/discover-turbopack.d.mts.map +0 -1
  71. package/dist/internal/build/source-maps/discover-turbopack.mjs.map +0 -1
  72. package/dist/internal/build/source-maps/discover-webpack.d.mts.map +0 -1
  73. package/dist/internal/build/source-maps/discover-webpack.mjs.map +0 -1
  74. package/dist/internal/build/source-maps/discover.d.mts.map +0 -1
  75. package/dist/internal/build/source-maps/discover.mjs.map +0 -1
  76. package/dist/internal/build/source-maps/index.d.mts.map +0 -1
  77. package/dist/internal/build/source-maps/index.mjs.map +0 -1
  78. package/dist/internal/build/source-maps/paths.d.mts.map +0 -1
  79. package/dist/internal/build/source-maps/paths.mjs.map +0 -1
  80. package/dist/internal/build/source-maps/upload.d.mts.map +0 -1
  81. package/dist/internal/build/source-maps/upload.mjs.map +0 -1
  82. package/dist/internal/build/value-injection-loader.d.mts.map +0 -1
  83. package/dist/internal/build/value-injection-loader.mjs.map +0 -1
  84. package/dist/internal/env.d.mts.map +0 -1
  85. package/dist/internal/env.mjs.map +0 -1
  86. package/dist/internal/logger.d.mts.map +0 -1
  87. package/dist/internal/logger.mjs.map +0 -1
  88. package/dist/internal/release-slug.d.mts.map +0 -1
  89. package/dist/internal/release-slug.mjs.map +0 -1
  90. package/dist/internal/route/handle-get.d.mts.map +0 -1
  91. package/dist/internal/route/handle-get.mjs.map +0 -1
  92. package/dist/internal/route/handle-post.d.mts.map +0 -1
  93. package/dist/internal/route/handle-post.mjs.map +0 -1
  94. package/dist/internal/route/proxy.d.mts.map +0 -1
  95. package/dist/internal/route/proxy.mjs.map +0 -1
  96. package/dist/internal/server/capture.d.mts.map +0 -1
  97. package/dist/internal/server/capture.mjs.map +0 -1
  98. package/dist/internal/server/console-bridge.d.mts.map +0 -1
  99. package/dist/internal/server/console-bridge.mjs.map +0 -1
  100. package/dist/internal/server/id-generator.d.mts.map +0 -1
  101. package/dist/internal/server/id-generator.mjs.map +0 -1
  102. package/dist/internal/server/instrumentation-options.d.mts.map +0 -1
  103. package/dist/internal/server/remote-config.d.mts.map +0 -1
  104. package/dist/internal/server/remote-config.mjs.map +0 -1
  105. package/dist/internal/server/trace-meta.d.mts.map +0 -1
  106. package/dist/internal/server/trace-meta.mjs.map +0 -1
  107. package/dist/internal/server/traceparent.d.mts.map +0 -1
  108. package/dist/internal/server/traceparent.mjs.map +0 -1
  109. package/dist/internal/server/types.d.mts.map +0 -1
  110. package/dist/internal/setup-warnings.d.mts.map +0 -1
  111. package/dist/internal/setup-warnings.mjs.map +0 -1
  112. package/dist/internal/url.d.mts.map +0 -1
  113. package/dist/internal/url.mjs.map +0 -1
  114. package/dist/internal/version.d.mts.map +0 -1
  115. package/dist/internal/version.mjs.map +0 -1
  116. package/dist/package.mjs.map +0 -1
  117. package/dist/provider.d.mts.map +0 -1
  118. package/dist/provider.mjs.map +0 -1
  119. package/dist/route-handler.d.mts.map +0 -1
  120. package/dist/route-handler.mjs.map +0 -1
@@ -0,0 +1,34 @@
1
+ //#region src/internal/server/wrap-server-action.d.ts
2
+ interface ServerActionOptions {
3
+ /**
4
+ * The action's arguments — used only to derive a value-free shape (typeof /
5
+ * class names), never recorded. Pass them to populate `args_shape`.
6
+ */
7
+ readonly args?: readonly unknown[];
8
+ }
9
+ /**
10
+ * Wraps a Next.js Server Action so a failure is attributed to the action.
11
+ * Records the action's name, args-shape (no values), and outcome on a dedicated
12
+ * span, and annotates any thrown error with that identity — it does **not**
13
+ * emit its own exception event. Next routes the rethrown error to
14
+ * `onRequestError`, which becomes the single server-side capture and is tagged
15
+ * `auto.function.nextjs.server_action` once it reads the annotation. That one
16
+ * event carries Next's `errorDigest`, so it groups with the client report
17
+ * instead of forking a second, digest-less issue.
18
+ *
19
+ * ```ts
20
+ * export async function createUser(formData: FormData) {
21
+ * "use server";
22
+ * return withInterfereServerAction(
23
+ * "createUser",
24
+ * async () => {
25
+ * // ...action body
26
+ * },
27
+ * { args: [formData] }
28
+ * );
29
+ * }
30
+ * ```
31
+ */
32
+ declare function withInterfereServerAction<T>(name: string, callback: () => T | Promise<T>, options?: ServerActionOptions): Promise<T>;
33
+ //#endregion
34
+ export { withInterfereServerAction };
@@ -0,0 +1 @@
1
+ import{markServerAction}from"./server-action-marker.mjs";import{SpanStatusCode,trace}from"@opentelemetry/api";function withInterfereServerAction(name,callback,options){return trace.getTracer(`@interfere/next/server`).startActiveSpan(`serverAction ${name}`,async span=>{span.setAttribute(`interfere.server_action.name`,name);let argsShape=options?.args?describeArgsShape(options.args):null;argsShape&&span.setAttribute(`interfere.server_action.args_shape`,argsShape);try{let result=await callback();return span.setAttribute(`interfere.server_action.outcome`,`success`),result}catch(error){throw span.setAttribute(`interfere.server_action.outcome`,`error`),span.setStatus({code:SpanStatusCode.ERROR}),markServerAction(error,{name,...argsShape?{argsShape}:{}}),error}finally{span.end()}})}function describeArgsShape(args){return args.map(arg=>arg===null?`null`:arg===void 0?`undefined`:typeof arg==`object`?arg.constructor?.name??`object`:typeof arg).join(`,`)}export{withInterfereServerAction};
package/dist/package.mjs CHANGED
@@ -1 +1 @@
1
- var name=`@interfere/next`,version=`11.0.0-canary.2`;export{name,version};
1
+ var name=`@interfere/next`,version=`11.0.0-canary.3`;export{name,version};
package/dist/server.d.mts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { CaptureErrorContext, OnRequestErrorContext } from "./internal/server/types.mjs";
2
2
  import { captureError, onRequestError } from "./internal/server/capture.mjs";
3
3
  import { TraceMeta } from "./internal/server/trace-meta.mjs";
4
- export { type CaptureErrorContext, type OnRequestErrorContext, TraceMeta, captureError, onRequestError };
4
+ import { withInterfereProxy } from "./internal/server/wrap-proxy.mjs";
5
+ import { withInterfereServerAction } from "./internal/server/wrap-server-action.mjs";
6
+ export { type CaptureErrorContext, type OnRequestErrorContext, TraceMeta, captureError, onRequestError, withInterfereProxy, withInterfereServerAction };
package/dist/server.mjs CHANGED
@@ -1 +1 @@
1
- import{captureError,onRequestError}from"./internal/server/capture.mjs";import{TraceMeta}from"./internal/server/trace-meta.mjs";export{TraceMeta,captureError,onRequestError};
1
+ import{captureError,onRequestError}from"./internal/server/capture.mjs";import{TraceMeta}from"./internal/server/trace-meta.mjs";import{withInterfereProxy}from"./internal/server/wrap-proxy.mjs";import{withInterfereServerAction}from"./internal/server/wrap-server-action.mjs";export{TraceMeta,captureError,onRequestError,withInterfereProxy,withInterfereServerAction};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interfere/next",
3
- "version": "11.0.0-canary.2",
3
+ "version": "11.0.0-canary.3",
4
4
  "license": "MIT",
5
5
  "description": "Build software that never breaks.",
6
6
  "keywords": [
@@ -100,26 +100,26 @@
100
100
  "dependencies": {
101
101
  "@interfere/constants": "^9.0.2-canary.0",
102
102
  "@interfere/helpers": "^9.0.0",
103
- "@interfere/react": "^11.0.0-canary.2",
104
- "@interfere/sdk": "^11.0.0-canary.2",
105
- "@interfere/types": "^9.0.3-canary.1",
103
+ "@interfere/react": "^11.0.0-canary.3",
104
+ "@interfere/sdk": "^11.0.0-canary.3",
105
+ "@interfere/types": "^9.0.3-canary.2",
106
106
  "@opentelemetry/api": "^1.9.1",
107
- "@opentelemetry/api-logs": "^0.218.0",
107
+ "@opentelemetry/api-logs": "^0.219.0",
108
108
  "@opentelemetry/baggage-span-processor": "^0.5.0",
109
109
  "@opentelemetry/context-async-hooks": "^2.7.1",
110
110
  "@opentelemetry/core": "^2.7.0",
111
- "@opentelemetry/exporter-logs-otlp-http": "^0.218.0",
112
- "@opentelemetry/exporter-metrics-otlp-http": "^0.218.0",
113
- "@opentelemetry/exporter-trace-otlp-http": "^0.218.0",
114
- "@opentelemetry/instrumentation": "^0.218.0",
115
- "@opentelemetry/instrumentation-undici": "^0.28.0",
111
+ "@opentelemetry/exporter-logs-otlp-http": "^0.219.0",
112
+ "@opentelemetry/exporter-metrics-otlp-http": "^0.219.0",
113
+ "@opentelemetry/exporter-trace-otlp-http": "^0.219.0",
114
+ "@opentelemetry/instrumentation": "^0.219.0",
115
+ "@opentelemetry/instrumentation-undici": "^0.29.0",
116
+ "@opentelemetry/otlp-transformer": "^0.219.0",
116
117
  "@opentelemetry/resources": "^2.7.0",
117
- "@opentelemetry/sdk-logs": "^0.218.0",
118
+ "@opentelemetry/sdk-logs": "^0.219.0",
118
119
  "@opentelemetry/sdk-metrics": "^2.7.0",
119
120
  "@opentelemetry/sdk-trace-base": "^2.7.0",
120
121
  "@opentelemetry/sdk-trace-node": "^2.7.1",
121
- "chalk": "^5.6.2",
122
- "uuid": "^14.0.0"
122
+ "chalk": "^5.6.2"
123
123
  },
124
124
  "peerDependencies": {
125
125
  "next": "^15.3.0 || ^16.0.0",
@@ -140,20 +140,19 @@
140
140
  "devDependencies": {
141
141
  "@interfere/test-utils": "^9.0.0",
142
142
  "@interfere/typescript-config": "^9.0.0",
143
- "@types/node": "^24.12.0",
144
- "@types/react": "19.2.15",
143
+ "@types/node": "^25.9.3",
144
+ "@types/react": "19.2.17",
145
145
  "@types/react-dom": "19.2.3",
146
- "@typescript/native-preview": "7.0.0-dev.20260601.1",
147
- "@vitest/browser": "4.1.8",
148
- "@vitest/browser-playwright": "4.1.8",
149
- "@vitest/coverage-v8": "4.1.8",
146
+ "@typescript/native-preview": "7.0.0-dev.20260617.2",
147
+ "@vitest/browser": "4.1.9",
148
+ "@vitest/browser-playwright": "4.1.9",
149
+ "@vitest/coverage-v8": "4.1.9",
150
150
  "next": "^16.2.4",
151
151
  "playwright": "^1.60.0",
152
152
  "react": "^19.2.6",
153
153
  "react-dom": "^19.2.6",
154
- "tsdown": "0.22.1",
155
- "vitest": "4.1.8",
156
- "vitest-browser-react": "2.2.0",
157
- "webpack": "^5.106.2"
154
+ "tsdown": "^0.22.2",
155
+ "vitest": "4.1.9",
156
+ "vitest-browser-react": "2.2.0"
158
157
  }
159
158
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.mts","names":[],"sources":["../src/config.ts"],"mappings":";;;;UAoBiB,uBAAA,SAAgC,UAAU;;AAA3D;;;;;EAOE,SAAA;IAAA,SAAuB,OAAA;EAAA;AAAA;AAAA,UAGR,mBAAA;EAAA,SACN,MAAA;EAAA,SACA,MAAA;EAyBwB;;;;;EAAA,SAnBxB,OAAA;EAmBA;;;AAAwB;AAGnC;;;;;EAHW,SATA,WAAA;EAAA,SACA,SAAA;EAaE;AAAA;AAoIb;;;;AAEqB;EAtIR,SALF,WAAA,EAAa,WAAW;AAAA;AAAA,iBAGnB,aAAA,CACd,UAAA,GAAY,uBAAA,GACX,UAAU;AAAA,UAoII,wBAAA;EAAA,SACN,OAAA;EAAA,SACA,UAAU;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { omitUndefined } from \"@interfere/helpers/omit-undefined\";\nimport {\n LOCAL_DEV_RELEASE_SLUG,\n type ReleaseSlug,\n} from \"@interfere/types/releases/slug\";\nimport { readFirstEnvValue } from \"@interfere/types/sdk/env\";\n\nimport type { NextConfig } from \"next\";\n\nimport { configureBuild } from \"./internal/build/configure-build.js\";\nimport { readInterfereEnv } from \"./internal/env.js\";\nimport { FatalError, log } from \"./internal/logger.js\";\nimport { resolveReleaseSlug } from \"./internal/release-slug.js\";\nimport {\n readNextMajorVersion,\n warnIfServerInstrumentationMissing,\n} from \"./internal/setup-warnings.js\";\n\nconst NEXT_INSTRUMENTATION_HOOK_FLAG_LAST_MAJOR = 14;\n\nexport interface NextConfigWithInterfere extends NextConfig {\n /**\n * Reserved for future SDK config. Setting `buildId` here is rejected\n * loudly — it caused server/client slug drift in 9.x. Override the\n * commit SHA via the `INTERFERE_SOURCE_ID` env var (set on both build\n * and runtime envs) instead.\n */\n interfere?: { readonly buildId?: never };\n}\n\nexport interface ResolvedBuildConfig {\n readonly apiKey: string | null;\n readonly apiUrl: string;\n /**\n * Server-internal — the build pipeline still uses this to key R2\n * source-map paths until Phase 7 re-keys them to slug. Never injected\n * into the bundle; never exposed via env.\n */\n readonly buildId: string | null;\n /**\n * Deploy-environment label (`INTERFERE_ENVIRONMENT` ?? `VERCEL_ENV`)\n * resolved at build time. Stamped into the bundle as\n * `__INTERFERE_ENVIRONMENT__` so the browser kernel — which can't read\n * non-public env vars — labels events with the same environment as the\n * server. `NODE_ENV` is deliberately not folded in: it stays the browser's\n * bundler-inlined runtime fallback, so dev bundles keep resolving\n * `development` even when this is unset.\n */\n readonly environment: string | null;\n readonly publicKey: string | null;\n /**\n * Deterministically derived from the leading 16 hex of the commit SHA, so\n * the build step and the collector arrive at the same\n * `rel_xxxxxxxxxxxxxxxx` without a round-trip. Stamped into the bundle as\n * `__INTERFERE_RELEASE_SLUG__`. `null` when no commit SHA is available —\n * release-pipeline calls bail in that case.\n */\n readonly releaseSlug: ReleaseSlug | null;\n}\n\nexport function withInterfere(\n nextConfig: NextConfigWithInterfere = {}\n): NextConfig {\n const {\n interfere,\n env: userEnv,\n webpack,\n turbopack,\n compiler,\n productionBrowserSourceMaps,\n ...rest\n } = nextConfig;\n\n if (interfere && \"buildId\" in interfere && interfere.buildId !== undefined) {\n return log.fatal(\"Removed: interfere.buildId\", [\n \"`interfere.buildId` was removed in SDK 10. It only worked at build time, so server-side spans drifted from the bundle's slug.\",\n \"Override the commit SHA via the `INTERFERE_SOURCE_ID` env var on both build and runtime envs instead.\",\n ]);\n }\n\n const projectDir = process.cwd();\n const config = resolveBuildConfig();\n const forceEnable = !!process.env[\"NEXT_PUBLIC_INTERFERE_FORCE_ENABLE\"];\n\n const releaseSlug = forceEnable ? LOCAL_DEV_RELEASE_SLUG : config.releaseSlug;\n const build = configureBuild({\n existingWebpack: webpack,\n existingTurbopack: turbopack,\n projectDir,\n values: {\n __INTERFERE_RELEASE_SLUG__: releaseSlug,\n ...(config.publicKey && {\n __INTERFERE_PROXY_MODE__: true,\n __INTERFERE_PUBLIC_KEY__: config.publicKey,\n }),\n ...(config.environment && {\n __INTERFERE_ENVIRONMENT__: config.environment,\n }),\n ...(forceEnable && { __INTERFERE_FORCE_ENABLE__: true }),\n },\n });\n\n if (config.publicKey !== null && !build.webpack && !build.turbopack) {\n return log.fatal(\"Missing instrumentation client\", [\n \"INTERFERE_PUBLIC_KEY is set but no instrumentation-client file was found.\",\n \"Create an instrumentation-client.ts file in your project root or src/ directory.\",\n ]);\n }\n\n if (config.publicKey !== null) {\n warnIfServerInstrumentationMissing(projectDir);\n }\n\n const nextMajor = readNextMajorVersion(projectDir);\n const needsInstrumentationHookFlag =\n nextMajor === null ||\n nextMajor <= NEXT_INSTRUMENTATION_HOOK_FLAG_LAST_MAJOR;\n\n const existingHook = (compiler as NextCompilerWithProductionHook | undefined)\n ?.runAfterProductionCompile;\n\n const browserSourceMaps =\n config.apiKey === null ? productionBrowserSourceMaps : true;\n if (config.apiKey !== null && productionBrowserSourceMaps === false) {\n log.warn(\"Forcing productionBrowserSourceMaps\", [\n \"withInterfere() requires production source maps to symbolicate errors.\",\n \"Your `productionBrowserSourceMaps: false` was overridden to `true`.\",\n ]);\n }\n\n return {\n ...rest,\n ...(userEnv ? { env: userEnv } : {}),\n\n compiler: {\n ...omitUndefined(compiler ?? {}),\n async runAfterProductionCompile(context: ProductionCompileContext) {\n if (existingHook) {\n await existingHook(context);\n }\n\n try {\n await runBuildReleasePipeline(context, config);\n } catch (error) {\n if (error instanceof FatalError) {\n throw error;\n }\n\n const message =\n error instanceof Error ? error.message : String(error);\n\n log.warn(\"Skipping release pipeline\", [\n \"Interfere encountered an unexpected error.\",\n \"Build will continue, but this release's data will be ingested, but ignored as evidence when generating insights.\",\n `Error: ${message}`,\n ]);\n }\n },\n },\n\n ...omitUndefined({\n productionBrowserSourceMaps: browserSourceMaps,\n turbopack: build.turbopack,\n webpack: build.webpack,\n }),\n\n ...(needsInstrumentationHookFlag\n ? {\n experimental: {\n ...(rest.experimental ?? {}),\n instrumentationHook: true,\n } as NonNullable<NextConfig[\"experimental\"]>,\n }\n : {}),\n };\n}\n\nfunction resolveBuildConfig(): ResolvedBuildConfig {\n const { apiKey, apiUrl, publicKey } = readInterfereEnv();\n const { commitSha, slug } = resolveReleaseSlug();\n\n return {\n apiKey: apiKey ?? null,\n apiUrl,\n buildId: commitSha,\n environment: readFirstEnvValue(process.env, [\n \"INTERFERE_ENVIRONMENT\",\n \"VERCEL_ENV\",\n ]),\n publicKey: publicKey ?? null,\n releaseSlug: slug,\n };\n}\n\nexport interface ProductionCompileContext {\n readonly distDir: string;\n readonly projectDir: string;\n}\n\ntype NextCompilerWithProductionHook = NonNullable<NextConfig[\"compiler\"]> & {\n runAfterProductionCompile?: (\n context: ProductionCompileContext\n ) => void | Promise<void>;\n};\n\nasync function runBuildReleasePipeline(\n context: ProductionCompileContext,\n config: ResolvedBuildConfig\n): Promise<void> {\n const { apiKey, buildId, releaseSlug } = config;\n\n if (!apiKey) {\n return log.fatal(\"API key not set\", [\n \"withInterfere() requires an API key to publish release metadata during production builds.\",\n \"Set the INTERFERE_API_KEY environment variable, or remove withInterfere() from your Next.js config.\",\n \"See: https://support.interfere.com/docs/guides/next-js\",\n ]);\n }\n\n if (!(buildId && releaseSlug)) {\n return log.fatal(\"Commit SHA missing\", [\n \"Could not resolve a commit SHA from environment variables or git.\",\n \"Set `INTERFERE_SOURCE_ID`, ensure your CI exposes its git SHA env var (e.g. `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`), or run inside a git checkout.\",\n ]);\n }\n\n const { runBuildPipeline } = await import(\"./internal/build/pipeline.js\");\n\n try {\n const result = await runBuildPipeline(context, {\n ...config,\n apiKey,\n buildId,\n releaseSlug,\n });\n\n if (!result.ready) {\n log.warn(\"Skipping\", [\"No source maps found\"]);\n return;\n }\n\n log.info(\"Completed\", [\n `https://interfere.com/~/${result.config?.org.slug}/surfaces/${result.config?.surface.slug}`,\n `Release: ${result.release?.destination.slug ?? \"Unknown\"}`,\n `Build: ${result.buildId}`,\n `Artifacts: ${result.fileCount} source maps`,\n ]);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n log.warn(\"Skipping release pipeline\", [\n \"Interfere failed to process this release.\",\n \"Events from this release will be ingested, but ignored as evidence when generating insights.\",\n \"Please check https://status.interfere.com for any outages, or contact support@interfere.com if the problem persists.\",\n `Error: ${message}`,\n ]);\n\n return;\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrument-client.d.mts","names":[],"sources":["../src/instrument-client.ts"],"mappings":";;;;;cAuBE,KAAA,QAAK,OAAA;;;iEAEI,MAAA,oEACM,MAAA;;;YAEX,IAAA,8CAAA,aAAA,KAAA,OAAA,4CAAA,MAAA,8BACa,QAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrument-client.mjs","names":[],"sources":["../src/instrument-client.ts"],"sourcesContent":["import { createWrapperSingleton } from \"@interfere/react/internal/wrapper-singleton\";\n\nimport { PRODUCER_VERSION } from \"./internal/version.js\";\n\n// biome-ignore lint/performance/noBarrelFile: customer-facing one-import surface — `@interfere/next` re-exports the runtime helpers so callers don't have to also import `@interfere/react/api`.\nexport { capture, span } from \"@interfere/react/api\";\nexport type {\n Kernel,\n KernelInternalOptions,\n KernelOptions,\n} from \"@interfere/react/internal/kernel\";\nexport type {\n ConsentCategory,\n ConsentState,\n GateableCategory,\n} from \"@interfere/types/sdk/plugins/manifest\";\n\nconst wrapper = createWrapperSingleton({\n producerVersion: PRODUCER_VERSION,\n initEntryName: \"instrumentation-client\",\n});\n\nexport const {\n close,\n consent,\n getKernel,\n getKernelOrNull,\n identity,\n init,\n subscribeToKernel,\n} = wrapper;\n"],"mappings":"oLAsBA,KAAa,CACX,MACA,QACA,UACA,gBACA,SACA,KACA,mBAZc,uBAAuB,CACrC,gBAAiB,iBACjB,cAAe,wBACjB,CAUI"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumentation-client.mjs","names":[],"sources":["../src/instrumentation-client.ts"],"sourcesContent":["import { init } from \"./instrument-client.js\";\n\n/**\n * Side-effect entry for Next.js 15.3+ which auto-loads `instrumentation-client.ts`\n * on every page load. Customer's `instrumentation-client.ts` becomes:\n *\n * ```ts\n * import \"@interfere/next/instrumentation-client\";\n * ```\n *\n * That single import boots the kernel with sensible defaults. Customers who\n * need overrides can call `init({...})` from `@interfere/next` directly —\n * `init()` is idempotent so the side-effect call here turns into a no-op.\n *\n * The `.catch` surfaces sync boot errors in dev — production swallows them\n * (a misconfigured SDK shouldn't take the customer's app down).\n */\ninit().catch((error: unknown) => {\n if (process.env[\"NODE_ENV\"] !== \"production\") {\n console.warn(\"[interfere] init() threw during boot\", error);\n }\n});\n"],"mappings":"0CAiBA,KAAK,EAAE,MAAO,OAAmB,CAC3B,QAAQ,IAAI,WAAgB,cAC9B,QAAQ,KAAK,uCAAwC,KAAK,CAE9D,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumentation.d.mts","names":[],"sources":["../src/instrumentation.ts"],"mappings":";;;;;;;;;;AAqFA;;;;;;;;;;;;;;;;;UAAiB,gBAAA;EAqCf;;;;;;;;EA5BA,mBAAA;EA4CA;;;AAA6B;AAY/B;EAlDE,iBAAA,QAAyB,OAAA;;;;;;;AAoDR;AA+HnB;;;;;;;;AAEU;;;;;EAhKR,gBAAA,EAAkB,eAAA;EAClB,mBAAA,EAAqB,kBAAA;EACrB,aAAA,EAAe,YAAA;;;;;;;;EAQf,WAAA,EAAa,iBAAA;;;;;;EAMb,kBAAA,EAAoB,MAAA,SAAe,cAAA;EACnC,cAAA,EAAgB,aAAA;AAAA;;;;;;;;;;iBAYF,qBAAA,CACd,IAAA,GAAM,4BAAA,GACL,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+HG,QAAA,CACpB,IAAA,GAAM,4BAAA,GACL,OAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumentation.edge.d.mts","names":[],"sources":["../src/instrumentation.edge.ts"],"mappings":";;;;;AA0BA;;;;;;;;AAEU;AAUV;;;;AAC0C;;;;;;;iBAb1B,QAAA,CACd,KAAA,GAAO,4BAAA,GACN,OAAO;;;;;;;iBAUM,qBAAA,CACd,KAAwC,GAAjC,4BAAiC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumentation.edge.mjs","names":[],"sources":["../src/instrumentation.edge.ts"],"sourcesContent":["import type { ServerInstrumentationOptions } from \"./internal/server/instrumentation-options.js\";\n\nexport type { InterfereOtelKit } from \"./instrumentation.js\";\nexport type { ServerInstrumentationOptions } from \"./internal/server/instrumentation-options.js\";\n\n/**\n * Edge-runtime entry for `@interfere/next/instrumentation`. Selected by\n * `package.json`'s `edge-light` / `workerd` / `worker` export conditions\n * — Next.js + Vercel pick this bundle when compiling\n * `instrumentation.ts` for the Edge runtime.\n *\n * The Node entry (`instrumentation.ts`) is built around\n * `NodeTracerProvider`, `AsyncLocalStorageContextManager`, undici\n * instrumentation, and a console→OTel bridge — none of which work in\n * the Edge runtime. Pulling that import graph into an Edge bundle would\n * (a) trip Next's `node:*`-in-edge warnings (release-slug derivation\n * uses `node:child_process` + `node:crypto`) and (b) crash on module\n * load if the Edge bundle were ever actually invoked.\n *\n * Both `register()` and `buildInterfereOtelKit()` are exported as\n * no-op stubs so customer TypeScript code compiles unchanged\n * regardless of which runtime the file ends up in. Edge-runtime\n * tracing (middleware spans, edge route handlers) needs an\n * `@opentelemetry/sdk-trace-base`-based pipeline with a fetch-based\n * exporter — tracked separately.\n */\nexport function register(\n _opts: ServerInstrumentationOptions = {}\n): Promise<void> {\n return Promise.resolve();\n}\n\n/**\n * Edge stub for the kit factory. Returns `null` so callers spreading\n * `kit?.spanProcessors ?? []` into a host bootstrap behave as if the\n * SDK is unconfigured — same shape as the Node entry returns when\n * `INTERFERE_PUBLIC_KEY` is unset.\n */\nexport function buildInterfereOtelKit(\n _opts: ServerInstrumentationOptions = {}\n): null {\n return null;\n}\n"],"mappings":"AA0BA,SAAgB,SACd,MAAsC,CAAC,EACxB,CACf,OAAO,QAAQ,QAAQ,CACzB,CAQA,SAAgB,sBACd,MAAsC,CAAC,EACjC,CACN,OAAO,IACT"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumentation.mjs","names":[],"sources":["../src/instrumentation.ts"],"sourcesContent":["import type {\n AttributeValue,\n Span,\n TextMapPropagator,\n} from \"@opentelemetry/api\";\nimport { metrics, propagation } from \"@opentelemetry/api\";\nimport { BaggageSpanProcessor } from \"@opentelemetry/baggage-span-processor\";\nimport { AsyncLocalStorageContextManager } from \"@opentelemetry/context-async-hooks\";\nimport {\n CompositePropagator,\n W3CBaggagePropagator,\n W3CTraceContextPropagator,\n} from \"@opentelemetry/core\";\nimport { OTLPLogExporter } from \"@opentelemetry/exporter-logs-otlp-http\";\nimport {\n AggregationTemporalityPreference,\n OTLPMetricExporter,\n} from \"@opentelemetry/exporter-metrics-otlp-http\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\";\nimport {\n type Instrumentation,\n registerInstrumentations,\n} from \"@opentelemetry/instrumentation\";\nimport { UndiciInstrumentation } from \"@opentelemetry/instrumentation-undici\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport {\n BatchLogRecordProcessor,\n LoggerProvider,\n type LogRecordProcessor,\n} from \"@opentelemetry/sdk-logs\";\nimport {\n MeterProvider,\n type MetricReader,\n PeriodicExportingMetricReader,\n} from \"@opentelemetry/sdk-metrics\";\nimport {\n BatchSpanProcessor,\n type SpanProcessor,\n} from \"@opentelemetry/sdk-trace-base\";\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\";\n\nimport { readInterfereEnv } from \"./internal/env.js\";\nimport { resolveReleaseSlug } from \"./internal/release-slug.js\";\nimport { bridgeConsoleToOtel } from \"./internal/server/console-bridge.js\";\nimport { PrerenderSafeIdGenerator } from \"./internal/server/id-generator.js\";\nimport type { ServerInstrumentationOptions } from \"./internal/server/instrumentation-options.js\";\nimport { fetchAndCacheRemoteConfig } from \"./internal/server/remote-config.js\";\nimport { withPublicKey } from \"./internal/url.js\";\nimport { PRODUCER_VERSION } from \"./internal/version.js\";\n\nexport { PrerenderSafeIdGenerator } from \"./internal/server/id-generator.js\";\nexport type { ServerInstrumentationOptions } from \"./internal/server/instrumentation-options.js\";\n\nconst DEFAULT_SERVICE_NAME = \"interfere-sdk-next-server\";\nconst SERVICE_NAMESPACE = \"interfere\";\n\nlet registered = false;\n\nfunction matchesAny(url: string, patterns: (string | RegExp)[]): boolean {\n for (const pattern of patterns) {\n if (pattern instanceof RegExp ? pattern.test(url) : url.includes(pattern)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Composable building blocks the Interfere SDK contributes to OTel —\n * span / log / metric processors, baggage propagator, undici\n * instrumentation, plus the resource attributes and side-effect\n * installers (console bridge + remote-config fetch).\n *\n * Use this when you want to plug Interfere into an existing OTel\n * bootstrap (e.g. `@vercel/otel`'s `registerOTel({...})`, DataDog's\n * `dd-trace-js`, or any custom `NodeTracerProvider` setup) instead of\n * the standalone `register()` path. The kit holds no global state and\n * touches no global slots — composition is the consumer's job.\n *\n * The standalone `register()` builds the kit internally and wires it\n * into private providers, so customer DX stays a one-liner export.\n *\n * Returns `null` when `INTERFERE_PUBLIC_KEY` is unset — callers can spread\n * `kit?.spanProcessors ?? []` without a no-op guard.\n */\nexport interface InterfereOtelKit {\n /**\n * Patches `console.{debug,log,info,warn,error}` to also emit OTel\n * `LogRecord`s via the global `LoggerProvider`. Caller is responsible\n * for ensuring a `LoggerProvider` is registered globally before\n * calling — `register()` handles this; for composed setups, call\n * after your bootstrap (`registerOTel({...})` etc.) has run. Returns\n * a disposer that restores the original `console.*` methods.\n */\n enableConsoleBridge: () => () => void;\n /**\n * Fetches the SDK's remote plugin config and caches it for the\n * runtime. Customer code's `isPluginEnabled(...)` checks read from\n * the cache. Safe to call repeatedly.\n */\n fetchRemoteConfig: () => Promise<void>;\n /**\n * Instrumentations the SDK ships. Currently `UndiciInstrumentation`\n * pre-configured with `propagateContextUrls` / `ignoreUrls` semantics\n * from `ServerInstrumentationOptions`.\n *\n * **Composition with `@vercel/otel`**: `instrumentations: [\"auto\"]`\n * registers Vercel's `globalThis.fetch` wrapper, which only\n * auto-propagates `traceparent` to Vercel deployment URLs — outbound\n * fetches to a different origin (e.g. `in.interfere.com`) get a\n * span but no header injection unless\n * `instrumentationConfig.fetch.propagateContextUrls` is set, and\n * even then it doesn't cover the lower-level undici dispatcher path\n * Next.js route handlers use. Spread `kit.instrumentations` after\n * `\"auto\"` to layer this UndiciInstrumentation on top — propagation\n * extends to every outbound undici call (filtered via `ignoreUrls`).\n * Risk of double span emission on overlapping call sites is bounded:\n * Vercel's fetch wraps `globalThis.fetch`, this hooks the undici\n * dispatcher one layer lower, so duplicates only appear when both\n * paths actually fire on the same call.\n */\n instrumentations: Instrumentation[];\n logRecordProcessors: LogRecordProcessor[];\n metricReaders: MetricReader[];\n /**\n * W3C baggage propagator. Trace context is intentionally *not*\n * included — `@vercel/otel`'s `propagators: [\"auto\"]` already\n * registers it, and standalone `register()` adds it itself when\n * the global slot is empty. Composing this on top extends rather\n * than overrides.\n */\n propagators: TextMapPropagator[];\n /**\n * Pre-built resource attribute set. Pass into your provider's\n * `Resource` directly, or into `@vercel/otel`'s `attributes` field\n * (which merges with Vercel's own auto-detected `vercel.*` attrs).\n */\n resourceAttributes: Record<string, AttributeValue>;\n spanProcessors: SpanProcessor[];\n}\n\n/**\n * Pure factory — no global registration, no provider construction. Returns\n * the OTel primitives the SDK contributes so a host bootstrap (Vercel,\n * DataDog, custom) can compose them in.\n *\n * Returns `null` when `INTERFERE_PUBLIC_KEY` isn't set, so callers can\n * unconditionally spread `kit?.spanProcessors ?? []` in dev where the\n * SDK isn't configured.\n */\nexport function buildInterfereOtelKit(\n opts: ServerInstrumentationOptions = {}\n): InterfereOtelKit | null {\n const env = readInterfereEnv();\n if (!env.publicKey) {\n return null;\n }\n\n const { slug: releaseSlug } = resolveReleaseSlug();\n if (!releaseSlug) {\n console.warn(\n \"[interfere] No commit SHA available; server spans will ship without `release.slug`. Set `INTERFERE_SOURCE_ID` (or any of `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`) on the runtime env.\"\n );\n }\n\n const sinkUrl = withPublicKey(`${env.apiUrl}/v2/sink`, env.publicKey);\n\n const ignoreUrls = [sinkUrl, ...(opts.ignoreUrls ?? [])];\n const propagateContextUrls = opts.propagateContextUrls ?? [];\n\n const exporterHeaders: Record<string, string> = {\n \"x-interfere-producer-version\": PRODUCER_VERSION,\n };\n\n const resourceAttributes: Record<string, AttributeValue> = {\n \"service.name\": opts.serviceName ?? DEFAULT_SERVICE_NAME,\n \"service.namespace\": SERVICE_NAMESPACE,\n \"deployment.environment.name\": env.nodeEnvironment,\n \"telemetry.sdk.language\": \"nodejs\",\n \"interfere.sdk.name\": \"@interfere/next\",\n \"interfere.sdk.version\": PRODUCER_VERSION,\n ...(releaseSlug ? { \"release.slug\": releaseSlug } : {}),\n };\n\n const spanProcessors: SpanProcessor[] = [\n new BaggageSpanProcessor(() => true),\n new BatchSpanProcessor(\n new OTLPTraceExporter({ url: sinkUrl, headers: exporterHeaders })\n ),\n ...(opts._internalAdditionalSpanProcessors ?? []),\n ];\n\n const logRecordProcessors: LogRecordProcessor[] = [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({ url: sinkUrl, headers: exporterHeaders })\n ),\n ...(opts._internalAdditionalLogRecordProcessors ?? []),\n ];\n\n const metricReaders: MetricReader[] = [\n new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({\n url: sinkUrl,\n headers: exporterHeaders,\n temporalityPreference: AggregationTemporalityPreference.DELTA,\n }),\n exportIntervalMillis: 30_000,\n }),\n ...(opts._internalAdditionalMetricReaders ?? []),\n ];\n\n const propagators: TextMapPropagator[] = [new W3CBaggagePropagator()];\n\n const instrumentations: Instrumentation[] = [\n new UndiciInstrumentation({\n ignoreRequestHook: (req: { origin: string; path: string }) => {\n const url = `${req.origin}${req.path}`;\n return matchesAny(url, ignoreUrls);\n },\n requestHook: (span: Span, req: { origin: string; path: string }) => {\n const url = `${req.origin}${req.path}`;\n if (matchesAny(url, propagateContextUrls)) {\n span.setAttribute(\"interfere.propagated\", true);\n }\n },\n }),\n ];\n\n return {\n resourceAttributes,\n spanProcessors,\n logRecordProcessors,\n metricReaders,\n propagators,\n instrumentations,\n enableConsoleBridge: () => bridgeConsoleToOtel(),\n fetchRemoteConfig: () => fetchAndCacheRemoteConfig(),\n };\n}\n\n/**\n * One-line server-side bootstrap for Next.js. Customers' `instrumentation.ts`\n * becomes:\n *\n * ```ts\n * export { register } from \"@interfere/next/instrumentation\";\n * ```\n *\n * Or, with overrides:\n *\n * ```ts\n * import { register as base } from \"@interfere/next/instrumentation\";\n * export const register = () => base({ serviceName: \"@my-org/api\" });\n * ```\n *\n * Customers who already run another OTel bootstrap (`@vercel/otel`,\n * DataDog `dd-trace-js`, custom `NodeTracerProvider`) should use\n * `buildInterfereOtelKit({...})` instead and compose the returned\n * processors / readers / propagators into their existing setup —\n * see the kit's JSDoc for examples.\n *\n * Constructs private `NodeTracerProvider` / `LoggerProvider` /\n * `MeterProvider` and registers them on the global slots. Last writer\n * wins on the globals, so customers running another OTel bootstrap\n * alongside this one will end up with whichever booted last; the kit\n * path avoids that fight entirely.\n *\n * Wired against the Node OTel SDK (`NodeTracerProvider`,\n * `AsyncLocalStorageContextManager`) — so this entry only ships into the\n * `nodejs` runtime bundle. The Edge runtime gets the no-op stub at\n * `instrumentation.edge.ts` via `package.json`'s `edge-light` /\n * `workerd` export conditions.\n *\n * Idempotent — repeat calls (e.g. HMR) short-circuit on the\n * module-scoped `registered` flag.\n *\n * Bails silently when `INTERFERE_PUBLIC_KEY` is unset so dev runs without\n * the SDK configured don't crash.\n */\nexport async function register(\n opts: ServerInstrumentationOptions = {}\n): Promise<void> {\n if (registered) {\n return;\n }\n\n const kit = buildInterfereOtelKit(opts);\n if (!kit) {\n return;\n }\n\n const resource = resourceFromAttributes(kit.resourceAttributes);\n\n const tracerProvider = new NodeTracerProvider({\n resource,\n spanProcessors: kit.spanProcessors,\n idGenerator: new PrerenderSafeIdGenerator(),\n });\n\n if (propagation.fields().length === 0) {\n propagation.setGlobalPropagator(\n new CompositePropagator({\n propagators: [new W3CTraceContextPropagator(), ...kit.propagators],\n })\n );\n }\n\n tracerProvider.register({\n contextManager: new AsyncLocalStorageContextManager().enable(),\n });\n\n const loggerProvider = new LoggerProvider({\n resource,\n processors: kit.logRecordProcessors,\n });\n\n const { logs: logsApi } = await import(\"@opentelemetry/api-logs\");\n logsApi.setGlobalLoggerProvider(loggerProvider);\n\n const meterProvider = new MeterProvider({\n resource,\n readers: kit.metricReaders,\n });\n\n metrics.setGlobalMeterProvider(meterProvider);\n\n registerInstrumentations({\n tracerProvider,\n meterProvider,\n instrumentations: kit.instrumentations,\n });\n\n if (opts.consoleBridge !== false) {\n kit.enableConsoleBridge();\n }\n\n registered = true;\n\n await kit.fetchRemoteConfig();\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"configure-build.d.mts","names":[],"sources":["../../../src/internal/build/configure-build.ts"],"mappings":";;;UAKiB,uBAAA;EAAA,SACN,yBAAA;EAAA,SACA,0BAAA;EAAA,SACA,wBAAA;EAAA,SACA,wBAAA;EAAA,SACA,0BAAA;AAAA;AAAA,UAqBD,mBAAA;EAAA,SACC,iBAAA,EAAmB,UAAA;EAAA,SACnB,eAAA,EAAiB,UAAA;EAAA,SACjB,UAAA;EAAA,SACA,MAAA,EAAQ,uBAAA;AAAA;AAAA,UAGT,oBAAA;EAAA,SACC,SAAA,EAAW,UAAA;EAAA,SACX,OAAA,EAAS,UAAU;AAAA;AAAA,iBAGd,cAAA;EACd,eAAA;EACA,iBAAA;EACA,UAAA;EACA;AAAA,GACC,mBAAA,GAAsB,oBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"configure-build.mjs","names":[],"sources":["../../../src/internal/build/configure-build.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { basename, dirname, join, normalize, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { NextConfig } from \"next\";\n\nexport interface InterfereInjectedValues {\n readonly __INTERFERE_ENVIRONMENT__?: string;\n readonly __INTERFERE_FORCE_ENABLE__?: boolean;\n readonly __INTERFERE_PROXY_MODE__?: boolean;\n readonly __INTERFERE_PUBLIC_KEY__?: string;\n readonly __INTERFERE_RELEASE_SLUG__: string | null;\n}\n\nconst INSTRUMENTATION_CLIENT_FILES = [\n \"instrumentation-client.ts\",\n \"instrumentation-client.tsx\",\n \"instrumentation-client.js\",\n \"instrumentation-client.jsx\",\n \"src/instrumentation-client.ts\",\n \"src/instrumentation-client.tsx\",\n \"src/instrumentation-client.js\",\n \"src/instrumentation-client.jsx\",\n] as const;\n\nconst LOADER_FILE_CANDIDATES = [\n \"value-injection-loader.ts\",\n \"value-injection-loader.js\",\n \"value-injection-loader.mjs\",\n \"value-injection-loader.cjs\",\n] as const;\n\ninterface ConfigureBuildInput {\n readonly existingTurbopack: NextConfig[\"turbopack\"] | undefined;\n readonly existingWebpack: NextConfig[\"webpack\"] | undefined;\n readonly projectDir: string;\n readonly values: InterfereInjectedValues;\n}\n\ninterface ConfigureBuildOutput {\n readonly turbopack: NextConfig[\"turbopack\"] | undefined;\n readonly webpack: NextConfig[\"webpack\"] | undefined;\n}\n\nexport function configureBuild({\n existingWebpack,\n existingTurbopack,\n projectDir,\n values,\n}: ConfigureBuildInput): ConfigureBuildOutput {\n const instrumentationClientPath =\n resolveInstrumentationClientPath(projectDir);\n\n return {\n webpack: buildWebpackHook(\n existingWebpack,\n instrumentationClientPath,\n values\n ),\n turbopack: buildTurbopackConfig(\n existingTurbopack,\n instrumentationClientPath,\n values\n ),\n };\n}\n\nfunction hasInjectedMetadata(metadata: InterfereInjectedValues): boolean {\n return (\n metadata.__INTERFERE_RELEASE_SLUG__ !== null ||\n metadata.__INTERFERE_PUBLIC_KEY__ !== undefined\n );\n}\n\nfunction buildWebpackHook(\n existingWebpack: NextConfig[\"webpack\"] | undefined,\n instrumentationClientPath: string | null,\n values: InterfereInjectedValues\n): NextConfig[\"webpack\"] | undefined {\n if (!(instrumentationClientPath && hasInjectedMetadata(values))) {\n return existingWebpack;\n }\n\n const normalizedPath = normalize(instrumentationClientPath);\n const loaderPath = resolveLoaderPath();\n\n return (webpackConfig, options) => {\n const outputConfig = existingWebpack\n ? existingWebpack(webpackConfig, options)\n : webpackConfig;\n const mutableConfig = outputConfig as {\n module?: { rules?: unknown[] };\n };\n\n const injectionRule = {\n test: (resource: string): boolean =>\n Boolean(resource) && normalize(resource) === normalizedPath,\n use: [\n {\n loader: loaderPath,\n options: { values },\n },\n ],\n };\n\n mutableConfig.module ??= {};\n mutableConfig.module.rules ??= [];\n mutableConfig.module.rules.push(injectionRule);\n\n return outputConfig;\n };\n}\n\nfunction buildTurbopackConfig(\n existingTurbopack: NextConfig[\"turbopack\"] | undefined,\n instrumentationClientPath: string | null,\n values: InterfereInjectedValues\n): NextConfig[\"turbopack\"] | undefined {\n \n \n \n \n \n \n \n \n \n \n const baseConfig = (existingTurbopack ?? {}) as {\n rules?: Record<string, unknown>;\n debugIds?: boolean;\n };\n const debugIds = baseConfig.debugIds ?? true;\n\n \n \n \n if (!(instrumentationClientPath && hasInjectedMetadata(values))) {\n if (existingTurbopack === undefined && debugIds === baseConfig.debugIds) {\n return existingTurbopack;\n }\n \n return { ...baseConfig, debugIds } as NextConfig[\"turbopack\"];\n }\n\n const ruleKey = `**/${basename(instrumentationClientPath)}`;\n const existingRule = (baseConfig.rules?.[ruleKey] ?? {}) as {\n loaders?: unknown[];\n };\n const existingLoaders = Array.isArray(existingRule.loaders)\n ? existingRule.loaders\n : [];\n\n return {\n ...baseConfig,\n debugIds,\n rules: {\n ...baseConfig.rules,\n [ruleKey]: {\n ...existingRule,\n loaders: [\n ...existingLoaders,\n {\n loader: resolveLoaderPath(),\n options: {\n serializedValues: JSON.stringify(values),\n },\n },\n ],\n },\n },\n } as NextConfig[\"turbopack\"];\n}\n\nfunction resolveInstrumentationClientPath(projectDir: string): string | null {\n for (const candidate of INSTRUMENTATION_CLIENT_FILES) {\n const filePath = resolve(projectDir, candidate);\n if (existsSync(filePath)) {\n return filePath;\n }\n }\n\n return null;\n}\n\nfunction resolveLoaderPath(): string {\n const directory = resolve(dirname(fileURLToPath(import.meta.url)));\n\n for (const candidate of LOADER_FILE_CANDIDATES) {\n const filePath = join(directory, candidate);\n if (existsSync(filePath)) {\n return filePath;\n }\n }\n\n return join(directory, \"value-injection-loader.js\");\n}\n"],"mappings":"mIAaA,MAAM,6BAA+B,CACnC,4BACA,6BACA,4BACA,6BACA,gCACA,iCACA,gCACA,gCACF,EAEM,uBAAyB,CAC7B,4BACA,4BACA,6BACA,4BACF,EAcA,SAAgB,eAAe,CAC7B,gBACA,kBACA,WACA,QAC4C,CAC5C,IAAM,0BACJ,iCAAiC,UAAU,EAE7C,MAAO,CACL,QAAS,iBACP,gBACA,0BACA,MACF,EACA,UAAW,qBACT,kBACA,0BACA,MACF,CACF,CACF,CAEA,SAAS,oBAAoB,SAA4C,CACvE,OACE,SAAS,6BAA+B,MACxC,SAAS,2BAA6B,IAAA,EAE1C,CAEA,SAAS,iBACP,gBACA,0BACA,OACmC,CACnC,GAAI,EAAE,2BAA6B,oBAAoB,MAAM,GAC3D,OAAO,gBAGT,IAAM,eAAiB,UAAU,yBAAyB,EACpD,WAAa,kBAAkB,EAErC,OAAQ,cAAe,UAAY,CACjC,IAAM,aAAe,gBACjB,gBAAgB,cAAe,OAAO,EACtC,cACE,cAAgB,aAIhB,cAAgB,CACpB,KAAO,UACL,EAAQ,UAAa,UAAU,QAAQ,IAAM,eAC/C,IAAK,CACH,CACE,OAAQ,WACR,QAAS,CAAE,MAAO,CACpB,CACF,CACF,EAMA,MAJA,eAAc,SAAW,CAAC,EAC1B,cAAc,OAAO,QAAU,CAAC,EAChC,cAAc,OAAO,MAAM,KAAK,aAAa,EAEtC,YACT,CACF,CAEA,SAAS,qBACP,kBACA,0BACA,OACqC,CAWrC,IAAM,WAAc,mBAAqB,CAAC,EAIpC,SAAW,WAAW,UAAY,GAKxC,GAAI,EAAE,2BAA6B,oBAAoB,MAAM,GAK3D,OAJI,oBAAsB,IAAA,IAAa,WAAa,WAAW,SACtD,kBAGF,CAAE,GAAG,WAAY,QAAS,EAGnC,IAAM,QAAU,MAAM,SAAS,yBAAyB,IAClD,aAAgB,WAAW,QAAQ,UAAY,CAAC,EAGhD,gBAAkB,MAAM,QAAQ,aAAa,OAAO,EACtD,aAAa,QACb,CAAC,EAEL,MAAO,CACL,GAAG,WACH,SACA,MAAO,CACL,GAAG,WAAW,OACb,SAAU,CACT,GAAG,aACH,QAAS,CACP,GAAG,gBACH,CACE,OAAQ,kBAAkB,EAC1B,QAAS,CACP,iBAAkB,KAAK,UAAU,MAAM,CACzC,CACF,CACF,CACF,CACF,CACF,CACF,CAEA,SAAS,iCAAiC,WAAmC,CAC3E,IAAK,IAAM,aAAa,6BAA8B,CACpD,IAAM,SAAW,QAAQ,WAAY,SAAS,EAC9C,GAAI,WAAW,QAAQ,EACrB,OAAO,QAEX,CAEA,OAAO,IACT,CAEA,SAAS,mBAA4B,CACnC,IAAM,UAAY,QAAQ,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC,CAAC,EAEjE,IAAK,IAAM,aAAa,uBAAwB,CAC9C,IAAM,SAAW,KAAK,UAAW,SAAS,EAC1C,GAAI,WAAW,QAAQ,EACrB,OAAO,QAEX,CAEA,OAAO,KAAK,UAAW,2BAA2B,CACpD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"detect-bundler.d.mts","names":[],"sources":["../../../src/internal/build/detect-bundler.ts"],"mappings":";;;KAIY,gBAAA,GAAmB,OAAO,CAAC,eAAA;AAAA,iBAEvB,mBAAA,CACd,GAAA,GAAK,QAAA,CAAS,MAAA,+BACd,IAAA,uBACC,gBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"detect-bundler.mjs","names":[],"sources":["../../../src/internal/build/detect-bundler.ts"],"sourcesContent":["import type { ManifestBundler } from \"@interfere/types/data/source-maps\";\n\nconst TURBOPACK_FLAGS = [\"--turbo\", \"--turbopack\"] as const;\n\nexport type NextBuildBundler = Extract<ManifestBundler, \"webpack\" | \"turbopack\">;\n\nexport function detectActiveBundler(\n env: Readonly<Record<string, string | undefined>> = process.env,\n argv: readonly string[] = process.argv\n): NextBuildBundler {\n if (env[\"TURBOPACK\"] === \"1\") {\n return \"turbopack\";\n }\n if (TURBOPACK_FLAGS.some((flag) => argv.includes(flag))) {\n return \"turbopack\";\n }\n return \"webpack\";\n}\n"],"mappings":"AAEA,MAAM,gBAAkB,CAAC,UAAW,aAAa,EAIjD,SAAgB,oBACd,IAAoD,QAAQ,IAC5D,KAA0B,QAAQ,KAChB,CAOlB,OANI,IAAI,YAAiB,KAGrB,gBAAgB,KAAM,MAAS,KAAK,SAAS,IAAI,CAAC,EAC7C,YAEF,SACT"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pipeline.d.mts","names":[],"sources":["../../../src/internal/build/pipeline.ts"],"mappings":";;;;;;UAciB,WAAA;EACf,OAAA;EACA,aAAA;EACA,QAAA;EACA,SAAA;EACA,SAAA;EACA,KAAA;EACA,UAAA;EACA,MAAA;AAAA;AAAA,KAGU,cAAA;EACN,KAAA;EAAc,MAAA;EAA0B,SAAA;AAAA;EAExC,KAAA;EACA,SAAA;EACA,OAAA,EAAS,qBAAA;EACT,MAAA,EAAQ,sBAAA;EACR,OAAA;EACA,MAAA,EAAQ,WAAA;AAAA;AAAA,iBAWQ,gBAAA,CACpB,OAAA,EAAS,wBAAA,EACT,QAAA,EAAU,mBAAA;EACR,MAAA;EACA,OAAA;EACA,WAAA,EAAa,WAAA;AAAA,IACd,OAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"pipeline.mjs","names":[],"sources":["../../../src/internal/build/pipeline.ts"],"sourcesContent":["import { HTTPClient, Interfere } from \"@interfere/sdk\";\nimport type { ReleasesConfigResponse } from \"@interfere/sdk/models/releases-config-response.js\";\nimport type { CreateReleaseResponse } from \"@interfere/types/releases/definition\";\nimport { type ReleaseSlug, releaseSlugSchema } from \"@interfere/types/releases/slug\";\n\nimport type {\n ProductionCompileContext,\n ResolvedBuildConfig,\n} from \"../../config.js\";\nimport { detectActiveBundler } from \"./detect-bundler.js\";\nimport { resolveReleaseRequest } from \"./release/index.js\";\nimport { discoverSourceMaps } from \"./source-maps/discover.js\";\nimport { cleanupSourceMaps, uploadSourceMaps } from \"./source-maps/index.js\";\n\nexport interface BuildTiming {\n cleanup: number;\n createRelease: number;\n discover: number;\n fileCount: number;\n preflight: number;\n total: number;\n totalBytes: number;\n upload: number;\n}\n\nexport type PipelineResult =\n | { ready: false; reason: \"no_source_maps\"; fileCount: 0 }\n | {\n ready: true;\n fileCount: number;\n release: CreateReleaseResponse;\n config: ReleasesConfigResponse;\n buildId: string;\n timing: BuildTiming;\n };\n\nasync function timed<T>(\n fn: () => Promise<T>\n): Promise<[result: T, durationMs: number]> {\n const start = performance.now();\n const result = await fn();\n return [result, Math.round(performance.now() - start)];\n}\n\nexport async function runBuildPipeline(\n context: ProductionCompileContext,\n metadata: ResolvedBuildConfig & {\n apiKey: string;\n buildId: string;\n releaseSlug: ReleaseSlug;\n }\n) {\n const { apiUrl, apiKey } = metadata;\n\n const httpClient = new HTTPClient();\n\n httpClient.addHook(\"beforeRequest\", (request) => {\n const nextRequest = new Request(request);\n\n nextRequest.headers.set(\"Authorization\", `Bearer ${apiKey}`);\n\n return nextRequest;\n });\n\n const sdk = new Interfere({ serverURL: apiUrl, httpClient });\n const security = { apiKey };\n\n const start = performance.now();\n\n const bundler = detectActiveBundler();\n\n const [{ discovered, config }, discoverMs] = await timed(async () => {\n const [discovered, config] = await Promise.all([\n discoverSourceMaps({\n bundler,\n projectDir: context.projectDir,\n distDir: context.distDir,\n }),\n sdk.releases.getConfig(security),\n ]);\n return { discovered, config };\n });\n\n if (discovered.files.length === 0) {\n return { ready: false, reason: \"no_source_maps\", fileCount: 0 };\n }\n\n const releaseRequest = resolveReleaseRequest(\n metadata.buildId,\n metadata.releaseSlug,\n config\n );\n\n const [release, createReleaseMs] = await timed(() =>\n sdk.releases.create(security, releaseRequest)\n );\n\n \n \n \n const releaseSlug = releaseSlugSchema.parse(release.destination.slug);\n const buildId = release.build.hash ?? metadata.buildId;\n\n const [{ totalBytes }, uploadMs] = await timed(() =>\n uploadSourceMaps({ apiUrl, bundler, discovered, httpClient, releaseSlug: releaseSlug })\n );\n\n \n \n \n \n \n const [, preflightMs] = await timed(() =>\n sdk.releases.preflight(security, { releaseSlug })\n );\n\n const [, cleanupMs] = await timed(() => cleanupSourceMaps(discovered.files));\n\n const timing: BuildTiming = {\n discover: discoverMs,\n createRelease: createReleaseMs,\n upload: uploadMs,\n preflight: preflightMs,\n cleanup: cleanupMs,\n total: Math.round(performance.now() - start),\n fileCount: discovered.files.length,\n totalBytes,\n };\n\n return {\n ready: true,\n fileCount: discovered.files.length,\n release: { ...release, destination: { ...release.destination, slug: releaseSlug } },\n config,\n buildId,\n timing,\n } satisfies PipelineResult;\n}\n"],"mappings":"qYAoCA,eAAe,MACb,GAC0C,CAC1C,IAAM,MAAQ,YAAY,IAAI,EAE9B,MAAO,CAAC,MADa,GAAG,EACR,KAAK,MAAM,YAAY,IAAI,EAAI,KAAK,CAAC,CACvD,CAEA,eAAsB,iBACpB,QACA,SAKA,CACA,GAAM,CAAE,OAAQ,QAAW,SAErB,WAAa,IAAI,WAEvB,WAAW,QAAQ,gBAAkB,SAAY,CAC/C,IAAM,YAAc,IAAI,QAAQ,OAAO,EAIvC,OAFA,YAAY,QAAQ,IAAI,gBAAiB,UAAU,QAAQ,EAEpD,WACT,CAAC,EAED,IAAM,IAAM,IAAI,UAAU,CAAE,UAAW,OAAQ,UAAW,CAAC,EACrD,SAAW,CAAE,MAAO,EAEpB,MAAQ,YAAY,IAAI,EAExB,QAAU,oBAAoB,EAE9B,CAAC,CAAE,WAAY,QAAU,YAAc,MAAM,MAAM,SAAY,CACnE,GAAM,CAAC,WAAY,QAAU,MAAM,QAAQ,IAAI,CAC7C,mBAAmB,CACjB,QACA,WAAY,QAAQ,WACpB,QAAS,QAAQ,OACnB,CAAC,EACD,IAAI,SAAS,UAAU,QAAQ,CACjC,CAAC,EACD,MAAO,CAAE,WAAY,MAAO,CAC9B,CAAC,EAED,GAAI,WAAW,MAAM,SAAW,EAC9B,MAAO,CAAE,MAAO,GAAO,OAAQ,iBAAkB,UAAW,CAAE,EAGhE,IAAM,eAAiB,sBACrB,SAAS,QACT,SAAS,YACT,MACF,EAEM,CAAC,QAAS,iBAAmB,MAAM,UACvC,IAAI,SAAS,OAAO,SAAU,cAAc,CAC9C,EAKM,YAAc,kBAAkB,MAAM,QAAQ,YAAY,IAAI,EAC9D,QAAU,QAAQ,MAAM,MAAQ,SAAS,QAEzC,CAAC,CAAE,YAAc,UAAY,MAAM,UACvC,iBAAiB,CAAE,OAAQ,QAAS,WAAY,WAAyB,WAAY,CAAC,CACxF,EAOM,EAAG,aAAe,MAAM,UAC5B,IAAI,SAAS,UAAU,SAAU,CAAE,WAAY,CAAC,CAClD,EAEM,EAAG,WAAa,MAAM,UAAY,kBAAkB,WAAW,KAAK,CAAC,EAErE,OAAsB,CAC1B,SAAU,WACV,cAAe,gBACf,OAAQ,SACR,UAAW,YACX,QAAS,UACT,MAAO,KAAK,MAAM,YAAY,IAAI,EAAI,KAAK,EAC3C,UAAW,WAAW,MAAM,OAC5B,UACF,EAEA,MAAO,CACL,MAAO,GACP,UAAW,WAAW,MAAM,OAC5B,QAAS,CAAE,GAAG,QAAS,YAAa,CAAE,GAAG,QAAQ,YAAa,KAAM,WAAY,CAAE,EAClF,OACA,QACA,MACF,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/internal/build/release/destinations/index.ts"],"mappings":";;;;;AAeA;;;;;;cAAa,YAAA,EAAc,MAAA,CACzB,mBAAA,QACM,0BAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["resolveVercel"],"sources":["../../../../../src/internal/build/release/destinations/index.ts"],"sourcesContent":["import type {\n DestinationProvider,\n ReleaseDestinationMetadata,\n} from \"@interfere/types/integrations\";\n\nimport { resolve as resolveVercel } from \"./vercel.js\";\n\n/**\n * Per-provider destination metadata resolvers. Mirrors `sources/` —\n * each entry knows how to read its platform's deployment env vars and\n * returns a `ReleaseDestinationMetadata` blob.\n *\n * Adding a new destination (cloudflare-pages, fly, render, …) is one\n * new file under this directory + one entry here.\n */\nexport const destinations: Record<\n DestinationProvider,\n () => ReleaseDestinationMetadata\n> = {\n vercel: resolveVercel,\n};\n"],"mappings":"kCAeA,MAAa,aAGT,CACF,OAAQA,OACV"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"vercel.d.mts","names":[],"sources":["../../../../../src/internal/build/release/destinations/vercel.ts"],"mappings":";;;iBAGgB,OAAA,IAAW,0BAA0B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"vercel.mjs","names":[],"sources":["../../../../../src/internal/build/release/destinations/vercel.ts"],"sourcesContent":["import type { ReleaseDestinationMetadata } from \"@interfere/types/integrations\";\nimport { parseEnvValue } from \"@interfere/types/sdk/env\";\n\nexport function resolve(): ReleaseDestinationMetadata {\n const environment = parseEnvValue(\n process.env[\"VERCEL_ENV\"] ?? process.env[\"VERCEL_TARGET_ENV\"]\n );\n\n const deploymentId = parseEnvValue(process.env[\"VERCEL_DEPLOYMENT_ID\"]);\n\n return {\n provider: \"vercel\",\n destinationReleaseId: deploymentId,\n environment,\n deploymentId,\n deploymentUrl: resolveDeploymentUrl(),\n environmentName: environment,\n environmentTarget: environment,\n };\n}\n\nfunction resolveDeploymentUrl(): string | null {\n const deploymentUrl = parseEnvValue(process.env[\"VERCEL_URL\"]);\n\n if (deploymentUrl === null) {\n return null;\n }\n\n if (\n deploymentUrl.startsWith(\"https://\") ||\n deploymentUrl.startsWith(\"http://\")\n ) {\n return deploymentUrl;\n }\n\n return `https://${deploymentUrl}`;\n}\n"],"mappings":"oDAGA,SAAgB,SAAsC,CACpD,IAAM,YAAc,cAClB,QAAQ,IAAI,YAAiB,QAAQ,IAAI,iBAC3C,EAEM,aAAe,cAAc,QAAQ,IAAI,oBAAuB,EAEtE,MAAO,CACL,SAAU,SACV,qBAAsB,aACtB,YACA,aACA,cAAe,qBAAqB,EACpC,gBAAiB,YACjB,kBAAmB,WACrB,CACF,CAEA,SAAS,sBAAsC,CAC7C,IAAM,cAAgB,cAAc,QAAQ,IAAI,UAAa,EAa7D,OAXI,gBAAkB,KACb,KAIP,cAAc,WAAW,UAAU,GACnC,cAAc,WAAW,SAAS,EAE3B,cAGF,WAAW,eACpB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"git.d.mts","names":[],"sources":["../../../../src/internal/build/release/git.ts"],"mappings":";;AAeA;;;;AAA6C;;;;;;;;iBAA7B,aAAA,CAAc,OAAe"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"git.mjs","names":[],"sources":["../../../../src/internal/build/release/git.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\n\n/**\n * Runs a git command and returns its stdout, or `null` when git isn't\n * available (no `.git` checkout, git binary missing, command errored).\n *\n * The ignore-on-failure shape lets callers compose this with env-var\n * reads as a fallback chain — env vars first (CI environments where\n * git isn't checked out), git as a last resort (local dev).\n *\n * Build-time only. `node:child_process` isn't available in the Edge\n * runtime, so this helper must never end up in `instrumentation.ts`'s\n * import graph (the SDK ships that entrypoint to both Node + Edge\n * runtimes via conditional exports).\n */\nexport function runGitCommand(command: string): string | null {\n try {\n const output = execSync(command, {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n\n return output.length > 0 ? output : null;\n } catch {\n return null;\n }\n}\n"],"mappings":"yCAeA,SAAgB,cAAc,QAAgC,CAC5D,GAAI,CACF,IAAM,OAAS,SAAS,QAAS,CAC/B,SAAU,OACV,MAAO,CAAC,SAAU,OAAQ,QAAQ,CACpC,CAAC,EAAE,KAAK,EAER,OAAO,OAAO,OAAS,EAAI,OAAS,IACtC,MAAQ,CACN,OAAO,IACT,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/internal/build/release/index.ts"],"mappings":";;;;;iBAUgB,qBAAA,CACd,OAAA,UACA,WAAA,EAAa,WAAA,EACb,MAAA,EAAQ,sBAAA,GACP,oBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/internal/build/release/index.ts"],"sourcesContent":["import type { ReleaseSlug } from \"@interfere/types/releases/slug\";\nimport type { ReleasesConfigResponse } from \"@interfere/sdk/models/releases-config-response.js\";\nimport type { CreateReleaseRequest } from \"@interfere/types/releases/definition\";\nimport { destinationProviderSchema } from \"@interfere/types/integrations\";\n\nimport { log } from \"../../logger.js\";\nimport { PRODUCER_VERSION } from \"../../version.js\";\nimport { destinations } from \"./destinations/index.js\";\nimport { sources } from \"./sources/index.js\";\n\nexport function resolveReleaseRequest(\n buildId: string,\n releaseSlug: ReleaseSlug,\n config: ReleasesConfigResponse\n): CreateReleaseRequest {\n if (!config.surface.sourceProvider) {\n return log.fatal(\"Missing version control provider\", [\n \"This surface does not have a version control provider configured.\",\n `Configure one at https://interfere.com/~/${config.org.slug}/surfaces/${config.surface.slug}`,\n ]);\n }\n\n const destinationProvider = destinationProviderSchema.safeParse(\n config.surface.destinationProvider\n );\n if (!destinationProvider.success) {\n return log.fatal(\"Missing deployment target\", [\n \"This surface does not have a deployment target integration configured.\",\n `Configure one at https://interfere.com/~/${config.org.slug}/surfaces/${config.surface.slug}`,\n ]);\n }\n\n return {\n source: sources[config.surface.sourceProvider](),\n destination: destinations[destinationProvider.data](),\n buildId,\n slug: releaseSlug,\n producerVersion: PRODUCER_VERSION,\n };\n}\n"],"mappings":"mPAUA,SAAgB,sBACd,QACA,YACA,OACsB,CACtB,GAAI,CAAC,OAAO,QAAQ,eAClB,OAAO,IAAI,MAAM,mCAAoC,CACnD,oEACA,4CAA4C,OAAO,IAAI,KAAK,YAAY,OAAO,QAAQ,MACzF,CAAC,EAGH,IAAM,oBAAsB,0BAA0B,UACpD,OAAO,QAAQ,mBACjB,EAQA,OAPK,oBAAoB,QAOlB,CACL,OAAQ,QAAQ,OAAO,QAAQ,gBAAgB,EAC/C,YAAa,aAAa,oBAAoB,MAAM,EACpD,QACA,KAAM,YACN,gBAAiB,gBACnB,EAZS,IAAI,MAAM,4BAA6B,CAC5C,yEACA,4CAA4C,OAAO,IAAI,KAAK,YAAY,OAAO,QAAQ,MACzF,CAAC,CAUL"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"github.d.mts","names":[],"sources":["../../../../../src/internal/build/release/sources/github.ts"],"mappings":";;;KAKK,mBAAA,GAAsB,OAAO,CAChC,qBAAA;EACE,QAAA;AAAA;AAAA,iBAGY,OAAA,IAAW,mBAAmB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"github.mjs","names":[],"sources":["../../../../../src/internal/build/release/sources/github.ts"],"sourcesContent":["import type { ReleaseSourceMetadata } from \"@interfere/types/integrations\";\nimport { parseEnvValue } from \"@interfere/types/sdk/env\";\n\nimport { runGitCommand } from \"../git.js\";\n\ntype GithubReleaseSource = Extract<\n ReleaseSourceMetadata,\n { provider: \"github\" }\n>;\n\nexport function resolve(): GithubReleaseSource {\n return {\n provider: \"github\",\n branch:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_REF\"]) ??\n parseEnvValue(process.env[\"GITHUB_REF_NAME\"]) ??\n parseEnvValue(process.env[\"GITHUB_HEAD_REF\"]) ??\n runGitCommand(\"git rev-parse --abbrev-ref HEAD\") ??\n \"unknown\",\n commitMessage:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_MESSAGE\"]) ??\n runGitCommand(\"git log -1 --pretty=%B\") ??\n \"\",\n commitSha:\n parseEnvValue(process.env[\"VERCEL_GIT_COMMIT_SHA\"]) ??\n parseEnvValue(process.env[\"GITHUB_SHA\"]) ??\n runGitCommand(\"git rev-parse HEAD\"),\n };\n}\n"],"mappings":"0FAUA,SAAgB,SAA+B,CAC7C,MAAO,CACL,SAAU,SACV,OACE,cAAc,QAAQ,IAAI,qBAAwB,GAClD,cAAc,QAAQ,IAAI,eAAkB,GAC5C,cAAc,QAAQ,IAAI,eAAkB,GAC5C,cAAc,iCAAiC,GAC/C,UACF,cACE,cAAc,QAAQ,IAAI,yBAA4B,GACtD,cAAc,wBAAwB,GACtC,GACF,UACE,cAAc,QAAQ,IAAI,qBAAwB,GAClD,cAAc,QAAQ,IAAI,UAAa,GACvC,cAAc,oBAAoB,CACtC,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../src/internal/build/release/sources/index.ts"],"mappings":";;;;;AAsBA;;;;;;;;;;;;AAAwE;cAA3D,OAAA,EAAS,MAAA,CAAO,cAAA,QAAsB,qBAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["resolveGithub"],"sources":["../../../../../src/internal/build/release/sources/index.ts"],"sourcesContent":["import type {\n ReleaseSourceMetadata,\n SourceProvider,\n} from \"@interfere/types/integrations\";\n\nimport { resolve as resolveGithub } from \"./github.js\";\n\n/**\n * Per-provider source metadata resolvers. Each entry knows how to read\n * its platform's env vars (and falls back to local git where applicable)\n * and returns a `ReleaseSourceMetadata` blob keyed to the provider.\n *\n * Adding a new provider (gitlab, bitbucket, …) is one new file under\n * this directory + one entry here. Every consumer that walks this\n * registry — release-create payload assembly in the build pipeline —\n * picks up the new provider for free.\n *\n * Lives under `internal/build/` because resolvers shell out to git via\n * `runGitCommand`, which depends on `node:child_process` (not Edge-safe).\n * Anything imported from `instrumentation.ts` must stay edge-safe; this\n * tree is build-only.\n */\nexport const sources: Record<SourceProvider, () => ReleaseSourceMetadata> = {\n github: resolveGithub,\n};\n"],"mappings":"kCAsBA,MAAa,QAA+D,CAC1E,OAAQA,OACV"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"discover-turbopack.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/discover-turbopack.ts"],"mappings":";;;;;AA6BA;;;;;;;;;;;;AAGqD;;;;;;iBAH/B,iBAAA,CAAkB,IAAA;EACtC,UAAA;EACA,OAAA;AAAA,IACE,OAAO;EAAG,KAAA,EAAO,aAAA;EAAiB,eAAA;AAAA"}
@@ -1 +0,0 @@
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 \n \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 \n \n \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 \n \n \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"}
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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 \n \n \n \n \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 +0,0 @@
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 +0,0 @@
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 +0,0 @@
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 +0,0 @@
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 \n \n \n \n \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"}
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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;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"}
@@ -1 +0,0 @@
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 \n \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 +0,0 @@
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 +0,0 @@
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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"env.d.mts","names":[],"sources":["../../src/internal/env.ts"],"mappings":";UAIiB,YAAA;EAAA,SACN,MAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,eAAA;EAAA,SACA,SAAA;EAAA,SACA,OAAA;IAAA,SACE,QAAA;IAAA,SACA,aAAA;EAAA;AAAA;;;;AAAa;AAa1B;;;;AAAiC;iBAAjB,iBAAA;AAAA,iBAOA,gBAAA,IAAoB,YAAY"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"env.mjs","names":[],"sources":["../../src/internal/env.ts"],"sourcesContent":["import { API_URL } from \"@interfere/constants/api\";\nimport { parseEnvValue } from \"@interfere/types/sdk/env\";\nimport { resolveEnvironment } from \"@interfere/types/sdk/runtime\";\n\nexport interface InterfereEnv {\n readonly apiKey: string | null;\n readonly apiUrl: string;\n readonly nextRuntime: string | null;\n readonly nodeEnvironment: string;\n readonly publicKey: string | null;\n readonly release: {\n readonly sourceId: string | null;\n readonly destinationId: string | null;\n };\n}\n\n/**\n * Server-side gate for the proxy route handler, the `captureError` /\n * `onRequestError` helpers, and the remote-config fetcher. Distinct\n * from the browser-side `isEnabledByEnvironment` (in\n * `@interfere/react/internal/kernel`) because the server has different\n * env conventions: `NEXT_PUBLIC_INTERFERE_FORCE_ENABLE` is the dev\n * opt-in, and there's no \"unknown runtime, default enabled\" case the\n * way the browser SDK has for plain-browser / Vite hosts.\n */\nexport function isEnabledOnServer(): boolean {\n if (process.env[\"NODE_ENV\"] === \"production\") {\n return true;\n }\n return !!process.env[\"NEXT_PUBLIC_INTERFERE_FORCE_ENABLE\"];\n}\n\nexport function readInterfereEnv(): InterfereEnv {\n const nodeEnvironment = resolveEnvironment({ env: process.env });\n\n return {\n apiKey: parseEnvValue(process.env[\"INTERFERE_API_KEY\"]),\n apiUrl: parseEnvValue(process.env[\"INTERFERE_API_URL\"]) ?? API_URL,\n nextRuntime: parseEnvValue(process.env[\"NEXT_RUNTIME\"]),\n nodeEnvironment,\n publicKey: parseEnvValue(process.env[\"INTERFERE_PUBLIC_KEY\"]),\n release: {\n sourceId: parseEnvValue(process.env[\"NEXT_PUBLIC_INTERFERE_BUILD_ID\"]),\n destinationId: parseEnvValue(\n process.env[\"NEXT_PUBLIC_INTERFERE_RELEASE_ID\"]\n ),\n },\n };\n}\n"],"mappings":"+JAyBA,SAAgB,mBAA6B,CAI3C,OAHI,QAAQ,IAAI,WAAgB,aACvB,GAEF,CAAC,CAAC,QAAQ,IAAI,kCACvB,CAEA,SAAgB,kBAAiC,CAC/C,IAAM,gBAAkB,mBAAmB,CAAE,IAAK,QAAQ,GAAI,CAAC,EAE/D,MAAO,CACL,OAAQ,cAAc,QAAQ,IAAI,iBAAoB,EACtD,OAAQ,cAAc,QAAQ,IAAI,iBAAoB,GAAK,QAC3D,YAAa,cAAc,QAAQ,IAAI,YAAe,EACtD,gBACA,UAAW,cAAc,QAAQ,IAAI,oBAAuB,EAC5D,QAAS,CACP,SAAU,cAAc,QAAQ,IAAI,8BAAiC,EACrE,cAAe,cACb,QAAQ,IAAI,gCACd,CACF,CACF,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger.d.mts","names":[],"sources":["../../src/internal/logger.ts"],"mappings":";;AAuDA;;;;cAAa,UAAA,SAAmB,KAAK;EAAA,SACjB,IAAI;AAAA;AAAA,cA8BX,GAAA;wBACS,KAAA;wBACA,KAAA;yBACC,KAAA;uBACF,KAAA;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger.mjs","names":[],"sources":["../../src/internal/logger.ts"],"sourcesContent":["import chalk from \"chalk\";\n\ntype LogLevel = \"info\" | \"warn\" | \"error\" | \"fatal\";\n\nconst styles = {\n info: {\n prefix: `${chalk.whiteBright.bold(\"❖\")}`,\n text: chalk.cyan.bold,\n content: chalk.white,\n prependLevel: false,\n },\n warn: {\n prefix: `${chalk.yellow.bold(\"⚠\")} `,\n text: chalk.yellow.bold,\n content: chalk.yellowBright,\n prependLevel: false,\n },\n error: {\n prefix: `${chalk.red.bold(\"⨯\")} `,\n text: chalk.red.bold,\n content: chalk.redBright,\n prependLevel: true,\n },\n fatal: {\n prefix: `${chalk.red.bold(\"⨯\")} `,\n text: chalk.red.bold,\n content: chalk.redBright,\n prependLevel: true,\n },\n} satisfies Record<\n LogLevel,\n {\n prefix: string;\n text: typeof chalk.bold;\n content: typeof chalk;\n prependLevel: boolean;\n }\n>;\n\nconst consoleMethods = {\n info: \"log\",\n warn: \"warn\",\n error: \"error\",\n fatal: \"error\",\n} satisfies Record<LogLevel, string>;\n\nfunction isTestEnv() {\n return Boolean(process.env[\"VITEST\"] || process.env[\"VITEST_WORKER_ID\"]);\n}\n\n/**\n * Thrown by `log.fatal` in test environments where `process.exit` is not\n * appropriate. Tagged so callers' catch blocks can re-throw fatal errors and\n * keep test-env behavior aligned with the production hard-exit.\n */\nexport class FatalError extends Error {\n override readonly name = \"FatalError\";\n}\n\nfunction emit(level: LogLevel, title: string, lines: string[]) {\n if (isTestEnv()) {\n return;\n }\n\n const style = styles[level];\n const method = consoleMethods[level] as keyof Console;\n const fn = globalThis.console[method];\n if (typeof fn !== \"function\") {\n return;\n }\n\n const invoke = (...args: unknown[]) =>\n Reflect.apply(fn, globalThis.console, args);\n\n const prependLevel = style.prependLevel\n ? `[${style.text(level.toUpperCase())}] `\n : \"\";\n\n invoke(`${prependLevel} ${chalk.white(\"Interfere →\")} ${style.text(title)}`);\n\n for (const [i, line] of lines.entries()) {\n const connector = i === lines.length - 1 ? \"└\" : \"├\";\n invoke(`${prependLevel} ${connector} ${style.content(line)}`);\n }\n}\n\nexport const log = {\n info: (title: string, lines: string[]) => emit(\"info\", title, lines),\n warn: (title: string, lines: string[]) => emit(\"warn\", title, lines),\n error: (title: string, lines: string[]) => emit(\"error\", title, lines),\n fatal(title: string, lines: string[]): never {\n emit(\"fatal\", title, lines);\n\n if (isTestEnv()) {\n throw new FatalError(title);\n }\n\n process.exit(1);\n },\n};\n"],"mappings":"yBAIA,MAAM,OAAS,CACb,KAAM,CACJ,OAAQ,GAAG,MAAM,YAAY,KAAK,GAAG,IACrC,KAAM,MAAM,KAAK,KACjB,QAAS,MAAM,MACf,aAAc,EAChB,EACA,KAAM,CACJ,OAAQ,GAAG,MAAM,OAAO,KAAK,GAAG,EAAE,GAClC,KAAM,MAAM,OAAO,KACnB,QAAS,MAAM,aACf,aAAc,EAChB,EACA,MAAO,CACL,OAAQ,GAAG,MAAM,IAAI,KAAK,GAAG,EAAE,GAC/B,KAAM,MAAM,IAAI,KAChB,QAAS,MAAM,UACf,aAAc,EAChB,EACA,MAAO,CACL,OAAQ,GAAG,MAAM,IAAI,KAAK,GAAG,EAAE,GAC/B,KAAM,MAAM,IAAI,KAChB,QAAS,MAAM,UACf,aAAc,EAChB,CACF,EAUM,eAAiB,CACrB,KAAM,MACN,KAAM,OACN,MAAO,QACP,MAAO,OACT,EAEA,SAAS,WAAY,CACnB,MAAO,GAAQ,QAAQ,IAAI,QAAa,QAAQ,IAAI,iBACtD,CAOA,IAAa,WAAb,cAAgC,KAAM,CACpC,KAAyB,YAC3B,EAEA,SAAS,KAAK,MAAiB,MAAe,MAAiB,CAC7D,GAAI,UAAU,EACZ,OAGF,IAAM,MAAQ,OAAO,OACf,OAAS,eAAe,OACxB,GAAK,WAAW,QAAQ,QAC9B,GAAI,OAAO,IAAO,WAChB,OAGF,IAAM,QAAU,GAAG,OACjB,QAAQ,MAAM,GAAI,WAAW,QAAS,IAAI,EAEtC,aAAe,MAAM,aACvB,IAAI,MAAM,KAAK,MAAM,YAAY,CAAC,EAAE,IACpC,GAEJ,OAAO,GAAG,aAAa,GAAG,MAAM,MAAM,aAAa,EAAE,GAAG,MAAM,KAAK,KAAK,GAAG,EAE3E,IAAK,GAAM,CAAC,EAAG,QAAS,MAAM,QAAQ,EAEpC,OAAO,GAAG,aAAa,GADL,IAAM,MAAM,OAAS,EAAI,IAAM,IACb,GAAG,MAAM,QAAQ,IAAI,GAAG,CAEhE,CAEA,MAAa,IAAM,CACjB,MAAO,MAAe,QAAoB,KAAK,OAAQ,MAAO,KAAK,EACnE,MAAO,MAAe,QAAoB,KAAK,OAAQ,MAAO,KAAK,EACnE,OAAQ,MAAe,QAAoB,KAAK,QAAS,MAAO,KAAK,EACrE,MAAM,MAAe,MAAwB,CAG3C,GAFA,KAAK,QAAS,MAAO,KAAK,EAEtB,UAAU,EACZ,MAAM,IAAI,WAAW,KAAK,EAG5B,QAAQ,KAAK,CAAC,CAChB,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"release-slug.d.mts","names":[],"sources":["../../src/internal/release-slug.ts"],"mappings":";;;;;AAwBA;;;;AAAgC;AAOhC;;;;;;;;iBAPgB,gBAAA;AAAA,iBAOA,kBAAA;EACd,SAAA;EACA,IAAA,EAAM,WAAW;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"release-slug.mjs","names":[],"sources":["../../src/internal/release-slug.ts"],"sourcesContent":["import { releaseSourceIdEnvKeys } from \"@interfere/types/integrations\";\nimport {\n deriveReleaseSlug,\n type ReleaseSlug,\n} from \"@interfere/types/releases/slug\";\nimport { readFirstEnvValue } from \"@interfere/types/sdk/env\";\n\nimport { runGitCommand } from \"./build/release/git.js\";\n\n/**\n * Walks the same env keys at build time (`withInterfere`) and at runtime\n * (server-side `register()`), then falls back to `git rev-parse HEAD`. Both\n * call sites resolving the same SHA → both derive the same `release.slug`,\n * so server and client spans agree by construction.\n *\n * Override path for non-CI builds: set `INTERFERE_SOURCE_ID` (or any other\n * key in `releaseSourceIdEnvKeys`) on both the build env and the runtime\n * env. The `interfere.buildId` next.config knob was removed in 10.0 because\n * it only worked at build time and caused server/client slug drift.\n *\n * `runGitCommand` (`node:child_process`) keeps this module on the Node side\n * of `@interfere/next`'s dual entry — the edge entrypoint\n * (`instrumentation.edge.ts`) intentionally doesn't import this file.\n */\nexport function resolveCommitSha(): string | null {\n return (\n readFirstEnvValue(process.env, releaseSourceIdEnvKeys) ??\n runGitCommand(\"git rev-parse HEAD\")\n );\n}\n\nexport function resolveReleaseSlug(): {\n commitSha: string | null;\n slug: ReleaseSlug | null;\n} {\n const commitSha = resolveCommitSha();\n return {\n commitSha,\n slug: commitSha ? deriveReleaseSlug(commitSha) : null,\n };\n}\n"],"mappings":"2OAwBA,SAAgB,kBAAkC,CAChD,OACE,kBAAkB,QAAQ,IAAK,sBAAsB,GACrD,cAAc,oBAAoB,CAEtC,CAEA,SAAgB,oBAGd,CACA,IAAM,UAAY,iBAAiB,EACnC,MAAO,CACL,UACA,KAAM,UAAY,kBAAkB,SAAS,EAAI,IACnD,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handle-get.d.mts","names":[],"sources":["../../../src/internal/route/handle-get.ts"],"mappings":";;AAiCA;;;;;;;;;;;;iBAAsB,SAAA,CAAU,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,QAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handle-get.mjs","names":[],"sources":["../../../src/internal/route/handle-get.ts"],"sourcesContent":["import { SW_SCRIPT } from \"@interfere/react/sw\";\n\nimport { log } from \"../logger.js\";\nimport {\n extractSubPath,\n formatProxyError,\n forwardToCollector,\n hasPublicKeyCredential,\n notConfiguredResponse,\n resolveAuthenticatedEnv,\n} from \"./proxy.js\";\n\nconst SW_HEADERS: Record<string, string> = {\n \"content-type\": \"application/javascript; charset=utf-8\",\n\n \"service-worker-allowed\": \"/\",\n\n \"cache-control\": \"public, max-age=3600\",\n};\n\n/**\n * Generic GET proxy. SDK 10.x routes `GET /v2/config` (and any future\n * GET-based endpoints) through here; SDK 9.x clients still hit\n * `GET /v1/config` and get the same delegated response on the collector\n * side.\n *\n * `/sw` is special-cased to serve the SDK's bundled service-worker\n * script directly out of the customer's Next.js process. `SW_SCRIPT`\n * is a string export emitted at @interfere/react build time\n * (`scripts/build-sw.ts`); on Node runtime the customer resolves it\n * via `node_modules`, on Edge runtime the customer's Next.js bundler\n * inlines it into the Edge worker. Either way, no `fs.readFileSync`.\n */\nexport async function handleGet(request: Request): Promise<Response> {\n const subPath = extractSubPath(request);\n\n if (subPath === \"/sw\") {\n return new Response(SW_SCRIPT, { status: 200, headers: SW_HEADERS });\n }\n\n const env = resolveAuthenticatedEnv();\n if (!hasPublicKeyCredential(request, env.publicKey)) {\n return notConfiguredResponse();\n }\n try {\n return await forwardToCollector(request, env, subPath);\n } catch (error) {\n const detail = formatProxyError(error);\n log.error(`Proxy ${request.method} ${subPath} failed`, detail.lines);\n return Response.json(\n { code: \"INTERFERE_PROXY_ERROR\", message: detail.message },\n { status: 502 }\n );\n }\n}\n"],"mappings":"2NAYA,MAAM,WAAqC,CACzC,eAAgB,wCAEhB,yBAA0B,IAE1B,gBAAiB,sBACnB,EAeA,eAAsB,UAAU,QAAqC,CACnE,IAAM,QAAU,eAAe,OAAO,EAEtC,GAAI,UAAY,MACd,OAAO,IAAI,SAAS,UAAW,CAAE,OAAQ,IAAK,QAAS,UAAW,CAAC,EAGrE,IAAM,IAAM,wBAAwB,EACpC,GAAI,CAAC,uBAAuB,QAAS,IAAI,SAAS,EAChD,OAAO,sBAAsB,EAE/B,GAAI,CACF,OAAO,MAAM,mBAAmB,QAAS,IAAK,OAAO,CACvD,OAAS,MAAO,CACd,IAAM,OAAS,iBAAiB,KAAK,EAErC,OADA,IAAI,MAAM,SAAS,QAAQ,OAAO,GAAG,QAAQ,SAAU,OAAO,KAAK,EAC5D,SAAS,KACd,CAAE,KAAM,wBAAyB,QAAS,OAAO,OAAQ,EACzD,CAAE,OAAQ,GAAI,CAChB,CACF,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handle-post.d.mts","names":[],"sources":["../../../src/internal/route/handle-post.ts"],"mappings":";;AAqBA;;;;;;;;;;iBAAsB,UAAA,CAAW,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,QAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handle-post.mjs","names":[],"sources":["../../../src/internal/route/handle-post.ts"],"sourcesContent":["import { log } from \"../logger.js\";\nimport {\n extractSubPath,\n formatProxyError,\n forwardToCollector,\n hasPublicKeyCredential,\n notConfiguredResponse,\n resolveAuthenticatedEnv,\n} from \"./proxy.js\";\n\n/**\n * Generic POST proxy. SDK 10.x routes everything through here:\n *\n * - `/v2/sink` (OTLP traces / metrics / logs)\n * - `/v2/replay/upload/:sessionId`\n * - `/v1/session*` (session sync + identify)\n *\n * No envelope-aware special-casing — that endpoint (`/v1/ingest`) was\n * 9.x-only and is not produced by 10.x. Customers on 9.x post directly\n * to the collector through the same proxy without touching this file.\n */\nexport async function handlePost(request: Request): Promise<Response> {\n const env = resolveAuthenticatedEnv();\n if (!hasPublicKeyCredential(request, env.publicKey)) {\n return notConfiguredResponse();\n }\n const subPath = extractSubPath(request);\n try {\n return await forwardToCollector(request, env, subPath);\n } catch (error) {\n const detail = formatProxyError(error);\n log.error(`Proxy ${request.method} ${subPath} failed`, detail.lines);\n return Response.json(\n { code: \"INTERFERE_PROXY_ERROR\", message: detail.message },\n { status: 502 }\n );\n }\n}\n"],"mappings":"gLAqBA,eAAsB,WAAW,QAAqC,CACpE,IAAM,IAAM,wBAAwB,EACpC,GAAI,CAAC,uBAAuB,QAAS,IAAI,SAAS,EAChD,OAAO,sBAAsB,EAE/B,IAAM,QAAU,eAAe,OAAO,EACtC,GAAI,CACF,OAAO,MAAM,mBAAmB,QAAS,IAAK,OAAO,CACvD,OAAS,MAAO,CACd,IAAM,OAAS,iBAAiB,KAAK,EAErC,OADA,IAAI,MAAM,SAAS,QAAQ,OAAO,GAAG,QAAQ,SAAU,OAAO,KAAK,EAC5D,SAAS,KACd,CAAE,KAAM,wBAAyB,QAAS,OAAO,OAAQ,EACzD,CAAE,OAAQ,GAAI,CAChB,CACF,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"proxy.d.mts","names":[],"sources":["../../../src/internal/route/proxy.ts"],"mappings":";;;;;AAiCA;;;;;iBAAgB,gBAAA,CAAiB,OAAA,EAAS,OAAA,GAAU,OAAO;AAAA,UAW1C,gBAAA;EACf,MAAA;EACA,SAAA;EACA,OAAA,EAAS,YAAY;AAAA;AAAA,iBAGP,uBAAA,IAA2B,gBAAgB;;iBAU3C,sBAAA,CACd,OAAA,EAAS,OAAO,EAChB,YAAA;AAAA,iBAQc,qBAAA,IAAyB,QAAQ;AAAA,iBAajC,cAAA,CAAe,OAAgB,EAAP,OAAO;;;AApCxB;AAGvB;;;;AAA2D;AAU3D;;;iBAgDgB,aAAA,CAAc,OAAgB,EAAP,OAAO;AAAA,iBAI9B,gBAAA,CAAiB,KAAA;EAC/B,OAAA;EACA,KAAA;AAAA;AAAA,iBAqDoB,kBAAA,CACpB,OAAA,EAAS,OAAA,EACT,GAAA,EAAK,gBAAA,EACL,OAAA,WACC,OAAA,CAAQ,QAAA"}