@interfere/next 9.0.2 → 10.0.1-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +39 -6
  2. package/dist/config.d.mts +25 -5
  3. package/dist/config.d.mts.map +1 -1
  4. package/dist/config.mjs +1 -100
  5. package/dist/config.mjs.map +1 -1
  6. package/dist/instrument-client.d.mts +11 -3
  7. package/dist/instrument-client.d.mts.map +1 -1
  8. package/dist/instrument-client.mjs +1 -11
  9. package/dist/instrument-client.mjs.map +1 -1
  10. package/dist/instrumentation-client.d.mts +1 -0
  11. package/dist/instrumentation-client.mjs +1 -0
  12. package/dist/instrumentation-client.mjs.map +1 -0
  13. package/dist/instrumentation.d.mts +134 -0
  14. package/dist/instrumentation.d.mts.map +1 -0
  15. package/dist/instrumentation.edge.d.mts +35 -0
  16. package/dist/instrumentation.edge.d.mts.map +1 -0
  17. package/dist/instrumentation.edge.mjs +1 -0
  18. package/dist/instrumentation.edge.mjs.map +1 -0
  19. package/dist/instrumentation.mjs +1 -0
  20. package/dist/instrumentation.mjs.map +1 -0
  21. package/dist/internal/build/configure-build.d.mts +3 -2
  22. package/dist/internal/build/configure-build.d.mts.map +1 -1
  23. package/dist/internal/build/configure-build.mjs +1 -87
  24. package/dist/internal/build/configure-build.mjs.map +1 -1
  25. package/dist/internal/build/detect-bundler.d.mts +7 -0
  26. package/dist/internal/build/detect-bundler.d.mts.map +1 -0
  27. package/dist/internal/build/detect-bundler.mjs +1 -0
  28. package/dist/internal/build/detect-bundler.mjs.map +1 -0
  29. package/dist/internal/build/pipeline.d.mts +13 -2
  30. package/dist/internal/build/pipeline.d.mts.map +1 -1
  31. package/dist/internal/build/pipeline.mjs +1 -66
  32. package/dist/internal/build/pipeline.mjs.map +1 -1
  33. package/dist/internal/build/release/destinations/index.d.mts +14 -0
  34. package/dist/internal/build/release/destinations/index.d.mts.map +1 -0
  35. package/dist/internal/build/release/destinations/index.mjs +1 -0
  36. package/dist/internal/build/release/destinations/index.mjs.map +1 -0
  37. package/dist/internal/build/release/destinations/vercel.d.mts.map +1 -1
  38. package/dist/internal/build/release/destinations/vercel.mjs +1 -23
  39. package/dist/internal/build/release/destinations/vercel.mjs.map +1 -1
  40. package/dist/internal/build/release/git.d.mts +13 -0
  41. package/dist/internal/build/release/git.d.mts.map +1 -1
  42. package/dist/internal/build/release/git.mjs +1 -21
  43. package/dist/internal/build/release/git.mjs.map +1 -1
  44. package/dist/internal/build/release/index.d.mts +2 -1
  45. package/dist/internal/build/release/index.d.mts.map +1 -1
  46. package/dist/internal/build/release/index.mjs +1 -19
  47. package/dist/internal/build/release/index.mjs.map +1 -1
  48. package/dist/internal/build/release/sources/github.d.mts.map +1 -1
  49. package/dist/internal/build/release/sources/github.mjs +1 -13
  50. package/dist/internal/build/release/sources/github.mjs.map +1 -1
  51. package/dist/internal/build/release/sources/index.d.mts +21 -0
  52. package/dist/internal/build/release/sources/index.d.mts.map +1 -0
  53. package/dist/internal/build/release/sources/index.mjs +1 -0
  54. package/dist/internal/build/release/sources/index.mjs.map +1 -0
  55. package/dist/internal/build/source-maps/discover-turbopack.d.mts +32 -0
  56. package/dist/internal/build/source-maps/discover-turbopack.d.mts.map +1 -0
  57. package/dist/internal/build/source-maps/discover-turbopack.mjs +1 -0
  58. package/dist/internal/build/source-maps/discover-turbopack.mjs.map +1 -0
  59. package/dist/internal/build/source-maps/discover-webpack.d.mts +53 -0
  60. package/dist/internal/build/source-maps/discover-webpack.d.mts.map +1 -0
  61. package/dist/internal/build/source-maps/discover-webpack.mjs +1 -0
  62. package/dist/internal/build/source-maps/discover-webpack.mjs.map +1 -0
  63. package/dist/internal/build/source-maps/discover.d.mts +28 -10
  64. package/dist/internal/build/source-maps/discover.d.mts.map +1 -1
  65. package/dist/internal/build/source-maps/discover.mjs +1 -87
  66. package/dist/internal/build/source-maps/discover.mjs.map +1 -1
  67. package/dist/internal/build/source-maps/index.d.mts +2 -24
  68. package/dist/internal/build/source-maps/index.d.mts.map +1 -1
  69. package/dist/internal/build/source-maps/index.mjs +1 -28
  70. package/dist/internal/build/source-maps/index.mjs.map +1 -1
  71. package/dist/internal/build/source-maps/paths.d.mts +28 -0
  72. package/dist/internal/build/source-maps/paths.d.mts.map +1 -0
  73. package/dist/internal/build/source-maps/paths.mjs +1 -0
  74. package/dist/internal/build/source-maps/paths.mjs.map +1 -0
  75. package/dist/internal/build/source-maps/upload.d.mts +46 -0
  76. package/dist/internal/build/source-maps/upload.d.mts.map +1 -0
  77. package/dist/internal/build/source-maps/upload.mjs +1 -0
  78. package/dist/internal/build/source-maps/upload.mjs.map +1 -0
  79. package/dist/internal/build/value-injection-loader.d.mts.map +1 -1
  80. package/dist/internal/build/value-injection-loader.mjs +2 -24
  81. package/dist/internal/build/value-injection-loader.mjs.map +1 -1
  82. package/dist/internal/env.d.mts +13 -3
  83. package/dist/internal/env.d.mts.map +1 -1
  84. package/dist/internal/env.mjs +1 -23
  85. package/dist/internal/env.mjs.map +1 -1
  86. package/dist/internal/logger.d.mts +9 -1
  87. package/dist/internal/logger.d.mts.map +1 -1
  88. package/dist/internal/logger.mjs +1 -60
  89. package/dist/internal/logger.mjs.map +1 -1
  90. package/dist/internal/release-slug.d.mts +25 -0
  91. package/dist/internal/release-slug.d.mts.map +1 -0
  92. package/dist/internal/release-slug.mjs +1 -0
  93. package/dist/internal/release-slug.mjs.map +1 -0
  94. package/dist/internal/route/handle-get.d.mts +14 -1
  95. package/dist/internal/route/handle-get.d.mts.map +1 -1
  96. package/dist/internal/route/handle-get.mjs +1 -22
  97. package/dist/internal/route/handle-get.mjs.map +1 -1
  98. package/dist/internal/route/handle-post.d.mts +11 -0
  99. package/dist/internal/route/handle-post.d.mts.map +1 -1
  100. package/dist/internal/route/handle-post.mjs +1 -70
  101. package/dist/internal/route/handle-post.mjs.map +1 -1
  102. package/dist/internal/route/proxy.d.mts +26 -4
  103. package/dist/internal/route/proxy.d.mts.map +1 -1
  104. package/dist/internal/route/proxy.mjs +1 -89
  105. package/dist/internal/route/proxy.mjs.map +1 -1
  106. package/dist/internal/server/capture.d.mts +2 -2
  107. package/dist/internal/server/capture.d.mts.map +1 -1
  108. package/dist/internal/server/capture.mjs +1 -55
  109. package/dist/internal/server/capture.mjs.map +1 -1
  110. package/dist/internal/server/console-bridge.d.mts +19 -0
  111. package/dist/internal/server/console-bridge.d.mts.map +1 -0
  112. package/dist/internal/server/console-bridge.mjs +1 -0
  113. package/dist/internal/server/console-bridge.mjs.map +1 -0
  114. package/dist/internal/server/id-generator.d.mts +38 -0
  115. package/dist/internal/server/id-generator.d.mts.map +1 -0
  116. package/dist/internal/server/id-generator.mjs +1 -0
  117. package/dist/internal/server/id-generator.mjs.map +1 -0
  118. package/dist/internal/server/instrumentation-options.d.mts +86 -0
  119. package/dist/internal/server/instrumentation-options.d.mts.map +1 -0
  120. package/dist/internal/server/instrumentation-options.mjs +1 -0
  121. package/dist/internal/server/remote-config.d.mts.map +1 -1
  122. package/dist/internal/server/remote-config.mjs +1 -29
  123. package/dist/internal/server/remote-config.mjs.map +1 -1
  124. package/dist/internal/server/trace-meta.d.mts +32 -0
  125. package/dist/internal/server/trace-meta.d.mts.map +1 -0
  126. package/dist/internal/server/trace-meta.mjs +1 -0
  127. package/dist/internal/server/trace-meta.mjs.map +1 -0
  128. package/dist/internal/server/traceparent.d.mts +16 -0
  129. package/dist/internal/server/traceparent.d.mts.map +1 -0
  130. package/dist/internal/server/traceparent.mjs +1 -0
  131. package/dist/internal/server/traceparent.mjs.map +1 -0
  132. package/dist/internal/server/types.d.mts +1 -7
  133. package/dist/internal/server/types.d.mts.map +1 -1
  134. package/dist/internal/server/types.mjs +1 -1
  135. package/dist/internal/setup-warnings.d.mts +17 -0
  136. package/dist/internal/setup-warnings.d.mts.map +1 -0
  137. package/dist/internal/setup-warnings.mjs +1 -0
  138. package/dist/internal/setup-warnings.mjs.map +1 -0
  139. package/dist/internal/url.d.mts +4 -0
  140. package/dist/internal/url.d.mts.map +1 -0
  141. package/dist/internal/url.mjs +1 -0
  142. package/dist/internal/url.mjs.map +1 -0
  143. package/dist/internal/version.mjs +1 -5
  144. package/dist/internal/version.mjs.map +1 -1
  145. package/dist/package.mjs +1 -5
  146. package/dist/provider.d.mts +23 -2
  147. package/dist/provider.d.mts.map +1 -0
  148. package/dist/provider.mjs +1 -3
  149. package/dist/provider.mjs.map +1 -0
  150. package/dist/route-handler.d.mts +7 -2
  151. package/dist/route-handler.d.mts.map +1 -1
  152. package/dist/route-handler.mjs +1 -31
  153. package/dist/route-handler.mjs.map +1 -1
  154. package/dist/server.d.mts +2 -2
  155. package/dist/server.mjs +1 -3
  156. package/package.json +78 -26
  157. package/dist/internal/route/sw-script.d.mts +0 -4
  158. package/dist/internal/route/sw-script.d.mts.map +0 -1
  159. package/dist/internal/route/sw-script.mjs +0 -38
  160. package/dist/internal/route/sw-script.mjs.map +0 -1
  161. package/dist/internal/server/dedupe.d.mts +0 -5
  162. package/dist/internal/server/dedupe.d.mts.map +0 -1
  163. package/dist/internal/server/dedupe.mjs +0 -11
  164. package/dist/internal/server/dedupe.mjs.map +0 -1
  165. package/dist/internal/server/envelope.d.mts +0 -14
  166. package/dist/internal/server/envelope.d.mts.map +0 -1
  167. package/dist/internal/server/envelope.mjs +0 -59
  168. package/dist/internal/server/envelope.mjs.map +0 -1
  169. package/dist/internal/server/normalize-request.d.mts +0 -7
  170. package/dist/internal/server/normalize-request.d.mts.map +0 -1
  171. package/dist/internal/server/normalize-request.mjs +0 -50
  172. package/dist/internal/server/normalize-request.mjs.map +0 -1
  173. package/dist/internal/server/runtime.d.mts +0 -14
  174. package/dist/internal/server/runtime.d.mts.map +0 -1
  175. package/dist/internal/server/runtime.mjs +0 -18
  176. package/dist/internal/server/runtime.mjs.map +0 -1
  177. package/dist/internal/server/transport.d.mts +0 -12
  178. package/dist/internal/server/transport.d.mts.map +0 -1
  179. package/dist/internal/server/transport.mjs +0 -26
  180. package/dist/internal/server/transport.mjs.map +0 -1
@@ -1,23 +1 @@
1
- import { parseEnvValue } from "@interfere/types/sdk/env";
2
- import { API_URL } from "@interfere/constants/api";
3
- import { normalizeEnv } from "@interfere/types/sdk/runtime";
4
- //#region src/internal/env.ts
5
- function isEnabledInEnvironment() {
6
- if (process.env["NODE_ENV"] === "production") return true;
7
- return !!process.env["NEXT_PUBLIC_INTERFERE_FORCE_ENABLE"];
8
- }
9
- function readInterfereEnv() {
10
- const nodeEnvironment = normalizeEnv(process.env["NODE_ENV"]) ?? "production";
11
- return {
12
- apiKey: parseEnvValue(process.env["INTERFERE_API_KEY"]),
13
- apiUrl: parseEnvValue(process.env["INTERFERE_API_URL"]) ?? API_URL,
14
- nextRuntime: parseEnvValue(process.env["NEXT_RUNTIME"]),
15
- nodeEnvironment,
16
- release: {
17
- sourceId: parseEnvValue(process.env["NEXT_PUBLIC_INTERFERE_BUILD_ID"]),
18
- destinationId: parseEnvValue(process.env["NEXT_PUBLIC_INTERFERE_RELEASE_ID"])
19
- }
20
- };
21
- }
22
- //#endregion
23
- export { isEnabledInEnvironment, readInterfereEnv };
1
+ import{API_URL}from"@interfere/constants/api";import{parseEnvValue}from"@interfere/types/sdk/env";import{normalizeEnv}from"@interfere/types/sdk/runtime";function isEnabledOnServer(){return process.env.NODE_ENV===`production`?!0:!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE}function readInterfereEnv(){let nodeEnvironment=normalizeEnv(process.env.NODE_ENV);return{apiKey:parseEnvValue(process.env.INTERFERE_API_KEY),apiUrl:parseEnvValue(process.env.INTERFERE_API_URL)??API_URL,nextRuntime:parseEnvValue(process.env.NEXT_RUNTIME),nodeEnvironment,publicKey:parseEnvValue(process.env.INTERFERE_PUBLIC_KEY),release:{sourceId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_BUILD_ID),destinationId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_RELEASE_ID)}}}export{isEnabledOnServer,readInterfereEnv};
@@ -1 +1 @@
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 type { Env } from \"@interfere/types/sdk/runtime\";\nimport { normalizeEnv } 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: Exclude<Env, null>;\n readonly release: {\n readonly sourceId: string | null;\n readonly destinationId: string | null;\n };\n}\n\nexport function isEnabledInEnvironment(): 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 = normalizeEnv(process.env[\"NODE_ENV\"]) ?? \"production\";\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 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":";;;;AAgBA,SAAgB,yBAAkC;AAChD,KAAI,QAAQ,IAAI,gBAAgB,aAC9B,QAAO;AAET,QAAO,CAAC,CAAC,QAAQ,IAAI;;AAGvB,SAAgB,mBAAiC;CAC/C,MAAM,kBAAkB,aAAa,QAAQ,IAAI,YAAY,IAAI;AAEjE,QAAO;EACL,QAAQ,cAAc,QAAQ,IAAI,qBAAqB;EACvD,QAAQ,cAAc,QAAQ,IAAI,qBAAqB,IAAI;EAC3D,aAAa,cAAc,QAAQ,IAAI,gBAAgB;EACvD;EACA,SAAS;GACP,UAAU,cAAc,QAAQ,IAAI,kCAAkC;GACtE,eAAe,cACb,QAAQ,IAAI,oCACb;GACF;EACF"}
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 type { Env } from \"@interfere/types/sdk/runtime\";\nimport { normalizeEnv } 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: Env;\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 = normalizeEnv(process.env[\"NODE_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":"yJA0BA,SAAgB,mBAA6B,CAI3C,OAHI,QAAQ,IAAI,WAAgB,aACvB,GAEF,CAAC,CAAC,QAAQ,IAAI,kCACvB,CAEA,SAAgB,kBAAiC,CAC/C,IAAM,gBAAkB,aAAa,QAAQ,IAAI,QAAW,EAE5D,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,4 +1,12 @@
1
1
  //#region src/internal/logger.d.ts
2
+ /**
3
+ * Thrown by `log.fatal` in test environments where `process.exit` is not
4
+ * appropriate. Tagged so callers' catch blocks can re-throw fatal errors and
5
+ * keep test-env behavior aligned with the production hard-exit.
6
+ */
7
+ declare class FatalError extends Error {
8
+ readonly name = "FatalError";
9
+ }
2
10
  declare const log: {
3
11
  info: (title: string, lines: string[]) => void;
4
12
  warn: (title: string, lines: string[]) => void;
@@ -6,4 +14,4 @@ declare const log: {
6
14
  fatal(title: string, lines: string[]): never;
7
15
  };
8
16
  //#endregion
9
- export { log };
17
+ export { FatalError, log };
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.mts","names":[],"sources":["../../src/internal/logger.ts"],"mappings":";cA6Ea,GAAA;wBACS,KAAA;wBACA,KAAA;yBACC,KAAA;uBACF,KAAA;AAAA"}
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,60 +1 @@
1
- import chalk from "chalk";
2
- //#region src/internal/logger.ts
3
- const styles = {
4
- info: {
5
- prefix: `${chalk.whiteBright.bold("❖")}`,
6
- text: chalk.cyan.bold,
7
- content: chalk.white,
8
- prependLevel: false
9
- },
10
- warn: {
11
- prefix: `${chalk.yellow.bold("⚠")} `,
12
- text: chalk.yellow.bold,
13
- content: chalk.yellowBright,
14
- prependLevel: false
15
- },
16
- error: {
17
- prefix: `${chalk.red.bold("⨯")} `,
18
- text: chalk.red.bold,
19
- content: chalk.redBright,
20
- prependLevel: true
21
- },
22
- fatal: {
23
- prefix: `${chalk.red.bold("⨯")} `,
24
- text: chalk.red.bold,
25
- content: chalk.redBright,
26
- prependLevel: true
27
- }
28
- };
29
- const consoleMethods = {
30
- info: "log",
31
- warn: "warn",
32
- error: "error",
33
- fatal: "error"
34
- };
35
- function isTestEnv() {
36
- return Boolean(process.env["VITEST"] || process.env["VITEST_WORKER_ID"]);
37
- }
38
- function emit(level, title, lines) {
39
- if (isTestEnv()) return;
40
- const style = styles[level];
41
- const method = consoleMethods[level];
42
- const fn = globalThis.console[method];
43
- if (typeof fn !== "function") return;
44
- const invoke = (...args) => Reflect.apply(fn, globalThis.console, args);
45
- const prependLevel = style.prependLevel ? `[${style.text(level.toUpperCase())}] ` : "";
46
- invoke(`${prependLevel} ${chalk.white("Interfere →")} ${style.text(title)}`);
47
- for (const [i, line] of lines.entries()) invoke(`${prependLevel} ${i === lines.length - 1 ? "└" : "├"} ${style.content(line)}`);
48
- }
49
- const log = {
50
- info: (title, lines) => emit("info", title, lines),
51
- warn: (title, lines) => emit("warn", title, lines),
52
- error: (title, lines) => emit("error", title, lines),
53
- fatal(title, lines) {
54
- emit("fatal", title, lines);
55
- if (isTestEnv()) throw new Error(title);
56
- process.exit(1);
57
- }
58
- };
59
- //#endregion
60
- export { log };
1
+ import chalk from"chalk";const styles={info:{prefix:`${chalk.whiteBright.bold(`❖`)}`,text:chalk.cyan.bold,content:chalk.white,prependLevel:!1},warn:{prefix:`${chalk.yellow.bold(`⚠`)} `,text:chalk.yellow.bold,content:chalk.yellowBright,prependLevel:!1},error:{prefix:`${chalk.red.bold(`⨯`)} `,text:chalk.red.bold,content:chalk.redBright,prependLevel:!0},fatal:{prefix:`${chalk.red.bold(`⨯`)} `,text:chalk.red.bold,content:chalk.redBright,prependLevel:!0}},consoleMethods={info:`log`,warn:`warn`,error:`error`,fatal:`error`};function isTestEnv(){return!!(process.env.VITEST||process.env.VITEST_WORKER_ID)}var FatalError=class extends Error{name=`FatalError`};function emit(level,title,lines){if(isTestEnv())return;let style=styles[level],method=consoleMethods[level],fn=globalThis.console[method];if(typeof fn!=`function`)return;let invoke=(...args)=>Reflect.apply(fn,globalThis.console,args),prependLevel=style.prependLevel?`[${style.text(level.toUpperCase())}] `:``;invoke(`${prependLevel} ${chalk.white(`Interfere →`)} ${style.text(title)}`);for(let[i,line]of lines.entries())invoke(`${prependLevel} ${i===lines.length-1?`└`:`├`} ${style.content(line)}`)}const log={info:(title,lines)=>emit(`info`,title,lines),warn:(title,lines)=>emit(`warn`,title,lines),error:(title,lines)=>emit(`error`,title,lines),fatal(title,lines){if(emit(`fatal`,title,lines),isTestEnv())throw new FatalError(title);process.exit(1)}};export{FatalError,log};
@@ -1 +1 @@
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\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 Error(title);\n }\n\n process.exit(1);\n },\n};\n"],"mappings":";;AAIA,MAAM,SAAS;CACb,MAAM;EACJ,QAAQ,GAAG,MAAM,YAAY,KAAK,IAAI;EACtC,MAAM,MAAM,KAAK;EACjB,SAAS,MAAM;EACf,cAAc;EACf;CACD,MAAM;EACJ,QAAQ,GAAG,MAAM,OAAO,KAAK,IAAI,CAAC;EAClC,MAAM,MAAM,OAAO;EACnB,SAAS,MAAM;EACf,cAAc;EACf;CACD,OAAO;EACL,QAAQ,GAAG,MAAM,IAAI,KAAK,IAAI,CAAC;EAC/B,MAAM,MAAM,IAAI;EAChB,SAAS,MAAM;EACf,cAAc;EACf;CACD,OAAO;EACL,QAAQ,GAAG,MAAM,IAAI,KAAK,IAAI,CAAC;EAC/B,MAAM,MAAM,IAAI;EAChB,SAAS,MAAM;EACf,cAAc;EACf;CACF;AAUD,MAAM,iBAAiB;CACrB,MAAM;CACN,MAAM;CACN,OAAO;CACP,OAAO;CACR;AAED,SAAS,YAAY;AACnB,QAAO,QAAQ,QAAQ,IAAI,aAAa,QAAQ,IAAI,oBAAoB;;AAG1E,SAAS,KAAK,OAAiB,OAAe,OAAiB;AAC7D,KAAI,WAAW,CACb;CAGF,MAAM,QAAQ,OAAO;CACrB,MAAM,SAAS,eAAe;CAC9B,MAAM,KAAK,WAAW,QAAQ;AAC9B,KAAI,OAAO,OAAO,WAChB;CAGF,MAAM,UAAU,GAAG,SACjB,QAAQ,MAAM,IAAI,WAAW,SAAS,KAAK;CAE7C,MAAM,eAAe,MAAM,eACvB,IAAI,MAAM,KAAK,MAAM,aAAa,CAAC,CAAC,MACpC;AAEJ,QAAO,GAAG,aAAa,GAAG,MAAM,MAAM,cAAc,CAAC,GAAG,MAAM,KAAK,MAAM,GAAG;AAE5E,MAAK,MAAM,CAAC,GAAG,SAAS,MAAM,SAAS,CAErC,QAAO,GAAG,aAAa,GADL,MAAM,MAAM,SAAS,IAAI,MAAM,IACb,GAAG,MAAM,QAAQ,KAAK,GAAG;;AAIjE,MAAa,MAAM;CACjB,OAAO,OAAe,UAAoB,KAAK,QAAQ,OAAO,MAAM;CACpE,OAAO,OAAe,UAAoB,KAAK,QAAQ,OAAO,MAAM;CACpE,QAAQ,OAAe,UAAoB,KAAK,SAAS,OAAO,MAAM;CACtE,MAAM,OAAe,OAAwB;AAC3C,OAAK,SAAS,OAAO,MAAM;AAE3B,MAAI,WAAW,CACb,OAAM,IAAI,MAAM,MAAM;AAGxB,UAAQ,KAAK,EAAE;;CAElB"}
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"}
@@ -0,0 +1,25 @@
1
+ import { ReleaseSlug } from "@interfere/types/releases/slug";
2
+
3
+ //#region src/internal/release-slug.d.ts
4
+ /**
5
+ * Walks the same env keys at build time (`withInterfere`) and at runtime
6
+ * (server-side `register()`), then falls back to `git rev-parse HEAD`. Both
7
+ * call sites resolving the same SHA → both derive the same `release.slug`,
8
+ * so server and client spans agree by construction.
9
+ *
10
+ * Override path for non-CI builds: set `INTERFERE_SOURCE_ID` (or any other
11
+ * key in `releaseSourceIdEnvKeys`) on both the build env and the runtime
12
+ * env. The `interfere.buildId` next.config knob was removed in 10.0 because
13
+ * it only worked at build time and caused server/client slug drift.
14
+ *
15
+ * `runGitCommand` (`node:child_process`) keeps this module on the Node side
16
+ * of `@interfere/next`'s dual entry — the edge entrypoint
17
+ * (`instrumentation.edge.ts`) intentionally doesn't import this file.
18
+ */
19
+ declare function resolveCommitSha(): string | null;
20
+ declare function resolveReleaseSlug(): {
21
+ commitSha: string | null;
22
+ slug: ReleaseSlug | null;
23
+ };
24
+ //#endregion
25
+ export { resolveCommitSha, resolveReleaseSlug };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-slug.d.mts","names":[],"sources":["../../src/internal/release-slug.ts"],"mappings":";;;;;AAwBA;;;;AAAgC;AAOhC;;;;;;;;iBAPgB,gBAAA,CAAA;AAAA,iBAOA,kBAAA,CAAA;EACd,SAAA;EACA,IAAA,EAAM,WAAW;AAAA"}
@@ -0,0 +1 @@
1
+ import{runGitCommand}from"./build/release/git.mjs";import{deriveReleaseSlug}from"@interfere/types/releases/slug";import{readFirstEnvValue}from"@interfere/types/sdk/env";import{releaseSourceIdEnvKeys}from"@interfere/types/integrations";function resolveCommitSha(){return readFirstEnvValue(process.env,releaseSourceIdEnvKeys)??runGitCommand(`git rev-parse HEAD`)}function resolveReleaseSlug(){let commitSha=resolveCommitSha();return{commitSha,slug:commitSha?deriveReleaseSlug(commitSha):null}}export{resolveCommitSha,resolveReleaseSlug};
@@ -0,0 +1 @@
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,4 +1,17 @@
1
1
  //#region src/internal/route/handle-get.d.ts
2
- declare function handleGet(request: Request): Response | Promise<Response>;
2
+ /**
3
+ * Generic GET proxy. SDK 10.x routes `GET /v2/config` (and any future
4
+ * GET-based endpoints) through here; SDK 9.x clients still hit
5
+ * `GET /v1/config` and get the same delegated response on the collector
6
+ * side.
7
+ *
8
+ * `/sw` is special-cased to serve the SDK's bundled service-worker
9
+ * script directly out of the customer's Next.js process. `SW_SCRIPT`
10
+ * is a string export emitted at @interfere/react build time
11
+ * (`scripts/build-sw.ts`); on Node runtime the customer resolves it
12
+ * via `node_modules`, on Edge runtime the customer's Next.js bundler
13
+ * inlines it into the Edge worker. Either way, no `fs.readFileSync`.
14
+ */
15
+ declare function handleGet(request: Request): Promise<Response>;
3
16
  //#endregion
4
17
  export { handleGet };
@@ -1 +1 @@
1
- {"version":3,"file":"handle-get.d.mts","names":[],"sources":["../../../src/internal/route/handle-get.ts"],"mappings":";iBAUgB,SAAA,CAAU,OAAA,EAAS,OAAA,GAAU,QAAA,GAAW,OAAA,CAAQ,QAAA"}
1
+ {"version":3,"file":"handle-get.d.mts","names":[],"sources":["../../../src/internal/route/handle-get.ts"],"mappings":";;AAqCA;;;;;;;;;;;;iBAAsB,SAAA,CAAU,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,QAAA"}
@@ -1,22 +1 @@
1
- import { extractSubPath, forwardToCollector, notConfiguredResponse, resolveAuthenticatedEnv } from "./proxy.mjs";
2
- import { SW_SCRIPT } from "./sw-script.mjs";
3
- import { API_PATHS } from "@interfere/constants/api";
4
- //#region src/internal/route/handle-get.ts
5
- function handleGet(request) {
6
- const subPath = extractSubPath(request);
7
- if (subPath.endsWith("/sw")) return new Response(SW_SCRIPT, {
8
- status: 200,
9
- headers: {
10
- "content-type": "application/javascript",
11
- "cache-control": "public, max-age=3600"
12
- }
13
- });
14
- if (subPath === API_PATHS.CONFIG) {
15
- const env = resolveAuthenticatedEnv();
16
- if (!env) return notConfiguredResponse();
17
- return forwardToCollector(request, env, subPath);
18
- }
19
- return new Response("Not Found", { status: 404 });
20
- }
21
- //#endregion
22
- export { handleGet };
1
+ import{log}from"../logger.mjs";import{extractSubPath,formatProxyError,forwardToCollector,hasPublicKeyCredential,notConfiguredResponse,resolveAuthenticatedEnv}from"./proxy.mjs";import{SW_SCRIPT}from"@interfere/react/sw";const SW_HEADERS={"content-type":`application/javascript; charset=utf-8`,"service-worker-allowed":`/`,"cache-control":`public, max-age=3600`};async function handleGet(request){let subPath=extractSubPath(request);if(subPath===`/sw`)return new Response(SW_SCRIPT,{status:200,headers:SW_HEADERS});let env=resolveAuthenticatedEnv();if(!hasPublicKeyCredential(request,env.publicKey))return notConfiguredResponse();try{return await forwardToCollector(request,env,subPath)}catch(error){let detail=formatProxyError(error);return log.error(`Proxy ${request.method} ${subPath} failed`,detail.lines),Response.json({code:`INTERFERE_PROXY_ERROR`,message:detail.message},{status:502})}}export{handleGet};
@@ -1 +1 @@
1
- {"version":3,"file":"handle-get.mjs","names":[],"sources":["../../../src/internal/route/handle-get.ts"],"sourcesContent":["import { API_PATHS } from \"@interfere/constants/api\";\n\nimport {\n extractSubPath,\n forwardToCollector,\n notConfiguredResponse,\n resolveAuthenticatedEnv,\n} from \"./proxy.js\";\nimport { SW_SCRIPT } from \"./sw-script.js\";\n\nexport function handleGet(request: Request): Response | Promise<Response> {\n const subPath = extractSubPath(request);\n\n if (subPath.endsWith(\"/sw\")) {\n return new Response(SW_SCRIPT, {\n status: 200,\n headers: {\n \"content-type\": \"application/javascript\",\n \"cache-control\": \"public, max-age=3600\",\n },\n });\n }\n\n if (subPath === API_PATHS.CONFIG) {\n const env = resolveAuthenticatedEnv();\n if (!env) {\n return notConfiguredResponse();\n }\n return forwardToCollector(request, env, subPath);\n }\n\n return new Response(\"Not Found\", { status: 404 });\n}\n"],"mappings":";;;;AAUA,SAAgB,UAAU,SAAgD;CACxE,MAAM,UAAU,eAAe,QAAQ;AAEvC,KAAI,QAAQ,SAAS,MAAM,CACzB,QAAO,IAAI,SAAS,WAAW;EAC7B,QAAQ;EACR,SAAS;GACP,gBAAgB;GAChB,iBAAiB;GAClB;EACF,CAAC;AAGJ,KAAI,YAAY,UAAU,QAAQ;EAChC,MAAM,MAAM,yBAAyB;AACrC,MAAI,CAAC,IACH,QAAO,uBAAuB;AAEhC,SAAO,mBAAmB,SAAS,KAAK,QAAQ;;AAGlD,QAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,KAAK,CAAC"}
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 // Allow the SW to control the whole origin, not just `/api/interfere/`.\n // The SDK still scopes its `register()` call narrowly; this header just\n // unlocks the option without re-issuing a new SW URL.\n \"service-worker-allowed\": \"/\",\n // Customers' edges (Vercel, Cloudflare) cache aggressively by default;\n // a 1-hour TTL balances \"pick up SW updates within a deploy cycle\"\n // against \"don't refetch on every navigation\".\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,wCAIhB,yBAA0B,IAI1B,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,4 +1,15 @@
1
1
  //#region src/internal/route/handle-post.d.ts
2
+ /**
3
+ * Generic POST proxy. SDK 10.x routes everything through here:
4
+ *
5
+ * - `/v2/sink` (OTLP traces / metrics / logs)
6
+ * - `/v2/replay/upload/:sessionId`
7
+ * - `/v1/session*` (session sync + identify)
8
+ *
9
+ * No envelope-aware special-casing — that endpoint (`/v1/ingest`) was
10
+ * 9.x-only and is not produced by 10.x. Customers on 9.x post directly
11
+ * to the collector through the same proxy without touching this file.
12
+ */
2
13
  declare function handlePost(request: Request): Promise<Response>;
3
14
  //#endregion
4
15
  export { handlePost };
@@ -1 +1 @@
1
- {"version":3,"file":"handle-post.d.mts","names":[],"sources":["../../../src/internal/route/handle-post.ts"],"mappings":";iBAqCsB,UAAA,CAAW,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,QAAA"}
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,70 +1 @@
1
- import { log } from "../logger.mjs";
2
- import { extractSubPath, formatProxyError, forwardToCollector, notConfiguredResponse, resolveAuthenticatedEnv } from "./proxy.mjs";
3
- import { API_PATHS } from "@interfere/constants/api";
4
- import { extractCountryHeader } from "@interfere/types/sdk/geo";
5
- //#region src/internal/route/handle-post.ts
6
- function parseEnvelopes(value) {
7
- if (!Array.isArray(value)) return null;
8
- return value;
9
- }
10
- function injectReleaseMetadata(envelopes, metadata) {
11
- if (metadata.sourceId === null && metadata.destinationId === null) return envelopes;
12
- return envelopes.map((envelope) => ({
13
- ...envelope,
14
- buildId: metadata.sourceId ?? envelope.buildId,
15
- releaseId: metadata.destinationId ?? envelope.releaseId
16
- }));
17
- }
18
- async function handlePost(request) {
19
- const env = resolveAuthenticatedEnv();
20
- if (!env) return notConfiguredResponse();
21
- const subPath = extractSubPath(request);
22
- try {
23
- if (subPath === API_PATHS.INGEST) return await handleIngest(request, env);
24
- return await forwardToCollector(request, env, subPath);
25
- } catch (error) {
26
- const detail = formatProxyError(error);
27
- log.error(`Proxy ${request.method} ${subPath} failed`, detail.lines);
28
- return Response.json({
29
- code: "INTERFERE_PROXY_ERROR",
30
- message: detail.message
31
- }, { status: 502 });
32
- }
33
- }
34
- async function handleIngest(request, env) {
35
- let payload;
36
- try {
37
- payload = await request.json();
38
- } catch {
39
- return Response.json({
40
- code: "INTERFERE_INVALID_JSON",
41
- message: "Request body must be valid JSON."
42
- }, { status: 400 });
43
- }
44
- const envelopes = parseEnvelopes(payload);
45
- if (envelopes === null) return Response.json({
46
- code: "INTERFERE_INVALID_ENVELOPES",
47
- message: "Request body must be an array of envelopes."
48
- }, { status: 400 });
49
- const traceparent = request.headers.get("traceparent");
50
- const upstream = await fetch(`${env.apiUrl}${API_PATHS.INGEST}`, {
51
- method: "POST",
52
- headers: {
53
- "content-type": "application/json",
54
- "x-api-key": env.apiKey,
55
- ...traceparent ? { traceparent } : {},
56
- ...(() => {
57
- const country = extractCountryHeader(request);
58
- return country ? { "x-country-code": country } : {};
59
- })()
60
- },
61
- body: JSON.stringify(injectReleaseMetadata(envelopes, env.release)),
62
- signal: AbortSignal.timeout(1e4)
63
- });
64
- return new Response(upstream.body, {
65
- status: upstream.status,
66
- headers: { "content-type": upstream.headers.get("content-type") ?? "application/json" }
67
- });
68
- }
69
- //#endregion
70
- export { handlePost };
1
+ import{log}from"../logger.mjs";import{extractSubPath,formatProxyError,forwardToCollector,hasPublicKeyCredential,notConfiguredResponse,resolveAuthenticatedEnv}from"./proxy.mjs";async function handlePost(request){let env=resolveAuthenticatedEnv();if(!hasPublicKeyCredential(request,env.publicKey))return notConfiguredResponse();let subPath=extractSubPath(request);try{return await forwardToCollector(request,env,subPath)}catch(error){let detail=formatProxyError(error);return log.error(`Proxy ${request.method} ${subPath} failed`,detail.lines),Response.json({code:`INTERFERE_PROXY_ERROR`,message:detail.message},{status:502})}}export{handlePost};
@@ -1 +1 @@
1
- {"version":3,"file":"handle-post.mjs","names":[],"sources":["../../../src/internal/route/handle-post.ts"],"sourcesContent":["import { API_PATHS } from \"@interfere/constants/api\";\nimport type { Envelope } from \"@interfere/types/sdk/envelope\";\nimport { extractCountryHeader } from \"@interfere/types/sdk/geo\";\n\nimport { log } from \"../logger.js\";\nimport {\n type AuthenticatedEnv,\n extractSubPath,\n formatProxyError,\n forwardToCollector,\n notConfiguredResponse,\n resolveAuthenticatedEnv,\n} from \"./proxy.js\";\n\nfunction parseEnvelopes(value: unknown): Envelope[] | null {\n if (!Array.isArray(value)) {\n return null;\n }\n\n return value as Envelope[];\n}\n\nfunction injectReleaseMetadata(\n envelopes: Envelope[],\n metadata: { sourceId: string | null; destinationId: string | null }\n): Envelope[] {\n if (metadata.sourceId === null && metadata.destinationId === null) {\n return envelopes;\n }\n\n return envelopes.map((envelope) => ({\n ...envelope,\n buildId: metadata.sourceId ?? envelope.buildId,\n releaseId: metadata.destinationId ?? envelope.releaseId,\n }));\n}\n\nexport async function handlePost(request: Request): Promise<Response> {\n const env = resolveAuthenticatedEnv();\n if (!env) {\n return notConfiguredResponse();\n }\n\n const subPath = extractSubPath(request);\n\n try {\n if (subPath === API_PATHS.INGEST) {\n return await handleIngest(request, env);\n }\n\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\nasync function handleIngest(\n request: Request,\n env: AuthenticatedEnv\n): Promise<Response> {\n let payload: unknown;\n try {\n payload = await request.json();\n } catch {\n return Response.json(\n {\n code: \"INTERFERE_INVALID_JSON\",\n message: \"Request body must be valid JSON.\",\n },\n { status: 400 }\n );\n }\n\n const envelopes = parseEnvelopes(payload);\n if (envelopes === null) {\n return Response.json(\n {\n code: \"INTERFERE_INVALID_ENVELOPES\",\n message: \"Request body must be an array of envelopes.\",\n },\n { status: 400 }\n );\n }\n\n const traceparent = request.headers.get(\"traceparent\");\n const upstream = await fetch(`${env.apiUrl}${API_PATHS.INGEST}`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": env.apiKey,\n ...(traceparent ? { traceparent } : {}),\n ...(() => {\n const country = extractCountryHeader(request);\n return country ? { \"x-country-code\": country } : {};\n })(),\n },\n body: JSON.stringify(injectReleaseMetadata(envelopes, env.release)),\n signal: AbortSignal.timeout(10_000),\n });\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: {\n \"content-type\":\n upstream.headers.get(\"content-type\") ?? \"application/json\",\n },\n });\n}\n"],"mappings":";;;;;AAcA,SAAS,eAAe,OAAmC;AACzD,KAAI,CAAC,MAAM,QAAQ,MAAM,CACvB,QAAO;AAGT,QAAO;;AAGT,SAAS,sBACP,WACA,UACY;AACZ,KAAI,SAAS,aAAa,QAAQ,SAAS,kBAAkB,KAC3D,QAAO;AAGT,QAAO,UAAU,KAAK,cAAc;EAClC,GAAG;EACH,SAAS,SAAS,YAAY,SAAS;EACvC,WAAW,SAAS,iBAAiB,SAAS;EAC/C,EAAE;;AAGL,eAAsB,WAAW,SAAqC;CACpE,MAAM,MAAM,yBAAyB;AACrC,KAAI,CAAC,IACH,QAAO,uBAAuB;CAGhC,MAAM,UAAU,eAAe,QAAQ;AAEvC,KAAI;AACF,MAAI,YAAY,UAAU,OACxB,QAAO,MAAM,aAAa,SAAS,IAAI;AAGzC,SAAO,MAAM,mBAAmB,SAAS,KAAK,QAAQ;UAC/C,OAAO;EACd,MAAM,SAAS,iBAAiB,MAAM;AACtC,MAAI,MAAM,SAAS,QAAQ,OAAO,GAAG,QAAQ,UAAU,OAAO,MAAM;AACpE,SAAO,SAAS,KACd;GAAE,MAAM;GAAyB,SAAS,OAAO;GAAS,EAC1D,EAAE,QAAQ,KAAK,CAChB;;;AAIL,eAAe,aACb,SACA,KACmB;CACnB,IAAI;AACJ,KAAI;AACF,YAAU,MAAM,QAAQ,MAAM;SACxB;AACN,SAAO,SAAS,KACd;GACE,MAAM;GACN,SAAS;GACV,EACD,EAAE,QAAQ,KAAK,CAChB;;CAGH,MAAM,YAAY,eAAe,QAAQ;AACzC,KAAI,cAAc,KAChB,QAAO,SAAS,KACd;EACE,MAAM;EACN,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;CAGH,MAAM,cAAc,QAAQ,QAAQ,IAAI,cAAc;CACtD,MAAM,WAAW,MAAM,MAAM,GAAG,IAAI,SAAS,UAAU,UAAU;EAC/D,QAAQ;EACR,SAAS;GACP,gBAAgB;GAChB,aAAa,IAAI;GACjB,GAAI,cAAc,EAAE,aAAa,GAAG,EAAE;GACtC,UAAU;IACR,MAAM,UAAU,qBAAqB,QAAQ;AAC7C,WAAO,UAAU,EAAE,kBAAkB,SAAS,GAAG,EAAE;OACjD;GACL;EACD,MAAM,KAAK,UAAU,sBAAsB,WAAW,IAAI,QAAQ,CAAC;EACnE,QAAQ,YAAY,QAAQ,IAAO;EACpC,CAAC;AAEF,QAAO,IAAI,SAAS,SAAS,MAAM;EACjC,QAAQ,SAAS;EACjB,SAAS,EACP,gBACE,SAAS,QAAQ,IAAI,eAAe,IAAI,oBAC3C;EACF,CAAC"}
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,18 +1,40 @@
1
1
  import { InterfereEnv } from "../env.mjs";
2
2
 
3
3
  //#region src/internal/route/proxy.d.ts
4
+ /**
5
+ * Clone the inbound request's headers, removing entries that should never
6
+ * cross the proxy boundary. Returns a mutable `Headers` so callers can
7
+ * `.set()`/`.delete()` upstream-specific values without having to merge
8
+ * record literals (which lose case-insensitivity and create the precedence
9
+ * footguns that masked the 2026-05-01 incident in code review).
10
+ */
11
+ declare function forwardedHeaders(request: Request): Headers;
4
12
  interface AuthenticatedEnv {
5
- apiKey: string;
6
13
  apiUrl: string;
14
+ publicKey: string | null;
7
15
  release: InterfereEnv["release"];
8
16
  }
9
- declare function resolveAuthenticatedEnv(): AuthenticatedEnv | null;
10
- declare function extractSubPath(request: Request): string;
17
+ declare function resolveAuthenticatedEnv(): AuthenticatedEnv;
18
+ /** True when the proxy can attach a publishable key from env or the request. */
19
+ declare function hasPublicKeyCredential(request: Request, envPublicKey: string | null): boolean;
11
20
  declare function notConfiguredResponse(): Response;
21
+ declare function extractSubPath(request: Request): string;
22
+ /**
23
+ * Preserve any query string verbatim when forwarding upstream.
24
+ *
25
+ * The browser SDK uses `?_pv=…` and `?pk=…` (and `?_pt=…` in direct-ingestion
26
+ * mode) as a `navigator.sendBeacon` fallback when `visibilitychange→
27
+ * hidden` aborts the keepalive fetch path. The collector's
28
+ * `otlpProducerGuard` and `surfacePkAuth` accept those values verbatim
29
+ * — but only if the proxy actually forwards them. Passing
30
+ * `request.url`'s `search` through (`""` when absent, leading `?`
31
+ * when present) keeps the rewrite transparent.
32
+ */
33
+ declare function extractSearch(request: Request): string;
12
34
  declare function formatProxyError(error: unknown): {
13
35
  message: string;
14
36
  lines: string[];
15
37
  };
16
38
  declare function forwardToCollector(request: Request, env: AuthenticatedEnv, subPath: string): Promise<Response>;
17
39
  //#endregion
18
- export { AuthenticatedEnv, extractSubPath, formatProxyError, forwardToCollector, notConfiguredResponse, resolveAuthenticatedEnv };
40
+ export { AuthenticatedEnv, extractSearch, extractSubPath, formatProxyError, forwardToCollector, forwardedHeaders, hasPublicKeyCredential, notConfiguredResponse, resolveAuthenticatedEnv };
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.mts","names":[],"sources":["../../../src/internal/route/proxy.ts"],"mappings":";;;UAaiB,gBAAA;EACf,MAAA;EACA,MAAA;EACA,OAAA,EAAS,YAAA;AAAA;AAAA,iBAGK,uBAAA,CAAA,GAA2B,gBAAA;AAAA,iBAQ3B,cAAA,CAAe,OAAA,EAAS,OAAA;AAAA,iBAMxB,qBAAA,CAAA,GAAyB,QAAA;AAAA,iBAazB,gBAAA,CAAiB,KAAA;EAC/B,OAAA;EACA,KAAA;AAAA;AAAA,iBAwBoB,kBAAA,CACpB,OAAA,EAAS,OAAA,EACT,GAAA,EAAK,gBAAA,EACL,OAAA,WACC,OAAA,CAAQ,QAAA"}
1
+ {"version":3,"file":"proxy.d.mts","names":[],"sources":["../../../src/internal/route/proxy.ts"],"mappings":";;;;;AAuDA;;;;;iBAAgB,gBAAA,CAAiB,OAAA,EAAS,OAAA,GAAU,OAAO;AAAA,UAW1C,gBAAA;EACf,MAAA;EACA,SAAA;EACA,OAAA,EAAS,YAAY;AAAA;AAAA,iBAGP,uBAAA,CAAA,GAA2B,gBAAgB;;iBAU3C,sBAAA,CACd,OAAA,EAAS,OAAO,EAChB,YAAA;AAAA,iBAQc,qBAAA,CAAA,GAAyB,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"}
@@ -1,89 +1 @@
1
- import { log } from "../logger.mjs";
2
- import { readInterfereEnv } from "../env.mjs";
3
- import { omitUndefined } from "@interfere/helpers/omit-undefined";
4
- import { extractCountryHeader } from "@interfere/types/sdk/geo";
5
- //#region src/internal/route/proxy.ts
6
- const PROXY_PATH_PATTERN = /\/api\/interfere(\/.*)/;
7
- function geoHeaders(request) {
8
- const country = extractCountryHeader(request);
9
- return country ? { "x-country-code": country } : {};
10
- }
11
- function resolveAuthenticatedEnv() {
12
- const env = readInterfereEnv();
13
- if (env.apiKey === null) return null;
14
- return {
15
- apiKey: env.apiKey,
16
- apiUrl: env.apiUrl,
17
- release: env.release
18
- };
19
- }
20
- function extractSubPath(request) {
21
- return new URL(request.url).pathname.match(PROXY_PATH_PATTERN)?.[1] ?? "/";
22
- }
23
- function notConfiguredResponse() {
24
- log.warn("Not configured", ["INTERFERE_API_KEY is not set. The proxy route will return 503."]);
25
- return Response.json({
26
- code: "INTERFERE_NOT_CONFIGURED",
27
- message: "INTERFERE_API_KEY is required."
28
- }, { status: 503 });
29
- }
30
- function formatProxyError(error) {
31
- if (!(error instanceof Error)) return {
32
- message: String(error),
33
- lines: [String(error)]
34
- };
35
- const lines = [`${error.name}: ${error.message}`];
36
- if ("cause" in error && error.cause) {
37
- const cause = error.cause instanceof Error ? error.cause.message : String(error.cause);
38
- lines.push(`cause: ${cause}`);
39
- }
40
- if ("code" in error && typeof error.code === "string") lines.push(`code: ${error.code}`);
41
- return {
42
- message: `${error.name}: ${error.message}`,
43
- lines
44
- };
45
- }
46
- async function forwardToCollector(request, env, subPath) {
47
- const url = `${env.apiUrl}${subPath}`;
48
- const traceparent = request.headers.get("traceparent");
49
- const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
50
- const upstream = await fetch(url, {
51
- ...omitUndefined({ body }),
52
- method: request.method,
53
- headers: {
54
- "content-type": request.headers.get("content-type") ?? "application/json",
55
- "x-api-key": env.apiKey,
56
- ...traceparent ? { traceparent } : {},
57
- ...geoHeaders(request)
58
- },
59
- signal: AbortSignal.timeout(1e4)
60
- });
61
- if (!upstream.ok) {
62
- const text = await upstream.text().catch(() => "");
63
- if (upstream.status >= 500) {
64
- log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [text]);
65
- return Response.json({
66
- code: "INTERFERE_UPSTREAM_ERROR",
67
- message: text
68
- }, { status: upstream.status });
69
- }
70
- if (upstream.status >= 400) {
71
- log.warn(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [text]);
72
- return Response.json({
73
- code: "INTERFERE_UPSTREAM_WARNING",
74
- message: text
75
- }, { status: upstream.status });
76
- }
77
- log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [text]);
78
- return Response.json({
79
- code: "INTERFERE_UPSTREAM_ERROR",
80
- message: text
81
- }, { status: upstream.status });
82
- }
83
- return new Response(upstream.body, {
84
- status: upstream.status,
85
- headers: { "content-type": upstream.headers.get("content-type") ?? "application/json" }
86
- });
87
- }
88
- //#endregion
89
- export { extractSubPath, formatProxyError, forwardToCollector, notConfiguredResponse, resolveAuthenticatedEnv };
1
+ import{readInterfereEnv}from"../env.mjs";import{log}from"../logger.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{resolveRoutePrefix}from"@interfere/constants/route-prefix";import{extractCountryHeader}from"@interfere/types/sdk/geo";const STRIPPED_AUTH_HEADERS=[`authorization`,`x-api-key`,`x-interfere-api-key`],STRIPPED_TRANSPORT_HEADERS=[`host`,`content-length`,`connection`,`keep-alive`,`transfer-encoding`,`te`,`trailer`,`upgrade`,`proxy-authenticate`,`proxy-authorization`];function forwardedHeaders(request){let headers=new Headers(request.headers);for(let name of STRIPPED_AUTH_HEADERS)headers.delete(name);for(let name of STRIPPED_TRANSPORT_HEADERS)headers.delete(name);return headers}function resolveAuthenticatedEnv(){let env=readInterfereEnv();return{apiUrl:env.apiUrl,publicKey:env.publicKey,release:env.release}}function hasPublicKeyCredential(request,envPublicKey){return envPublicKey?!0:new URL(request.url).searchParams.has(`pk`)}function notConfiguredResponse(){return log.warn(`Not configured`,[`INTERFERE_PUBLIC_KEY is not set and the request has no ?pk= query param. The proxy route will return 503.`]),Response.json({code:`INTERFERE_NOT_CONFIGURED`,message:`INTERFERE_PUBLIC_KEY is required.`},{status:503})}function extractSubPath(request){let prefix=resolveRoutePrefix(),url=new URL(request.url),idx=url.pathname.indexOf(prefix);if(idx===-1)return`/`;let remainder=url.pathname.slice(idx+prefix.length);return remainder===``?`/`:remainder.startsWith(`/`)?remainder:`/${remainder}`}function extractSearch(request){return new URL(request.url).search}function formatProxyError(error){if(!(error instanceof Error))return{message:String(error),lines:[String(error)]};let lines=[`${error.name}: ${error.message}`];if(`cause`in error&&error.cause){let cause=error.cause instanceof Error?error.cause.message:String(error.cause);lines.push(`cause: ${cause}`)}return`code`in error&&typeof error.code==`string`&&lines.push(`code: ${error.code}`),{message:`${error.name}: ${error.message}`,lines}}function buildUpstreamUrl(apiUrl,subPath,request,publicKey){let incoming=new URL(request.url),upstream=new URL(`${apiUrl}${subPath}`);for(let[key,value]of incoming.searchParams)upstream.searchParams.append(key,value);return publicKey&&!upstream.searchParams.has(`pk`)&&upstream.searchParams.set(`pk`,publicKey),upstream.toString()}async function forwardToCollector(request,env,subPath){let url=buildUpstreamUrl(env.apiUrl,subPath,request,env.publicKey),body=request.method!==`GET`&&request.method!==`HEAD`?await request.text():void 0,headers=forwardedHeaders(request);headers.has(`content-type`)||headers.set(`content-type`,`application/json`);let country=extractCountryHeader(request);country!==null&&headers.set(`x-country-code`,country);let upstream=await fetch(url,{...omitUndefined({body}),method:request.method,headers,signal:AbortSignal.timeout(1e4)});if(!upstream.ok){let text=await upstream.text().catch(()=>``);return upstream.status>=500?(log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`,[text]),Response.json({code:`INTERFERE_UPSTREAM_ERROR`,message:text},{status:upstream.status})):upstream.status>=400?(log.warn(`Upstream ${upstream.status} for ${request.method} ${subPath}`,[text]),Response.json({code:`INTERFERE_UPSTREAM_WARNING`,message:text},{status:upstream.status})):(log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`,[text]),Response.json({code:`INTERFERE_UPSTREAM_ERROR`,message:text},{status:upstream.status}))}return new Response(upstream.body,{status:upstream.status,headers:{"content-type":upstream.headers.get(`content-type`)??`application/json`}})}export{extractSearch,extractSubPath,formatProxyError,forwardToCollector,forwardedHeaders,hasPublicKeyCredential,notConfiguredResponse,resolveAuthenticatedEnv};
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.mjs","names":[],"sources":["../../../src/internal/route/proxy.ts"],"sourcesContent":["import { omitUndefined } from \"@interfere/helpers/omit-undefined\";\nimport { extractCountryHeader } from \"@interfere/types/sdk/geo\";\n\nimport { type InterfereEnv, readInterfereEnv } from \"../env.js\";\nimport { log } from \"../logger.js\";\n\nconst PROXY_PATH_PATTERN = /\\/api\\/interfere(\\/.*)/;\n\nfunction geoHeaders(request: Request): Record<string, string> {\n const country = extractCountryHeader(request);\n return country ? { \"x-country-code\": country } : {};\n}\n\nexport interface AuthenticatedEnv {\n apiKey: string;\n apiUrl: string;\n release: InterfereEnv[\"release\"];\n}\n\nexport function resolveAuthenticatedEnv(): AuthenticatedEnv | null {\n const env = readInterfereEnv();\n if (env.apiKey === null) {\n return null;\n }\n return { apiKey: env.apiKey, apiUrl: env.apiUrl, release: env.release };\n}\n\nexport function extractSubPath(request: Request): string {\n const url = new URL(request.url);\n const match = url.pathname.match(PROXY_PATH_PATTERN);\n return match?.[1] ?? \"/\";\n}\n\nexport function notConfiguredResponse(): Response {\n log.warn(\"Not configured\", [\n \"INTERFERE_API_KEY is not set. The proxy route will return 503.\",\n ]);\n return Response.json(\n {\n code: \"INTERFERE_NOT_CONFIGURED\",\n message: \"INTERFERE_API_KEY is required.\",\n },\n { status: 503 }\n );\n}\n\nexport function formatProxyError(error: unknown): {\n message: string;\n lines: string[];\n} {\n if (!(error instanceof Error)) {\n return { message: String(error), lines: [String(error)] };\n }\n\n const lines = [`${error.name}: ${error.message}`];\n\n if (\"cause\" in error && error.cause) {\n const cause =\n error.cause instanceof Error ? error.cause.message : String(error.cause);\n lines.push(`cause: ${cause}`);\n }\n\n if (\n \"code\" in error &&\n typeof (error as NodeJS.ErrnoException).code === \"string\"\n ) {\n lines.push(`code: ${(error as NodeJS.ErrnoException).code}`);\n }\n\n return { message: `${error.name}: ${error.message}`, lines };\n}\n\nexport async function forwardToCollector(\n request: Request,\n env: AuthenticatedEnv,\n subPath: string\n): Promise<Response> {\n const url = `${env.apiUrl}${subPath}`;\n const traceparent = request.headers.get(\"traceparent\");\n const hasBody = request.method !== \"GET\" && request.method !== \"HEAD\";\n const body = hasBody ? await request.text() : undefined;\n\n const upstream = await fetch(url, {\n ...omitUndefined({ body }),\n method: request.method,\n headers: {\n \"content-type\": request.headers.get(\"content-type\") ?? \"application/json\",\n \"x-api-key\": env.apiKey,\n ...(traceparent ? { traceparent } : {}),\n ...geoHeaders(request),\n },\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!upstream.ok) {\n const text = await upstream.text().catch(() => \"\");\n\n if (upstream.status >= 500) {\n log.error(\n `Upstream ${upstream.status} for ${request.method} ${subPath}`,\n [text]\n );\n return Response.json(\n { code: \"INTERFERE_UPSTREAM_ERROR\", message: text },\n { status: upstream.status }\n );\n }\n if (upstream.status >= 400) {\n log.warn(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [\n text,\n ]);\n return Response.json(\n { code: \"INTERFERE_UPSTREAM_WARNING\", message: text },\n { status: upstream.status }\n );\n }\n\n log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [\n text,\n ]);\n return Response.json(\n { code: \"INTERFERE_UPSTREAM_ERROR\", message: text },\n { status: upstream.status }\n );\n }\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: {\n \"content-type\":\n upstream.headers.get(\"content-type\") ?? \"application/json\",\n },\n });\n}\n"],"mappings":";;;;;AAMA,MAAM,qBAAqB;AAE3B,SAAS,WAAW,SAA0C;CAC5D,MAAM,UAAU,qBAAqB,QAAQ;AAC7C,QAAO,UAAU,EAAE,kBAAkB,SAAS,GAAG,EAAE;;AASrD,SAAgB,0BAAmD;CACjE,MAAM,MAAM,kBAAkB;AAC9B,KAAI,IAAI,WAAW,KACjB,QAAO;AAET,QAAO;EAAE,QAAQ,IAAI;EAAQ,QAAQ,IAAI;EAAQ,SAAS,IAAI;EAAS;;AAGzE,SAAgB,eAAe,SAA0B;AAGvD,QADc,IADE,IAAI,QAAQ,IACX,CAAC,SAAS,MAAM,mBACrB,GAAG,MAAM;;AAGvB,SAAgB,wBAAkC;AAChD,KAAI,KAAK,kBAAkB,CACzB,iEACD,CAAC;AACF,QAAO,SAAS,KACd;EACE,MAAM;EACN,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;;AAGH,SAAgB,iBAAiB,OAG/B;AACA,KAAI,EAAE,iBAAiB,OACrB,QAAO;EAAE,SAAS,OAAO,MAAM;EAAE,OAAO,CAAC,OAAO,MAAM,CAAC;EAAE;CAG3D,MAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,IAAI,MAAM,UAAU;AAEjD,KAAI,WAAW,SAAS,MAAM,OAAO;EACnC,MAAM,QACJ,MAAM,iBAAiB,QAAQ,MAAM,MAAM,UAAU,OAAO,MAAM,MAAM;AAC1E,QAAM,KAAK,UAAU,QAAQ;;AAG/B,KACE,UAAU,SACV,OAAQ,MAAgC,SAAS,SAEjD,OAAM,KAAK,SAAU,MAAgC,OAAO;AAG9D,QAAO;EAAE,SAAS,GAAG,MAAM,KAAK,IAAI,MAAM;EAAW;EAAO;;AAG9D,eAAsB,mBACpB,SACA,KACA,SACmB;CACnB,MAAM,MAAM,GAAG,IAAI,SAAS;CAC5B,MAAM,cAAc,QAAQ,QAAQ,IAAI,cAAc;CAEtD,MAAM,OADU,QAAQ,WAAW,SAAS,QAAQ,WAAW,SACxC,MAAM,QAAQ,MAAM,GAAG,KAAA;CAE9C,MAAM,WAAW,MAAM,MAAM,KAAK;EAChC,GAAG,cAAc,EAAE,MAAM,CAAC;EAC1B,QAAQ,QAAQ;EAChB,SAAS;GACP,gBAAgB,QAAQ,QAAQ,IAAI,eAAe,IAAI;GACvD,aAAa,IAAI;GACjB,GAAI,cAAc,EAAE,aAAa,GAAG,EAAE;GACtC,GAAG,WAAW,QAAQ;GACvB;EACD,QAAQ,YAAY,QAAQ,IAAO;EACpC,CAAC;AAEF,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,YAAY,GAAG;AAElD,MAAI,SAAS,UAAU,KAAK;AAC1B,OAAI,MACF,YAAY,SAAS,OAAO,OAAO,QAAQ,OAAO,GAAG,WACrD,CAAC,KAAK,CACP;AACD,UAAO,SAAS,KACd;IAAE,MAAM;IAA4B,SAAS;IAAM,EACnD,EAAE,QAAQ,SAAS,QAAQ,CAC5B;;AAEH,MAAI,SAAS,UAAU,KAAK;AAC1B,OAAI,KAAK,YAAY,SAAS,OAAO,OAAO,QAAQ,OAAO,GAAG,WAAW,CACvE,KACD,CAAC;AACF,UAAO,SAAS,KACd;IAAE,MAAM;IAA8B,SAAS;IAAM,EACrD,EAAE,QAAQ,SAAS,QAAQ,CAC5B;;AAGH,MAAI,MAAM,YAAY,SAAS,OAAO,OAAO,QAAQ,OAAO,GAAG,WAAW,CACxE,KACD,CAAC;AACF,SAAO,SAAS,KACd;GAAE,MAAM;GAA4B,SAAS;GAAM,EACnD,EAAE,QAAQ,SAAS,QAAQ,CAC5B;;AAGH,QAAO,IAAI,SAAS,SAAS,MAAM;EACjC,QAAQ,SAAS;EACjB,SAAS,EACP,gBACE,SAAS,QAAQ,IAAI,eAAe,IAAI,oBAC3C;EACF,CAAC"}
1
+ {"version":3,"file":"proxy.mjs","names":[],"sources":["../../../src/internal/route/proxy.ts"],"sourcesContent":["import { resolveRoutePrefix } from \"@interfere/constants/route-prefix\";\nimport { omitUndefined } from \"@interfere/helpers/omit-undefined\";\nimport { extractCountryHeader } from \"@interfere/types/sdk/geo\";\n\nimport { type InterfereEnv, readInterfereEnv } from \"../env.js\";\nimport { log } from \"../logger.js\";\n\n// Never forward customer API keys from browser-originated ingestion requests.\nconst STRIPPED_AUTH_HEADERS = [\n \"authorization\",\n \"x-api-key\",\n \"x-interfere-api-key\",\n] as const;\n\n// Headers tied to the *inbound* HTTP transaction. These must not leak onto\n// the *outbound* `fetch` because the runtime computes them fresh for the new\n// body / connection, and forwarding them stale either silently corrupts the\n// request or hangs it until a timeout fires.\n//\n// Specifically `content-length`: `handleIngest` parses the incoming JSON,\n// injects build/release metadata, then re-`JSON.stringify`s the result. The\n// new body almost always has a different byte length to the original, so\n// forwarding the inbound `content-length` makes undici stall writing the\n// body until our 10s `AbortSignal.timeout` fires with\n// `Request body length does not match content-length header`. This was the\n// 2026-05-01 prod symptom (Vercel proxy 502s on `POST /v1/ingest` from\n// dashboard + homepage).\n//\n// `host` would route the upstream fetch back at the proxy hostname. fetch\n// sets it correctly from the URL automatically.\n//\n// The remainder are RFC 7230 §6.1 hop-by-hop headers — meaningful only on\n// the connection that received them. There's no canonical stdlib list for\n// any of this; every proxy in the Node ecosystem hand-rolls the same set\n// (`http-proxy`, Cloudflare Workers docs, Hono, undici's ProxyAgent, …).\nconst STRIPPED_TRANSPORT_HEADERS = [\n \"host\",\n \"content-length\",\n \"connection\",\n \"keep-alive\",\n \"transfer-encoding\",\n \"te\",\n \"trailer\",\n \"upgrade\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n] as const;\n\n/**\n * Clone the inbound request's headers, removing entries that should never\n * cross the proxy boundary. Returns a mutable `Headers` so callers can\n * `.set()`/`.delete()` upstream-specific values without having to merge\n * record literals (which lose case-insensitivity and create the precedence\n * footguns that masked the 2026-05-01 incident in code review).\n */\nexport function forwardedHeaders(request: Request): Headers {\n const headers = new Headers(request.headers);\n for (const name of STRIPPED_AUTH_HEADERS) {\n headers.delete(name);\n }\n for (const name of STRIPPED_TRANSPORT_HEADERS) {\n headers.delete(name);\n }\n return headers;\n}\n\nexport interface AuthenticatedEnv {\n apiUrl: string;\n publicKey: string | null;\n release: InterfereEnv[\"release\"];\n}\n\nexport function resolveAuthenticatedEnv(): AuthenticatedEnv {\n const env = readInterfereEnv();\n return {\n apiUrl: env.apiUrl,\n publicKey: env.publicKey,\n release: env.release,\n };\n}\n\n/** True when the proxy can attach a publishable key from env or the request. */\nexport function hasPublicKeyCredential(\n request: Request,\n envPublicKey: string | null\n): boolean {\n if (envPublicKey) {\n return true;\n }\n return new URL(request.url).searchParams.has(\"pk\");\n}\n\nexport function notConfiguredResponse(): Response {\n log.warn(\"Not configured\", [\n \"INTERFERE_PUBLIC_KEY is not set and the request has no ?pk= query param. The proxy route will return 503.\",\n ]);\n return Response.json(\n {\n code: \"INTERFERE_NOT_CONFIGURED\",\n message: \"INTERFERE_PUBLIC_KEY is required.\",\n },\n { status: 503 }\n );\n}\n\nexport function extractSubPath(request: Request): string {\n const prefix = resolveRoutePrefix();\n const url = new URL(request.url);\n const idx = url.pathname.indexOf(prefix);\n if (idx === -1) {\n return \"/\";\n }\n const remainder = url.pathname.slice(idx + prefix.length);\n if (remainder === \"\") {\n return \"/\";\n }\n return remainder.startsWith(\"/\") ? remainder : `/${remainder}`;\n}\n\n/**\n * Preserve any query string verbatim when forwarding upstream.\n *\n * The browser SDK uses `?_pv=…` and `?pk=…` (and `?_pt=…` in direct-ingestion\n * mode) as a `navigator.sendBeacon` fallback when `visibilitychange→\n * hidden` aborts the keepalive fetch path. The collector's\n * `otlpProducerGuard` and `surfacePkAuth` accept those values verbatim\n * — but only if the proxy actually forwards them. Passing\n * `request.url`'s `search` through (`\"\"` when absent, leading `?`\n * when present) keeps the rewrite transparent.\n */\nexport function extractSearch(request: Request): string {\n return new URL(request.url).search;\n}\n\nexport function formatProxyError(error: unknown): {\n message: string;\n lines: string[];\n} {\n if (!(error instanceof Error)) {\n return { message: String(error), lines: [String(error)] };\n }\n\n const lines = [`${error.name}: ${error.message}`];\n\n if (\"cause\" in error && error.cause) {\n const cause =\n error.cause instanceof Error ? error.cause.message : String(error.cause);\n lines.push(`cause: ${cause}`);\n }\n\n if (\n \"code\" in error &&\n typeof (error as NodeJS.ErrnoException).code === \"string\"\n ) {\n lines.push(`code: ${(error as NodeJS.ErrnoException).code}`);\n }\n\n return { message: `${error.name}: ${error.message}`, lines };\n}\n\n/**\n * Append `?pk=` to the outbound URL from the server env. Proxy mode\n * means the browser never sees `INTERFERE_PUBLIC_KEY` (it's not\n * `NEXT_PUBLIC_`-exposed), so the proxy is the only place the\n * credential can attach to the request. Preserves any existing query\n * params (e.g. `_pv=` debug flag). If the inbound request already\n * carries `?pk=`, that value wins — a misconfigured server-env pk\n * shouldn't clobber an explicit one from the SDK.\n */\nfunction buildUpstreamUrl(\n apiUrl: string,\n subPath: string,\n request: Request,\n publicKey: string | null\n): string {\n const incoming = new URL(request.url);\n const upstream = new URL(`${apiUrl}${subPath}`);\n\n for (const [key, value] of incoming.searchParams) {\n upstream.searchParams.append(key, value);\n }\n\n if (publicKey && !upstream.searchParams.has(\"pk\")) {\n upstream.searchParams.set(\"pk\", publicKey);\n }\n\n return upstream.toString();\n}\n\nexport async function forwardToCollector(\n request: Request,\n env: AuthenticatedEnv,\n subPath: string\n): Promise<Response> {\n const url = buildUpstreamUrl(env.apiUrl, subPath, request, env.publicKey);\n const hasBody = request.method !== \"GET\" && request.method !== \"HEAD\";\n const body = hasBody ? await request.text() : undefined;\n\n const headers = forwardedHeaders(request);\n // Default to JSON only when the inbound request didn't pin a content-type\n // — non-`/v1/ingest` paths relay the body bytes verbatim, so honour\n // whatever the caller said it was sending.\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n const country = extractCountryHeader(request);\n if (country !== null) {\n headers.set(\"x-country-code\", country);\n }\n\n const upstream = await fetch(url, {\n ...omitUndefined({ body }),\n method: request.method,\n headers,\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!upstream.ok) {\n const text = await upstream.text().catch(() => \"\");\n\n if (upstream.status >= 500) {\n log.error(\n `Upstream ${upstream.status} for ${request.method} ${subPath}`,\n [text]\n );\n return Response.json(\n { code: \"INTERFERE_UPSTREAM_ERROR\", message: text },\n { status: upstream.status }\n );\n }\n if (upstream.status >= 400) {\n log.warn(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [\n text,\n ]);\n return Response.json(\n { code: \"INTERFERE_UPSTREAM_WARNING\", message: text },\n { status: upstream.status }\n );\n }\n\n log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [\n text,\n ]);\n return Response.json(\n { code: \"INTERFERE_UPSTREAM_ERROR\", message: text },\n { status: upstream.status }\n );\n }\n\n return new Response(upstream.body, {\n status: upstream.status,\n headers: {\n \"content-type\":\n upstream.headers.get(\"content-type\") ?? \"application/json\",\n },\n });\n}\n"],"mappings":"kQAQA,MAAM,sBAAwB,CAC5B,gBACA,YACA,qBACF,EAuBM,2BAA6B,CACjC,OACA,iBACA,aACA,aACA,oBACA,KACA,UACA,UACA,qBACA,qBACF,EASA,SAAgB,iBAAiB,QAA2B,CAC1D,IAAM,QAAU,IAAI,QAAQ,QAAQ,OAAO,EAC3C,IAAK,IAAM,QAAQ,sBACjB,QAAQ,OAAO,IAAI,EAErB,IAAK,IAAM,QAAQ,2BACjB,QAAQ,OAAO,IAAI,EAErB,OAAO,OACT,CAQA,SAAgB,yBAA4C,CAC1D,IAAM,IAAM,iBAAiB,EAC7B,MAAO,CACL,OAAQ,IAAI,OACZ,UAAW,IAAI,UACf,QAAS,IAAI,OACf,CACF,CAGA,SAAgB,uBACd,QACA,aACS,CAIT,OAHI,aACK,GAEF,IAAI,IAAI,QAAQ,GAAG,EAAE,aAAa,IAAI,IAAI,CACnD,CAEA,SAAgB,uBAAkC,CAIhD,OAHA,IAAI,KAAK,iBAAkB,CACzB,2GACF,CAAC,EACM,SAAS,KACd,CACE,KAAM,2BACN,QAAS,mCACX,EACA,CAAE,OAAQ,GAAI,CAChB,CACF,CAEA,SAAgB,eAAe,QAA0B,CACvD,IAAM,OAAS,mBAAmB,EAC5B,IAAM,IAAI,IAAI,QAAQ,GAAG,EACzB,IAAM,IAAI,SAAS,QAAQ,MAAM,EACvC,GAAI,MAAQ,GACV,MAAO,IAET,IAAM,UAAY,IAAI,SAAS,MAAM,IAAM,OAAO,MAAM,EAIxD,OAHI,YAAc,GACT,IAEF,UAAU,WAAW,GAAG,EAAI,UAAY,IAAI,WACrD,CAaA,SAAgB,cAAc,QAA0B,CACtD,OAAO,IAAI,IAAI,QAAQ,GAAG,EAAE,MAC9B,CAEA,SAAgB,iBAAiB,MAG/B,CACA,GAAI,EAAE,iBAAiB,OACrB,MAAO,CAAE,QAAS,OAAO,KAAK,EAAG,MAAO,CAAC,OAAO,KAAK,CAAC,CAAE,EAG1D,IAAM,MAAQ,CAAC,GAAG,MAAM,KAAK,IAAI,MAAM,SAAS,EAEhD,GAAI,UAAW,OAAS,MAAM,MAAO,CACnC,IAAM,MACJ,MAAM,iBAAiB,MAAQ,MAAM,MAAM,QAAU,OAAO,MAAM,KAAK,EACzE,MAAM,KAAK,UAAU,OAAO,CAC9B,CASA,MANE,SAAU,OACV,OAAQ,MAAgC,MAAS,UAEjD,MAAM,KAAK,SAAU,MAAgC,MAAM,EAGtD,CAAE,QAAS,GAAG,MAAM,KAAK,IAAI,MAAM,UAAW,KAAM,CAC7D,CAWA,SAAS,iBACP,OACA,QACA,QACA,UACQ,CACR,IAAM,SAAW,IAAI,IAAI,QAAQ,GAAG,EAC9B,SAAW,IAAI,IAAI,GAAG,SAAS,SAAS,EAE9C,IAAK,GAAM,CAAC,IAAK,SAAU,SAAS,aAClC,SAAS,aAAa,OAAO,IAAK,KAAK,EAOzC,OAJI,WAAa,CAAC,SAAS,aAAa,IAAI,IAAI,GAC9C,SAAS,aAAa,IAAI,KAAM,SAAS,EAGpC,SAAS,SAAS,CAC3B,CAEA,eAAsB,mBACpB,QACA,IACA,QACmB,CACnB,IAAM,IAAM,iBAAiB,IAAI,OAAQ,QAAS,QAAS,IAAI,SAAS,EAElE,KADU,QAAQ,SAAW,OAAS,QAAQ,SAAW,OACxC,MAAM,QAAQ,KAAK,EAAI,IAAA,GAExC,QAAU,iBAAiB,OAAO,EAInC,QAAQ,IAAI,cAAc,GAC7B,QAAQ,IAAI,eAAgB,kBAAkB,EAEhD,IAAM,QAAU,qBAAqB,OAAO,EACxC,UAAY,MACd,QAAQ,IAAI,iBAAkB,OAAO,EAGvC,IAAM,SAAW,MAAM,MAAM,IAAK,CAChC,GAAG,cAAc,CAAE,IAAK,CAAC,EACzB,OAAQ,QAAQ,OAChB,QACA,OAAQ,YAAY,QAAQ,GAAM,CACpC,CAAC,EAED,GAAI,CAAC,SAAS,GAAI,CAChB,IAAM,KAAO,MAAM,SAAS,KAAK,EAAE,UAAY,EAAE,EAyBjD,OAvBI,SAAS,QAAU,KACrB,IAAI,MACF,YAAY,SAAS,OAAO,OAAO,QAAQ,OAAO,GAAG,UACrD,CAAC,IAAI,CACP,EACO,SAAS,KACd,CAAE,KAAM,2BAA4B,QAAS,IAAK,EAClD,CAAE,OAAQ,SAAS,MAAO,CAC5B,GAEE,SAAS,QAAU,KACrB,IAAI,KAAK,YAAY,SAAS,OAAO,OAAO,QAAQ,OAAO,GAAG,UAAW,CACvE,IACF,CAAC,EACM,SAAS,KACd,CAAE,KAAM,6BAA8B,QAAS,IAAK,EACpD,CAAE,OAAQ,SAAS,MAAO,CAC5B,IAGF,IAAI,MAAM,YAAY,SAAS,OAAO,OAAO,QAAQ,OAAO,GAAG,UAAW,CACxE,IACF,CAAC,EACM,SAAS,KACd,CAAE,KAAM,2BAA4B,QAAS,IAAK,EAClD,CAAE,OAAQ,SAAS,MAAO,CAC5B,EACF,CAEA,OAAO,IAAI,SAAS,SAAS,KAAM,CACjC,OAAQ,SAAS,OACjB,QAAS,CACP,eACE,SAAS,QAAQ,IAAI,cAAc,GAAK,kBAC5C,CACF,CAAC,CACH"}
@@ -1,9 +1,9 @@
1
1
  import { CaptureErrorContext, OnRequestErrorContext } from "./types.mjs";
2
2
 
3
3
  //#region src/internal/server/capture.d.ts
4
- declare function captureError(error: unknown, request?: unknown, context?: CaptureErrorContext): Promise<void>;
4
+ declare function captureError(error: unknown, _request?: unknown, context?: CaptureErrorContext): void;
5
5
  declare function onRequestError(error: Error & {
6
6
  digest?: string;
7
- }, request: unknown, context: OnRequestErrorContext): Promise<void>;
7
+ }, _request: unknown, context: OnRequestErrorContext): void;
8
8
  //#endregion
9
9
  export { captureError, onRequestError };
@@ -1 +1 @@
1
- {"version":3,"file":"capture.d.mts","names":[],"sources":["../../../src/internal/server/capture.ts"],"mappings":";;;iBAwBsB,YAAA,CACpB,KAAA,WACA,OAAA,YACA,OAAA,GAAU,mBAAA,GACT,OAAA;AAAA,iBAoCmB,cAAA,CACpB,KAAA,EAAO,KAAA;EAAU,MAAA;AAAA,GACjB,OAAA,WACA,OAAA,EAAS,qBAAA,GACR,OAAA"}
1
+ {"version":3,"file":"capture.d.mts","names":[],"sources":["../../../src/internal/server/capture.ts"],"mappings":";;;iBA+GgB,YAAA,CACd,KAAA,WACA,QAAA,YACA,OAAA,GAAU,mBAAmB;AAAA,iBAwBf,cAAA,CACd,KAAA,EAAO,KAAA;EAAU,MAAA;AAAA,GACjB,QAAA,WACA,OAAA,EAAS,qBAAqB"}