@interfere/next 1.0.0 → 1.0.2

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 (95) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +13 -0
  2. package/dist/config.d.mts +11 -0
  3. package/dist/config.d.mts.map +1 -0
  4. package/dist/config.mjs +115 -0
  5. package/dist/config.mjs.map +1 -0
  6. package/dist/instrument-client.d.mts +3 -0
  7. package/dist/instrument-client.mjs +2 -0
  8. package/dist/internal/build/configure-build.d.mts +25 -0
  9. package/dist/internal/build/configure-build.d.mts.map +1 -0
  10. package/dist/internal/build/configure-build.mjs +87 -0
  11. package/dist/internal/build/configure-build.mjs.map +1 -0
  12. package/dist/internal/build/release/destinations/vercel.d.mts +6 -0
  13. package/dist/internal/build/release/destinations/vercel.d.mts.map +1 -0
  14. package/dist/internal/build/release/destinations/vercel.mjs +25 -0
  15. package/dist/internal/build/release/destinations/vercel.mjs.map +1 -0
  16. package/dist/internal/build/release/git.d.mts +4 -0
  17. package/dist/internal/build/release/git.d.mts.map +1 -0
  18. package/dist/internal/build/release/git.mjs +21 -0
  19. package/dist/internal/build/release/git.mjs.map +1 -0
  20. package/dist/internal/build/release/index.d.mts +7 -0
  21. package/dist/internal/build/release/index.d.mts.map +1 -0
  22. package/dist/internal/build/release/index.mjs +24 -0
  23. package/dist/internal/build/release/index.mjs.map +1 -0
  24. package/dist/internal/build/release/sources/github.d.mts +6 -0
  25. package/dist/internal/build/release/sources/github.d.mts.map +1 -0
  26. package/dist/internal/build/release/sources/github.mjs +15 -0
  27. package/dist/internal/build/release/sources/github.mjs.map +1 -0
  28. package/dist/internal/build/source-maps/discover.d.mts +15 -0
  29. package/dist/internal/build/source-maps/discover.d.mts.map +1 -0
  30. package/dist/internal/build/source-maps/discover.mjs +62 -0
  31. package/dist/internal/build/source-maps/discover.mjs.map +1 -0
  32. package/dist/internal/build/source-maps/index.d.mts +23 -0
  33. package/dist/internal/build/source-maps/index.d.mts.map +1 -0
  34. package/dist/internal/build/source-maps/index.mjs +34 -0
  35. package/dist/internal/build/source-maps/index.mjs.map +1 -0
  36. package/dist/internal/build/value-injection-loader.d.mts +13 -0
  37. package/dist/internal/build/value-injection-loader.d.mts.map +1 -0
  38. package/dist/internal/build/value-injection-loader.mjs +24 -0
  39. package/dist/internal/build/value-injection-loader.mjs.map +1 -0
  40. package/dist/internal/env.d.mts +16 -0
  41. package/dist/internal/env.d.mts.map +1 -0
  42. package/dist/internal/env.mjs +19 -0
  43. package/dist/internal/env.mjs.map +1 -0
  44. package/dist/internal/logger.d.mts +8 -0
  45. package/dist/internal/logger.d.mts.map +1 -0
  46. package/dist/internal/logger.mjs +44 -0
  47. package/dist/internal/logger.mjs.map +1 -0
  48. package/dist/internal/route/handle-get.d.mts +4 -0
  49. package/dist/internal/route/handle-get.d.mts.map +1 -0
  50. package/dist/internal/route/handle-get.mjs +15 -0
  51. package/dist/internal/route/handle-get.mjs.map +1 -0
  52. package/dist/internal/route/handle-post.d.mts +4 -0
  53. package/dist/internal/route/handle-post.d.mts.map +1 -0
  54. package/dist/internal/route/handle-post.mjs +105 -0
  55. package/dist/internal/route/handle-post.mjs.map +1 -0
  56. package/dist/internal/route/sw-script.d.mts +4 -0
  57. package/dist/internal/route/sw-script.d.mts.map +1 -0
  58. package/dist/internal/route/sw-script.mjs +38 -0
  59. package/dist/internal/route/sw-script.mjs.map +1 -0
  60. package/dist/internal/server/capture.d.mts +9 -0
  61. package/dist/internal/server/capture.d.mts.map +1 -0
  62. package/dist/internal/server/capture.mjs +50 -0
  63. package/dist/internal/server/capture.mjs.map +1 -0
  64. package/dist/internal/server/dedupe.d.mts +5 -0
  65. package/dist/internal/server/dedupe.d.mts.map +1 -0
  66. package/dist/internal/server/dedupe.mjs +11 -0
  67. package/dist/internal/server/dedupe.mjs.map +1 -0
  68. package/dist/internal/server/envelope.d.mts +14 -0
  69. package/dist/internal/server/envelope.d.mts.map +1 -0
  70. package/dist/internal/server/envelope.mjs +55 -0
  71. package/dist/internal/server/envelope.mjs.map +1 -0
  72. package/dist/internal/server/normalize-request.d.mts +7 -0
  73. package/dist/internal/server/normalize-request.d.mts.map +1 -0
  74. package/dist/internal/server/normalize-request.mjs +50 -0
  75. package/dist/internal/server/normalize-request.mjs.map +1 -0
  76. package/dist/internal/server/runtime.d.mts +14 -0
  77. package/dist/internal/server/runtime.d.mts.map +1 -0
  78. package/dist/internal/server/runtime.mjs +18 -0
  79. package/dist/internal/server/runtime.mjs.map +1 -0
  80. package/dist/internal/server/transport.d.mts +12 -0
  81. package/dist/internal/server/transport.d.mts.map +1 -0
  82. package/dist/internal/server/transport.mjs +17 -0
  83. package/dist/internal/server/transport.mjs.map +1 -0
  84. package/dist/internal/server/types.d.mts +17 -0
  85. package/dist/internal/server/types.d.mts.map +1 -0
  86. package/dist/internal/server/types.mjs +1 -0
  87. package/dist/provider.d.mts +3 -0
  88. package/dist/provider.mjs +3 -0
  89. package/dist/route-handler.d.mts +7 -0
  90. package/dist/route-handler.d.mts.map +1 -0
  91. package/dist/route-handler.mjs +26 -0
  92. package/dist/route-handler.mjs.map +1 -0
  93. package/dist/server.d.mts +3 -0
  94. package/dist/server.mjs +2 -0
  95. package/package.json +27 -27
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"sourcesContent":["import { unlink } from \"node:fs/promises\";\n\nimport { discover, normalizeDistDir } from \"./discover.js\";\n\nexport interface BuildClient {\n createRelease(): Promise<{ slug: string; orgSlug: string; buildId: string }>;\n uploadSourceMaps(releaseSlug: string, body: FormData): Promise<void>;\n}\n\nexport type PipelineResult =\n | { ready: false; reason: \"no_source_maps\"; fileCount: 0 }\n | { ready: true; fileCount: number; releaseSlug: string; orgSlug: string; buildId: string };\n\nexport async function runSourceMapPipeline(\n projectDir: string,\n distDir: string | undefined,\n client: BuildClient,\n cleanup = true,\n): Promise<PipelineResult> {\n const { files, mapping, sourceFileCount } = await discover(projectDir, normalizeDistDir(distDir));\n\n if (files.length === 0) {\n return { ready: false, reason: \"no_source_maps\", fileCount: 0 };\n }\n\n const { slug, orgSlug, buildId } = await client.createRelease();\n\n const body = new FormData();\n const hashes: Record<string, string> = {};\n\n for (const file of files) {\n body.append(\"files\", new Blob([file.content], { type: \"application/json\" }), file.path);\n hashes[file.path] = file.hash;\n }\n\n body.append(\"metadata\", JSON.stringify({ sourceMapToGenerated: mapping, hashes, sourceFileCount }));\n\n await client.uploadSourceMaps(slug, body);\n\n if (cleanup) {\n await Promise.all(files.map((f) => unlink(f.absolute).catch(() => undefined)));\n }\n\n return { ready: true, fileCount: files.length, releaseSlug: slug, orgSlug, buildId };\n}\n"],"mappings":";;;AAaA,eAAsB,qBACpB,YACA,SACA,QACA,UAAU,MACe;CACzB,MAAM,EAAE,OAAO,SAAS,oBAAoB,MAAM,SAAS,YAAY,iBAAiB,QAAQ,CAAC;AAEjG,KAAI,MAAM,WAAW,EACnB,QAAO;EAAE,OAAO;EAAO,QAAQ;EAAkB,WAAW;EAAG;CAGjE,MAAM,EAAE,MAAM,SAAS,YAAY,MAAM,OAAO,eAAe;CAE/D,MAAM,OAAO,IAAI,UAAU;CAC3B,MAAM,SAAiC,EAAE;AAEzC,MAAK,MAAM,QAAQ,OAAO;AACxB,OAAK,OAAO,SAAS,IAAI,KAAK,CAAC,KAAK,QAAQ,EAAE,EAAE,MAAM,oBAAoB,CAAC,EAAE,KAAK,KAAK;AACvF,SAAO,KAAK,QAAQ,KAAK;;AAG3B,MAAK,OAAO,YAAY,KAAK,UAAU;EAAE,sBAAsB;EAAS;EAAQ;EAAiB,CAAC,CAAC;AAEnG,OAAM,OAAO,iBAAiB,MAAM,KAAK;AAEzC,KAAI,QACF,OAAM,QAAQ,IAAI,MAAM,KAAK,MAAM,OAAO,EAAE,SAAS,CAAC,YAAY,KAAA,EAAU,CAAC,CAAC;AAGhF,QAAO;EAAE,OAAO;EAAM,WAAW,MAAM;EAAQ,aAAa;EAAM;EAAS;EAAS"}
@@ -0,0 +1,13 @@
1
+ import { InterfereInjectedValues } from "./configure-build.mjs";
2
+
3
+ //#region src/internal/build/value-injection-loader.d.ts
4
+ interface ValueInjectionLoaderOptions {
5
+ readonly values?: Partial<InterfereInjectedValues>;
6
+ readonly serializedValues?: string;
7
+ }
8
+ interface LoaderThis<T> {
9
+ getOptions(): T;
10
+ }
11
+ declare function valueInjectionLoader(this: LoaderThis<ValueInjectionLoaderOptions>, userCode: string): string;
12
+ //#endregion
13
+ export { ValueInjectionLoaderOptions, valueInjectionLoader as default };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-injection-loader.d.mts","names":[],"sources":["../../../src/internal/build/value-injection-loader.ts"],"mappings":";;;UAEiB,2BAAA;EAAA,SACN,MAAA,GAAS,OAAA,CAAQ,uBAAA;EAAA,SACjB,gBAAA;AAAA;AAAA,UAGD,UAAA;EACR,UAAA,IAAc,CAAA;AAAA;AAAA,iBAGQ,oBAAA,CACtB,IAAA,EAAM,UAAA,CAAW,2BAAA,GACjB,QAAA"}
@@ -0,0 +1,24 @@
1
+ //#region src/internal/build/value-injection-loader.ts
2
+ function valueInjectionLoader(userCode) {
3
+ const values = resolveValues(this.getOptions());
4
+ const lines = Object.entries(values).filter(([, value]) => value !== void 0).map(([key, value]) => {
5
+ return `globalThis["${key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"] = ${JSON.stringify(value)};`;
6
+ });
7
+ if (lines.length === 0) return userCode;
8
+ return `${lines.join("\n")}\n${userCode}`;
9
+ }
10
+ function resolveValues(options) {
11
+ if (typeof options.serializedValues === "string") try {
12
+ const parsed = JSON.parse(options.serializedValues);
13
+ if (isRecord(parsed)) return parsed;
14
+ return {};
15
+ } catch {
16
+ return {};
17
+ }
18
+ return options.values ?? {};
19
+ }
20
+ function isRecord(value) {
21
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22
+ }
23
+ //#endregion
24
+ export { valueInjectionLoader as default };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-injection-loader.mjs","names":[],"sources":["../../../src/internal/build/value-injection-loader.ts"],"sourcesContent":["import type { InterfereInjectedValues } from \"./configure-build.js\";\n\nexport interface ValueInjectionLoaderOptions {\n readonly values?: Partial<InterfereInjectedValues>;\n readonly serializedValues?: string;\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(options: ValueInjectionLoaderOptions): Record<string, unknown> {\n if (typeof options.serializedValues === \"string\") {\n try {\n const parsed = JSON.parse(options.serializedValues);\n if (isRecord(parsed)) {\n return parsed;\n }\n return {};\n } catch {\n return {};\n }\n }\n\n return options.values ?? {};\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":";AAWA,SAAwB,qBAEtB,UACQ;CACR,MAAM,SAAS,cAAc,KAAK,YAAY,CAAC;CAC/C,MAAM,QAAQ,OAAO,QAAQ,OAAO,CACjC,QAAQ,GAAG,WAAW,UAAU,KAAA,EAAU,CAC1C,KAAK,CAAC,KAAK,WAAW;AAErB,SAAO,eADY,IAAI,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,OAAM,CACjC,OAAO,KAAK,UAAU,MAAM,CAAC;GAC9D;AAEJ,KAAI,MAAM,WAAW,EACnB,QAAO;AAGT,QAAO,GAAG,MAAM,KAAK,KAAK,CAAC,IAAI;;AAGjC,SAAS,cAAc,SAA+D;AACpF,KAAI,OAAO,QAAQ,qBAAqB,SACtC,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,QAAQ,iBAAiB;AACnD,MAAI,SAAS,OAAO,CAClB,QAAO;AAET,SAAO,EAAE;SACH;AACN,SAAO,EAAE;;AAIb,QAAO,QAAQ,UAAU,EAAE;;AAG7B,SAAS,SAAS,OAAkD;AAClE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM"}
@@ -0,0 +1,16 @@
1
+ import { Env } from "@interfere/types/sdk/runtime";
2
+
3
+ //#region src/internal/env.d.ts
4
+ interface InterfereEnv {
5
+ readonly apiKey: string | null;
6
+ readonly apiUrl: string;
7
+ readonly nextRuntime: string | null;
8
+ readonly nodeEnvironment: Exclude<Env, null>;
9
+ readonly release: {
10
+ readonly sourceId: string | null;
11
+ readonly destinationId: string | null;
12
+ };
13
+ }
14
+ declare function readInterfereEnv(): InterfereEnv;
15
+ //#endregion
16
+ export { InterfereEnv, readInterfereEnv };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.mts","names":[],"sources":["../../src/internal/env.ts"],"mappings":";;;UAKiB,YAAA;EAAA,SACN,MAAA;EAAA,SACA,MAAA;EAAA,SACA,WAAA;EAAA,SACA,eAAA,EAAiB,OAAA,CAAQ,GAAA;EAAA,SACzB,OAAA;IAAA,SACE,QAAA;IAAA,SACA,aAAA;EAAA;AAAA;AAAA,iBAIG,gBAAA,CAAA,GAAoB,YAAA"}
@@ -0,0 +1,19 @@
1
+ import { API_URL } from "@interfere/constants/api";
2
+ import { parseEnvValue } from "@interfere/types/sdk/env";
3
+ import { normalizeEnv } from "@interfere/types/sdk/runtime";
4
+ //#region src/internal/env.ts
5
+ function readInterfereEnv() {
6
+ const nodeEnvironment = normalizeEnv(process.env.NODE_ENV) ?? "production";
7
+ return {
8
+ apiKey: parseEnvValue(process.env.INTERFERE_API_KEY),
9
+ apiUrl: parseEnvValue(process.env.INTERFERE_API_URL) ?? API_URL,
10
+ nextRuntime: parseEnvValue(process.env.NEXT_RUNTIME),
11
+ nodeEnvironment,
12
+ release: {
13
+ sourceId: parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_BUILD_ID),
14
+ destinationId: parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_RELEASE_ID)
15
+ }
16
+ };
17
+ }
18
+ //#endregion
19
+ export { readInterfereEnv };
@@ -0,0 +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 readInterfereEnv(): InterfereEnv {\n const nodeEnvironment = normalizeEnv(process.env.NODE_ENV) ?? \"production\";\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,mBAAiC;CAC/C,MAAM,kBAAkB,aAAa,QAAQ,IAAI,SAAS,IAAI;AAC9D,QAAO;EACL,QAAQ,cAAc,QAAQ,IAAI,kBAAkB;EACpD,QAAQ,cAAc,QAAQ,IAAI,kBAAkB,IAAI;EACxD,aAAa,cAAc,QAAQ,IAAI,aAAa;EACpD;EACA,SAAS;GACP,UAAU,cAAc,QAAQ,IAAI,+BAA+B;GACnE,eAAe,cACb,QAAQ,IAAI,iCACb;GACF;EACF"}
@@ -0,0 +1,8 @@
1
+ //#region src/internal/logger.d.ts
2
+ declare const log: {
3
+ info: (title: string, lines: string[]) => void;
4
+ warn: (title: string, lines: string[]) => void;
5
+ error: (title: string, lines: string[]) => void;
6
+ };
7
+ //#endregion
8
+ export { log };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.mts","names":[],"sources":["../../src/internal/logger.ts"],"mappings":";cA0Da,GAAA;wBACS,KAAA;wBACA,KAAA;yBACC,KAAA;AAAA"}
@@ -0,0 +1,44 @@
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
+ },
9
+ warn: {
10
+ prefix: `${chalk.yellow.bold("⚠")} `,
11
+ text: chalk.yellow.bold,
12
+ content: chalk.yellowBright
13
+ },
14
+ error: {
15
+ prefix: `${chalk.red.bold("⨯")} `,
16
+ text: chalk.red.bold,
17
+ content: chalk.redBright
18
+ }
19
+ };
20
+ const consoleMethods = {
21
+ info: "log",
22
+ warn: "warn",
23
+ error: "error"
24
+ };
25
+ function isTestEnv() {
26
+ return Boolean(process.env.VITEST || process.env.VITEST_WORKER_ID);
27
+ }
28
+ function emit(level, title, lines) {
29
+ if (isTestEnv()) return;
30
+ const style = styles[level];
31
+ const method = consoleMethods[level];
32
+ const fn = globalThis.console[method];
33
+ if (typeof fn !== "function") return;
34
+ const invoke = (...args) => Reflect.apply(fn, globalThis.console, args);
35
+ invoke(`${style.prefix} ${chalk.white("Interfere →")} ${style.text(title)}`);
36
+ for (const [i, line] of lines.entries()) invoke(`${i === lines.length - 1 ? "└" : "├"} ${style.content(line)}`);
37
+ }
38
+ const log = {
39
+ info: (title, lines) => emit("info", title, lines),
40
+ warn: (title, lines) => emit("warn", title, lines),
41
+ error: (title, lines) => emit("error", title, lines)
42
+ };
43
+ //#endregion
44
+ export { log };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.mjs","names":[],"sources":["../../src/internal/logger.ts"],"sourcesContent":["import chalk from \"chalk\";\n\ntype LogLevel = \"info\" | \"warn\" | \"error\";\n\nconst styles = {\n info: {\n prefix: `${chalk.whiteBright.bold(\"❖\")}`,\n text: chalk.cyan.bold,\n content: chalk.white,\n },\n warn: {\n prefix: `${chalk.yellow.bold(\"⚠\")} `,\n text: chalk.yellow.bold,\n content: chalk.yellowBright,\n },\n error: {\n prefix: `${chalk.red.bold(\"⨯\")} `,\n text: chalk.red.bold,\n content: chalk.redBright,\n },\n} satisfies Record<\n LogLevel,\n { prefix: string; text: typeof chalk.bold; content: typeof chalk }\n>;\n\nconst consoleMethods = {\n info: \"log\",\n warn: \"warn\",\n error: \"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 invoke(`${style.prefix} ${chalk.white(\"Interfere →\")} ${style.text(title)}`);\n\n for (const [i, line] of lines.entries()) {\n const connector = i === lines.length - 1 ? \"└\" : \"├\";\n invoke(`${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};\n"],"mappings":";;AAIA,MAAM,SAAS;CACb,MAAM;EACJ,QAAQ,GAAG,MAAM,YAAY,KAAK,IAAI;EACtC,MAAM,MAAM,KAAK;EACjB,SAAS,MAAM;EAChB;CACD,MAAM;EACJ,QAAQ,GAAG,MAAM,OAAO,KAAK,IAAI,CAAC;EAClC,MAAM,MAAM,OAAO;EACnB,SAAS,MAAM;EAChB;CACD,OAAO;EACL,QAAQ,GAAG,MAAM,IAAI,KAAK,IAAI,CAAC;EAC/B,MAAM,MAAM,IAAI;EAChB,SAAS,MAAM;EAChB;CACF;AAKD,MAAM,iBAAiB;CACrB,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,SAAS,YAAY;AACnB,QAAO,QAAQ,QAAQ,IAAI,UAAU,QAAQ,IAAI,iBAAiB;;AAGpE,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;AAE7C,QAAO,GAAG,MAAM,OAAO,GAAG,MAAM,MAAM,cAAc,CAAC,GAAG,MAAM,KAAK,MAAM,GAAG;AAE5E,MAAK,MAAM,CAAC,GAAG,SAAS,MAAM,SAAS,CAErC,QAAO,GADW,MAAM,MAAM,SAAS,IAAI,MAAM,IAC7B,GAAG,MAAM,QAAQ,KAAK,GAAG;;AAIjD,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;CACvE"}
@@ -0,0 +1,4 @@
1
+ //#region src/internal/route/handle-get.d.ts
2
+ declare function handleGet(request: Request): Response;
3
+ //#endregion
4
+ export { handleGet };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-get.d.mts","names":[],"sources":["../../../src/internal/route/handle-get.ts"],"mappings":";iBAEgB,SAAA,CAAU,OAAA,EAAS,OAAA,GAAU,QAAA"}
@@ -0,0 +1,15 @@
1
+ import { SW_SCRIPT } from "./sw-script.mjs";
2
+ //#region src/internal/route/handle-get.ts
3
+ function handleGet(request) {
4
+ if (!new URL(request.url).pathname.endsWith("/sw")) return new Response("Not Found", { status: 404 });
5
+ return new Response(SW_SCRIPT, {
6
+ status: 200,
7
+ headers: {
8
+ "content-type": "application/javascript",
9
+ "service-worker-allowed": "/",
10
+ "cache-control": "public, max-age=3600"
11
+ }
12
+ });
13
+ }
14
+ //#endregion
15
+ export { handleGet };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-get.mjs","names":[],"sources":["../../../src/internal/route/handle-get.ts"],"sourcesContent":["import { SW_SCRIPT } from \"./sw-script.js\";\n\nexport function handleGet(request: Request): Response {\n const pathname = new URL(request.url).pathname;\n if (!pathname.endsWith(\"/sw\")) {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n return new Response(SW_SCRIPT, {\n status: 200,\n headers: {\n \"content-type\": \"application/javascript\",\n \"service-worker-allowed\": \"/\",\n \"cache-control\": \"public, max-age=3600\",\n },\n });\n}\n"],"mappings":";;AAEA,SAAgB,UAAU,SAA4B;AAEpD,KAAI,CADa,IAAI,IAAI,QAAQ,IAAI,CAAC,SACxB,SAAS,MAAM,CAC3B,QAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,KAAK,CAAC;AAGnD,QAAO,IAAI,SAAS,WAAW;EAC7B,QAAQ;EACR,SAAS;GACP,gBAAgB;GAChB,0BAA0B;GAC1B,iBAAiB;GAClB;EACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ //#region src/internal/route/handle-post.d.ts
2
+ declare function handlePost(request: Request): Promise<Response>;
3
+ //#endregion
4
+ export { handlePost };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-post.d.mts","names":[],"sources":["../../../src/internal/route/handle-post.ts"],"mappings":";iBA2CsB,UAAA,CAAW,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,QAAA"}
@@ -0,0 +1,105 @@
1
+ import { log } from "../logger.mjs";
2
+ import { readInterfereEnv } from "../env.mjs";
3
+ import { API_PATHS } from "@interfere/constants/api";
4
+ //#region src/internal/route/handle-post.ts
5
+ function parseEnvelopes(value) {
6
+ if (!Array.isArray(value)) return null;
7
+ return value;
8
+ }
9
+ function injectReleaseMetadata(envelopes, metadata) {
10
+ if (metadata.sourceId === null && metadata.destinationId === null) return envelopes;
11
+ return envelopes.map((envelope) => ({
12
+ ...envelope,
13
+ buildId: metadata.sourceId ?? envelope.buildId,
14
+ releaseId: metadata.destinationId ?? envelope.releaseId
15
+ }));
16
+ }
17
+ const PROXY_PATH_PATTERN = /\/api\/interfere(\/.*)/;
18
+ function extractSubPath(request) {
19
+ return new URL(request.url).pathname.match(PROXY_PATH_PATTERN)?.[1] ?? "/";
20
+ }
21
+ async function handlePost(request) {
22
+ const env = readInterfereEnv();
23
+ if (env.apiKey === null) {
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
+ const authed = {
31
+ apiKey: env.apiKey,
32
+ apiUrl: env.apiUrl,
33
+ release: env.release
34
+ };
35
+ const subPath = extractSubPath(request);
36
+ try {
37
+ if (subPath === API_PATHS.INGEST) return await handleIngest(request, authed);
38
+ return await forwardToCollector(request, authed, subPath);
39
+ } catch (error) {
40
+ log.error(`Proxy ${request.method} ${subPath} failed`, [error instanceof Error ? error.message : String(error)]);
41
+ return Response.json({
42
+ code: "INTERFERE_PROXY_ERROR",
43
+ message: "Proxy request failed."
44
+ }, { status: 502 });
45
+ }
46
+ }
47
+ async function handleIngest(request, env) {
48
+ let payload;
49
+ try {
50
+ payload = await request.json();
51
+ } catch {
52
+ return Response.json({
53
+ code: "INTERFERE_INVALID_JSON",
54
+ message: "Request body must be valid JSON."
55
+ }, { status: 400 });
56
+ }
57
+ const envelopes = parseEnvelopes(payload);
58
+ if (envelopes === null) return Response.json({
59
+ code: "INTERFERE_INVALID_ENVELOPES",
60
+ message: "Request body must be an array of envelopes."
61
+ }, { status: 400 });
62
+ const traceparent = request.headers.get("traceparent");
63
+ const upstream = await fetch(`${env.apiUrl}${API_PATHS.INGEST}`, {
64
+ method: "POST",
65
+ headers: {
66
+ "content-type": "application/json",
67
+ "x-api-key": env.apiKey,
68
+ ...traceparent ? { traceparent } : {}
69
+ },
70
+ body: JSON.stringify(injectReleaseMetadata(envelopes, env.release)),
71
+ keepalive: true
72
+ });
73
+ return new Response(upstream.body, {
74
+ status: upstream.status,
75
+ headers: { "content-type": upstream.headers.get("content-type") ?? "application/json" }
76
+ });
77
+ }
78
+ async function forwardToCollector(request, env, subPath) {
79
+ const url = `${env.apiUrl}${subPath}`;
80
+ const traceparent = request.headers.get("traceparent");
81
+ const upstream = await fetch(url, {
82
+ method: request.method,
83
+ headers: {
84
+ "content-type": request.headers.get("content-type") ?? "application/json",
85
+ "x-api-key": env.apiKey,
86
+ ...traceparent ? { traceparent } : {}
87
+ },
88
+ body: request.body,
89
+ keepalive: true
90
+ });
91
+ if (!upstream.ok) {
92
+ const body = await upstream.text().catch(() => "");
93
+ log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [body]);
94
+ return Response.json({
95
+ code: "INTERFERE_UPSTREAM_ERROR",
96
+ message: body
97
+ }, { status: upstream.status });
98
+ }
99
+ return new Response(upstream.body, {
100
+ status: upstream.status,
101
+ headers: { "content-type": upstream.headers.get("content-type") ?? "application/json" }
102
+ });
103
+ }
104
+ //#endregion
105
+ export { handlePost };
@@ -0,0 +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\";\n\nimport { type InterfereEnv, readInterfereEnv } from \"../env.js\";\nimport { log } from \"../logger.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\nconst PROXY_PATH_PATTERN = /\\/api\\/interfere(\\/.*)/;\n\nfunction 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\ninterface AuthenticatedEnv {\n apiKey: string;\n apiUrl: string;\n release: InterfereEnv[\"release\"];\n}\n\nexport async function handlePost(request: Request): Promise<Response> {\n const env = readInterfereEnv();\n\n if (env.apiKey === null) {\n log.warn(\"Not configured\", [\n \"INTERFERE_API_KEY is not set. The proxy route will return 503.\",\n ]);\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\n const authed: AuthenticatedEnv = {\n apiKey: env.apiKey,\n apiUrl: env.apiUrl,\n release: env.release,\n };\n\n const subPath = extractSubPath(request);\n\n try {\n if (subPath === API_PATHS.INGEST) {\n return await handleIngest(request, authed);\n }\n\n return await forwardToCollector(request, authed, subPath);\n } catch (error) {\n log.error(`Proxy ${request.method} ${subPath} failed`, [\n error instanceof Error ? error.message : String(error),\n ]);\n return Response.json(\n { code: \"INTERFERE_PROXY_ERROR\", message: \"Proxy request failed.\" },\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 body: JSON.stringify(injectReleaseMetadata(envelopes, env.release)),\n keepalive: true,\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\nasync 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\n const upstream = await fetch(url, {\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 },\n body: request.body,\n keepalive: true,\n });\n\n if (!upstream.ok) {\n const body = await upstream.text().catch(() => \"\");\n log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [\n body,\n ]);\n return Response.json(\n { code: \"INTERFERE_UPSTREAM_ERROR\", message: body },\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":"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"}
@@ -0,0 +1,4 @@
1
+ //#region src/internal/route/sw-script.d.ts
2
+ declare const SW_SCRIPT = "importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.3.0/workbox-sw.js');\n\nself.addEventListener('install', function() { self.skipWaiting(); });\nself.addEventListener('activate', function(e) { e.waitUntil(self.clients.claim()); });\n\nself.addEventListener('unhandledrejection', function(event) {\n if (event.reason && event.reason.name === 'no-response') {\n event.preventDefault();\n }\n});\n\nworkbox.setConfig({ debug: false });\n\nworkbox.routing.registerRoute(\n function(ctx) {\n return ctx.request.method === 'POST' && ctx.url.pathname.startsWith('/api/interfere/');\n },\n new workbox.strategies.NetworkOnly({\n plugins: [\n new workbox.backgroundSync.BackgroundSyncPlugin('interfere-queue', {\n maxRetentionTime: 1440,\n }),\n {\n fetchDidSucceed: function(ctx) {\n if (ctx.response.status >= 500) {\n throw new Error(ctx.request.url + ' returned ' + ctx.response.status);\n }\n return ctx.response;\n },\n },\n ],\n }),\n 'POST'\n);";
3
+ //#endregion
4
+ export { SW_SCRIPT };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sw-script.d.mts","names":[],"sources":["../../../src/internal/route/sw-script.ts"],"mappings":";cAAa,SAAA"}
@@ -0,0 +1,38 @@
1
+ //#region src/internal/route/sw-script.ts
2
+ const SW_SCRIPT = `\
3
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.3.0/workbox-sw.js');
4
+
5
+ self.addEventListener('install', function() { self.skipWaiting(); });
6
+ self.addEventListener('activate', function(e) { e.waitUntil(self.clients.claim()); });
7
+
8
+ self.addEventListener('unhandledrejection', function(event) {
9
+ if (event.reason && event.reason.name === 'no-response') {
10
+ event.preventDefault();
11
+ }
12
+ });
13
+
14
+ workbox.setConfig({ debug: false });
15
+
16
+ workbox.routing.registerRoute(
17
+ function(ctx) {
18
+ return ctx.request.method === 'POST' && ctx.url.pathname.startsWith('/api/interfere/');
19
+ },
20
+ new workbox.strategies.NetworkOnly({
21
+ plugins: [
22
+ new workbox.backgroundSync.BackgroundSyncPlugin('interfere-queue', {
23
+ maxRetentionTime: 1440,
24
+ }),
25
+ {
26
+ fetchDidSucceed: function(ctx) {
27
+ if (ctx.response.status >= 500) {
28
+ throw new Error(ctx.request.url + ' returned ' + ctx.response.status);
29
+ }
30
+ return ctx.response;
31
+ },
32
+ },
33
+ ],
34
+ }),
35
+ 'POST'
36
+ );`;
37
+ //#endregion
38
+ export { SW_SCRIPT };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sw-script.mjs","names":[],"sources":["../../../src/internal/route/sw-script.ts"],"sourcesContent":["export const SW_SCRIPT = `\\\nimportScripts('https://storage.googleapis.com/workbox-cdn/releases/7.3.0/workbox-sw.js');\n\nself.addEventListener('install', function() { self.skipWaiting(); });\nself.addEventListener('activate', function(e) { e.waitUntil(self.clients.claim()); });\n\nself.addEventListener('unhandledrejection', function(event) {\n if (event.reason && event.reason.name === 'no-response') {\n event.preventDefault();\n }\n});\n\nworkbox.setConfig({ debug: false });\n\nworkbox.routing.registerRoute(\n function(ctx) {\n return ctx.request.method === 'POST' && ctx.url.pathname.startsWith('/api/interfere/');\n },\n new workbox.strategies.NetworkOnly({\n plugins: [\n new workbox.backgroundSync.BackgroundSyncPlugin('interfere-queue', {\n maxRetentionTime: 1440,\n }),\n {\n fetchDidSucceed: function(ctx) {\n if (ctx.response.status >= 500) {\n throw new Error(ctx.request.url + ' returned ' + ctx.response.status);\n }\n return ctx.response;\n },\n },\n ],\n }),\n 'POST'\n);`;\n"],"mappings":";AAAA,MAAa,YAAY"}
@@ -0,0 +1,9 @@
1
+ import { CaptureErrorContext, OnRequestErrorContext } from "./types.mjs";
2
+
3
+ //#region src/internal/server/capture.d.ts
4
+ declare function captureError(error: unknown, request?: unknown, context?: CaptureErrorContext): Promise<void>;
5
+ declare function onRequestError(error: Error & {
6
+ digest?: string;
7
+ }, request: unknown, context: OnRequestErrorContext): Promise<void>;
8
+ //#endregion
9
+ export { captureError, onRequestError };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.mts","names":[],"sources":["../../../src/internal/server/capture.ts"],"mappings":";;;iBAqBsB,YAAA,CACpB,KAAA,WACA,OAAA,YACA,OAAA,GAAU,mBAAA,GACT,OAAA;AAAA,iBA4BmB,cAAA,CACpB,KAAA,EAAO,KAAA;EAAU,MAAA;AAAA,GACjB,OAAA,WACA,OAAA,EAAS,qBAAA,GACR,OAAA"}
@@ -0,0 +1,50 @@
1
+ import { isErrorCaptured, markErrorCaptured } from "./dedupe.mjs";
2
+ import { buildErrorEnvelope } from "./envelope.mjs";
3
+ import { normalizeRequest } from "./normalize-request.mjs";
4
+ import { resolveServerCaptureRuntime } from "./runtime.mjs";
5
+ import { sendEnvelope } from "./transport.mjs";
6
+ //#region src/internal/server/capture.ts
7
+ const ON_REQUEST_ERROR_MECHANISM = {
8
+ type: "onRequestError",
9
+ handled: false,
10
+ synthetic: false
11
+ };
12
+ const DEFAULT_REQUEST = {
13
+ method: "GET",
14
+ path: "/",
15
+ headers: new Headers()
16
+ };
17
+ async function captureError(error, request, context) {
18
+ const runtime = resolveServerCaptureRuntime();
19
+ if (runtime.apiKey === null) return;
20
+ const normalizedRequest = normalizeRequest(request);
21
+ const envelope = buildErrorEnvelope({
22
+ error,
23
+ request: normalizedRequest,
24
+ context,
25
+ runtime
26
+ });
27
+ try {
28
+ await sendEnvelope({
29
+ envelope,
30
+ runtime,
31
+ traceparent: context?.traceparent ?? normalizedRequest?.headers.get("traceparent") ?? void 0
32
+ });
33
+ } catch {}
34
+ }
35
+ async function onRequestError(error, request, context) {
36
+ if (isErrorCaptured(error)) return;
37
+ markErrorCaptured(error);
38
+ const normalizedRequest = normalizeRequest(request) ?? DEFAULT_REQUEST;
39
+ await captureError(error, normalizedRequest, {
40
+ mechanism: ON_REQUEST_ERROR_MECHANISM,
41
+ nextjs: {
42
+ ...context,
43
+ requestMethod: normalizedRequest.method,
44
+ requestPath: normalizedRequest.path,
45
+ ...error.digest ? { errorDigest: error.digest } : {}
46
+ }
47
+ });
48
+ }
49
+ //#endregion
50
+ export { captureError, onRequestError };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.mjs","names":[],"sources":["../../../src/internal/server/capture.ts"],"sourcesContent":["import type { ErrorMechanism } from \"@interfere/types/sdk/plugins/payload/errors\";\n\nimport { isErrorCaptured, markErrorCaptured } from \"./dedupe.js\";\nimport { buildErrorEnvelope } from \"./envelope.js\";\nimport { normalizeRequest, TRACEPARENT_HEADER } from \"./normalize-request.js\";\nimport { resolveServerCaptureRuntime } from \"./runtime.js\";\nimport { sendEnvelope } from \"./transport.js\";\nimport type { CaptureErrorContext, OnRequestErrorContext } from \"./types.js\";\n\nconst ON_REQUEST_ERROR_MECHANISM: ErrorMechanism = {\n type: \"onRequestError\",\n handled: false,\n synthetic: false,\n};\n\nconst DEFAULT_REQUEST = {\n method: \"GET\",\n path: \"/\",\n headers: new Headers(),\n};\n\nexport async function captureError(\n error: unknown,\n request?: unknown,\n context?: CaptureErrorContext\n): Promise<void> {\n const runtime = resolveServerCaptureRuntime();\n if (runtime.apiKey === null) {\n return;\n }\n\n const normalizedRequest = normalizeRequest(request);\n const envelope = buildErrorEnvelope({\n error,\n request: normalizedRequest,\n context,\n runtime,\n });\n\n try {\n await sendEnvelope({\n envelope,\n runtime,\n traceparent:\n context?.traceparent ??\n normalizedRequest?.headers.get(TRACEPARENT_HEADER) ??\n undefined,\n });\n } catch {\n /* best-effort */\n }\n}\n\nexport async function onRequestError(\n error: Error & { digest?: string },\n request: unknown,\n context: OnRequestErrorContext\n): Promise<void> {\n if (isErrorCaptured(error)) {\n return;\n }\n markErrorCaptured(error);\n\n const normalizedRequest = normalizeRequest(request) ?? DEFAULT_REQUEST;\n\n await captureError(error, normalizedRequest, {\n mechanism: ON_REQUEST_ERROR_MECHANISM,\n nextjs: {\n ...context,\n requestMethod: normalizedRequest.method,\n requestPath: normalizedRequest.path,\n ...(error.digest ? { errorDigest: error.digest } : {}),\n },\n });\n}\n"],"mappings":";;;;;;AASA,MAAM,6BAA6C;CACjD,MAAM;CACN,SAAS;CACT,WAAW;CACZ;AAED,MAAM,kBAAkB;CACtB,QAAQ;CACR,MAAM;CACN,SAAS,IAAI,SAAS;CACvB;AAED,eAAsB,aACpB,OACA,SACA,SACe;CACf,MAAM,UAAU,6BAA6B;AAC7C,KAAI,QAAQ,WAAW,KACrB;CAGF,MAAM,oBAAoB,iBAAiB,QAAQ;CACnD,MAAM,WAAW,mBAAmB;EAClC;EACA,SAAS;EACT;EACA;EACD,CAAC;AAEF,KAAI;AACF,QAAM,aAAa;GACjB;GACA;GACA,aACE,SAAS,eACT,mBAAmB,QAAQ,IAAA,cAAuB,IAClD,KAAA;GACH,CAAC;SACI;;AAKV,eAAsB,eACpB,OACA,SACA,SACe;AACf,KAAI,gBAAgB,MAAM,CACxB;AAEF,mBAAkB,MAAM;CAExB,MAAM,oBAAoB,iBAAiB,QAAQ,IAAI;AAEvD,OAAM,aAAa,OAAO,mBAAmB;EAC3C,WAAW;EACX,QAAQ;GACN,GAAG;GACH,eAAe,kBAAkB;GACjC,aAAa,kBAAkB;GAC/B,GAAI,MAAM,SAAS,EAAE,aAAa,MAAM,QAAQ,GAAG,EAAE;GACtD;EACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ //#region src/internal/server/dedupe.d.ts
2
+ declare function isErrorCaptured(error: unknown): boolean;
3
+ declare function markErrorCaptured(error: unknown): void;
4
+ //#endregion
5
+ export { isErrorCaptured, markErrorCaptured };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedupe.d.mts","names":[],"sources":["../../../src/internal/server/dedupe.ts"],"mappings":";iBAEgB,eAAA,CAAgB,KAAA;AAAA,iBAIhB,iBAAA,CAAkB,KAAA"}
@@ -0,0 +1,11 @@
1
+ //#region src/internal/server/dedupe.ts
2
+ const seenErrors = /* @__PURE__ */ new WeakSet();
3
+ function isErrorCaptured(error) {
4
+ return error instanceof Error && seenErrors.has(error);
5
+ }
6
+ function markErrorCaptured(error) {
7
+ if (!(error instanceof Error)) return;
8
+ seenErrors.add(error);
9
+ }
10
+ //#endregion
11
+ export { isErrorCaptured, markErrorCaptured };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedupe.mjs","names":[],"sources":["../../../src/internal/server/dedupe.ts"],"sourcesContent":["const seenErrors = new WeakSet<Error>();\n\nexport function isErrorCaptured(error: unknown): boolean {\n return error instanceof Error && seenErrors.has(error);\n}\n\nexport function markErrorCaptured(error: unknown): void {\n if (!(error instanceof Error)) {\n return;\n }\n\n seenErrors.add(error);\n}\n"],"mappings":";AAAA,MAAM,6BAAa,IAAI,SAAgB;AAEvC,SAAgB,gBAAgB,OAAyB;AACvD,QAAO,iBAAiB,SAAS,WAAW,IAAI,MAAM;;AAGxD,SAAgB,kBAAkB,OAAsB;AACtD,KAAI,EAAE,iBAAiB,OACrB;AAGF,YAAW,IAAI,MAAM"}
@@ -0,0 +1,14 @@
1
+ import { CaptureErrorContext, NormalizedRequest } from "./types.mjs";
2
+ import { ServerCaptureRuntime } from "./runtime.mjs";
3
+ import { Envelope } from "@interfere/types/sdk/envelope";
4
+
5
+ //#region src/internal/server/envelope.d.ts
6
+ interface BuildErrorEnvelopeParams {
7
+ readonly context?: CaptureErrorContext;
8
+ readonly error: unknown;
9
+ readonly request: NormalizedRequest | null;
10
+ readonly runtime: ServerCaptureRuntime;
11
+ }
12
+ declare function buildErrorEnvelope(params: BuildErrorEnvelopeParams): Envelope<"error">;
13
+ //#endregion
14
+ export { buildErrorEnvelope };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.mts","names":[],"sources":["../../../src/internal/server/envelope.ts"],"mappings":";;;;;UAmBU,wBAAA;EAAA,SACC,OAAA,GAAU,mBAAA;EAAA,SACV,KAAA;EAAA,SACA,OAAA,EAAS,iBAAA;EAAA,SACT,OAAA,EAAS,oBAAA;AAAA;AAAA,iBAGJ,kBAAA,CACd,MAAA,EAAQ,wBAAA,GACP,QAAA"}
@@ -0,0 +1,55 @@
1
+ import { sessionIdSchema } from "@interfere/types/data/session";
2
+ import { toError, toExceptions } from "@interfere/types/sdk/errors";
3
+ import { v7 } from "uuid";
4
+ //#region src/internal/server/envelope.ts
5
+ const SESSION_HEADER = "x-interfere-session";
6
+ const DEFAULT_ERROR_MECHANISM = {
7
+ type: "captureError",
8
+ handled: true
9
+ };
10
+ function buildErrorEnvelope(params) {
11
+ const { error, request, context, runtime } = params;
12
+ const session = resolveSession(request?.headers ?? new Headers());
13
+ let nextjsContext;
14
+ if (context?.nextjs) nextjsContext = toNextjsContext(context.nextjs);
15
+ else if (request) nextjsContext = toNextjsRequestContext(request);
16
+ return {
17
+ uuid: v7(),
18
+ v: 0,
19
+ type: "error",
20
+ payload: { exceptions: toExceptions(toError(error), context?.mechanism ?? DEFAULT_ERROR_MECHANISM) },
21
+ clientTs: Date.now(),
22
+ runtime: runtime.runtime,
23
+ environment: runtime.environment,
24
+ buildId: runtime.buildId,
25
+ releaseId: runtime.releaseId,
26
+ sessionId: session.id,
27
+ ...session.source ? { sessionSource: session.source } : {},
28
+ ...nextjsContext ? { context: nextjsContext } : {}
29
+ };
30
+ }
31
+ function toNextjsRequestContext(request) {
32
+ return {
33
+ runtime: "nextjs",
34
+ requestMethod: request.method,
35
+ requestPath: request.path
36
+ };
37
+ }
38
+ function toNextjsContext(context) {
39
+ return {
40
+ runtime: "nextjs",
41
+ ...context
42
+ };
43
+ }
44
+ function resolveSession(headers) {
45
+ const sessionId = headers.get(SESSION_HEADER);
46
+ if (sessionId === null) return { id: null };
47
+ const parsed = sessionIdSchema.safeParse(sessionId);
48
+ if (!parsed.success) return { id: null };
49
+ return {
50
+ id: parsed.data,
51
+ source: "header"
52
+ };
53
+ }
54
+ //#endregion
55
+ export { buildErrorEnvelope };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.mjs","names":["uuidv7"],"sources":["../../../src/internal/server/envelope.ts"],"sourcesContent":["import type { SessionId } from \"@interfere/types/data/session\";\nimport { sessionIdSchema } from \"@interfere/types/data/session\";\nimport type { Envelope, SessionSource } from \"@interfere/types/sdk/envelope\";\nimport { toError, toExceptions } from \"@interfere/types/sdk/errors\";\nimport type { NextjsContext } from \"@interfere/types/sdk/plugins/context/next\";\nimport type { ErrorMechanism } from \"@interfere/types/sdk/plugins/payload/errors\";\n\nimport { v7 as uuidv7 } from \"uuid\";\n\nimport type { ServerCaptureRuntime } from \"./runtime.js\";\nimport type { CaptureErrorContext, NormalizedRequest } from \"./types.js\";\n\nconst SESSION_HEADER = \"x-interfere-session\";\n\nconst DEFAULT_ERROR_MECHANISM: ErrorMechanism = {\n type: \"captureError\",\n handled: true,\n};\n\ninterface BuildErrorEnvelopeParams {\n readonly context?: CaptureErrorContext;\n readonly error: unknown;\n readonly request: NormalizedRequest | null;\n readonly runtime: ServerCaptureRuntime;\n}\n\nexport function buildErrorEnvelope(\n params: BuildErrorEnvelopeParams\n): Envelope<\"error\"> {\n const { error, request, context, runtime } = params;\n const session = resolveSession(request?.headers ?? new Headers());\n\n let nextjsContext: NextjsContext | undefined;\n if (context?.nextjs) {\n nextjsContext = toNextjsContext(context.nextjs);\n } else if (request) {\n nextjsContext = toNextjsRequestContext(request);\n }\n\n return {\n uuid: uuidv7(),\n v: 0,\n type: \"error\",\n payload: {\n exceptions: toExceptions(\n toError(error),\n context?.mechanism ?? DEFAULT_ERROR_MECHANISM\n ),\n },\n clientTs: Date.now(),\n runtime: runtime.runtime,\n environment: runtime.environment,\n buildId: runtime.buildId,\n releaseId: runtime.releaseId,\n sessionId: session.id,\n ...(session.source ? { sessionSource: session.source } : {}),\n ...(nextjsContext ? { context: nextjsContext } : {}),\n };\n}\n\nfunction toNextjsRequestContext(request: NormalizedRequest): NextjsContext {\n return {\n runtime: \"nextjs\",\n requestMethod: request.method,\n requestPath: request.path,\n };\n}\n\nfunction toNextjsContext(\n context: Omit<NextjsContext, \"runtime\">\n): NextjsContext {\n return {\n runtime: \"nextjs\",\n ...context,\n };\n}\n\nfunction resolveSession(headers: Headers): {\n readonly id: SessionId | null;\n readonly source?: SessionSource;\n} {\n const sessionId = headers.get(SESSION_HEADER);\n if (sessionId === null) {\n return { id: null };\n }\n\n const parsed = sessionIdSchema.safeParse(sessionId);\n if (!parsed.success) {\n return { id: null };\n }\n\n return {\n id: parsed.data,\n source: \"header\",\n };\n}\n"],"mappings":";;;;AAYA,MAAM,iBAAiB;AAEvB,MAAM,0BAA0C;CAC9C,MAAM;CACN,SAAS;CACV;AASD,SAAgB,mBACd,QACmB;CACnB,MAAM,EAAE,OAAO,SAAS,SAAS,YAAY;CAC7C,MAAM,UAAU,eAAe,SAAS,WAAW,IAAI,SAAS,CAAC;CAEjE,IAAI;AACJ,KAAI,SAAS,OACX,iBAAgB,gBAAgB,QAAQ,OAAO;UACtC,QACT,iBAAgB,uBAAuB,QAAQ;AAGjD,QAAO;EACL,MAAMA,IAAQ;EACd,GAAG;EACH,MAAM;EACN,SAAS,EACP,YAAY,aACV,QAAQ,MAAM,EACd,SAAS,aAAa,wBACvB,EACF;EACD,UAAU,KAAK,KAAK;EACpB,SAAS,QAAQ;EACjB,aAAa,QAAQ;EACrB,SAAS,QAAQ;EACjB,WAAW,QAAQ;EACnB,WAAW,QAAQ;EACnB,GAAI,QAAQ,SAAS,EAAE,eAAe,QAAQ,QAAQ,GAAG,EAAE;EAC3D,GAAI,gBAAgB,EAAE,SAAS,eAAe,GAAG,EAAE;EACpD;;AAGH,SAAS,uBAAuB,SAA2C;AACzE,QAAO;EACL,SAAS;EACT,eAAe,QAAQ;EACvB,aAAa,QAAQ;EACtB;;AAGH,SAAS,gBACP,SACe;AACf,QAAO;EACL,SAAS;EACT,GAAG;EACJ;;AAGH,SAAS,eAAe,SAGtB;CACA,MAAM,YAAY,QAAQ,IAAI,eAAe;AAC7C,KAAI,cAAc,KAChB,QAAO,EAAE,IAAI,MAAM;CAGrB,MAAM,SAAS,gBAAgB,UAAU,UAAU;AACnD,KAAI,CAAC,OAAO,QACV,QAAO,EAAE,IAAI,MAAM;AAGrB,QAAO;EACL,IAAI,OAAO;EACX,QAAQ;EACT"}
@@ -0,0 +1,7 @@
1
+ import { NormalizedRequest } from "./types.mjs";
2
+
3
+ //#region src/internal/server/normalize-request.d.ts
4
+ declare const TRACEPARENT_HEADER = "traceparent";
5
+ declare function normalizeRequest(request: unknown): NormalizedRequest | null;
6
+ //#endregion
7
+ export { TRACEPARENT_HEADER, normalizeRequest };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-request.d.mts","names":[],"sources":["../../../src/internal/server/normalize-request.ts"],"mappings":";;;cAEa,kBAAA;AAAA,iBAEG,gBAAA,CAAiB,OAAA,YAAmB,iBAAA"}