@interfere/next 3.0.0 → 5.0.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 (113) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +13 -0
  2. package/dist/config.d.mts +21 -0
  3. package/dist/config.d.mts.map +1 -0
  4. package/dist/config.mjs +103 -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/pipeline.d.mts +49 -0
  13. package/dist/internal/build/pipeline.d.mts.map +1 -0
  14. package/dist/internal/build/pipeline.mjs +67 -0
  15. package/dist/internal/build/pipeline.mjs.map +1 -0
  16. package/dist/internal/build/release/destinations/vercel.d.mts +6 -0
  17. package/dist/internal/build/release/destinations/vercel.d.mts.map +1 -0
  18. package/dist/internal/build/release/destinations/vercel.mjs +25 -0
  19. package/dist/internal/build/release/destinations/vercel.mjs.map +1 -0
  20. package/dist/internal/build/release/git.d.mts +4 -0
  21. package/dist/internal/build/release/git.d.mts.map +1 -0
  22. package/dist/internal/build/release/git.mjs +21 -0
  23. package/dist/internal/build/release/git.mjs.map +1 -0
  24. package/dist/internal/build/release/index.d.mts +8 -0
  25. package/dist/internal/build/release/index.d.mts.map +1 -0
  26. package/dist/internal/build/release/index.mjs +20 -0
  27. package/dist/internal/build/release/index.mjs.map +1 -0
  28. package/dist/internal/build/release/sources/github.d.mts +6 -0
  29. package/dist/internal/build/release/sources/github.d.mts.map +1 -0
  30. package/dist/internal/build/release/sources/github.mjs +15 -0
  31. package/dist/internal/build/release/sources/github.mjs.map +1 -0
  32. package/dist/internal/build/source-maps/discover.d.mts +15 -0
  33. package/dist/internal/build/source-maps/discover.d.mts.map +1 -0
  34. package/dist/internal/build/source-maps/discover.mjs +62 -0
  35. package/dist/internal/build/source-maps/discover.mjs.map +1 -0
  36. package/dist/internal/build/source-maps/index.d.mts +26 -0
  37. package/dist/internal/build/source-maps/index.d.mts.map +1 -0
  38. package/dist/internal/build/source-maps/index.mjs +28 -0
  39. package/dist/internal/build/source-maps/index.mjs.map +1 -0
  40. package/dist/internal/build/value-injection-loader.d.mts +13 -0
  41. package/dist/internal/build/value-injection-loader.d.mts.map +1 -0
  42. package/dist/internal/build/value-injection-loader.mjs +24 -0
  43. package/dist/internal/build/value-injection-loader.mjs.map +1 -0
  44. package/dist/internal/env.d.mts +16 -0
  45. package/dist/internal/env.d.mts.map +1 -0
  46. package/dist/internal/env.mjs +19 -0
  47. package/dist/internal/env.mjs.map +1 -0
  48. package/dist/internal/logger.d.mts +9 -0
  49. package/dist/internal/logger.d.mts.map +1 -0
  50. package/dist/internal/logger.mjs +60 -0
  51. package/dist/internal/logger.mjs.map +1 -0
  52. package/dist/internal/route/handle-get.d.mts +4 -0
  53. package/dist/internal/route/handle-get.d.mts.map +1 -0
  54. package/dist/internal/route/handle-get.mjs +23 -0
  55. package/dist/internal/route/handle-get.mjs.map +1 -0
  56. package/dist/internal/route/handle-post.d.mts +4 -0
  57. package/dist/internal/route/handle-post.d.mts.map +1 -0
  58. package/dist/internal/route/handle-post.mjs +65 -0
  59. package/dist/internal/route/handle-post.mjs.map +1 -0
  60. package/dist/internal/route/proxy.d.mts +18 -0
  61. package/dist/internal/route/proxy.d.mts.map +1 -0
  62. package/dist/internal/route/proxy.mjs +82 -0
  63. package/dist/internal/route/proxy.mjs.map +1 -0
  64. package/dist/internal/route/sw-script.d.mts +4 -0
  65. package/dist/internal/route/sw-script.d.mts.map +1 -0
  66. package/dist/internal/route/sw-script.mjs +38 -0
  67. package/dist/internal/route/sw-script.mjs.map +1 -0
  68. package/dist/internal/server/capture.d.mts +9 -0
  69. package/dist/internal/server/capture.d.mts.map +1 -0
  70. package/dist/internal/server/capture.mjs +52 -0
  71. package/dist/internal/server/capture.mjs.map +1 -0
  72. package/dist/internal/server/dedupe.d.mts +5 -0
  73. package/dist/internal/server/dedupe.d.mts.map +1 -0
  74. package/dist/internal/server/dedupe.mjs +11 -0
  75. package/dist/internal/server/dedupe.mjs.map +1 -0
  76. package/dist/internal/server/envelope.d.mts +14 -0
  77. package/dist/internal/server/envelope.d.mts.map +1 -0
  78. package/dist/internal/server/envelope.mjs +57 -0
  79. package/dist/internal/server/envelope.mjs.map +1 -0
  80. package/dist/internal/server/normalize-request.d.mts +7 -0
  81. package/dist/internal/server/normalize-request.d.mts.map +1 -0
  82. package/dist/internal/server/normalize-request.mjs +50 -0
  83. package/dist/internal/server/normalize-request.mjs.map +1 -0
  84. package/dist/internal/server/remote-config.d.mts +5 -0
  85. package/dist/internal/server/remote-config.d.mts.map +1 -0
  86. package/dist/internal/server/remote-config.mjs +28 -0
  87. package/dist/internal/server/remote-config.mjs.map +1 -0
  88. package/dist/internal/server/runtime.d.mts +14 -0
  89. package/dist/internal/server/runtime.d.mts.map +1 -0
  90. package/dist/internal/server/runtime.mjs +18 -0
  91. package/dist/internal/server/runtime.mjs.map +1 -0
  92. package/dist/internal/server/transport.d.mts +12 -0
  93. package/dist/internal/server/transport.d.mts.map +1 -0
  94. package/dist/internal/server/transport.mjs +17 -0
  95. package/dist/internal/server/transport.mjs.map +1 -0
  96. package/dist/internal/server/types.d.mts +17 -0
  97. package/dist/internal/server/types.d.mts.map +1 -0
  98. package/dist/internal/server/types.mjs +1 -0
  99. package/dist/internal/version.d.mts +4 -0
  100. package/dist/internal/version.d.mts.map +1 -0
  101. package/dist/internal/version.mjs +5 -0
  102. package/dist/internal/version.mjs.map +1 -0
  103. package/dist/package.mjs +5 -0
  104. package/dist/package.mjs.map +1 -0
  105. package/dist/provider.d.mts +3 -0
  106. package/dist/provider.mjs +3 -0
  107. package/dist/route-handler.d.mts +7 -0
  108. package/dist/route-handler.d.mts.map +1 -0
  109. package/dist/route-handler.mjs +26 -0
  110. package/dist/route-handler.mjs.map +1 -0
  111. package/dist/server.d.mts +4 -0
  112. package/dist/server.mjs +3 -0
  113. package/package.json +26 -26
@@ -0,0 +1,62 @@
1
+ import { isAbsolute, join, relative, resolve } from "node:path";
2
+ import { readFile, readdir } from "node:fs/promises";
3
+ import { createHash } from "node:crypto";
4
+ //#region src/internal/build/source-maps/discover.ts
5
+ const SOURCEMAPPING_RE = /\/\/[#@]\s*sourceMappingURL=(\S+)\s*$/;
6
+ function resolveDistDir(projectDir, distDir) {
7
+ return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);
8
+ }
9
+ async function findJsFiles(dir) {
10
+ return (await readdir(dir, { recursive: true }).catch(() => [])).filter((entry) => entry.endsWith(".js")).map((entry) => join(dir, entry));
11
+ }
12
+ async function discover(projectDir, distDir) {
13
+ const absDistDir = resolveDistDir(projectDir, distDir);
14
+ const relDistDir = relative(projectDir, absDistDir);
15
+ const [staticFiles, serverFiles] = await Promise.all([findJsFiles(join(absDistDir, "static")), findJsFiles(join(absDistDir, "server"))]);
16
+ const jsPaths = [...staticFiles, ...serverFiles];
17
+ const mapping = {};
18
+ const mapAbsolutes = /* @__PURE__ */ new Map();
19
+ for (const jsAbs of jsPaths) {
20
+ const content = await readFile(jsAbs, "utf8");
21
+ const match = SOURCEMAPPING_RE.exec(content);
22
+ if (!match?.[1]) continue;
23
+ const mapAbs = `${jsAbs.slice(0, jsAbs.lastIndexOf("/") + 1)}${decodeURIComponent(match[1])}`;
24
+ const jsPublic = toPublicPath(relative(projectDir, jsAbs), relDistDir);
25
+ const mapPublic = toPublicPath(relative(projectDir, mapAbs), relDistDir);
26
+ mapping[mapPublic] = jsPublic;
27
+ mapAbsolutes.set(mapPublic, mapAbs);
28
+ }
29
+ const loaded = (await Promise.all([...mapAbsolutes.entries()].map(async ([mapPublic, mapAbs]) => {
30
+ const content = await readFile(mapAbs, "utf8").catch(() => null);
31
+ if (content === null) return null;
32
+ return {
33
+ absolute: mapAbs,
34
+ path: mapPublic,
35
+ content,
36
+ hash: createHash("sha256").update(content).digest("hex")
37
+ };
38
+ }))).filter((f) => f !== null);
39
+ const validMapping = {};
40
+ for (const file of loaded) {
41
+ const js = mapping[file.path];
42
+ if (js) validMapping[file.path] = js;
43
+ }
44
+ return {
45
+ files: loaded,
46
+ mapping: validMapping,
47
+ sourceFileCount: mapAbsolutes.size
48
+ };
49
+ }
50
+ function normalizeDistDir(distDir = ".next") {
51
+ let d = distDir.split("\\").join("/");
52
+ while (d.startsWith("./")) d = d.slice(2);
53
+ return d;
54
+ }
55
+ function toPublicPath(rel, distDir) {
56
+ const p = rel.split("\\").join("/");
57
+ if (p.startsWith(`${distDir}/`)) return `_next/${p.slice(distDir.length + 1)}`;
58
+ if (p.startsWith(".next/")) return `_next/${p.slice(6)}`;
59
+ return p;
60
+ }
61
+ //#endregion
62
+ export { discover, normalizeDistDir };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.mjs","names":[],"sources":["../../../../src/internal/build/source-maps/discover.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve } from \"node:path\";\n\nconst SOURCEMAPPING_RE = /\\/\\/[#@]\\s*sourceMappingURL=(\\S+)\\s*$/;\n\nexport type SourceMapFile = {\n readonly absolute: string;\n readonly path: string;\n readonly content: string;\n readonly hash: string;\n};\n\nfunction resolveDistDir(projectDir: string, distDir: string) {\n return isAbsolute(distDir) ? distDir : resolve(projectDir, distDir);\n}\n\nasync function findJsFiles(dir: string) {\n const entries = await readdir(dir, { recursive: true }).catch(\n () => [] as string[]\n );\n return entries\n .filter((entry) => entry.endsWith(\".js\"))\n .map((entry) => join(dir, entry));\n}\n\nexport async function discover(projectDir: string, distDir: string) {\n const absDistDir = resolveDistDir(projectDir, distDir);\n const relDistDir = relative(projectDir, absDistDir);\n\n const [staticFiles, serverFiles] = await Promise.all([\n findJsFiles(join(absDistDir, \"static\")),\n findJsFiles(join(absDistDir, \"server\")),\n ]);\n\n const jsPaths = [...staticFiles, ...serverFiles];\n\n const mapping: Record<string, string> = {};\n const mapAbsolutes = new Map<string, string>();\n\n for (const jsAbs of jsPaths) {\n const content = await readFile(jsAbs, \"utf8\");\n const match = SOURCEMAPPING_RE.exec(content);\n if (!match?.[1]) continue;\n\n const jsDir = jsAbs.slice(0, jsAbs.lastIndexOf(\"/\") + 1);\n const mapRef = decodeURIComponent(match[1]);\n const mapAbs = `${jsDir}${mapRef}`;\n const jsPublic = toPublicPath(relative(projectDir, jsAbs), relDistDir);\n const mapPublic = toPublicPath(relative(projectDir, mapAbs), relDistDir);\n\n mapping[mapPublic] = jsPublic;\n mapAbsolutes.set(mapPublic, mapAbs);\n }\n\n const files = await Promise.all(\n [...mapAbsolutes.entries()].map(async ([mapPublic, mapAbs]) => {\n const content = await readFile(mapAbs, \"utf8\").catch(() => null);\n if (content === null) return null;\n\n return {\n absolute: mapAbs,\n path: mapPublic,\n content,\n hash: createHash(\"sha256\").update(content).digest(\"hex\"),\n };\n }),\n );\n\n const loaded = files.filter((f): f is SourceMapFile => f !== null);\n\n const validMapping: Record<string, string> = {};\n for (const file of loaded) {\n const js = mapping[file.path];\n if (js) validMapping[file.path] = js;\n }\n\n return { files: loaded, mapping: validMapping, sourceFileCount: mapAbsolutes.size };\n}\n\nexport function normalizeDistDir(distDir = \".next\") {\n let d = distDir.split(\"\\\\\").join(\"/\");\n while (d.startsWith(\"./\")) d = d.slice(2);\n return d;\n}\n\nfunction toPublicPath(rel: string, distDir: string) {\n const p = rel.split(\"\\\\\").join(\"/\");\n if (p.startsWith(`${distDir}/`)) return `_next/${p.slice(distDir.length + 1)}`;\n if (p.startsWith(\".next/\")) return `_next/${p.slice(6)}`;\n return p;\n}\n"],"mappings":";;;;AAIA,MAAM,mBAAmB;AASzB,SAAS,eAAe,YAAoB,SAAiB;AAC3D,QAAO,WAAW,QAAQ,GAAG,UAAU,QAAQ,YAAY,QAAQ;;AAGrE,eAAe,YAAY,KAAa;AAItC,SAHgB,MAAM,QAAQ,KAAK,EAAE,WAAW,MAAM,CAAC,CAAC,YAChD,EAAE,CACT,EAEE,QAAQ,UAAU,MAAM,SAAS,MAAM,CAAC,CACxC,KAAK,UAAU,KAAK,KAAK,MAAM,CAAC;;AAGrC,eAAsB,SAAS,YAAoB,SAAiB;CAClE,MAAM,aAAa,eAAe,YAAY,QAAQ;CACtD,MAAM,aAAa,SAAS,YAAY,WAAW;CAEnD,MAAM,CAAC,aAAa,eAAe,MAAM,QAAQ,IAAI,CACnD,YAAY,KAAK,YAAY,SAAS,CAAC,EACvC,YAAY,KAAK,YAAY,SAAS,CAAC,CACxC,CAAC;CAEF,MAAM,UAAU,CAAC,GAAG,aAAa,GAAG,YAAY;CAEhD,MAAM,UAAkC,EAAE;CAC1C,MAAM,+BAAe,IAAI,KAAqB;AAE9C,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,UAAU,MAAM,SAAS,OAAO,OAAO;EAC7C,MAAM,QAAQ,iBAAiB,KAAK,QAAQ;AAC5C,MAAI,CAAC,QAAQ,GAAI;EAIjB,MAAM,SAAS,GAFD,MAAM,MAAM,GAAG,MAAM,YAAY,IAAI,GAAG,EAAE,GACzC,mBAAmB,MAAM,GAAG;EAE3C,MAAM,WAAW,aAAa,SAAS,YAAY,MAAM,EAAE,WAAW;EACtE,MAAM,YAAY,aAAa,SAAS,YAAY,OAAO,EAAE,WAAW;AAExE,UAAQ,aAAa;AACrB,eAAa,IAAI,WAAW,OAAO;;CAiBrC,MAAM,UAdQ,MAAM,QAAQ,IAC1B,CAAC,GAAG,aAAa,SAAS,CAAC,CAAC,IAAI,OAAO,CAAC,WAAW,YAAY;EAC7D,MAAM,UAAU,MAAM,SAAS,QAAQ,OAAO,CAAC,YAAY,KAAK;AAChE,MAAI,YAAY,KAAM,QAAO;AAE7B,SAAO;GACL,UAAU;GACV,MAAM;GACN;GACA,MAAM,WAAW,SAAS,CAAC,OAAO,QAAQ,CAAC,OAAO,MAAM;GACzD;GACD,CACH,EAEoB,QAAQ,MAA0B,MAAM,KAAK;CAElE,MAAM,eAAuC,EAAE;AAC/C,MAAK,MAAM,QAAQ,QAAQ;EACzB,MAAM,KAAK,QAAQ,KAAK;AACxB,MAAI,GAAI,cAAa,KAAK,QAAQ;;AAGpC,QAAO;EAAE,OAAO;EAAQ,SAAS;EAAc,iBAAiB,aAAa;EAAM;;AAGrF,SAAgB,iBAAiB,UAAU,SAAS;CAClD,IAAI,IAAI,QAAQ,MAAM,KAAK,CAAC,KAAK,IAAI;AACrC,QAAO,EAAE,WAAW,KAAK,CAAE,KAAI,EAAE,MAAM,EAAE;AACzC,QAAO;;AAGT,SAAS,aAAa,KAAa,SAAiB;CAClD,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC,KAAK,IAAI;AACnC,KAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,CAAE,QAAO,SAAS,EAAE,MAAM,QAAQ,SAAS,EAAE;AAC5E,KAAI,EAAE,WAAW,SAAS,CAAE,QAAO,SAAS,EAAE,MAAM,EAAE;AACtD,QAAO"}
@@ -0,0 +1,26 @@
1
+ import { SourceMapFile, discover, normalizeDistDir } from "./discover.mjs";
2
+
3
+ //#region src/internal/build/source-maps/index.d.ts
4
+ declare function buildUploadBody(discovered: {
5
+ files: SourceMapFile[];
6
+ mapping: Record<string, string>;
7
+ sourceFileCount: number;
8
+ }): {
9
+ body: {
10
+ files: {
11
+ fileName: string;
12
+ content: Blob;
13
+ }[];
14
+ metadata: {
15
+ sourceMapToGenerated: Record<string, string>;
16
+ hashes: {
17
+ [k: string]: string;
18
+ };
19
+ sourceFileCount: number;
20
+ };
21
+ };
22
+ totalBytes: number;
23
+ };
24
+ declare function cleanupSourceMaps(files: SourceMapFile[]): Promise<void>;
25
+ //#endregion
26
+ export { type SourceMapFile, buildUploadBody, cleanupSourceMaps, discover, normalizeDistDir };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/internal/build/source-maps/index.ts"],"mappings":";;;iBAMgB,eAAA,CAAgB,UAAA;EAC9B,KAAA,EAAO,aAAA;EACP,OAAA,EAAS,MAAA;EACT,eAAA;AAAA;;;;;;;;;;;;;;;;iBAqBoB,iBAAA,CAAkB,KAAA,EAAO,aAAA,KAAe,OAAA"}
@@ -0,0 +1,28 @@
1
+ import { discover, normalizeDistDir } from "./discover.mjs";
2
+ import { unlink } from "node:fs/promises";
3
+ //#region src/internal/build/source-maps/index.ts
4
+ function buildUploadBody(discovered) {
5
+ let totalBytes = 0;
6
+ return {
7
+ body: {
8
+ files: discovered.files.map((file) => {
9
+ totalBytes += file.content.length;
10
+ return {
11
+ fileName: file.path,
12
+ content: new Blob([file.content], { type: "application/json" })
13
+ };
14
+ }),
15
+ metadata: {
16
+ sourceMapToGenerated: discovered.mapping,
17
+ hashes: Object.fromEntries(discovered.files.map((f) => [f.path, f.hash])),
18
+ sourceFileCount: discovered.sourceFileCount
19
+ }
20
+ },
21
+ totalBytes
22
+ };
23
+ }
24
+ async function cleanupSourceMaps(files) {
25
+ await Promise.all(files.map((f) => unlink(f.absolute).catch(() => void 0)));
26
+ }
27
+ //#endregion
28
+ export { buildUploadBody, cleanupSourceMaps, discover, normalizeDistDir };
@@ -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 type { SourceMapFile } from \"./discover.js\";\n\nexport { discover, normalizeDistDir, type SourceMapFile } from \"./discover.js\";\n\nexport function buildUploadBody(discovered: {\n files: SourceMapFile[];\n mapping: Record<string, string>;\n sourceFileCount: number;\n}) {\n let totalBytes = 0;\n\n const files = discovered.files.map((file) => {\n totalBytes += file.content.length;\n return {\n fileName: file.path,\n content: new Blob([file.content], { type: \"application/json\" }),\n };\n });\n\n const metadata = {\n sourceMapToGenerated: discovered.mapping,\n hashes: Object.fromEntries(discovered.files.map((f) => [f.path, f.hash])),\n sourceFileCount: discovered.sourceFileCount,\n };\n\n return { body: { files, metadata }, totalBytes };\n}\n\nexport async function cleanupSourceMaps(files: SourceMapFile[]) {\n await Promise.all(files.map((f) => unlink(f.absolute).catch(() => undefined)));\n}\n"],"mappings":";;;AAMA,SAAgB,gBAAgB,YAI7B;CACD,IAAI,aAAa;AAgBjB,QAAO;EAAE,MAAM;GAAE,OAdH,WAAW,MAAM,KAAK,SAAS;AAC3C,kBAAc,KAAK,QAAQ;AAC3B,WAAO;KACL,UAAU,KAAK;KACf,SAAS,IAAI,KAAK,CAAC,KAAK,QAAQ,EAAE,EAAE,MAAM,oBAAoB,CAAC;KAChE;KACD;GAQsB,UANP;IACf,sBAAsB,WAAW;IACjC,QAAQ,OAAO,YAAY,WAAW,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACzE,iBAAiB,WAAW;IAC7B;GAEiC;EAAE;EAAY;;AAGlD,eAAsB,kBAAkB,OAAwB;AAC9D,OAAM,QAAQ,IAAI,MAAM,KAAK,MAAM,OAAO,EAAE,SAAS,CAAC,YAAY,KAAA,EAAU,CAAC,CAAC"}
@@ -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\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;AAE9D,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,9 @@
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
+ fatal(title: string, lines: string[]): never;
7
+ };
8
+ //#endregion
9
+ export { log };
@@ -0,0 +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"}
@@ -0,0 +1,60 @@
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 };
@@ -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\" | \"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,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;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"}
@@ -0,0 +1,4 @@
1
+ //#region src/internal/route/handle-get.d.ts
2
+ declare function handleGet(request: Request): Response | Promise<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":";iBAUgB,SAAA,CAAU,OAAA,EAAS,OAAA,GAAU,QAAA,GAAW,OAAA,CAAQ,QAAA"}
@@ -0,0 +1,23 @@
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
+ "service-worker-allowed": "/",
12
+ "cache-control": "public, max-age=3600"
13
+ }
14
+ });
15
+ if (subPath === API_PATHS.CONFIG) {
16
+ const env = resolveAuthenticatedEnv();
17
+ if (!env) return notConfiguredResponse();
18
+ return forwardToCollector(request, env, subPath);
19
+ }
20
+ return new Response("Not Found", { status: 404 });
21
+ }
22
+ //#endregion
23
+ export { handleGet };
@@ -0,0 +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 \"service-worker-allowed\": \"/\",\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,0BAA0B;GAC1B,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"}
@@ -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":";iBAoCsB,UAAA,CAAW,OAAA,EAAS,OAAA,GAAU,OAAA,CAAQ,QAAA"}
@@ -0,0 +1,65 @@
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
+ //#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
+ async function handlePost(request) {
18
+ const env = resolveAuthenticatedEnv();
19
+ if (!env) return notConfiguredResponse();
20
+ const subPath = extractSubPath(request);
21
+ try {
22
+ if (subPath === API_PATHS.INGEST) return await handleIngest(request, env);
23
+ return await forwardToCollector(request, env, subPath);
24
+ } catch (error) {
25
+ const detail = formatProxyError(error);
26
+ log.error(`Proxy ${request.method} ${subPath} failed`, detail.lines);
27
+ return Response.json({
28
+ code: "INTERFERE_PROXY_ERROR",
29
+ message: detail.message
30
+ }, { status: 502 });
31
+ }
32
+ }
33
+ async function handleIngest(request, env) {
34
+ let payload;
35
+ try {
36
+ payload = await request.json();
37
+ } catch {
38
+ return Response.json({
39
+ code: "INTERFERE_INVALID_JSON",
40
+ message: "Request body must be valid JSON."
41
+ }, { status: 400 });
42
+ }
43
+ const envelopes = parseEnvelopes(payload);
44
+ if (envelopes === null) return Response.json({
45
+ code: "INTERFERE_INVALID_ENVELOPES",
46
+ message: "Request body must be an array of envelopes."
47
+ }, { status: 400 });
48
+ const traceparent = request.headers.get("traceparent");
49
+ const upstream = await fetch(`${env.apiUrl}${API_PATHS.INGEST}`, {
50
+ method: "POST",
51
+ headers: {
52
+ "content-type": "application/json",
53
+ "x-api-key": env.apiKey,
54
+ ...traceparent ? { traceparent } : {}
55
+ },
56
+ body: JSON.stringify(injectReleaseMetadata(envelopes, env.release)),
57
+ signal: AbortSignal.timeout(1e4)
58
+ });
59
+ return new Response(upstream.body, {
60
+ status: upstream.status,
61
+ headers: { "content-type": upstream.headers.get("content-type") ?? "application/json" }
62
+ });
63
+ }
64
+ //#endregion
65
+ 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 { 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 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":";;;;AAaA,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;GACvC;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"}
@@ -0,0 +1,18 @@
1
+ import { InterfereEnv } from "../env.mjs";
2
+
3
+ //#region src/internal/route/proxy.d.ts
4
+ interface AuthenticatedEnv {
5
+ apiKey: string;
6
+ apiUrl: string;
7
+ release: InterfereEnv["release"];
8
+ }
9
+ declare function resolveAuthenticatedEnv(): AuthenticatedEnv | null;
10
+ declare function extractSubPath(request: Request): string;
11
+ declare function notConfiguredResponse(): Response;
12
+ declare function formatProxyError(error: unknown): {
13
+ message: string;
14
+ lines: string[];
15
+ };
16
+ declare function forwardToCollector(request: Request, env: AuthenticatedEnv, subPath: string): Promise<Response>;
17
+ //#endregion
18
+ export { AuthenticatedEnv, extractSubPath, formatProxyError, forwardToCollector, notConfiguredResponse, resolveAuthenticatedEnv };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.mts","names":[],"sources":["../../../src/internal/route/proxy.ts"],"mappings":";;;UAKiB,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"}
@@ -0,0 +1,82 @@
1
+ import { log } from "../logger.mjs";
2
+ import { readInterfereEnv } from "../env.mjs";
3
+ //#region src/internal/route/proxy.ts
4
+ const PROXY_PATH_PATTERN = /\/api\/interfere(\/.*)/;
5
+ function resolveAuthenticatedEnv() {
6
+ const env = readInterfereEnv();
7
+ if (env.apiKey === null) return null;
8
+ return {
9
+ apiKey: env.apiKey,
10
+ apiUrl: env.apiUrl,
11
+ release: env.release
12
+ };
13
+ }
14
+ function extractSubPath(request) {
15
+ return new URL(request.url).pathname.match(PROXY_PATH_PATTERN)?.[1] ?? "/";
16
+ }
17
+ function notConfiguredResponse() {
18
+ log.warn("Not configured", ["INTERFERE_API_KEY is not set. The proxy route will return 503."]);
19
+ return Response.json({
20
+ code: "INTERFERE_NOT_CONFIGURED",
21
+ message: "INTERFERE_API_KEY is required."
22
+ }, { status: 503 });
23
+ }
24
+ function formatProxyError(error) {
25
+ if (!(error instanceof Error)) return {
26
+ message: String(error),
27
+ lines: [String(error)]
28
+ };
29
+ const lines = [`${error.name}: ${error.message}`];
30
+ if ("cause" in error && error.cause) {
31
+ const cause = error.cause instanceof Error ? error.cause.message : String(error.cause);
32
+ lines.push(`cause: ${cause}`);
33
+ }
34
+ if ("code" in error && typeof error.code === "string") lines.push(`code: ${error.code}`);
35
+ return {
36
+ message: `${error.name}: ${error.message}`,
37
+ lines
38
+ };
39
+ }
40
+ async function forwardToCollector(request, env, subPath) {
41
+ const url = `${env.apiUrl}${subPath}`;
42
+ const traceparent = request.headers.get("traceparent");
43
+ const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
44
+ const upstream = await fetch(url, {
45
+ method: request.method,
46
+ headers: {
47
+ "content-type": request.headers.get("content-type") ?? "application/json",
48
+ "x-api-key": env.apiKey,
49
+ ...traceparent ? { traceparent } : {}
50
+ },
51
+ ...body === void 0 ? {} : { body },
52
+ signal: AbortSignal.timeout(1e4)
53
+ });
54
+ if (!upstream.ok) {
55
+ const text = await upstream.text().catch(() => "");
56
+ if (upstream.status >= 500) {
57
+ log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [text]);
58
+ return Response.json({
59
+ code: "INTERFERE_UPSTREAM_ERROR",
60
+ message: text
61
+ }, { status: upstream.status });
62
+ }
63
+ if (upstream.status >= 400) {
64
+ log.warn(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [text]);
65
+ return Response.json({
66
+ code: "INTERFERE_UPSTREAM_WARNING",
67
+ message: text
68
+ }, { status: upstream.status });
69
+ }
70
+ log.error(`Upstream ${upstream.status} for ${request.method} ${subPath}`, [text]);
71
+ return Response.json({
72
+ code: "INTERFERE_UPSTREAM_ERROR",
73
+ message: text
74
+ }, { status: upstream.status });
75
+ }
76
+ return new Response(upstream.body, {
77
+ status: upstream.status,
78
+ headers: { "content-type": upstream.headers.get("content-type") ?? "application/json" }
79
+ });
80
+ }
81
+ //#endregion
82
+ export { extractSubPath, formatProxyError, forwardToCollector, notConfiguredResponse, resolveAuthenticatedEnv };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.mjs","names":[],"sources":["../../../src/internal/route/proxy.ts"],"sourcesContent":["import { type InterfereEnv, readInterfereEnv } from \"../env.js\";\nimport { log } from \"../logger.js\";\n\nconst PROXY_PATH_PATTERN = /\\/api\\/interfere(\\/.*)/;\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 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 === undefined ? {} : { body }),\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":";;;AAGA,MAAM,qBAAqB;AAQ3B,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,QAFY,IAAI,IAAI,QAAQ,IAAI,CACd,SAAS,MAAM,mBAAmB,GACrC,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,QAAQ,QAAQ;EAChB,SAAS;GACP,gBAAgB,QAAQ,QAAQ,IAAI,eAAe,IAAI;GACvD,aAAa,IAAI;GACjB,GAAI,cAAc,EAAE,aAAa,GAAG,EAAE;GACvC;EACD,GAAI,SAAS,KAAA,IAAY,EAAE,GAAG,EAAE,MAAM;EACtC,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"}
@@ -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 === 429 || 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 === 429 || 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 === 429 || 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"}