@interfere/next 11.2.1 → 12.0.1

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 (97) hide show
  1. package/README.md +25 -25
  2. package/dist/config.d.mts +7 -8
  3. package/dist/config.mjs +1 -1
  4. package/dist/instrument-client.d.mts +5 -5
  5. package/dist/instrument-client.mjs +1 -1
  6. package/dist/instrumentation.d.mts +11 -8
  7. package/dist/instrumentation.edge.d.mts +3 -3
  8. package/dist/instrumentation.edge.mjs +1 -1
  9. package/dist/instrumentation.mjs +1 -1
  10. package/dist/internal/build/configure-build.d.mts +21 -15
  11. package/dist/internal/build/configure-build.mjs +1 -1
  12. package/dist/internal/build/detect-bundler.d.mts +3 -4
  13. package/dist/internal/build/pipeline.d.mts +40 -27
  14. package/dist/internal/build/pipeline.mjs +1 -1
  15. package/dist/internal/build/release/git.d.mts +2 -3
  16. package/dist/internal/build/release/index.d.mts +51 -5
  17. package/dist/internal/build/release/index.mjs +1 -1
  18. package/dist/internal/build/source-maps/discover-turbopack.d.mts +2 -3
  19. package/dist/internal/build/source-maps/discover-turbopack.mjs +1 -1
  20. package/dist/internal/build/source-maps/discover-webpack.d.mts +3 -4
  21. package/dist/internal/build/source-maps/discover-webpack.mjs +1 -1
  22. package/dist/internal/build/source-maps/discover.d.mts +9 -5
  23. package/dist/internal/build/source-maps/discover.mjs +1 -1
  24. package/dist/internal/build/source-maps/guard.d.mts +2 -3
  25. package/dist/internal/build/source-maps/guard.mjs +1 -1
  26. package/dist/internal/build/source-maps/paths.d.mts +5 -6
  27. package/dist/internal/build/source-maps/paths.mjs +1 -1
  28. package/dist/internal/build/telemetry.d.mts +5 -0
  29. package/dist/internal/build/telemetry.mjs +1 -0
  30. package/dist/internal/build/value-injection-loader.d.mts +5 -8
  31. package/dist/internal/build/value-injection-loader.mjs +2 -2
  32. package/dist/internal/build-marker-guard.d.mts +5 -6
  33. package/dist/internal/build-marker-guard.mjs +1 -1
  34. package/dist/internal/env.d.mts +13 -15
  35. package/dist/internal/env.mjs +1 -1
  36. package/dist/internal/logger.d.mts +5 -6
  37. package/dist/internal/logger.mjs +1 -1
  38. package/dist/internal/release-slug.d.mts +3 -5
  39. package/dist/internal/release-slug.mjs +1 -1
  40. package/dist/internal/server/cache-safe-trace-context.d.mts +24 -0
  41. package/dist/internal/server/cache-safe-trace-context.mjs +1 -0
  42. package/dist/internal/server/capture.d.mts +3 -4
  43. package/dist/internal/server/capture.mjs +1 -1
  44. package/dist/internal/server/console-bridge.d.mts +2 -3
  45. package/dist/internal/server/console-bridge.mjs +1 -1
  46. package/dist/internal/server/edge-exporter.d.mts +5 -6
  47. package/dist/internal/server/edge-exporter.mjs +1 -1
  48. package/dist/internal/server/freshness-propagator.d.mts +41 -0
  49. package/dist/internal/server/freshness-propagator.mjs +1 -0
  50. package/dist/internal/server/global-handlers.d.mts +4 -5
  51. package/dist/internal/server/global-handlers.mjs +1 -1
  52. package/dist/internal/server/id-generator.d.mts +2 -3
  53. package/dist/internal/server/instrumentation-options.d.mts +3 -4
  54. package/dist/internal/server/remote-config.d.mts +3 -4
  55. package/dist/internal/server/remote-config.mjs +1 -1
  56. package/dist/internal/server/server-action-marker.d.mts +10 -5
  57. package/dist/internal/server/server-action-marker.mjs +1 -1
  58. package/dist/internal/server/server-flush.d.mts +3 -4
  59. package/dist/internal/server/server-flush.mjs +1 -1
  60. package/dist/internal/server/static-generation.d.mts +17 -0
  61. package/dist/internal/server/static-generation.mjs +1 -0
  62. package/dist/internal/server/trace-meta.d.mts +13 -26
  63. package/dist/internal/server/trace-meta.mjs +1 -1
  64. package/dist/internal/server/traceparent.d.mts +2 -3
  65. package/dist/internal/server/traceparent.mjs +1 -1
  66. package/dist/internal/server/types.d.mts +5 -8
  67. package/dist/internal/server/wrap-proxy.d.mts +3 -4
  68. package/dist/internal/server/wrap-proxy.mjs +1 -1
  69. package/dist/internal/server/wrap-server-action.d.mts +2 -3
  70. package/dist/internal/server/wrap-server-action.mjs +1 -1
  71. package/dist/internal/setup-warnings.d.mts +3 -4
  72. package/dist/internal/setup-warnings.mjs +1 -1
  73. package/dist/internal/version.d.mts +2 -3
  74. package/dist/package.mjs +1 -1
  75. package/dist/provider.d.mts +3 -3
  76. package/dist/provider.mjs +1 -1
  77. package/package.json +49 -42
  78. package/dist/internal/build/release/destinations/cli.d.mts +0 -6
  79. package/dist/internal/build/release/destinations/cli.mjs +0 -1
  80. package/dist/internal/build/release/destinations/cloudflare.d.mts +0 -5
  81. package/dist/internal/build/release/destinations/cloudflare.mjs +0 -1
  82. package/dist/internal/build/release/destinations/index.d.mts +0 -14
  83. package/dist/internal/build/release/destinations/index.mjs +0 -1
  84. package/dist/internal/build/release/destinations/vercel.d.mts +0 -5
  85. package/dist/internal/build/release/destinations/vercel.mjs +0 -1
  86. package/dist/internal/build/release/sources/github.d.mts +0 -8
  87. package/dist/internal/build/release/sources/github.mjs +0 -1
  88. package/dist/internal/build/release/sources/index.d.mts +0 -20
  89. package/dist/internal/build/release/sources/index.mjs +0 -1
  90. package/dist/internal/build/source-maps/concurrency.d.mts +0 -4
  91. package/dist/internal/build/source-maps/concurrency.mjs +0 -1
  92. package/dist/internal/build/source-maps/index.d.mts +0 -6
  93. package/dist/internal/build/source-maps/index.mjs +0 -1
  94. package/dist/internal/build/source-maps/upload.d.mts +0 -39
  95. package/dist/internal/build/source-maps/upload.mjs +0 -1
  96. package/dist/internal/url.d.mts +0 -4
  97. package/dist/internal/url.mjs +0 -1
@@ -1,12 +1,11 @@
1
1
  import { SourceMapFile } from "./discover.mjs";
2
2
  //#region src/internal/build/source-maps/discover-webpack.d.ts
3
- declare function injectDebugIdIntoMap(content: string, debugId: string): string;
4
- declare function discoverWebpack(opts: {
3
+ export declare function injectDebugIdIntoMap(content: string, debugId: string): string;
4
+ export declare function discoverWebpack(opts: {
5
5
  projectDir: string;
6
6
  distDir: string;
7
7
  }): Promise<{
8
8
  files: SourceMapFile[];
9
9
  sourceFileCount: number;
10
10
  }>;
11
- //#endregion
12
- export { discoverWebpack, injectDebugIdIntoMap };
11
+ //#endregion
@@ -1 +1 @@
1
- import{resolveDistDir,toPublicPath,walkDistTrees}from"./paths.mjs";import{relative}from"node:path";import{createHash,randomUUID}from"node:crypto";import{readFile,writeFile}from"node:fs/promises";import{injectDebugIdIntoJs,readDebugIdFromJs}from"@interfere/types/data/source-maps";const SOURCEMAPPING_RE=/\/\/[#@]\s*sourceMappingURL=(\S+)\s*$/;function injectDebugIdIntoMap(content,debugId){let json=JSON.parse(content);return json.debugId=debugId,JSON.stringify(json)}async function discoverWebpack(opts){let absDistDir=resolveDistDir(opts.projectDir,opts.distDir),relDistDir=relative(opts.projectDir,absDistDir),jsPaths=await walkDistTrees(absDistDir,`.js`),pairs=new Map;for(let jsAbs of jsPaths){let content=await readFile(jsAbs,`utf8`),match=SOURCEMAPPING_RE.exec(content);if(!match?.[1])continue;let mapAbs=`${jsAbs.slice(0,jsAbs.lastIndexOf(`/`)+1)}${decodeURIComponent(match[1])}`,jsPublic=toPublicPath(relative(opts.projectDir,jsAbs),relDistDir),mapPublic=toPublicPath(relative(opts.projectDir,mapAbs),relDistDir);pairs.set(mapPublic,{mapAbs,jsAbs,jsPublic,jsContent:content,existingDebugId:readDebugIdFromJs(content)})}return{files:(await Promise.all(Array.from(pairs.entries(),async([mapPublic,pair])=>{let mapContent=await readFile(pair.mapAbs,`utf8`).catch(()=>null);if(mapContent===null)return null;let debugId=pair.existingDebugId??randomUUID();if(!pair.existingDebugId){let injectedJs=injectDebugIdIntoJs(pair.jsContent,debugId);await writeFile(pair.jsAbs,injectedJs,`utf8`)}let finalMap=JSON.parse(mapContent).debugId===debugId?mapContent:injectDebugIdIntoMap(mapContent,debugId);return finalMap!==mapContent&&await writeFile(pair.mapAbs,finalMap,`utf8`),{absolute:pair.mapAbs,path:mapPublic,content:finalMap,hash:createHash(`sha256`).update(finalMap).digest(`hex`),debugId,chunkUrl:pair.jsPublic}}))).filter(f=>f!==null),sourceFileCount:pairs.size}}export{discoverWebpack,injectDebugIdIntoMap};
1
+ import{resolveDistDir,toPublicPath,walkDistTrees}from"./paths.mjs";import{relative}from"node:path";import{createHash,randomUUID}from"node:crypto";import{injectDebugIdIntoJs,readDebugIdFromJs}from"@interfere/types/data/source-maps";import{mapWithConcurrency}from"@interfere/helpers/map-with-concurrency";import{readFile,writeFile}from"node:fs/promises";const SOURCEMAPPING_RE=/\/\/[#@]\s*sourceMappingURL=(?<sourceMap>\S+)\s*$/u;function injectDebugIdIntoMap(content,debugId){let json=JSON.parse(content);if(typeof json!=`object`||!json||Array.isArray(json))throw TypeError(`Source map must be a JSON object`);return Reflect.set(json,`debugId`,debugId),JSON.stringify(json)}async function discoverWebpack(opts){let absDistDir=resolveDistDir(opts.projectDir,opts.distDir),relDistDir=relative(opts.projectDir,absDistDir),jsPaths=await walkDistTrees(absDistDir,`.js`),discovered=await mapWithConcurrency(jsPaths,16,async jsAbs=>{let content=await readFile(jsAbs,`utf8`),match=SOURCEMAPPING_RE.exec(content);if(!match?.groups?.sourceMap)return null;let mapAbs=`${jsAbs.slice(0,jsAbs.lastIndexOf(`/`)+1)}${decodeURIComponent(match.groups.sourceMap)}`,jsPublic=toPublicPath(relative(opts.projectDir,jsAbs),relDistDir);return[toPublicPath(relative(opts.projectDir,mapAbs),relDistDir),{existingDebugId:readDebugIdFromJs(content),jsAbs,jsContent:content,jsPublic,mapAbs}]}),pairs=new Map;for(let[mapPublic,pair]of discovered.filter(entry=>entry!==null)){let chunkAbsolutes=pairs.get(mapPublic)?.chunkAbsolutes??[];pairs.set(mapPublic,{...pair,chunkAbsolutes:[...chunkAbsolutes,pair.jsAbs]})}return{files:(await Promise.all(Array.from(pairs.entries(),async([mapPublic,pair])=>{let mapContent=await readFile(pair.mapAbs,`utf8`).catch(()=>null);if(mapContent===null)return null;let debugId=pair.existingDebugId??randomUUID(),mapJson=JSON.parse(mapContent),finalMap=typeof mapJson==`object`&&mapJson&&`debugId`in mapJson&&mapJson.debugId===debugId?mapContent:injectDebugIdIntoMap(mapContent,debugId);if(!pair.existingDebugId){let injectedJs=injectDebugIdIntoJs(pair.jsContent,debugId);await writeFile(pair.jsAbs,injectedJs,`utf8`)}return finalMap!==mapContent&&await writeFile(pair.mapAbs,finalMap,`utf8`),{absolute:pair.mapAbs,chunkAbsolutes:pair.chunkAbsolutes,chunkUrl:pair.jsPublic,content:finalMap,debugId,hash:createHash(`sha256`).update(finalMap).digest(`hex`),path:mapPublic}}))).filter(f=>f!==null),sourceFileCount:pairs.size}}export{discoverWebpack,injectDebugIdIntoMap};
@@ -2,22 +2,26 @@ import { NextBuildBundler } from "../detect-bundler.mjs";
2
2
  import { injectDebugIdIntoMap } from "./discover-webpack.mjs";
3
3
  import { injectDebugIdIntoJs } from "@interfere/types/data/source-maps";
4
4
  //#region src/internal/build/source-maps/discover.d.ts
5
- interface SourceMapFile {
5
+ export interface SourceMapFile {
6
6
  readonly absolute: string;
7
+ readonly chunkAbsolutes: string[];
7
8
  readonly chunkUrl: string;
8
9
  readonly content: string;
9
10
  readonly debugId: string;
10
11
  readonly hash: string;
11
12
  readonly path: string;
12
13
  }
13
- interface DiscoveryResult {
14
+ export interface DiscoveryResult {
14
15
  readonly files: SourceMapFile[];
15
16
  readonly sourceFileCount: number;
16
17
  }
17
- declare function discoverSourceMaps(opts: {
18
+ export declare function discoverSourceMaps(opts: {
18
19
  bundler: NextBuildBundler;
19
20
  projectDir: string;
20
21
  distDir: string;
21
- }): Promise<DiscoveryResult>;
22
+ }): Promise<{
23
+ files: SourceMapFile[];
24
+ sourceFileCount: number;
25
+ }>;
22
26
  //#endregion
23
- export { DiscoveryResult, SourceMapFile, discoverSourceMaps, injectDebugIdIntoJs, injectDebugIdIntoMap };
27
+ export { injectDebugIdIntoJs, injectDebugIdIntoMap };
@@ -1 +1 @@
1
- import{normalizeDistDir}from"./paths.mjs";import{discoverTurbopack}from"./discover-turbopack.mjs";import{discoverWebpack,injectDebugIdIntoMap}from"./discover-webpack.mjs";import{injectDebugIdIntoJs}from"@interfere/types/data/source-maps";async function discoverSourceMaps(opts){let distDir=normalizeDistDir(opts.distDir);switch(opts.bundler){case`webpack`:return discoverWebpack({projectDir:opts.projectDir,distDir});case`turbopack`:return discoverTurbopack({projectDir:opts.projectDir,distDir})}}export{discoverSourceMaps,injectDebugIdIntoJs,injectDebugIdIntoMap};
1
+ import{normalizeDistDir}from"./paths.mjs";import{discoverTurbopack}from"./discover-turbopack.mjs";import{discoverWebpack,injectDebugIdIntoMap}from"./discover-webpack.mjs";import{injectDebugIdIntoJs}from"@interfere/types/data/source-maps";async function discoverSourceMaps(opts){let distDir=normalizeDistDir(opts.distDir);return{webpack:discoverWebpack,turbopack:discoverTurbopack}[opts.bundler]({projectDir:opts.projectDir,distDir})}export{discoverSourceMaps,injectDebugIdIntoJs,injectDebugIdIntoMap};
@@ -1,9 +1,8 @@
1
1
  import { SourceMapFile } from "./discover.mjs";
2
2
  //#region src/internal/build/source-maps/guard.d.ts
3
- declare function assertClientChunksAreMapped(opts: {
3
+ export declare function assertClientChunksAreMapped(opts: {
4
4
  projectDir: string;
5
5
  distDir: string;
6
6
  discovered: readonly SourceMapFile[];
7
7
  }): Promise<void>;
8
- //#endregion
9
- export { assertClientChunksAreMapped };
8
+ //#endregion
@@ -1 +1 @@
1
- import{log}from"../../logger.mjs";import{resolveDistDir,walkDistTrees}from"./paths.mjs";import{readFile}from"node:fs/promises";import{readDebugIdFromJs}from"@interfere/types/data/source-maps";async function assertClientChunksAreMapped(opts){if(opts.discovered.some(file=>file.chunkUrl.includes(`static/chunks`)))return;let absDistDir=resolveDistDir(opts.projectDir,opts.distDir),clientChunks=(await walkDistTrees(absDistDir,`.js`)).filter(path=>path.replaceAll(`\\`,`/`).includes(`/static/chunks/`)),stampedCount=(await Promise.all(clientChunks.map(async jsAbs=>{let content=await readFile(jsAbs,`utf8`).catch(()=>``);return readDebugIdFromJs(content)!==null}))).filter(Boolean).length;stampedCount!==0&&log.fatal(`Client source maps were not uploaded`,[`${stampedCount} client chunk(s) carry debug IDs but no source maps were uploaded — browser errors from this release won't symbolicate.`,`A coexisting build tool likely deleted them before withInterfere() ran; make withInterfere() the outer wrapper so its discovery runs first, or disable that tool's post-upload map deletion.`])}export{assertClientChunksAreMapped};
1
+ import{log}from"../../logger.mjs";import{resolveDistDir,walkDistTrees}from"./paths.mjs";import{readDebugIdFromJs}from"@interfere/types/data/source-maps";import{readFile}from"node:fs/promises";async function assertClientChunksAreMapped(opts){if(opts.discovered.some(file=>file.chunkUrl.includes(`static/chunks`)))return;let absDistDir=resolveDistDir(opts.projectDir,opts.distDir),clientChunks=(await walkDistTrees(absDistDir,`.js`)).filter(path=>path.replaceAll(`\\`,`/`).includes(`/static/chunks/`)),stampedCount=(await Promise.all(clientChunks.map(async jsAbs=>{let content=await readFile(jsAbs,`utf8`).catch(()=>``);return readDebugIdFromJs(content)!==null}))).filter(Boolean).length;stampedCount!==0&&log.fatal(`Client source maps were not uploaded`,[`${stampedCount} client chunk(s) carry debug IDs but no source maps were uploaded — browser errors from this release won't symbolicate.`,`A coexisting build tool likely deleted them before withInterfere() ran; make withInterfere() the outer wrapper so its discovery runs first, or disable that tool's post-upload map deletion.`])}export{assertClientChunksAreMapped};
@@ -3,19 +3,19 @@
3
3
  * Strips Windows path separators and leading `./` segments so the rest of
4
4
  * the discovery code can assume POSIX-style paths relative to `projectDir`.
5
5
  */
6
- declare function normalizeDistDir(distDir?: string): string;
6
+ export declare function normalizeDistDir(distDir?: string): string;
7
7
  /**
8
8
  * Resolves an absolute filesystem path for the build's `distDir`. Accepts
9
9
  * either an absolute path (passed through) or a path relative to
10
10
  * `projectDir`.
11
11
  */
12
- declare function resolveDistDir(projectDir: string, distDir: string): string;
12
+ export declare function resolveDistDir(projectDir: string, distDir: string): string;
13
13
  /**
14
14
  * Maps an on-disk path (relative to `projectDir`) to the URL path Next.js
15
15
  * will serve it at. Both `_next/` and `.next/` shapes resolve to the public
16
16
  * `_next/` prefix the browser sees in `//# sourceMappingURL=...` comments.
17
17
  */
18
- declare function toPublicPath(rel: string, distDir: string): string;
18
+ export declare function toPublicPath(rel: string, distDir: string): string;
19
19
  /**
20
20
  * Recursively collects files under `<absDistDir>/static` and
21
21
  * `<absDistDir>/server` matching the given suffix. Both subtrees are
@@ -23,6 +23,5 @@ declare function toPublicPath(rel: string, distDir: string): string;
23
23
  * leave one missing, so a missing directory is treated as empty rather
24
24
  * than fatal.
25
25
  */
26
- declare function walkDistTrees(absDistDir: string, suffix: ".js" | ".js.map"): Promise<string[]>;
27
- //#endregion
28
- export { normalizeDistDir, resolveDistDir, toPublicPath, walkDistTrees };
26
+ export declare function walkDistTrees(absDistDir: string, suffix: ".js" | ".js.map"): Promise<string[]>;
27
+ //#endregion
@@ -1 +1 @@
1
- import{isAbsolute,join,resolve}from"node:path";import{readdir}from"node:fs/promises";const NEXT_PUBLIC_PREFIX=`_next/`;function normalizeDistDir(distDir=`.next`){return distDir.replaceAll(`\\`,`/`).replace(/^(\.\/)+/,``)}function resolveDistDir(projectDir,distDir){return isAbsolute(distDir)?distDir:resolve(projectDir,distDir)}function toPublicPath(rel,distDir){let p=rel.replaceAll(`\\`,`/`);return p.startsWith(`${distDir}/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length+1)}`:p.startsWith(`.next/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(6)}`:p}async function walkDistTrees(absDistDir,suffix){return(await Promise.all([`static`,`server`].map(async subtree=>{let root=join(absDistDir,subtree),entries=await readdir(root,{recursive:!0}).catch(()=>[]),out=[];for(let entry of entries)typeof entry==`string`&&entry.endsWith(suffix)&&out.push(join(root,entry));return out}))).flat()}export{normalizeDistDir,resolveDistDir,toPublicPath,walkDistTrees};
1
+ import{isAbsolute,join,resolve}from"node:path";import{readdir}from"node:fs/promises";const NEXT_PUBLIC_PREFIX=`_next/`;function normalizeDistDir(distDir=`.next`){return distDir.replaceAll(`\\`,`/`).replace(/^(?:\.\/)+/u,``)}function resolveDistDir(projectDir,distDir){return isAbsolute(distDir)?distDir:resolve(projectDir,distDir)}function toPublicPath(rel,distDir){let p=rel.replaceAll(`\\`,`/`);return p.startsWith(`${distDir}/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(distDir.length+1)}`:p.startsWith(`.next/`)?`${NEXT_PUBLIC_PREFIX}${p.slice(6)}`:p}async function walkDistTrees(absDistDir,suffix){return(await Promise.all([`static`,`server`].map(async subtree=>{let root=join(absDistDir,subtree),entries=await readdir(root,{recursive:!0}).catch(()=>[]),out=[];for(let entry of entries)entry.endsWith(suffix)&&out.push(join(root,entry));return out}))).flat()}export{normalizeDistDir,resolveDistDir,toPublicPath,walkDistTrees};
@@ -0,0 +1,5 @@
1
+ import { Interfere } from "@interfere/javascript";
2
+ //#region src/internal/build/telemetry.d.ts
3
+ export type BuildTelemetry = Omit<Interfere.TelemetryRequest, "result" | "preflight" | "releaseSlug">;
4
+ export declare const EMPTY_TELEMETRY: BuildTelemetry;
5
+ //#endregion
@@ -0,0 +1 @@
1
+ const EMPTY_TELEMETRY={cleanup:0,createRelease:0,discover:0,fileCount:0,total:0,totalBytes:0,upload:0};export{EMPTY_TELEMETRY};
@@ -1,14 +1,11 @@
1
1
  //#region src/internal/build/value-injection-loader.d.ts
2
- type BakedGlobals = Record<string, unknown>;
3
- interface ValueInjectionLoaderOptions {
2
+ export interface ValueInjectionLoaderOptions {
4
3
  readonly serializedFetch?: string;
5
4
  readonly serializedValues?: string;
6
5
  }
7
6
  interface LoaderThis<T> {
8
- async(): (error: Error | null, content?: string) => void;
9
- getOptions(): T;
7
+ async: () => (error: Error | null, content?: string) => void;
8
+ getOptions: () => T;
10
9
  }
11
- declare function valueInjectionLoader(this: LoaderThis<ValueInjectionLoaderOptions>, userCode: string): void;
12
- declare function remoteGlobals(raw: unknown): BakedGlobals;
13
- //#endregion
14
- export { ValueInjectionLoaderOptions, valueInjectionLoader as default, remoteGlobals };
10
+ export default function valueInjectionLoader(this: LoaderThis<ValueInjectionLoaderOptions>, userCode: string): void;
11
+ //#endregion
@@ -1,2 +1,2 @@
1
- import{omitUndefined}from"@interfere/helpers/omit-undefined";import{INGEST_URL_GLOBAL}from"@interfere/types/sdk/injected-globals";import{SERVER_TRACING_GLOBAL}from"@interfere/types/sdk/server-tracing";import{PLUGINS_GLOBAL,remoteConfigSchema}from"@interfere/types/sdk/remote-config";import{LOG_SOURCING_GLOBAL}from"@interfere/types/sdk/log-sourcing";let remoteConfigPromise=null;function valueInjectionLoader(userCode){let options=this.getOptions(),callback=this.async(),values=resolveValues(options);resolveRemoteConfig(resolveFetch(options)).then(globals=>{callback(null,render({...values,...globals},userCode))}).catch(()=>callback(null,render(values,userCode)))}function remoteGlobals(raw){if(!isRecord(raw))return{};let{serverTracing,logSourcing,ingestUrl,plugins}=raw,{shape}=remoteConfigSchema;return omitUndefined({[SERVER_TRACING_GLOBAL]:shape.serverTracing.catch(void 0).parse(serverTracing),[LOG_SOURCING_GLOBAL]:shape.logSourcing.catch(void 0).parse(logSourcing),[INGEST_URL_GLOBAL]:shape.ingestUrl.catch(void 0).parse(ingestUrl),[PLUGINS_GLOBAL]:shape.plugins.partial().optional().catch(void 0).parse(plugins)})}function render(values,userCode){let lines=Object.entries(values).map(([key,value])=>`globalThis[${JSON.stringify(key)}] = ${JSON.stringify(value)};`);return lines.length===0?userCode:`${lines.join(`
2
- `)}\n${userCode}`}function resolveRemoteConfig(fetchOptions){return fetchOptions?(remoteConfigPromise??=fetchRemoteConfig(fetchOptions),remoteConfigPromise):Promise.resolve({})}async function fetchRemoteConfig(fetchOptions){try{let url=`${fetchOptions.apiUrl}/v2/config?pk=${encodeURIComponent(fetchOptions.publicKey)}`,response=await fetch(url,{method:`GET`,headers:{"content-type":`application/json`},signal:AbortSignal.timeout(3e3)});return response.ok?remoteGlobals(await response.json()):{}}catch{return{}}}function parseJson(text){if(typeof text==`string`)try{return JSON.parse(text)}catch{return}}function resolveFetch(options){let parsed=parseJson(options.serializedFetch);return isRemoteConfigFetch(parsed)?parsed:null}function isRemoteConfigFetch(value){return isRecord(value)&&typeof value.apiUrl==`string`&&typeof value.publicKey==`string`}function resolveValues(options){let parsed=parseJson(options.serializedValues);return isRecord(parsed)?parsed:{}}function isRecord(value){return typeof value==`object`&&!!value&&!Array.isArray(value)}export{valueInjectionLoader as default,remoteGlobals};
1
+ import{omitUndefined}from"@interfere/helpers/omit-undefined";import{INGEST_URL_GLOBAL}from"@interfere/types/sdk/injected-globals";import{SERVER_TRACING_GLOBAL}from"@interfere/types/sdk/server-tracing";import{PLUGINS_GLOBAL}from"@interfere/types/sdk/remote-config";import{LOG_SOURCING_GLOBAL}from"@interfere/types/sdk/log-sourcing";import{callbackify}from"node:util";import{createBuildConfigResolver}from"@interfere/build/config";const resolveBuildConfig=createBuildConfigResolver();function valueInjectionLoader(userCode){let options=this.getOptions(),callback=this.async(),values=resolveValues(options);callbackify(async()=>{let globals=await resolveRemoteConfig(resolveFetch(options)).catch(()=>({}));return render({...values,...globals},userCode)})(callback)}function remoteGlobals(config){return omitUndefined({[SERVER_TRACING_GLOBAL]:config.serverTracing,[LOG_SOURCING_GLOBAL]:config.logSourcing,[INGEST_URL_GLOBAL]:config.ingestUrl,[PLUGINS_GLOBAL]:config.plugins})}function render(values,userCode){let lines=Object.entries(values).map(([key,value])=>`globalThis[${JSON.stringify(key)}] = ${JSON.stringify(value)};`);return lines.length===0?userCode:`${lines.join(`
2
+ `)}\n${userCode}`}async function resolveRemoteConfig(fetchOptions){return fetchOptions?resolveBuildConfig(fetchOptions.apiUrl,fetchOptions.publicKey,fetchOptions.cacheScope).then(remoteGlobals):{}}function parseJson(text){if(typeof text==`string`)try{return JSON.parse(text)}catch{return}}function resolveFetch(options){let parsed=parseJson(options.serializedFetch);return isRemoteConfigFetch(parsed)?parsed:null}function isRemoteConfigFetch(value){return isRecord(value)&&typeof value.apiUrl==`string`&&typeof value.publicKey==`string`&&(value.cacheScope===void 0||typeof value.cacheScope==`string`)}function resolveValues(options){let parsed=parseJson(options.serializedValues);return isRecord(parsed)?parsed:{}}function isRecord(value){return typeof value==`object`&&!!value&&!Array.isArray(value)}export{valueInjectionLoader as default};
@@ -1,7 +1,6 @@
1
1
  //#region src/internal/build-marker-guard.d.ts
2
- declare function buildIntegrationRan(): boolean;
3
- declare function hasEnvCredentials(): boolean;
4
- declare function warnBuildIntegrationMissing(): void;
5
- declare function warnBuildIntegrationDegraded(): void;
6
- //#endregion
7
- export { buildIntegrationRan, hasEnvCredentials, warnBuildIntegrationDegraded, warnBuildIntegrationMissing };
2
+ export declare function buildIntegrationRan(): boolean;
3
+ export declare function hasEnvCredentials(): boolean;
4
+ export declare function warnBuildIntegrationMissing(): void;
5
+ export declare function warnBuildIntegrationDegraded(): void;
6
+ //#endregion
@@ -1 +1 @@
1
- import{BUILD_MARKER_GLOBAL}from"@interfere/types/sdk/injected-globals";function buildIntegrationRan(){return globalThis[BUILD_MARKER_GLOBAL]!==void 0}function hasEnvCredentials(){return typeof process>`u`?!1:!!process.env.INTERFERE_PUBLIC_KEY||!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE}function warnBuildIntegrationMissing(){console.warn(`[interfere] withInterfere() did not run for this build, so Interfere is inactive and will send no events. Another Next config wrapper can silently drop it when wrapping withInterfere(). Make withInterfere() the outermost wrapper in next.config, or upgrade the wrapping tool.`)}function warnBuildIntegrationDegraded(){console.warn(`[interfere] withInterfere() did not run for this build. Interfere will still send events using credentials from the environment, but release association and sourcemaps are unavailable. Make withInterfere() the outermost wrapper in next.config to restore them.`)}export{buildIntegrationRan,hasEnvCredentials,warnBuildIntegrationDegraded,warnBuildIntegrationMissing};
1
+ import{BUILD_MARKER_GLOBAL}from"@interfere/types/sdk/injected-globals";function buildIntegrationRan(){let globals=globalThis;return BUILD_MARKER_GLOBAL in globals&&globals[BUILD_MARKER_GLOBAL]!==void 0}function hasEnvCredentials(){return typeof process>`u`?!1:!!process.env.INTERFERE_PUBLIC_KEY||!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE}function warnBuildIntegrationMissing(){console.warn(`[interfere] withInterfere() did not run for this build, so Interfere is inactive and will send no events. Another Next config wrapper can silently drop it when wrapping withInterfere(). Make withInterfere() the outermost wrapper in next.config, or upgrade the wrapping tool.`)}function warnBuildIntegrationDegraded(){console.warn(`[interfere] withInterfere() did not run for this build. Interfere will still send events using credentials from the environment, but release association and sourcemaps are unavailable. Make withInterfere() the outermost wrapper in next.config to restore them.`)}export{buildIntegrationRan,hasEnvCredentials,warnBuildIntegrationDegraded,warnBuildIntegrationMissing};
@@ -1,15 +1,4 @@
1
1
  //#region src/internal/env.d.ts
2
- interface InterfereEnv {
3
- readonly apiKey: string | null;
4
- readonly apiUrl: string;
5
- readonly nextRuntime: string | null;
6
- readonly nodeEnvironment: string;
7
- readonly publicKey: string | null;
8
- readonly release: {
9
- readonly sourceId: string | null;
10
- readonly destinationId: string | null;
11
- };
12
- }
13
2
  /**
14
3
  * Server-side gate for the proxy route handler, the `captureError` /
15
4
  * `onRequestError` helpers, and the remote-config fetcher. Distinct
@@ -19,7 +8,16 @@ interface InterfereEnv {
19
8
  * opt-in, and there's no "unknown runtime, default enabled" case the
20
9
  * way the browser SDK has for plain-browser / Vite hosts.
21
10
  */
22
- declare function isEnabledOnServer(): boolean;
23
- declare function readInterfereEnv(): InterfereEnv;
24
- //#endregion
25
- export { InterfereEnv, isEnabledOnServer, readInterfereEnv };
11
+ export declare function isEnabledOnServer(): boolean;
12
+ export declare function readInterfereEnv(): {
13
+ apiKey: string | null;
14
+ apiUrl: string;
15
+ nextRuntime: string | null;
16
+ nodeEnvironment: string;
17
+ publicKey: string | null;
18
+ release: {
19
+ destinationId: string | null;
20
+ sourceId: string | null;
21
+ };
22
+ };
23
+ //#endregion
@@ -1 +1 @@
1
- import{API_URL}from"@interfere/constants/api";import{parseEnvValue}from"@interfere/types/sdk/env";import{resolveEnvironment}from"@interfere/types/sdk/runtime";function isEnabledOnServer(){return process.env.NODE_ENV===`production`||!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE}function readInterfereEnv(){let nodeEnvironment=resolveEnvironment({env:process.env});return{apiKey:parseEnvValue(process.env.INTERFERE_API_KEY),apiUrl:parseEnvValue(process.env.INTERFERE_API_URL)??API_URL,nextRuntime:parseEnvValue(process.env.NEXT_RUNTIME),nodeEnvironment,publicKey:parseEnvValue(process.env.INTERFERE_PUBLIC_KEY),release:{sourceId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_BUILD_ID),destinationId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_RELEASE_ID)}}}export{isEnabledOnServer,readInterfereEnv};
1
+ import{API_URL}from"@interfere/constants/api";import{ENVIRONMENT_GLOBAL}from"@interfere/types/sdk/injected-globals";import{getStringGlobal}from"@interfere/react/util/global";import{parseEnvValue}from"@interfere/types/sdk/env";import{resolveEnvironment}from"@interfere/types/sdk/runtime";function isEnabledOnServer(){return process.env.NODE_ENV===`production`||!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE}function readInterfereEnv(){let nodeEnvironment=resolveEnvironment({env:process.env,explicit:getStringGlobal(ENVIRONMENT_GLOBAL)});return{apiKey:parseEnvValue(process.env.INTERFERE_API_KEY),apiUrl:parseEnvValue(process.env.INTERFERE_API_URL)??API_URL,nextRuntime:parseEnvValue(process.env.NEXT_RUNTIME),nodeEnvironment,publicKey:parseEnvValue(process.env.INTERFERE_PUBLIC_KEY),release:{destinationId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_RELEASE_ID),sourceId:parseEnvValue(process.env.NEXT_PUBLIC_INTERFERE_BUILD_ID)}}}export{isEnabledOnServer,readInterfereEnv};
@@ -4,14 +4,13 @@
4
4
  * appropriate. Tagged so callers' catch blocks can re-throw fatal errors and
5
5
  * keep test-env behavior aligned with the production hard-exit.
6
6
  */
7
- declare class FatalError extends Error {
7
+ export declare class FatalError extends Error {
8
8
  readonly name = "FatalError";
9
9
  }
10
- declare const log: {
11
- info: (title: string, lines: string[]) => void;
12
- warn: (title: string, lines: string[]) => void;
10
+ export declare const log: {
13
11
  error: (title: string, lines: string[]) => void;
14
12
  fatal(title: string, lines: string[]): never;
13
+ info: (title: string, lines: string[]) => void;
14
+ warn: (title: string, lines: string[]) => void;
15
15
  };
16
- //#endregion
17
- export { FatalError, log };
16
+ //#endregion
@@ -1 +1 @@
1
- import chalk from"chalk";const styles={info:{prefix:`${chalk.whiteBright.bold(`❖`)}`,text:chalk.cyan.bold,content:chalk.white,prependLevel:!1},warn:{prefix:`${chalk.yellow.bold(`⚠`)} `,text:chalk.yellow.bold,content:chalk.yellowBright,prependLevel:!1},error:{prefix:`${chalk.red.bold(`⨯`)} `,text:chalk.red.bold,content:chalk.redBright,prependLevel:!0},fatal:{prefix:`${chalk.red.bold(`⨯`)} `,text:chalk.red.bold,content:chalk.redBright,prependLevel:!0}},consoleMethods={info:`log`,warn:`warn`,error:`error`,fatal:`error`};function isTestEnv(){return!!(process.env.VITEST||process.env.VITEST_WORKER_ID)}var FatalError=class extends Error{name=`FatalError`};function emit(level,title,lines){if(isTestEnv())return;let style=styles[level],method=consoleMethods[level],fn=globalThis.console[method];if(typeof fn!=`function`)return;let invoke=(...args)=>Reflect.apply(fn,globalThis.console,args),prependLevel=style.prependLevel?`[${style.text(level.toUpperCase())}] `:``;invoke(`${prependLevel} ${chalk.white(`Interfere →`)} ${style.text(title)}`);for(let[i,line]of lines.entries())invoke(`${prependLevel} ${i===lines.length-1?`└`:`├`} ${style.content(line)}`)}const log={info:(title,lines)=>emit(`info`,title,lines),warn:(title,lines)=>emit(`warn`,title,lines),error:(title,lines)=>emit(`error`,title,lines),fatal(title,lines){if(emit(`fatal`,title,lines),isTestEnv())throw new FatalError(title);process.exit(1)}};export{FatalError,log};
1
+ import chalk from"chalk";const styles={error:{content:chalk.redBright,prefix:`${chalk.red.bold(`⨯`)} `,prependLevel:!0,text:chalk.red.bold},fatal:{content:chalk.redBright,prefix:`${chalk.red.bold(`⨯`)} `,prependLevel:!0,text:chalk.red.bold},info:{content:chalk.white,prefix:chalk.whiteBright.bold(`❖`),prependLevel:!1,text:chalk.cyan.bold},warn:{content:chalk.yellowBright,prefix:`${chalk.yellow.bold(`⚠`)} `,prependLevel:!1,text:chalk.yellow.bold}},consoleMethods={error:`error`,fatal:`error`,info:`log`,warn:`warn`};function isTestEnv(){return!!(process.env.VITEST||process.env.VITEST_WORKER_ID)}var FatalError=class extends Error{name=`FatalError`};function emit(level,title,lines){if(isTestEnv())return;let style=styles[level],method=consoleMethods[level],fn=globalThis.console[method];if(typeof fn!=`function`)return;let prependLevel=style.prependLevel?`[${style.text(level.toUpperCase())}] `:``;fn.call(globalThis.console,`${prependLevel} ${chalk.white(`Interfere →`)} ${style.text(title)}`);for(let[i,line]of lines.entries()){let connector=i===lines.length-1?`└`:`├`;fn.call(globalThis.console,`${prependLevel} ${connector} ${style.content(line)}`)}}const log={error:(title,lines)=>{emit(`error`,title,lines)},fatal(title,lines){if(emit(`fatal`,title,lines),isTestEnv())throw new FatalError(title);process.exit(1)},info:(title,lines)=>{emit(`info`,title,lines)},warn:(title,lines)=>{emit(`warn`,title,lines)}};export{FatalError,log};
@@ -1,9 +1,7 @@
1
- import { ReleaseSlug } from "@interfere/types/releases/slug";
2
1
  import { RunGitCommand } from "@interfere/types/sdk/github-source";
3
2
  //#region src/internal/release-slug.d.ts
4
- declare function resolveReleaseSlug(runGit?: RunGitCommand): {
3
+ export declare function resolveReleaseSlug(runGit?: RunGitCommand): {
5
4
  commitSha: string | null;
6
- slug: ReleaseSlug | null;
5
+ slug: (`rel_${string}` & import("zod").$brand<"ReleaseSlug">) | null;
7
6
  };
8
- //#endregion
9
- export { resolveReleaseSlug };
7
+ //#endregion
@@ -1 +1 @@
1
- import{deriveReleaseSlug,releaseSlugSchema}from"@interfere/types/releases/slug";import{RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{resolveReleaseCommitSha}from"@interfere/types/sdk/github-source";const noGit=()=>null;function readBakedReleaseSlug(){let value=globalThis[RELEASE_SLUG_GLOBAL];if(typeof value!=`string`)return null;let parsed=releaseSlugSchema.safeParse(value);return parsed.success?parsed.data:null}function resolveReleaseSlug(runGit=noGit){let baked=readBakedReleaseSlug();if(baked)return{commitSha:null,slug:baked};let commitSha=resolveReleaseCommitSha(process.env,runGit);return{commitSha,slug:commitSha?deriveReleaseSlug(commitSha):null}}export{resolveReleaseSlug};
1
+ import{deriveReleaseSlug,releaseSlugSchema}from"@interfere/types/releases/slug";import{RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{resolveReleaseCommitSha}from"@interfere/types/sdk/github-source";const noGit=()=>null;function readBakedReleaseSlug(){let globals=globalThis;if(!(RELEASE_SLUG_GLOBAL in globals))return null;let parsed=releaseSlugSchema.safeParse(globals[RELEASE_SLUG_GLOBAL]);return parsed.success?parsed.data:null}function resolveReleaseSlug(runGit=noGit){let baked=readBakedReleaseSlug();if(baked)return{commitSha:null,slug:baked};let commitSha=resolveReleaseCommitSha(process.env,runGit);return{commitSha,slug:commitSha?deriveReleaseSlug(commitSha):null}}export{resolveReleaseSlug};
@@ -0,0 +1,24 @@
1
+ import { Context, TextMapSetter } from "@opentelemetry/api";
2
+ import { W3CTraceContextPropagator } from "@opentelemetry/core";
3
+ //#region src/internal/server/cache-safe-trace-context.d.ts
4
+ export interface CacheSafeTraceContextPropagatorOptions {
5
+ isStaticRender?: () => boolean;
6
+ }
7
+ /**
8
+ * W3C trace-context propagator that refuses to feed `clientTraceMetadata`
9
+ * during static-generation renders (build prerender, runtime ISR
10
+ * revalidation). Trace context injected into such a render is baked into
11
+ * cached HTML and served verbatim to every visitor in the cache window —
12
+ * there is no per-visitor server trace for a cache hit, so the idiomatic
13
+ * output is no trace meta at all, exactly what Next produces for
14
+ * build-time prerenders. Detected by the carrier shape: Next's
15
+ * `clientTraceMetadata` collector is the only inject path that passes an
16
+ * array carrier. Every other carrier (outgoing fetch headers during a
17
+ * revalidation render included) injects normally.
18
+ */
19
+ export declare class CacheSafeTraceContextPropagator extends W3CTraceContextPropagator {
20
+ private readonly isStaticRender;
21
+ constructor(options?: CacheSafeTraceContextPropagatorOptions);
22
+ inject<Carrier>(context: Context, carrier: Carrier, setter: TextMapSetter<Carrier>): void;
23
+ }
24
+ //#endregion
@@ -0,0 +1 @@
1
+ import{isStaticGenerationRender}from"./static-generation.mjs";import{W3CTraceContextPropagator}from"@opentelemetry/core";var CacheSafeTraceContextPropagator=class extends W3CTraceContextPropagator{isStaticRender;constructor(options={}){super(),this.isStaticRender=options.isStaticRender??isStaticGenerationRender}inject(context,carrier,setter){Array.isArray(carrier)&&this.isStaticRender()||super.inject(context,carrier,setter)}};export{CacheSafeTraceContextPropagator};
@@ -1,13 +1,12 @@
1
1
  import { CaptureErrorContext, OnRequestErrorContext } from "./types.mjs";
2
2
  //#region src/internal/server/capture.d.ts
3
- declare function captureError(error: unknown, _request?: unknown, context?: CaptureErrorContext): void;
3
+ export declare function captureError(error: unknown, _request?: unknown, context?: CaptureErrorContext): void;
4
4
  interface OnRequestErrorRequest {
5
5
  readonly headers?: Record<string, string>;
6
6
  readonly method?: string;
7
7
  readonly path?: string;
8
8
  }
9
- declare function onRequestError(error: Error & {
9
+ export declare function onRequestError(error: Error & {
10
10
  digest?: string;
11
11
  }, request: OnRequestErrorRequest | undefined, context: OnRequestErrorContext): Promise<void>;
12
- //#endregion
13
- export { captureError, onRequestError };
12
+ //#endregion
@@ -1 +1 @@
1
- import{isEnabledOnServer}from"../env.mjs";import{flushServerTelemetry}from"./server-flush.mjs";import{isPluginEnabled}from"./remote-config.mjs";import{readServerAction}from"./server-action-marker.mjs";import{SpanKind,SpanStatusCode,trace}from"@opentelemetry/api";import{MECHANISM_TYPE,isNonErrorException,toException}from"@interfere/types/sdk/errors";const ON_REQUEST_ERROR_MECHANISM={type:MECHANISM_TYPE.nextjs.onRequestError,handled:!1,synthetic:!1},SERVER_ACTION_MECHANISM={type:MECHANISM_TYPE.nextjs.serverAction,handled:!1,synthetic:!1},ROUTE_HANDLER_MECHANISM={type:MECHANISM_TYPE.nextjs.routeHandler,handled:!1,synthetic:!1},DEFAULT_CAPTURE_ERROR_MECHANISM={type:MECHANISM_TYPE.nextjs.captureError,handled:!0},CONTROL_FLOW_DIGEST_PREFIXES=[`NEXT_REDIRECT`,`NEXT_NOT_FOUND`,`NEXT_HTTP_ERROR_FALLBACK`];function isNextControlFlowError(error){if(!(error instanceof Error))return!1;let{digest}=error;return typeof digest==`string`&&CONTROL_FLOW_DIGEST_PREFIXES.some(prefix=>digest.startsWith(prefix))}const seen=new WeakSet;function addNextjsAttrs(attrs,nextjs,handled){nextjs&&(nextjs.errorDigest&&(attrs[`interfere.error.digest`]=nextjs.errorDigest),nextjs.requestMethod&&(attrs[`http.request.method`]=nextjs.requestMethod),nextjs.requestPath&&(attrs[`url.path`]=nextjs.requestPath),nextjs.routePath&&(attrs[`http.route`]=nextjs.routePath),nextjs.routeType===`route`&&!handled&&(attrs[`http.response.status_code`]=500))}function addRequestContextAttrs(attrs,context){if(context?.serverAction&&(attrs[`interfere.server_action.name`]=context.serverAction.name,context.serverAction.argsShape&&(attrs[`interfere.server_action.args_shape`]=context.serverAction.argsShape)),context?.requestHeaders)for(let[name,headerValue]of Object.entries(context.requestHeaders))attrs[`http.request.header.${name}`]=headerValue}function addExceptionAttrs(attrs,value){if(isNonErrorException(value)){attrs[`exception.type`]=value.type,attrs[`exception.message`]=value.value,attrs[`interfere.exception.kind`]=`non-error`;return}attrs[`exception.type`]=value.name,attrs[`exception.message`]=value.message,attrs[`interfere.exception.kind`]=`error`,value.stack&&(attrs[`exception.stacktrace`]=value.stack)}function buildAttrs(value,mechanism,context){let attrs={"interfere.exception.mechanism":mechanism.type,"interfere.exception.handled":mechanism.handled};return addNextjsAttrs(attrs,context?.nextjs,mechanism.handled),addRequestContextAttrs(attrs,context),addExceptionAttrs(attrs,value),attrs}function recordException({error,mechanism,context}){let value=toException(error),attrs=buildAttrs(value,mechanism,context),tracer=trace.getTracer(`@interfere/next/server`),active=trace.getActiveSpan();if(active?.isRecording()){active.addEvent(`exception`,attrs),mechanism.handled||active.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message});return}let span=tracer.startSpan(`interfere.captureError`,{kind:SpanKind.INTERNAL});span.addEvent(`exception`,attrs),mechanism.handled||span.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message}),span.end()}function captureError(error,_request,context){if(isEnabledOnServer()&&isPluginEnabled(`errors`)&&!isNextControlFlowError(error)){if(error instanceof Error){if(seen.has(error))return;seen.add(error)}recordException({error,mechanism:context?.mechanism??DEFAULT_CAPTURE_ERROR_MECHANISM,context})}}const CAPTURED_REQUEST_HEADERS=[`accept`,`accept-language`,`content-length`,`content-type`,`host`,`referer`,`user-agent`,`x-forwarded-for`,`x-forwarded-host`,`x-forwarded-proto`,`x-vercel-id`];function pickAllowedHeaders(headers){if(!headers)return;let picked={};for(let name of CAPTURED_REQUEST_HEADERS){let value=headers[name];typeof value==`string`&&(picked[name]=value)}return Object.keys(picked).length>0?picked:void 0}async function onRequestError(error,request,context){if(isNextControlFlowError(error)||seen.has(error)||(seen.add(error),!isEnabledOnServer())||!isPluginEnabled(`errors`))return;let action=readServerAction(error),mechanism=ON_REQUEST_ERROR_MECHANISM;action?mechanism=SERVER_ACTION_MECHANISM:context.routeType===`route`&&(mechanism=ROUTE_HANDLER_MECHANISM);let requestHeaders=pickAllowedHeaders(request?.headers);recordException({error,mechanism,context:{mechanism,nextjs:{...context,...request?.method?{requestMethod:request.method}:{},...request?.path?{requestPath:request.path}:{},...error.digest?{errorDigest:error.digest}:{}},...requestHeaders?{requestHeaders}:{},...action?{serverAction:action}:{}}});try{await flushServerTelemetry()}catch{return}}export{captureError,onRequestError};
1
+ import{isEnabledOnServer}from"../env.mjs";import{flushServerTelemetry}from"./server-flush.mjs";import{isPluginEnabled}from"./remote-config.mjs";import{readServerAction}from"./server-action-marker.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{SpanKind,SpanStatusCode,trace}from"@opentelemetry/api";import{MECHANISM_TYPE,isNonErrorException,toException}from"@interfere/types/sdk/errors";const ON_REQUEST_ERROR_MECHANISM={handled:!1,synthetic:!1,type:MECHANISM_TYPE.nextjs.onRequestError},SERVER_ACTION_MECHANISM={handled:!1,synthetic:!1,type:MECHANISM_TYPE.nextjs.serverAction},ROUTE_HANDLER_MECHANISM={handled:!1,synthetic:!1,type:MECHANISM_TYPE.nextjs.routeHandler},DEFAULT_CAPTURE_ERROR_MECHANISM={handled:!0,type:MECHANISM_TYPE.nextjs.captureError},CONTROL_FLOW_DIGEST_PREFIXES=[`NEXT_REDIRECT`,`NEXT_NOT_FOUND`,`NEXT_HTTP_ERROR_FALLBACK`];function isNextControlFlowError(error){if(!(error instanceof Error))return!1;let digest=`digest`in error?error.digest:void 0;return typeof digest==`string`&&CONTROL_FLOW_DIGEST_PREFIXES.some(prefix=>digest.startsWith(prefix))}const seen=new WeakSet;function addNextjsAttrs(attrs,nextjs,handled){nextjs&&(nextjs.errorDigest&&(attrs[`interfere.error.digest`]=nextjs.errorDigest),nextjs.requestMethod&&(attrs[`http.request.method`]=nextjs.requestMethod),nextjs.requestPath&&(attrs[`url.path`]=nextjs.requestPath),nextjs.routePath&&(attrs[`http.route`]=nextjs.routePath),nextjs.routeType===`route`&&!handled&&(attrs[`http.response.status_code`]=500))}function addRequestContextAttrs(attrs,context){if(context?.serverAction&&(attrs[`interfere.server_action.name`]=context.serverAction.name,context.serverAction.argsShape&&(attrs[`interfere.server_action.args_shape`]=context.serverAction.argsShape)),context?.requestHeaders)for(let[name,headerValue]of Object.entries(context.requestHeaders))attrs[`http.request.header.${name}`]=headerValue}function addExceptionAttrs(attrs,value){if(isNonErrorException(value)){attrs[`exception.type`]=value.type,attrs[`exception.message`]=value.value,attrs[`interfere.exception.kind`]=`non-error`;return}attrs[`exception.type`]=value.name,attrs[`exception.message`]=value.message,attrs[`interfere.exception.kind`]=`error`,value.stack&&(attrs[`exception.stacktrace`]=value.stack)}function buildAttrs(value,mechanism,context){let attrs={"interfere.exception.handled":mechanism.handled,"interfere.exception.mechanism":mechanism.type};return addNextjsAttrs(attrs,context?.nextjs,mechanism.handled),addRequestContextAttrs(attrs,context),addExceptionAttrs(attrs,value),attrs}function recordException({error,mechanism,context}){let value=toException(error),attrs=buildAttrs(value,mechanism,context),tracer=trace.getTracer(`@interfere/next/server`),active=trace.getActiveSpan();if(active?.isRecording()){active.addEvent(`exception`,attrs),mechanism.handled||active.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message});return}let span=tracer.startSpan(`interfere.captureError`,{kind:SpanKind.INTERNAL});span.addEvent(`exception`,attrs),mechanism.handled||span.setStatus({code:SpanStatusCode.ERROR,message:isNonErrorException(value)?value.value:value.message}),span.end()}function captureError(error,_request,context){if(isEnabledOnServer()&&isPluginEnabled(`errors`)&&!isNextControlFlowError(error)){if(error instanceof Error){if(seen.has(error))return;seen.add(error)}recordException({context,error,mechanism:context?.mechanism??DEFAULT_CAPTURE_ERROR_MECHANISM})}}const CAPTURED_REQUEST_HEADERS=[`accept`,`accept-language`,`content-length`,`content-type`,`host`,`referer`,`user-agent`,`x-forwarded-for`,`x-forwarded-host`,`x-forwarded-proto`,`x-vercel-id`];function pickAllowedHeaders(headers){if(!headers)return;let picked={};for(let name of CAPTURED_REQUEST_HEADERS){let value=headers[name];typeof value==`string`&&(picked[name]=value)}return Object.keys(picked).length>0?picked:void 0}async function onRequestError(error,request,context){if(isNextControlFlowError(error)||seen.has(error)||(seen.add(error),!isEnabledOnServer())||!isPluginEnabled(`errors`))return;let action=readServerAction(error),mechanism=ON_REQUEST_ERROR_MECHANISM;action?mechanism=SERVER_ACTION_MECHANISM:context.routeType===`route`&&(mechanism=ROUTE_HANDLER_MECHANISM);let requestHeaders=pickAllowedHeaders(request?.headers);recordException({context:omitUndefined({mechanism,nextjs:omitUndefined({...context,requestMethod:request?.method||void 0,requestPath:request?.path||void 0,errorDigest:error.digest||void 0}),requestHeaders,serverAction:action??void 0}),error,mechanism});try{await flushServerTelemetry()}catch{return}}export{captureError,onRequestError};
@@ -19,6 +19,5 @@
19
19
  * call only captures the active context; an arg mutated before the
20
20
  * microtask runs is serialized in its mutated state.
21
21
  */
22
- declare function bridgeConsoleToOtel(): () => void;
23
- //#endregion
24
- export { bridgeConsoleToOtel };
22
+ export declare function bridgeConsoleToOtel(): () => void;
23
+ //#endregion
@@ -1 +1 @@
1
- import{context,trace}from"@opentelemetry/api";import{logs}from"@opentelemetry/api-logs";const CONSOLE_METHODS=[`debug`,`log`,`info`,`warn`,`error`],SEVERITY={debug:5,log:9,info:9,warn:13,error:17},MAX_BODY_CHARS=8192;function buildBody(args){let body=args.map(stringify).join(` `);return body.length>MAX_BODY_CHARS?`${body.slice(0,MAX_BODY_CHARS)}…`:body}function stringify(value){if(typeof value==`string`)return value;if(value instanceof Error)return value.stack??`${value.name}: ${value.message}`;try{return JSON.stringify(value)}catch{return String(value)}}function extractException(args){for(let arg of args)if(arg instanceof Error)return arg}function buildExceptionAttributes(args){let exception=extractException(args);if(!exception)return;let attrs={"exception.type":exception.name,"exception.message":exception.message};return exception.stack&&(attrs[`exception.stacktrace`]=exception.stack),attrs}function bridgeConsoleToOtel(){let logger=logs.getLogger(`@interfere/next/console`),emitting=!1,bridgeFailures=0,original={debug:console.debug,log:console.log,info:console.info,warn:console.warn,error:console.error};function emitLog(orig,severity,method,args,activeContext,activeSpan){if(!emitting){emitting=!0;try{let attributes=buildExceptionAttributes(args);logger.emit({severityNumber:severity,severityText:method.toUpperCase(),body:buildBody(args),...activeSpan?{context:activeContext}:{},...attributes?{attributes}:{}})}catch(error){bridgeFailures+=1,bridgeFailures%100==1&&orig.call(console,`[interfere] console→OTel bridge emission failed (${bridgeFailures} total):`,error)}finally{emitting=!1}}}for(let method of CONSOLE_METHODS){let orig=original[method],severity=SEVERITY[method];console[method]=(...args)=>{orig.apply(console,args);let activeContext=context.active(),activeSpan=trace.getSpan(activeContext);queueMicrotask(()=>{emitLog(orig,severity,method,args,activeContext,activeSpan)})}}return()=>{for(let method of CONSOLE_METHODS)console[method]=original[method]}}export{bridgeConsoleToOtel};
1
+ import{omitUndefined}from"@interfere/helpers/omit-undefined";import{context,trace}from"@opentelemetry/api";import{logs}from"@opentelemetry/api-logs";const CONSOLE_METHODS=[`debug`,`log`,`info`,`warn`,`error`],SEVERITY={debug:5,error:17,info:9,log:9,warn:13},MAX_BODY_CHARS=8192;function buildBody(args){let body=args.map(element=>stringify(element)).join(` `);return body.length>MAX_BODY_CHARS?`${body.slice(0,MAX_BODY_CHARS)}…`:body}function stringify(value){if(typeof value==`string`)return value;if(value instanceof Error)return value.stack??`${value.name}: ${value.message}`;try{return JSON.stringify(value)}catch{return String(value)}}function extractException(args){for(let arg of args)if(arg instanceof Error)return arg}function buildExceptionAttributes(args){let exception=extractException(args);if(exception)return omitUndefined({"exception.type":exception.name,"exception.message":exception.message,"exception.stacktrace":exception.stack||void 0})}function bridgeConsoleToOtel(){let logger=logs.getLogger(`@interfere/next/console`),emitting=!1,bridgeFailures=0,original={debug:console.debug,error:console.error,info:console.info,log:console.log,warn:console.warn};function emitLog(orig,severity,method,args,activeContext,activeSpan){if(!emitting){emitting=!0;try{let attributes=buildExceptionAttributes(args);logger.emit(omitUndefined({body:buildBody(args),severityNumber:severity,severityText:method.toUpperCase(),context:activeSpan?activeContext:void 0,attributes}))}catch(error){bridgeFailures+=1,bridgeFailures%100==1&&orig.call(console,`[interfere] console→OTel bridge emission failed (${bridgeFailures} total):`,error)}finally{emitting=!1}}}for(let method of CONSOLE_METHODS){let orig=original[method],severity=SEVERITY[method];console[method]=(...args)=>{orig.apply(console,args);let activeContext=context.active(),activeSpan=trace.getSpan(activeContext);queueMicrotask(()=>{emitLog(orig,severity,method,args,activeContext,activeSpan)})}}return(()=>{for(let method of CONSOLE_METHODS)console[method]=original[method]})}export{bridgeConsoleToOtel};
@@ -1,13 +1,12 @@
1
1
  import { ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base";
2
+ import { InterfereClient } from "@interfere/javascript";
2
3
  import { ExportResult } from "@opentelemetry/core";
3
4
  //#region src/internal/server/edge-exporter.d.ts
4
- declare class FetchTraceExporter implements SpanExporter {
5
- private readonly url;
6
- private readonly headers;
7
- constructor(url: string, headers: Record<string, string>);
5
+ export declare class FetchTraceExporter implements SpanExporter {
6
+ private readonly client;
7
+ constructor(options: InterfereClient.Options);
8
8
  export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
9
9
  shutdown(): Promise<void>;
10
10
  forceFlush(): Promise<void>;
11
11
  }
12
- //#endregion
13
- export { FetchTraceExporter };
12
+ //#endregion
@@ -1 +1 @@
1
- import{ExportResultCode}from"@opentelemetry/core";import{JsonTraceSerializer}from"@opentelemetry/otlp-transformer/build/esm/trace/json/trace.js";var FetchTraceExporter=class{url;headers;constructor(url,headers){this.url=url,this.headers=headers}export(spans,resultCallback){if(spans.length===0){resultCallback({code:ExportResultCode.SUCCESS});return}let payload=JsonTraceSerializer.serializeRequest(spans);if(!payload||payload.byteLength===0){resultCallback({code:ExportResultCode.SUCCESS});return}fetch(this.url,{method:`POST`,headers:{...this.headers,"content-type":`application/json`},body:new TextDecoder().decode(payload),keepalive:!0}).catch(()=>{}),resultCallback({code:ExportResultCode.SUCCESS})}shutdown(){return Promise.resolve()}forceFlush(){return Promise.resolve()}};export{FetchTraceExporter};
1
+ import{InterfereClient}from"@interfere/javascript";import{toError}from"@interfere/types/sdk/errors";import{ExportResultCode}from"@opentelemetry/core";import{JsonTraceSerializer}from"@opentelemetry/otlp-transformer";import{z}from"zod";var FetchTraceExporter=class{client;constructor(options){this.client=new InterfereClient({...options,maxRetries:0,fetch:Object.assign(async(url,init)=>globalThis.fetch(url,{...init,keepalive:!0}),globalThis.fetch)})}export(spans,resultCallback){if(spans.length===0){resultCallback({code:ExportResultCode.SUCCESS});return}let payload=JsonTraceSerializer.serializeRequest(spans);if(!payload||payload.byteLength===0){resultCallback({code:ExportResultCode.SUCCESS});return}(async()=>{try{let body=z.record(z.string(),z.unknown()).parse(JSON.parse(new TextDecoder().decode(payload)));await this.client.drain.otlpExport({signal:`traces`,body}),resultCallback({code:ExportResultCode.SUCCESS})}catch(error){resultCallback({code:ExportResultCode.FAILED,error:toError(error)})}})()}async shutdown(){return Promise.resolve()}async forceFlush(){return Promise.resolve()}};export{FetchTraceExporter};
@@ -0,0 +1,41 @@
1
+ import { Context, TextMapPropagator, TextMapSetter } from "@opentelemetry/api";
2
+ //#region src/internal/server/freshness-propagator.d.ts
3
+ export interface FreshnessStampingPropagatorOptions {
4
+ isStaticRender?: () => boolean;
5
+ }
6
+ /**
7
+ * Stamp-only propagator that writes a `tracestate` freshness entry
8
+ * (`interfere=<unix seconds>`) at inject time. It never touches
9
+ * `traceparent`, so it composes cleanly after any W3C trace-context
10
+ * propagator — the standalone `register()` path pairs it with
11
+ * `CacheSafeTraceContextPropagator`, and composed bootstraps
12
+ * (`@vercel/otel`'s `propagators: ["auto", ...kit.propagators]`,
13
+ * dd-trace, custom providers) pick it up through `kit.propagators`
14
+ * without conflicting with their own trace-context propagator.
15
+ *
16
+ * Why: Next's `clientTraceMetadata` bakes the injected trace context
17
+ * into any HTML it caches — ISR revalidations and CDN full-page caches
18
+ * then serve one render's `traceparent` to every visitor in the cache
19
+ * window, and the browser SDK would stitch all of those sessions onto a
20
+ * single stale trace. The client's propagation reader uses this stamp
21
+ * to drop traceparents older than its freshness window; a re-injected
22
+ * stamp always overwrites an inherited one, so the value reflects this
23
+ * render, not the upstream request that carried it in.
24
+ *
25
+ * Static-generation renders (build prerender, runtime ISR revalidation)
26
+ * feed `clientTraceMetadata` through an array carrier. On those, the
27
+ * stamp is written only when a trace-context propagator ahead of this
28
+ * one already wrote `traceparent` into the carrier — a composed setup
29
+ * whose own propagator this SDK cannot gate, where the stamp is the
30
+ * only staleness defense. In the standalone `register()` path the
31
+ * cache-safe propagator skips `traceparent` first, so no meta is
32
+ * emitted at all, matching Next's build-time prerender output.
33
+ */
34
+ export declare class FreshnessStampingPropagator implements TextMapPropagator {
35
+ private readonly isStaticRender;
36
+ constructor(options?: FreshnessStampingPropagatorOptions);
37
+ inject<Carrier>(context: Context, carrier: Carrier, setter: TextMapSetter<Carrier>): void;
38
+ extract(context: Context): Context;
39
+ fields(): string[];
40
+ }
41
+ //#endregion
@@ -0,0 +1 @@
1
+ import{isStaticGenerationRender}from"./static-generation.mjs";import{isSpanContextValid,trace}from"@opentelemetry/api";import{TraceState,isTracingSuppressed}from"@opentelemetry/core";import{TRACESTATE_FRESHNESS_KEY,freshnessStamp}from"@interfere/types/sdk/trace-freshness";const TRACE_STATE_HEADER=`tracestate`;function carrierHoldsTraceparent(carrier){return carrier.some(entry=>typeof entry==`object`&&!!entry&&`key`in entry&&entry.key===`traceparent`)}var FreshnessStampingPropagator=class{isStaticRender;constructor(options={}){this.isStaticRender=options.isStaticRender??isStaticGenerationRender}inject(context,carrier,setter){let spanContext=trace.getSpanContext(context);if(!spanContext||!isSpanContextValid(spanContext)||isTracingSuppressed(context)||Array.isArray(carrier)&&this.isStaticRender()&&!carrierHoldsTraceparent(carrier))return;let traceState=(spanContext.traceState??new TraceState).set(TRACESTATE_FRESHNESS_KEY,freshnessStamp(Date.now()));setter.set(carrier,TRACE_STATE_HEADER,traceState.serialize())}extract(context){return context}fields(){return[TRACE_STATE_HEADER]}};export{FreshnessStampingPropagator};
@@ -1,11 +1,10 @@
1
1
  //#region src/internal/server/global-handlers.d.ts
2
- interface GlobalHandlerOptions {
2
+ export interface GlobalHandlerOptions {
3
3
  readonly captureUncaughtException: boolean;
4
4
  readonly captureUnhandledRejection: boolean;
5
5
  readonly exitOnUncaughtException: boolean;
6
6
  readonly flush: () => Promise<void>;
7
7
  }
8
- declare function installGlobalHandlers(options: GlobalHandlerOptions): void;
9
- declare function uninstallGlobalHandlers(): void;
10
- //#endregion
11
- export { GlobalHandlerOptions, installGlobalHandlers, uninstallGlobalHandlers };
8
+ export declare function installGlobalHandlers(options: GlobalHandlerOptions): void;
9
+ export declare function uninstallGlobalHandlers(): void;
10
+ //#endregion
@@ -1 +1 @@
1
- import{captureError}from"./capture.mjs";import{MECHANISM_TYPE}from"@interfere/types/sdk/errors";let uncaughtHandler=null,unhandledHandler=null;function installGlobalHandlers(options){options.captureUncaughtException&&uncaughtHandler===null&&(uncaughtHandler=error=>{handleUncaughtException(error,options)},process.on(`uncaughtException`,uncaughtHandler)),options.captureUnhandledRejection&&unhandledHandler===null&&(unhandledHandler=reason=>{handleUnhandledRejection(reason,options)},process.on(`unhandledRejection`,unhandledHandler))}function uninstallGlobalHandlers(){uncaughtHandler!==null&&(process.off(`uncaughtException`,uncaughtHandler),uncaughtHandler=null),unhandledHandler!==null&&(process.off(`unhandledRejection`,unhandledHandler),unhandledHandler=null)}async function handleUncaughtException(error,options){captureError(error,void 0,{mechanism:{type:MECHANISM_TYPE.node.uncaughtException,handled:!1}}),await flushWithTimeout(options.flush),options.exitOnUncaughtException&&process.exit(1)}async function handleUnhandledRejection(reason,options){captureError(reason,void 0,{mechanism:{type:MECHANISM_TYPE.node.unhandledRejection,handled:!1}}),await flushWithTimeout(options.flush)}async function flushWithTimeout(flush){let{promise:timedOut,resolve:expire}=Promise.withResolvers(),timer=setTimeout(()=>expire(void 0),2e3);timer.unref?.();try{await Promise.race([Promise.allSettled([flush()]),timedOut])}finally{clearTimeout(timer)}}export{installGlobalHandlers,uninstallGlobalHandlers};
1
+ import{captureError}from"./capture.mjs";import{MECHANISM_TYPE}from"@interfere/types/sdk/errors";let uncaughtHandler=null,unhandledHandler=null;function installGlobalHandlers(options){options.captureUncaughtException&&uncaughtHandler===null&&(uncaughtHandler=error=>{handleUncaughtException(error,options)},process.on(`uncaughtException`,uncaughtHandler)),options.captureUnhandledRejection&&unhandledHandler===null&&(unhandledHandler=reason=>{handleUnhandledRejection(reason,options)},process.on(`unhandledRejection`,unhandledHandler))}function uninstallGlobalHandlers(){uncaughtHandler!==null&&(process.off(`uncaughtException`,uncaughtHandler),uncaughtHandler=null),unhandledHandler!==null&&(process.off(`unhandledRejection`,unhandledHandler),unhandledHandler=null)}async function handleUncaughtException(error,options){captureError(error,void 0,{mechanism:{handled:!1,type:MECHANISM_TYPE.node.uncaughtException}}),await flushWithTimeout(options.flush),options.exitOnUncaughtException&&process.exit(1)}async function handleUnhandledRejection(reason,options){captureError(reason,void 0,{mechanism:{handled:!1,type:MECHANISM_TYPE.node.unhandledRejection}}),await flushWithTimeout(options.flush)}async function flushWithTimeout(flush){let{promise:timedOut,resolve:expire}=Promise.withResolvers(),timer=setTimeout(()=>{expire(void 0)},2e3);timer.unref?.();try{await Promise.race([Promise.allSettled([flush()]),timedOut])}finally{clearTimeout(timer)}}export{installGlobalHandlers,uninstallGlobalHandlers};
@@ -21,7 +21,7 @@ import { IdGenerator } from "@opentelemetry/sdk-trace-base";
21
21
  * a monotonic counter. Counter widths are masked to keep IDs at their
22
22
  * spec-mandated lengths even after wrap.
23
23
  */
24
- declare class PrerenderSafeIdGenerator implements IdGenerator {
24
+ export declare class PrerenderSafeIdGenerator implements IdGenerator {
25
25
  private readonly random;
26
26
  private readonly tracePrefix;
27
27
  private readonly spanPrefix;
@@ -33,5 +33,4 @@ declare class PrerenderSafeIdGenerator implements IdGenerator {
33
33
  private fallbackTraceId;
34
34
  private fallbackSpanId;
35
35
  }
36
- //#endregion
37
- export { PrerenderSafeIdGenerator };
36
+ //#endregion
@@ -21,7 +21,7 @@ import { LogRecordProcessor } from "@opentelemetry/sdk-logs";
21
21
  * so they're erased before bundling — the Edge runtime bundle never sees
22
22
  * them at all.
23
23
  */
24
- interface ServerInstrumentationOptions {
24
+ export interface ServerInstrumentationOptions {
25
25
  /** @internal */
26
26
  _internalAdditionalLogRecordProcessors?: LogRecordProcessor[];
27
27
  /**
@@ -47,7 +47,7 @@ interface ServerInstrumentationOptions {
47
47
  captureUnhandledRejection?: boolean;
48
48
  /**
49
49
  * OTLP payload compression. Default `"none"`. `"gzip"` shrinks each
50
- * `/v2/sink` POST body.
50
+ * `/drain/v1/*` POST body.
51
51
  */
52
52
  compression?: "gzip" | "none";
53
53
  /**
@@ -63,5 +63,4 @@ interface ServerInstrumentationOptions {
63
63
  */
64
64
  serviceName?: string;
65
65
  }
66
- //#endregion
67
- export { ServerInstrumentationOptions };
66
+ //#endregion
@@ -1,5 +1,4 @@
1
1
  //#region src/internal/server/remote-config.d.ts
2
- declare function fetchAndCacheRemoteConfig(): Promise<void>;
3
- declare function isPluginEnabled(plugin: string): boolean;
4
- //#endregion
5
- export { fetchAndCacheRemoteConfig, isPluginEnabled };
2
+ export declare function fetchAndCacheRemoteConfig(): Promise<void>;
3
+ export declare function isPluginEnabled(plugin: string): boolean;
4
+ //#endregion
@@ -1 +1 @@
1
- import{isEnabledOnServer,readInterfereEnv}from"../env.mjs";import{withPublicKey}from"../url.mjs";import{API_PATHS}from"@interfere/constants/api";import{readBakedPlugins}from"@interfere/types/sdk/remote-config";let cachedConfig=null;async function fetchAndCacheRemoteConfig(){if(readBakedPlugins()||!isEnabledOnServer())return;let env=readInterfereEnv();if(env.publicKey!==null)try{let url=withPublicKey(`${env.apiUrl}${API_PATHS.CONFIG}`,env.publicKey),response=await fetch(url,{method:`GET`,headers:{"content-type":`application/json`},signal:AbortSignal.timeout(1e4)});if(!response.ok)return;let config=await response.json();config?.plugins&&(cachedConfig=config.plugins)}catch{return}}function isPluginEnabled(plugin){let config=readBakedPlugins()??cachedConfig;return!config||config[plugin]!==!1}export{fetchAndCacheRemoteConfig,isPluginEnabled};
1
+ import{isEnabledOnServer,readInterfereEnv}from"../env.mjs";import{InterfereClient}from"@interfere/javascript";import{readBakedPlugins,remoteConfigInputSchema}from"@interfere/types/sdk/remote-config";let cachedConfig=null;async function fetchAndCacheRemoteConfig(){if(readBakedPlugins()||!isEnabledOnServer())return;let env=readInterfereEnv();if(env.publicKey!==null)try{let client=new InterfereClient({baseUrl:env.apiUrl,publicKeyHeader:{apiKey:env.publicKey},timeoutInSeconds:10,maxRetries:0}),config=remoteConfigInputSchema.parse(await client.config.getSdkConfig());config.plugins&&(cachedConfig=config.plugins)}catch{return}}function isPluginEnabled(plugin){let config=readBakedPlugins()??cachedConfig;return!config||config[plugin]!==!1}export{fetchAndCacheRemoteConfig,isPluginEnabled};
@@ -1,9 +1,14 @@
1
1
  //#region src/internal/server/server-action-marker.d.ts
2
- interface ServerActionMarker {
2
+ export interface ServerActionMarker {
3
3
  readonly argsShape?: string;
4
4
  readonly name: string;
5
5
  }
6
- declare function markServerAction(error: unknown, info: ServerActionMarker): void;
7
- declare function readServerAction(error: unknown): ServerActionMarker | undefined;
8
- //#endregion
9
- export { ServerActionMarker, markServerAction, readServerAction };
6
+ export declare function markServerAction(error: unknown, info: ServerActionMarker): void;
7
+ export declare function readServerAction(error: unknown): {
8
+ name: string;
9
+ argsShape?: never;
10
+ } | {
11
+ name: string;
12
+ argsShape: string;
13
+ } | undefined;
14
+ //#endregion
@@ -1 +1 @@
1
- const MARKER=`__interfere_server_action__`;function markServerAction(error,info){typeof error!=`object`||!error||Object.defineProperty(error,MARKER,{value:info,enumerable:!1,configurable:!0,writable:!0})}function readServerAction(error){if(!(typeof error!=`object`||!error))return error[MARKER]}export{markServerAction,readServerAction};
1
+ const MARKER=`__interfere_server_action__`;function markServerAction(error,info){typeof error==`object`&&error&&Object.defineProperty(error,MARKER,{configurable:!0,enumerable:!1,value:info,writable:!0})}function readServerAction(error){if(typeof error!=`object`||!error||!(MARKER in error))return;let marker=error[MARKER];if(typeof marker==`object`&&marker&&`name`in marker&&typeof marker.name==`string`){if(!(`argsShape`in marker)||marker.argsShape===void 0)return{name:marker.name};if(typeof marker.argsShape==`string`)return{name:marker.name,argsShape:marker.argsShape}}}export{markServerAction,readServerAction};
@@ -1,5 +1,4 @@
1
1
  //#region src/internal/server/server-flush.d.ts
2
- declare function setServerFlush(fn: () => Promise<void>): void;
3
- declare function flushServerTelemetry(): Promise<void>;
4
- //#endregion
5
- export { flushServerTelemetry, setServerFlush };
2
+ export declare function setServerFlush(fn: () => Promise<void>): void;
3
+ export declare function flushServerTelemetry(): Promise<void>;
4
+ //#endregion
@@ -1 +1 @@
1
- let flushFn=null;function setServerFlush(fn){flushFn=fn}function flushServerTelemetry(){return flushFn?flushFn():Promise.resolve()}export{flushServerTelemetry,setServerFlush};
1
+ let flushFn=null;function setServerFlush(fn){flushFn=fn}async function flushServerTelemetry(){return flushFn?flushFn():Promise.resolve()}export{flushServerTelemetry,setServerFlush};