@interfere/next 11.0.5 → 11.1.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.
package/dist/config.mjs CHANGED
@@ -1 +1 @@
1
- import{configureBuild}from"./internal/build/configure-build.mjs";import{readInterfereEnv}from"./internal/env.mjs";import{FatalError,log}from"./internal/logger.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{readNextMajorVersion,warnIfServerInstrumentationMissing}from"./internal/setup-warnings.mjs";import{API_URL}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{classifyReleasePipelineError,diagnoseRelease,isInterfereApiKey}from"@interfere/types/sdk/build-diagnostics";import{resolveDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{API_URL_GLOBAL,ENVIRONMENT_GLOBAL,FORCE_ENABLE_GLOBAL,PUBLIC_KEY_GLOBAL,RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{PHASE_PRODUCTION_BUILD}from"next/constants.js";const CLIENT_TRACE_METADATA_KEYS=[`traceparent`,`baggage`],DIAGNOSTIC_CONTEXT={publicKeyEnvVar:`INTERFERE_PUBLIC_KEY`};function reportReleaseDiagnostic(code,input){let diagnostic=diagnoseRelease(code,DIAGNOSTIC_CONTEXT,input),lines=[...diagnostic.details];if(diagnostic.severity===`fatal`){log.fatal(diagnostic.title,lines);return}log.warn(diagnostic.title,lines)}function isThenable(value){return typeof value==`object`&&!!value&&`then`in value&&typeof value.then==`function`}function withInterfere(settingsOrConfig={},maybeConfig){let[settings,nextConfig]=maybeConfig===void 0?[{},settingsOrConfig]:[settingsOrConfig,maybeConfig];return(phase,context)=>{let resolved=typeof nextConfig==`function`?nextConfig(phase,context??{defaultConfig:{}}):nextConfig;return isThenable(resolved)?Promise.resolve(resolved).then(config=>buildInterfereConfig(phase,settings,config)):buildInterfereConfig(phase,settings,resolved)}}function buildInterfereConfig(phase,settings,nextConfig){let{interfere,env:userEnv,webpack,turbopack,compiler,productionBrowserSourceMaps,...rest}=nextConfig;if(interfere&&`buildId`in interfere&&interfere.buildId!==void 0)return log.fatal(`Removed: interfere.buildId`,["`interfere.buildId` was removed in SDK 10. It only worked at build time, so server-side spans drifted from the bundle's slug.","Override the commit SHA via the `INTERFERE_SOURCE_ID` env var on both build and runtime envs instead."]);let projectDir=process.cwd(),config=resolveBuildConfig(settings,phase),apiHost=resolveBrowserApiHost(interfere?.apiHost,config.apiUrl),forceEnable=!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE,releaseSlug=forceEnable?LOCAL_DEV_RELEASE_SLUG:config.releaseSlug,nextMajor=readNextMajorVersion(projectDir),build=configureBuild({existingWebpack:webpack,existingTurbopack:turbopack,nextMajor,projectDir,remoteConfigFetch:resolveRemoteConfigFetch(config,phase),values:{[RELEASE_SLUG_GLOBAL]:releaseSlug,...config.publicKey&&{[PUBLIC_KEY_GLOBAL]:config.publicKey,...apiHost&&{[API_URL_GLOBAL]:apiHost}},...config.environment&&{[ENVIRONMENT_GLOBAL]:config.environment},...forceEnable&&{[FORCE_ENABLE_GLOBAL]:!0}}});if(config.publicKey!==null&&!build.clientInstrumentationApplies)return log.fatal(`Missing instrumentation client`,[`INTERFERE_PUBLIC_KEY is set but no instrumentation-client file was found.`,`Create an instrumentation-client.ts file in your project root or src/ directory.`]);config.publicKey!==null&&warnIfServerInstrumentationMissing(projectDir);let experimental=interfereExperimentalConfig({existing:rest.experimental,instrumentationHook:nextMajor===null||nextMajor<=14,traceMetadata:config.publicKey!==null||forceEnable}),existingHook=compiler?.runAfterProductionCompile,browserSourceMaps=config.apiKey!==null||productionBrowserSourceMaps;return config.apiKey!==null&&productionBrowserSourceMaps===!1&&log.warn(`Forcing productionBrowserSourceMaps`,[`withInterfere() requires production source maps to symbolicate errors.`,"Your `productionBrowserSourceMaps: false` was overridden to `true`."]),{...rest,...userEnv?{env:userEnv}:{},compiler:{...omitUndefined(compiler??{}),async runAfterProductionCompile(context){existingHook&&await existingHook(context);try{await runBuildReleasePipeline(context,config)}catch(error){if(error instanceof FatalError)throw error;let message=error instanceof Error?error.message:String(error);log.warn(`Skipping release pipeline`,[`Interfere encountered an unexpected error.`,`Build will continue, but this release's data will be ingested, but ignored as finding when generating insights.`,`Error: ${message}`])}}},...omitUndefined({productionBrowserSourceMaps:browserSourceMaps,turbopack:build.turbopack,webpack:build.webpack}),...experimental?{experimental}:{}}}function interfereExperimentalConfig({existing,instrumentationHook,traceMetadata}){let merged={...existing,...instrumentationHook?{instrumentationHook:!0}:{},...traceMetadata?{clientTraceMetadata:[...new Set([...existing?.clientTraceMetadata??[],...CLIENT_TRACE_METADATA_KEYS])]}:{}};return Object.keys(merged).length>0?merged:void 0}function resolveBrowserApiHost(apiHost,apiUrl){let host=apiHost??apiUrl;if(host!==API_URL)return normalizeHost(host)}function normalizeHost(host){try{return new URL(host).origin}catch{return log.fatal(`Invalid apiHost`,[`interfere.apiHost must be a full URL, e.g. "https://in.yourapp.com".`,`Received: ${host}`])}}function resolveBuildConfig(settings,phase){let{apiKey,apiUrl,publicKey}=readInterfereEnv(),{commitSha,slug}=resolveReleaseSlug(),environment=phase===PHASE_PRODUCTION_BUILD?resolveDeployEnvironment(process.env):null;return{apiKey:apiKey??null,apiUrl,buildId:commitSha,environment,publicKey:publicKey??null,purgeSourceMaps:settings.sourceMaps?.purge??!0,releaseSlug:slug}}function resolveRemoteConfigFetch(config,phase){if(!(phase!==PHASE_PRODUCTION_BUILD||!config.publicKey))return{apiUrl:config.apiUrl,publicKey:config.publicKey}}async function runBuildReleasePipeline(context,config){let{apiKey,buildId,releaseSlug}=config;if(!apiKey)return log.fatal(`Secret key not set`,[`withInterfere() requires a secret key to publish release metadata during production builds.`,`Set the INTERFERE_API_KEY environment variable, or remove withInterfere() from your Next.js config.`,`See: https://interfere.com/docs/sdk/next-js`]);if(!isInterfereApiKey(apiKey))return reportReleaseDiagnostic(`API_KEY_WRONG_PREFIX`,{apiKey});if(!(buildId&&releaseSlug))return log.fatal(`Commit SHA missing`,[`Could not resolve a commit SHA from environment variables or git.`,"Set `INTERFERE_SOURCE_ID`, ensure your CI exposes its git SHA env var (e.g. `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`), or run inside a git checkout."]);let{runBuildPipeline}=await import(`./internal/build/pipeline.mjs`);try{let result=await runBuildPipeline(context,{...config,apiKey,buildId,releaseSlug});if(!result.ready){log.warn(`Skipping`,[`No source maps found`]);return}log.info(`Completed`,[`https://interfere.com/~/${result.config?.org.slug}/surfaces/${result.config?.surface.slug}`,`Release: ${result.release?.destination.slug??`Unknown`}`,`Build: ${result.buildId}`,`Artifacts: ${result.fileCount} source maps`])}catch(error){let message=error instanceof Error?error.message:String(error);reportReleaseDiagnostic(classifyReleasePipelineError(error),{errorMessage:message});return}}export{withInterfere};
1
+ import{configureBuild}from"./internal/build/configure-build.mjs";import{readInterfereEnv}from"./internal/env.mjs";import{FatalError,log}from"./internal/logger.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{readNextMajorVersion,warnIfServerInstrumentationMissing}from"./internal/setup-warnings.mjs";import{API_URL}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{classifyReleasePipelineError,diagnoseRelease,isInterfereApiKey}from"@interfere/types/sdk/build-diagnostics";import{resolveDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{API_URL_GLOBAL,BUILD_MARKER_GLOBAL,ENVIRONMENT_GLOBAL,FORCE_ENABLE_GLOBAL,PUBLIC_KEY_GLOBAL,RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{PHASE_PRODUCTION_BUILD}from"next/constants.js";const CLIENT_TRACE_METADATA_KEYS=[`traceparent`,`baggage`],DIAGNOSTIC_CONTEXT={publicKeyEnvVar:`INTERFERE_PUBLIC_KEY`};function reportReleaseDiagnostic(code,input){let diagnostic=diagnoseRelease(code,DIAGNOSTIC_CONTEXT,input),lines=[...diagnostic.details];if(diagnostic.severity===`fatal`){log.fatal(diagnostic.title,lines);return}log.warn(diagnostic.title,lines)}function isThenable(value){return typeof value==`object`&&!!value&&`then`in value&&typeof value.then==`function`}function withInterfere(settingsOrConfig={},maybeConfig){let[settings,nextConfig]=maybeConfig===void 0?[{},settingsOrConfig]:[settingsOrConfig,maybeConfig];return(phase,context)=>{let resolved=typeof nextConfig==`function`?nextConfig(phase,context??{defaultConfig:{}}):nextConfig;return isThenable(resolved)?Promise.resolve(resolved).then(config=>buildInterfereConfig(phase,settings,config)):buildInterfereConfig(phase,settings,resolved)}}function interfereInjectedValues(config,apiHost,forceEnable){let releaseSlug=forceEnable?LOCAL_DEV_RELEASE_SLUG:config.releaseSlug;return{[RELEASE_SLUG_GLOBAL]:releaseSlug,[BUILD_MARKER_GLOBAL]:!0,...config.publicKey&&{[PUBLIC_KEY_GLOBAL]:config.publicKey,...apiHost&&{[API_URL_GLOBAL]:apiHost}},...config.environment&&{[ENVIRONMENT_GLOBAL]:config.environment},...forceEnable&&{[FORCE_ENABLE_GLOBAL]:!0}}}function interfereCompilerConfig(compiler,config){let existingHook=compiler?.runAfterProductionCompile;return omitUndefined({...compiler,async runAfterProductionCompile(context){existingHook&&await existingHook(context);try{await runBuildReleasePipeline(context,config)}catch(error){if(error instanceof FatalError)throw error;let message=error instanceof Error?error.message:String(error);log.warn(`Skipping release pipeline`,[`Interfere encountered an unexpected error.`,`Build will continue, but this release's data will be ingested, but ignored as finding when generating insights.`,`Error: ${message}`])}}})}function resolveBrowserSourceMaps(config,productionBrowserSourceMaps){return config.apiKey!==null&&productionBrowserSourceMaps===!1&&log.warn(`Forcing productionBrowserSourceMaps`,[`withInterfere() requires production source maps to symbolicate errors.`,"Your `productionBrowserSourceMaps: false` was overridden to `true`."]),config.apiKey!==null||productionBrowserSourceMaps}function buildInterfereConfig(phase,settings,nextConfig){let{interfere,env:userEnv,webpack,turbopack,compiler,productionBrowserSourceMaps,...rest}=nextConfig;if(interfere&&`buildId`in interfere&&interfere.buildId!==void 0)return log.fatal(`Removed: interfere.buildId`,["`interfere.buildId` was removed in SDK 10. It only worked at build time, so server-side spans drifted from the bundle's slug.","Override the commit SHA via the `INTERFERE_SOURCE_ID` env var on both build and runtime envs instead."]);let projectDir=process.cwd(),config=resolveBuildConfig(settings,phase),apiHost=resolveBrowserApiHost(interfere?.apiHost,config.apiUrl),forceEnable=!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE,nextMajor=readNextMajorVersion(projectDir),build=configureBuild({existingWebpack:webpack,existingTurbopack:turbopack,nextMajor,projectDir,remoteConfigFetch:resolveRemoteConfigFetch(config,phase),values:interfereInjectedValues(config,apiHost,forceEnable)});if(config.publicKey!==null&&!build.clientInstrumentationApplies)return log.fatal(`Missing instrumentation client`,[`INTERFERE_PUBLIC_KEY is set but no instrumentation-client file was found.`,`Create an instrumentation-client.ts file in your project root or src/ directory.`]);config.publicKey!==null&&warnIfServerInstrumentationMissing(projectDir);let experimental=interfereExperimentalConfig({existing:rest.experimental,instrumentationHook:nextMajor===null||nextMajor<=14,traceMetadata:config.publicKey!==null||forceEnable});return omitUndefined({...rest,...userEnv?{env:userEnv}:{},compiler:interfereCompilerConfig(compiler,config),productionBrowserSourceMaps:resolveBrowserSourceMaps(config,productionBrowserSourceMaps),turbopack:build.turbopack,webpack:build.webpack,...experimental?{experimental}:{}})}function interfereExperimentalConfig({existing,instrumentationHook,traceMetadata}){let merged={...existing,...instrumentationHook?{instrumentationHook:!0}:{},...traceMetadata?{clientTraceMetadata:[...new Set([...existing?.clientTraceMetadata??[],...CLIENT_TRACE_METADATA_KEYS])]}:{}};return Object.keys(merged).length>0?merged:void 0}function resolveBrowserApiHost(apiHost,apiUrl){let host=apiHost??apiUrl;if(host!==API_URL)return normalizeHost(host)}function normalizeHost(host){try{return new URL(host).origin}catch{return log.fatal(`Invalid apiHost`,[`interfere.apiHost must be a full URL, e.g. "https://in.yourapp.com".`,`Received: ${host}`])}}function resolveBuildConfig(settings,phase){let{apiKey,apiUrl,publicKey}=readInterfereEnv(),{commitSha,slug}=resolveReleaseSlug(),environment=phase===PHASE_PRODUCTION_BUILD?resolveDeployEnvironment(process.env):null;return{apiKey:apiKey??null,apiUrl,buildId:commitSha,environment,publicKey:publicKey??null,purgeSourceMaps:settings.sourceMaps?.purge??!0,releaseSlug:slug}}function resolveRemoteConfigFetch(config,phase){if(!(phase!==PHASE_PRODUCTION_BUILD||!config.publicKey))return{apiUrl:config.apiUrl,publicKey:config.publicKey}}async function runBuildReleasePipeline(context,config){let{apiKey,buildId,releaseSlug}=config;if(!apiKey)return log.fatal(`Secret key not set`,[`withInterfere() requires a secret key to publish release metadata during production builds.`,`Set the INTERFERE_API_KEY environment variable, or remove withInterfere() from your Next.js config.`,`See: https://interfere.com/docs/sdk/next-js`]);if(!isInterfereApiKey(apiKey))return reportReleaseDiagnostic(`API_KEY_WRONG_PREFIX`,{apiKey});if(!(buildId&&releaseSlug))return log.fatal(`Commit SHA missing`,[`Could not resolve a commit SHA from environment variables or git.`,"Set `INTERFERE_SOURCE_ID`, ensure your CI exposes its git SHA env var (e.g. `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`), or run inside a git checkout."]);let{runBuildPipeline}=await import(`./internal/build/pipeline.mjs`);try{let result=await runBuildPipeline(context,{...config,apiKey,buildId,releaseSlug});if(!result.ready){log.warn(`Skipping`,[`No source maps found`]);return}log.info(`Completed`,[`https://interfere.com/~/${result.config?.org.slug}/surfaces/${result.config?.surface.slug}`,`Release: ${result.release?.destination.slug??`Unknown`}`,`Build: ${result.buildId}`,`Artifacts: ${result.fileCount} source maps`])}catch(error){let message=error instanceof Error?error.message:String(error);reportReleaseDiagnostic(classifyReleasePipelineError(error),{errorMessage:message})}}export{withInterfere};
@@ -1,14 +1,15 @@
1
1
  import { capture, span } from "@interfere/react/api";
2
- import { Kernel, KernelInternalOptions, KernelOptions } from "@interfere/react/internal/kernel";
2
+ import { Kernel, Kernel as Kernel$1, KernelInternalOptions, KernelOptions, KernelOptions as KernelOptions$1 } from "@interfere/react/internal/kernel";
3
3
  import { ConsentCategory, ConsentState, GateableCategory } from "@interfere/types/sdk/plugins/manifest";
4
4
  //#region src/instrument-client.d.ts
5
5
  declare const close: () => Promise<void>, consent: {
6
- get(): import("@interfere/types/sdk/plugins/manifest").ConsentState | null;
7
- set(value?: import("@interfere/types/sdk/plugins/manifest").ConsentState): void;
8
- }, getKernel: () => import("@interfere/react/internal/kernel").Kernel, getKernelOrNull: () => import("@interfere/react/internal/kernel").Kernel | null, identity: {
9
- clear(): void;
10
- get(): import("@interfere/types/sdk/identify").IdentifyParams | null;
11
- set(params: import("@interfere/types/sdk/identify").IdentifyParams): Promise<void>;
12
- }, init: (opts?: import("@interfere/react/internal/kernel").KernelOptions) => Promise<import("@interfere/react/internal/kernel").Kernel | null>, subscribeToKernel: (listener: () => void) => () => void;
6
+ get: () => import("@interfere/types/sdk/plugins/manifest").ConsentState | null;
7
+ set: (value?: import("@interfere/types/sdk/plugins/manifest").ConsentState) => void;
8
+ }, getKernel: () => Kernel$1, getKernelOrNull: () => Kernel$1 | null, identity: {
9
+ clear: () => void;
10
+ get: () => import("@interfere/types/sdk/identify").IdentifyParams | null;
11
+ set: (params: import("@interfere/types/sdk/identify").IdentifyParams) => Promise<void>;
12
+ }, subscribeToKernel: (listener: () => void) => () => void;
13
+ declare function init(opts?: KernelOptions$1): Promise<Kernel$1 | null>;
13
14
  //#endregion
14
15
  export { type ConsentCategory, type ConsentState, type GateableCategory, type Kernel, type KernelInternalOptions, type KernelOptions, capture, close, consent, getKernel, getKernelOrNull, identity, init, span, subscribeToKernel };
@@ -1 +1 @@
1
- import{PRODUCER_VERSION}from"./internal/version.mjs";import{createWrapperSingleton}from"@interfere/react/internal/wrapper-singleton";import{capture,span}from"@interfere/react/api";const{close,consent,getKernel,getKernelOrNull,identity,init,subscribeToKernel}=createWrapperSingleton({producerVersion:PRODUCER_VERSION,initEntryName:`instrumentation-client`});export{capture,close,consent,getKernel,getKernelOrNull,identity,init,span,subscribeToKernel};
1
+ import{buildIntegrationRan,hasEnvCredentials,warnBuildIntegrationDegraded,warnBuildIntegrationMissing}from"./internal/build-marker-guard.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{createWrapperSingleton}from"@interfere/react/internal/wrapper-singleton";import{capture,span}from"@interfere/react/api";const wrapper=createWrapperSingleton({producerVersion:PRODUCER_VERSION,initEntryName:`instrumentation-client`}),{close,consent,getKernel,getKernelOrNull,identity,subscribeToKernel}=wrapper;function init(opts){return buildIntegrationRan()?wrapper.init(opts):initAfterHoistedImports(opts)}async function initAfterHoistedImports(opts){if(await Promise.resolve(),!buildIntegrationRan()){let{promise,resolve}=Promise.withResolvers();setTimeout(resolve,0),await promise}return buildIntegrationRan()?wrapper.init(opts):hasEnvCredentials()?(warnBuildIntegrationDegraded(),wrapper.init(opts)):(warnBuildIntegrationMissing(),null)}export{capture,close,consent,getKernel,getKernelOrNull,identity,init,span,subscribeToKernel};
@@ -1 +1 @@
1
- export { };
1
+ export {}
@@ -1 +1 @@
1
- import{readInterfereEnv}from"./internal/env.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{setServerFlush}from"./internal/server/server-flush.mjs";import{withPublicKey}from"./internal/url.mjs";import{fetchAndCacheRemoteConfig}from"./internal/server/remote-config.mjs";import{onRequestError}from"./internal/server/capture.mjs";import{bridgeConsoleToOtel}from"./internal/server/console-bridge.mjs";import{installGlobalHandlers}from"./internal/server/global-handlers.mjs";import{PrerenderSafeIdGenerator}from"./internal/server/id-generator.mjs";import{readServerTracingMode}from"@interfere/types/sdk/server-tracing";import{propagation}from"@opentelemetry/api";import{resourceFromAttributes}from"@opentelemetry/resources";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator}from"@opentelemetry/core";import{readLogSourcingMode}from"@interfere/types/sdk/log-sourcing";import{BaggageSpanProcessor}from"@opentelemetry/baggage-span-processor";import{AsyncLocalStorageContextManager}from"@opentelemetry/context-async-hooks";import{OTLPLogExporter}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPTraceExporter}from"@opentelemetry/exporter-trace-otlp-http";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{CompressionAlgorithm}from"@opentelemetry/otlp-exporter-base";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{NodeTracerProvider}from"@opentelemetry/sdk-trace-node";const EXPORT_TIMEOUT_MS=2e3;let registered=!1,tracerProvider=null,loggerProvider=null;async function flush(){await Promise.all([tracerProvider?.forceFlush(),loggerProvider?.forceFlush()])}function buildInterfereOtelKit(opts={}){let env=readInterfereEnv();if(!env.publicKey)return null;let{slug:releaseSlug}=resolveReleaseSlug();releaseSlug||console.warn("[interfere] No commit SHA available; server spans will ship without `release.slug`. Set `INTERFERE_SOURCE_ID` (or any of `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`) on the runtime env.");let sinkUrl=withPublicKey(`${env.apiUrl}/v2/sink`,env.publicKey),exporterHeaders={"x-interfere-producer-version":PRODUCER_VERSION},resourceAttributes={"service.name":opts.serviceName??`interfere-sdk-next-server`,"service.namespace":`interfere`,"deployment.environment.name":env.nodeEnvironment,"telemetry.sdk.language":`nodejs`,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,...releaseSlug?{"release.slug":releaseSlug}:{}},compression=opts.compression===`gzip`?CompressionAlgorithm.GZIP:CompressionAlgorithm.NONE,isDrainMode=readServerTracingMode()===`drain`,spanProcessors=[new BaggageSpanProcessor(()=>!0),...isDrainMode?[]:[new BatchSpanProcessor(new OTLPTraceExporter({url:sinkUrl,headers:exporterHeaders,compression,timeoutMillis:EXPORT_TIMEOUT_MS}))],...opts._internalAdditionalSpanProcessors??[]],isLogDrainMode=readLogSourcingMode()===`drain`;return{resourceAttributes,spanProcessors,logRecordProcessors:[...isLogDrainMode?[]:[new BatchLogRecordProcessor(new OTLPLogExporter({url:sinkUrl,headers:exporterHeaders,compression,timeoutMillis:EXPORT_TIMEOUT_MS}))],...opts._internalAdditionalLogRecordProcessors??[]],propagators:[new W3CBaggagePropagator],instrumentations:[],enableConsoleBridge:()=>isLogDrainMode?()=>void 0:bridgeConsoleToOtel(),fetchRemoteConfig:()=>fetchAndCacheRemoteConfig()}}async function register(opts={}){if(registered)return;let kit=buildInterfereOtelKit(opts);if(!kit)return;readServerTracingMode()===`drain`&&console.info(`[interfere] server tracing in drain mode; SDK trace exporter disabled — server traces come from the platform trace drain.`);let resource=resourceFromAttributes(kit.resourceAttributes);tracerProvider=new NodeTracerProvider({resource,spanProcessors:kit.spanProcessors,idGenerator:new PrerenderSafeIdGenerator}),propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,...kit.propagators]})),tracerProvider.register({contextManager:new AsyncLocalStorageContextManager().enable()}),loggerProvider=new LoggerProvider({resource,processors:kit.logRecordProcessors});let{logs:logsApi}=await import(`@opentelemetry/api-logs`);logsApi.setGlobalLoggerProvider(loggerProvider),registerInstrumentations({tracerProvider,instrumentations:kit.instrumentations}),opts.consoleBridge!==!1&&kit.enableConsoleBridge(),installGlobalHandlers({captureUncaughtException:opts.captureUncaughtException??!0,captureUnhandledRejection:opts.captureUnhandledRejection??!0,exitOnUncaughtException:process.env.NODE_ENV===`production`,flush}),setServerFlush(flush),registered=!0}export{PrerenderSafeIdGenerator,buildInterfereOtelKit,flush,onRequestError,register};
1
+ import{readInterfereEnv}from"./internal/env.mjs";import{resolveReleaseSlug}from"./internal/release-slug.mjs";import{PRODUCER_VERSION}from"./internal/version.mjs";import{setServerFlush}from"./internal/server/server-flush.mjs";import{withPublicKey}from"./internal/url.mjs";import{fetchAndCacheRemoteConfig}from"./internal/server/remote-config.mjs";import{onRequestError}from"./internal/server/capture.mjs";import{bridgeConsoleToOtel}from"./internal/server/console-bridge.mjs";import{installGlobalHandlers}from"./internal/server/global-handlers.mjs";import{PrerenderSafeIdGenerator}from"./internal/server/id-generator.mjs";import{readServerTracingMode}from"@interfere/types/sdk/server-tracing";import{propagation}from"@opentelemetry/api";import{resourceFromAttributes}from"@opentelemetry/resources";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator}from"@opentelemetry/core";import{readLogSourcingMode}from"@interfere/types/sdk/log-sourcing";import{BaggageSpanProcessor}from"@opentelemetry/baggage-span-processor";import{AsyncLocalStorageContextManager}from"@opentelemetry/context-async-hooks";import{OTLPLogExporter}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPTraceExporter}from"@opentelemetry/exporter-trace-otlp-http";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{CompressionAlgorithm}from"@opentelemetry/otlp-exporter-base";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{NodeTracerProvider}from"@opentelemetry/sdk-trace-node";const EXPORT_TIMEOUT_MS=2e3;let registered=!1,tracerProvider=null,loggerProvider=null;async function flush(){await Promise.all([tracerProvider?.forceFlush(),loggerProvider?.forceFlush()])}function buildInterfereOtelKit(opts={}){let env=readInterfereEnv();if(!env.publicKey)return null;let{slug:releaseSlug}=resolveReleaseSlug();releaseSlug||console.warn("[interfere] No commit SHA available; server spans will ship without `release.slug`. Set `INTERFERE_SOURCE_ID` (or any of `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA`) on the runtime env.");let sinkUrl=withPublicKey(`${env.apiUrl}/v2/sink`,env.publicKey),exporterHeaders={"x-interfere-producer-version":PRODUCER_VERSION},resourceAttributes={"service.name":opts.serviceName??`interfere-sdk-next-server`,"service.namespace":`interfere`,"deployment.environment.name":env.nodeEnvironment,"telemetry.sdk.language":`nodejs`,"interfere.sdk.name":`@interfere/next`,"interfere.sdk.version":PRODUCER_VERSION,...releaseSlug?{"release.slug":releaseSlug}:{}},compression=opts.compression===`gzip`?CompressionAlgorithm.GZIP:CompressionAlgorithm.NONE,isDrainMode=readServerTracingMode()===`drain`,spanProcessors=[new BaggageSpanProcessor(()=>!0),...isDrainMode?[]:[new BatchSpanProcessor(new OTLPTraceExporter({url:sinkUrl,headers:exporterHeaders,compression,timeoutMillis:EXPORT_TIMEOUT_MS}))],...opts._internalAdditionalSpanProcessors??[]],isLogDrainMode=readLogSourcingMode()===`drain`;return{resourceAttributes,spanProcessors,logRecordProcessors:[...isLogDrainMode?[]:[new BatchLogRecordProcessor({exporter:new OTLPLogExporter({url:sinkUrl,headers:exporterHeaders,compression,timeoutMillis:EXPORT_TIMEOUT_MS})})],...opts._internalAdditionalLogRecordProcessors??[]],propagators:[new W3CBaggagePropagator],instrumentations:[],enableConsoleBridge:()=>isLogDrainMode?()=>{}:bridgeConsoleToOtel(),fetchRemoteConfig:()=>fetchAndCacheRemoteConfig()}}async function register(opts={}){if(registered)return;let kit=buildInterfereOtelKit(opts);if(!kit)return;readServerTracingMode()===`drain`&&console.info(`[interfere] server tracing in drain mode; SDK trace exporter disabled — server traces come from the platform trace drain.`);let resource=resourceFromAttributes(kit.resourceAttributes);tracerProvider=new NodeTracerProvider({resource,spanProcessors:kit.spanProcessors,idGenerator:new PrerenderSafeIdGenerator}),propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,...kit.propagators]})),tracerProvider.register({contextManager:new AsyncLocalStorageContextManager().enable()}),loggerProvider=new LoggerProvider({resource,processors:kit.logRecordProcessors});let{logs:logsApi}=await import(`@opentelemetry/api-logs`);logsApi.setGlobalLoggerProvider(loggerProvider),registerInstrumentations({tracerProvider,instrumentations:kit.instrumentations}),opts.consoleBridge!==!1&&kit.enableConsoleBridge(),installGlobalHandlers({captureUncaughtException:opts.captureUncaughtException??!0,captureUnhandledRejection:opts.captureUnhandledRejection??!0,exitOnUncaughtException:process.env.NODE_ENV===`production`,flush}),setServerFlush(flush),registered=!0}export{PrerenderSafeIdGenerator,buildInterfereOtelKit,flush,onRequestError,register};
@@ -2,6 +2,7 @@ import { NextConfig } from "next";
2
2
  //#region src/internal/build/configure-build.d.ts
3
3
  interface InterfereInjectedValues {
4
4
  readonly __INTERFERE_API_URL__?: string;
5
+ readonly __INTERFERE_BUILD__?: boolean;
5
6
  readonly __INTERFERE_ENVIRONMENT__?: string;
6
7
  readonly __INTERFERE_FORCE_ENABLE__?: boolean;
7
8
  readonly __INTERFERE_PUBLIC_KEY__?: string;
@@ -1 +1 @@
1
- import{omitUndefined}from"@interfere/helpers/omit-undefined";import{existsSync}from"node:fs";import{basename,dirname,join,normalize,resolve}from"node:path";import{fileURLToPath}from"node:url";const INSTRUMENTATION_EXTENSIONS=[`ts`,`tsx`,`js`,`jsx`];function instrumentationCandidates(base){return[``,`src/`].flatMap(dir=>INSTRUMENTATION_EXTENSIONS.map(ext=>`${dir}${base}.${ext}`))}const LOADER_FILE_CANDIDATES=[`ts`,`js`,`mjs`,`cjs`].map(ext=>`value-injection-loader.${ext}`);function configureBuild({existingWebpack,existingTurbopack,nextMajor,projectDir,remoteConfigFetch,values}){let clientPath=resolveFirstExisting(projectDir,instrumentationCandidates(`instrumentation-client`)),targets=[clientPath,resolveFirstExisting(projectDir,instrumentationCandidates(`instrumentation`))].filter(path=>path!==null),hasMetadata=values.__INTERFERE_RELEASE_SLUG__!==null||values.__INTERFERE_PUBLIC_KEY__!==void 0,injectionApplies=targets.length>0&&hasMetadata;return{clientInstrumentationApplies:!!clientPath&&hasMetadata,webpack:buildWebpackHook(existingWebpack,targets,values,remoteConfigFetch,injectionApplies),turbopack:buildTurbopackConfig(existingTurbopack,targets,values,remoteConfigFetch,injectionApplies,nextMajor)}}function buildWebpackHook(existingWebpack,targets,values,remoteConfigFetch,injectionApplies){if(!injectionApplies)return existingWebpack;let normalizedTargets=new Set(targets.map(path=>normalize(path))),injectionLoaderPath=resolveLoaderPath();return(webpackConfig,options)=>{let outputConfig=existingWebpack?existingWebpack(webpackConfig,options):webpackConfig,mutableConfig=outputConfig;return mutableConfig.module??={},mutableConfig.module.rules??=[],mutableConfig.module.rules.push({test:resource=>!!resource&&normalizedTargets.has(normalize(resource)),use:[{loader:injectionLoaderPath,options:omitUndefined({serializedValues:JSON.stringify(values),serializedFetch:remoteConfigFetch?JSON.stringify(remoteConfigFetch):void 0})}]}),outputConfig}}function buildTurbopackConfig(existingTurbopack,targets,values,remoteConfigFetch,injectionApplies,nextMajor){let baseConfig=existingTurbopack??{},debugIds=nextMajor===null||nextMajor>=16?baseConfig.debugIds??!0:baseConfig.debugIds;if(!injectionApplies)return omitUndefined({...baseConfig,debugIds});let rules={...baseConfig.rules},loaderPath=resolveLoaderPath();for(let target of targets){let ruleKey=`**/${basename(target)}`;rules[ruleKey]=appendTurbopackLoader(rules[ruleKey],{loader:loaderPath,options:omitUndefined({serializedValues:JSON.stringify(values),serializedFetch:remoteConfigFetch?JSON.stringify(remoteConfigFetch):void 0})})}return omitUndefined({...baseConfig,debugIds,rules})}function appendTurbopackLoader(existing,loader){let rule=existing??{},loaders=Array.isArray(rule.loaders)?rule.loaders:[];return{...rule,loaders:[...loaders,loader]}}function resolveFirstExisting(projectDir,candidates){for(let candidate of candidates){let filePath=resolve(projectDir,candidate);if(existsSync(filePath))return filePath}return null}function resolveLoaderPath(){let directory=resolve(dirname(fileURLToPath(import.meta.url)));for(let candidate of LOADER_FILE_CANDIDATES){let filePath=join(directory,candidate);if(existsSync(filePath))return filePath}return join(directory,`value-injection-loader.js`)}export{configureBuild};
1
+ import{omitUndefined}from"@interfere/helpers/omit-undefined";import{existsSync}from"node:fs";import{basename,dirname,join,normalize,resolve}from"node:path";import{fileURLToPath}from"node:url";const INSTRUMENTATION_EXTENSIONS=[`ts`,`tsx`,`js`,`jsx`];function instrumentationCandidates(base){return[``,`src/`].flatMap(dir=>INSTRUMENTATION_EXTENSIONS.map(ext=>`${dir}${base}.${ext}`))}const LOADER_FILE_CANDIDATES=[`ts`,`js`,`mjs`,`cjs`].map(ext=>`value-injection-loader.${ext}`);function configureBuild({existingWebpack,existingTurbopack,nextMajor,projectDir,remoteConfigFetch,values}){let clientPath=resolveFirstExisting(projectDir,instrumentationCandidates(`instrumentation-client`)),targets=[clientPath,resolveFirstExisting(projectDir,instrumentationCandidates(`instrumentation`))].filter(path=>path!==null),hasMetadata=values.__INTERFERE_RELEASE_SLUG__!==null||values.__INTERFERE_PUBLIC_KEY__!==void 0,injectionApplies=targets.length>0;return{clientInstrumentationApplies:!!clientPath&&hasMetadata,webpack:buildWebpackHook(existingWebpack,targets,values,remoteConfigFetch,injectionApplies),turbopack:buildTurbopackConfig(existingTurbopack,targets,values,remoteConfigFetch,injectionApplies,nextMajor)}}function buildWebpackHook(existingWebpack,targets,values,remoteConfigFetch,injectionApplies){if(!injectionApplies)return existingWebpack;let normalizedTargets=new Set(targets.map(path=>normalize(path))),injectionLoaderPath=resolveLoaderPath();return(webpackConfig,options)=>{let outputConfig=existingWebpack?existingWebpack(webpackConfig,options):webpackConfig,mutableConfig=outputConfig;return mutableConfig.module??={},mutableConfig.module.rules??=[],mutableConfig.module.rules.push({test:resource=>!!resource&&normalizedTargets.has(normalize(resource)),use:[{loader:injectionLoaderPath,options:omitUndefined({serializedValues:JSON.stringify(values),serializedFetch:remoteConfigFetch?JSON.stringify(remoteConfigFetch):void 0})}]}),outputConfig}}function buildTurbopackConfig(existingTurbopack,targets,values,remoteConfigFetch,injectionApplies,nextMajor){let baseConfig=existingTurbopack??{},debugIds=nextMajor===null||nextMajor>=16?baseConfig.debugIds??!0:baseConfig.debugIds;if(!injectionApplies)return omitUndefined({...baseConfig,debugIds});let rules={...baseConfig.rules},loaderPath=resolveLoaderPath();for(let target of targets){let ruleKey=`**/${basename(target)}`;rules[ruleKey]=appendTurbopackLoader(rules[ruleKey],{loader:loaderPath,options:omitUndefined({serializedValues:JSON.stringify(values),serializedFetch:remoteConfigFetch?JSON.stringify(remoteConfigFetch):void 0})})}return omitUndefined({...baseConfig,debugIds,rules})}function appendTurbopackLoader(existing,loader){let rule=existing??{},loaders=Array.isArray(rule.loaders)?rule.loaders:[];return{...rule,loaders:[...loaders,loader]}}function resolveFirstExisting(projectDir,candidates){for(let candidate of candidates){let filePath=resolve(projectDir,candidate);if(existsSync(filePath))return filePath}return null}function resolveLoaderPath(){let directory=resolve(dirname(fileURLToPath(import.meta.url)));for(let candidate of LOADER_FILE_CANDIDATES){let filePath=join(directory,candidate);if(existsSync(filePath))return filePath}return join(directory,`value-injection-loader.js`)}export{configureBuild};
@@ -1 +1 @@
1
- import{log}from"../../logger.mjs";import{PRODUCER_VERSION}from"../../version.mjs";import{destinations}from"./destinations/index.mjs";import{sources}from"./sources/index.mjs";import{applyDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{releaseDestinationProviderSchema}from"@interfere/types/integrations";function resolveReleaseRequest(buildId,environment,releaseSlug,config){if(!config.surface.sourceProvider)return log.fatal(`Missing version control provider`,[`This surface does not have a version control provider configured.`,`Configure one at https://interfere.com/~/${config.org.slug}/surfaces/${config.surface.slug}`]);let destinationProvider=releaseDestinationProviderSchema.safeParse(config.surface.destinationProvider);return destinationProvider.success?{source:sources[config.surface.sourceProvider](),destination:applyDeployEnvironment(destinations[destinationProvider.data](releaseSlug),environment),buildId,slug:releaseSlug,producerVersion:PRODUCER_VERSION}:log.fatal(`Missing deployment target`,[`This surface does not have a deployment target integration configured.`,`Configure one at https://interfere.com/~/${config.org.slug}/surfaces/${config.surface.slug}`])}export{resolveReleaseRequest};
1
+ import{log}from"../../logger.mjs";import{PRODUCER_VERSION}from"../../version.mjs";import{destinations}from"./destinations/index.mjs";import{sources}from"./sources/index.mjs";import{applyDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{configuredSourceProviderSchema,releaseDestinationProviderSchema}from"@interfere/types/integrations";function resolveReleaseRequest(buildId,environment,releaseSlug,config){let sourceProvider=configuredSourceProviderSchema.safeParse(config.surface.sourceProvider);if(!sourceProvider.success)return log.fatal(`Missing version control provider`,[`This surface does not have a version control provider configured.`,`Configure one at https://interfere.com/~/${config.org.slug}/surfaces/${config.surface.slug}`]);let destinationProvider=releaseDestinationProviderSchema.safeParse(config.surface.destinationProvider);return destinationProvider.success?{source:sources[sourceProvider.data](),destination:applyDeployEnvironment(destinations[destinationProvider.data](releaseSlug),environment),buildId,slug:releaseSlug,producerVersion:PRODUCER_VERSION}:log.fatal(`Missing deployment target`,[`This surface does not have a deployment target integration configured.`,`Configure one at https://interfere.com/~/${config.org.slug}/surfaces/${config.surface.slug}`])}export{resolveReleaseRequest};
@@ -1 +1 @@
1
- import{runGitCommand}from"../git.mjs";import{parseEnvValue}from"@interfere/types/sdk/env";function resolve(){return{provider:`github`,branch:parseEnvValue(process.env.VERCEL_GIT_COMMIT_REF)??parseEnvValue(process.env.GITHUB_REF_NAME)??parseEnvValue(process.env.GITHUB_HEAD_REF)??runGitCommand(`git rev-parse --abbrev-ref HEAD`)??`unknown`,commitMessage:parseEnvValue(process.env.VERCEL_GIT_COMMIT_MESSAGE)??runGitCommand(`git log -1 --pretty=%B`)??``,commitSha:parseEnvValue(process.env.VERCEL_GIT_COMMIT_SHA)??parseEnvValue(process.env.GITHUB_SHA)??runGitCommand(`git rev-parse HEAD`)}}export{resolve};
1
+ import{runGitCommand}from"../git.mjs";import{resolveGithubReleaseSource}from"@interfere/types/sdk/github-source";function resolve(){return resolveGithubReleaseSource(process.env,runGitCommand)}export{resolve};
@@ -1 +1 @@
1
- import{resolve}from"./github.mjs";const sources={github:resolve};export{sources};
1
+ import{resolve}from"./github.mjs";const sources={github:resolve,ghe_cloud:resolve,ghe_server:resolve};export{sources};
@@ -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 clientChunks=(await walkDistTrees(resolveDistDir(opts.projectDir,opts.distDir),`.js`)).filter(path=>path.replaceAll(`\\`,`/`).includes(`/static/chunks/`)),stampedCount=(await Promise.all(clientChunks.map(async jsAbs=>readDebugIdFromJs(await readFile(jsAbs,`utf8`).catch(()=>``))!==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{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};
@@ -0,0 +1,7 @@
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 };
@@ -0,0 +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 +1 @@
1
- import{runGitCommand}from"./build/release/git.mjs";import{deriveReleaseSlug,releaseSlugSchema}from"@interfere/types/releases/slug";import{RELEASE_SLUG_GLOBAL}from"@interfere/types/sdk/injected-globals";import{readFirstEnvValue}from"@interfere/types/sdk/env";import{releaseSourceIdEnvKeys}from"@interfere/types/integrations";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 resolveCommitSha(){return readFirstEnvValue(process.env,releaseSourceIdEnvKeys)??runGitCommand(`git rev-parse HEAD`)}function resolveReleaseSlug(){let baked=readBakedReleaseSlug();if(baked)return{commitSha:null,slug:baked};let commitSha=resolveCommitSha();return{commitSha,slug:commitSha?deriveReleaseSlug(commitSha):null}}export{resolveReleaseSlug};
1
+ import{runGitCommand}from"./build/release/git.mjs";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";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 resolveCommitSha(){return resolveReleaseCommitSha(process.env,runGitCommand)}function resolveReleaseSlug(){let baked=readBakedReleaseSlug();if(baked)return{commitSha:null,slug:baked};let commitSha=resolveCommitSha();return{commitSha,slug:commitSha?deriveReleaseSlug(commitSha):null}}export{resolveReleaseSlug};
@@ -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.digest;return typeof digest==`string`&&CONTROL_FLOW_DIGEST_PREFIXES.some(prefix=>digest.startsWith(prefix))}const seen=new WeakSet;function buildAttrs(value,mechanism,context){let attrs={"interfere.exception.mechanism":mechanism.type,"interfere.exception.handled":mechanism.handled},digest=context?.nextjs?.errorDigest;if(digest&&(attrs[`interfere.error.digest`]=digest),context?.nextjs?.requestMethod&&(attrs[`http.request.method`]=context.nextjs.requestMethod),context?.nextjs?.requestPath&&(attrs[`url.path`]=context.nextjs.requestPath),context?.nextjs?.routePath&&(attrs[`http.route`]=context.nextjs.routePath),context?.nextjs?.routeType===`route`&&!mechanism.handled&&(attrs[`http.response.status_code`]=500),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;return isNonErrorException(value)?(attrs[`exception.type`]=value.type,attrs[`exception.message`]=value.value,attrs[`interfere.exception.kind`]=`non-error`,attrs):(attrs[`exception.type`]=value.name,attrs[`exception.message`]=value.message,attrs[`interfere.exception.kind`]=`error`,value.stack&&(attrs[`exception.stacktrace`]=value.stack),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{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 +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};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,body,activeContext,activeSpan,attributes){if(!emitting){emitting=!0;try{logger.emit({severityNumber:severity,severityText:method.toUpperCase(),body,...activeSpan?{context:activeContext}:{},...attributes?{attributes}:{}})}catch(error){bridgeFailures++,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 body=args.map(stringify).join(` `),activeContext=context.active(),activeSpan=trace.getSpan(activeContext),attributes=buildExceptionAttributes(args);queueMicrotask(()=>{emitLog(orig,severity,method,body,activeContext,activeSpan,attributes)})}}return()=>{for(let method of CONSOLE_METHODS)console[method]=original[method]}}export{bridgeConsoleToOtel};
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};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,body,activeContext,activeSpan,attributes){if(!emitting){emitting=!0;try{logger.emit({severityNumber:severity,severityText:method.toUpperCase(),body,...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 body=args.map(stringify).join(` `),activeContext=context.active(),activeSpan=trace.getSpan(activeContext),attributes=buildExceptionAttributes(args);queueMicrotask(()=>{emitLog(orig,severity,method,body,activeContext,activeSpan,attributes)})}}return()=>{for(let method of CONSOLE_METHODS)console[method]=original[method]}}export{bridgeConsoleToOtel};
@@ -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(()=>void 0),resultCallback({code:ExportResultCode.SUCCESS})}shutdown(){return Promise.resolve()}forceFlush(){return Promise.resolve()}};export{FetchTraceExporter};
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 +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)}function flushWithTimeout(flush){return new Promise(resolve=>{let timer=setTimeout(resolve,2e3);timer.unref?.(),flush().finally(()=>{clearTimeout(timer),resolve()})})}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:{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 +1 @@
1
- import{RandomIdGenerator}from"@opentelemetry/sdk-trace-base";import{randomBytes}from"node:crypto";const TRACE_COUNTER_MODULUS=2**32,SPAN_COUNTER_MODULUS=2**16;var PrerenderSafeIdGenerator=class{random=new RandomIdGenerator;tracePrefix;spanPrefix;traceCounter=0;spanCounter=0;constructor(){let seed=randomBytes(36/2);this.tracePrefix=seed.subarray(0,24/2).toString(`hex`),this.spanPrefix=seed.subarray(24/2).toString(`hex`)}generateTraceId(){try{return this.random.generateTraceId()}catch{return this.fallbackTraceId()}}generateSpanId(){try{return this.random.generateSpanId()}catch{return this.fallbackSpanId()}}fallbackTraceId(){return this.traceCounter=(this.traceCounter+1)%TRACE_COUNTER_MODULUS,this.tracePrefix+this.traceCounter.toString(16).padStart(8,`0`)}fallbackSpanId(){return this.spanCounter=(this.spanCounter+1)%SPAN_COUNTER_MODULUS,this.spanPrefix+this.spanCounter.toString(16).padStart(4,`0`)}};export{PrerenderSafeIdGenerator};
1
+ import{RandomIdGenerator}from"@opentelemetry/sdk-trace-base";import{randomBytes}from"node:crypto";const TRACE_COUNTER_MODULUS=2**32,SPAN_COUNTER_MODULUS=2**16;var PrerenderSafeIdGenerator=class{random=new RandomIdGenerator;tracePrefix;spanPrefix;traceCounter=0;spanCounter=0;constructor(){let seed=randomBytes(18);this.tracePrefix=seed.subarray(0,12).toString(`hex`),this.spanPrefix=seed.subarray(12).toString(`hex`)}generateTraceId(){try{return this.random.generateTraceId()}catch{return this.fallbackTraceId()}}generateSpanId(){try{return this.random.generateSpanId()}catch{return this.fallbackSpanId()}}fallbackTraceId(){return this.traceCounter=(this.traceCounter+1)%TRACE_COUNTER_MODULUS,this.tracePrefix+this.traceCounter.toString(16).padStart(8,`0`)}fallbackSpanId(){return this.spanCounter=(this.spanCounter+1)%SPAN_COUNTER_MODULUS,this.spanPrefix+this.spanCounter.toString(16).padStart(4,`0`)}};export{PrerenderSafeIdGenerator};
@@ -25,10 +25,10 @@ interface ServerInstrumentationOptions {
25
25
  /** @internal */
26
26
  _internalAdditionalLogRecordProcessors?: LogRecordProcessor[];
27
27
  /**
28
- * @internal
29
- *
30
28
  * Extra span processors fanned into the NodeTracerProvider's processor
31
29
  * list. See `_internalAdditionalLogRecordProcessors`.
30
+ *
31
+ * @internal
32
32
  */
33
33
  _internalAdditionalSpanProcessors?: SpanProcessor[];
34
34
  /**
@@ -29,6 +29,6 @@ interface ServerActionOptions {
29
29
  * }
30
30
  * ```
31
31
  */
32
- declare function withInterfereServerAction<T>(name: string, callback: () => T | Promise<T>, options?: ServerActionOptions): Promise<T>;
32
+ declare function withInterfereServerAction<T>(name: string, action: () => T | Promise<T>, options?: ServerActionOptions): Promise<T>;
33
33
  //#endregion
34
34
  export { withInterfereServerAction };
@@ -1 +1 @@
1
- import{markServerAction}from"./server-action-marker.mjs";import{SpanStatusCode,trace}from"@opentelemetry/api";function withInterfereServerAction(name,callback,options){return trace.getTracer(`@interfere/next/server`).startActiveSpan(`serverAction ${name}`,async span=>{span.setAttribute(`interfere.server_action.name`,name);let argsShape=options?.args?describeArgsShape(options.args):null;argsShape&&span.setAttribute(`interfere.server_action.args_shape`,argsShape);try{let result=await callback();return span.setAttribute(`interfere.server_action.outcome`,`success`),result}catch(error){throw span.setAttribute(`interfere.server_action.outcome`,`error`),span.setStatus({code:SpanStatusCode.ERROR}),markServerAction(error,{name,...argsShape?{argsShape}:{}}),error}finally{span.end()}})}function describeArgsShape(args){return args.map(arg=>arg===null?`null`:arg===void 0?`undefined`:typeof arg==`object`?arg.constructor?.name??`object`:typeof arg).join(`,`)}export{withInterfereServerAction};
1
+ import{markServerAction}from"./server-action-marker.mjs";import{SpanStatusCode,trace}from"@opentelemetry/api";function withInterfereServerAction(name,action,options){return trace.getTracer(`@interfere/next/server`).startActiveSpan(`serverAction ${name}`,async span=>{span.setAttribute(`interfere.server_action.name`,name);let argsShape=options?.args?describeArgsShape(options.args):null;argsShape&&span.setAttribute(`interfere.server_action.args_shape`,argsShape);try{let result=await action();return span.setAttribute(`interfere.server_action.outcome`,`success`),result}catch(error){throw span.setAttribute(`interfere.server_action.outcome`,`error`),span.setStatus({code:SpanStatusCode.ERROR}),markServerAction(error,{name,...argsShape?{argsShape}:{}}),error}finally{span.end()}})}function describeArgsShape(args){return args.map(arg=>arg===null?`null`:arg===void 0?`undefined`:typeof arg==`object`?arg.constructor?.name??`object`:typeof arg).join(`,`)}export{withInterfereServerAction};
@@ -1 +1 @@
1
- import{log}from"./logger.mjs";import{createRequire}from"node:module";import{existsSync}from"node:fs";import{resolve}from"node:path";const SERVER_INSTRUMENTATION_FILES=[`instrumentation.ts`,`instrumentation.tsx`,`instrumentation.js`,`instrumentation.jsx`,`src/instrumentation.ts`,`src/instrumentation.tsx`,`src/instrumentation.js`,`src/instrumentation.jsx`];function hasServerInstrumentation(projectDir){return SERVER_INSTRUMENTATION_FILES.some(c=>existsSync(resolve(projectDir,c)))}function warnIfServerInstrumentationMissing(projectDir){hasServerInstrumentation(projectDir)||log.warn(`No instrumentation.ts found`,[`Server-side traces will be skipped. To enable, create instrumentation.ts at the project root with:`,` export { register } from '@interfere/next/instrumentation';`])}function readNextMajorVersion(projectDir){try{let pkg=createRequire(`${projectDir}/_`)(`next/package.json`),major=Number.parseInt(pkg.version?.split(`.`)[0]??``,10);return Number.isFinite(major)?major:null}catch{return null}}export{readNextMajorVersion,warnIfServerInstrumentationMissing};
1
+ import{log}from"./logger.mjs";import{createRequire}from"node:module";import{existsSync}from"node:fs";import path from"node:path";const SERVER_INSTRUMENTATION_FILES=[`instrumentation.ts`,`instrumentation.tsx`,`instrumentation.js`,`instrumentation.jsx`,`src/instrumentation.ts`,`src/instrumentation.tsx`,`src/instrumentation.js`,`src/instrumentation.jsx`];function hasServerInstrumentation(projectDir){return SERVER_INSTRUMENTATION_FILES.some(c=>existsSync(path.resolve(projectDir,c)))}function warnIfServerInstrumentationMissing(projectDir){hasServerInstrumentation(projectDir)||log.warn(`No instrumentation.ts found`,[`Server-side traces will be skipped. To enable, create instrumentation.ts at the project root with:`,` export { register } from '@interfere/next/instrumentation';`])}function readNextMajorVersion(projectDir){try{let pkg=createRequire(`${projectDir}/_`)(`next/package.json`),major=Number.parseInt(pkg.version?.split(`.`)[0]??``,10);return Number.isFinite(major)?major:null}catch{return null}}export{readNextMajorVersion,warnIfServerInstrumentationMissing};
package/dist/package.mjs CHANGED
@@ -1 +1 @@
1
- var name=`@interfere/next`,version=`11.0.5`;export{name,version};
1
+ var name=`@interfere/next`,version=`11.1.0`;export{name,version};
package/dist/provider.mjs CHANGED
@@ -1 +1 @@
1
- "use client";import{getKernelOrNull,subscribeToKernel}from"./instrument-client.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{InterfereProvider as InterfereProvider$1,useInterfere,useSession}from"@interfere/react/provider";import{useSyncExternalStore}from"react";import{jsx}from"react/jsx-runtime";const nullSnapshot=()=>null;function InterfereProvider({children,consent,plugins,errorBoundary}){return jsx(InterfereProvider$1,{kernel:useSyncExternalStore(subscribeToKernel,getKernelOrNull,nullSnapshot),...omitUndefined({consent,plugins,errorBoundary}),children})}export{InterfereProvider,useInterfere,useSession};
1
+ "use client";import{getKernelOrNull,subscribeToKernel}from"./instrument-client.mjs";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{InterfereProvider as InterfereProvider$1,useInterfere,useSession}from"@interfere/react/provider";import{useSyncExternalStore}from"react";import{jsx}from"react/jsx-runtime";const nullSnapshot=()=>null;function InterfereProvider({children,consent,plugins,errorBoundary}){let kernel=useSyncExternalStore(subscribeToKernel,getKernelOrNull,nullSnapshot);return jsx(InterfereProvider$1,{kernel,...omitUndefined({consent,plugins,errorBoundary}),children})}export{InterfereProvider,useInterfere,useSession};
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@interfere/next",
3
- "version": "11.0.5",
3
+ "version": "11.1.0",
4
4
  "license": "MIT",
5
5
  "description": "Build software that never breaks.",
6
6
  "keywords": [
7
7
  "observability",
8
- "@typescript/native-preview",
8
+ "typescript",
9
9
  "react",
10
10
  "nextjs",
11
11
  "error-tracking"
@@ -90,29 +90,29 @@
90
90
  "scripts": {
91
91
  "build": "tsdown",
92
92
  "test": "vitest run",
93
- "typecheck": "tsgo --noEmit"
93
+ "typecheck": "tsc --noEmit"
94
94
  },
95
95
  "dependencies": {
96
- "@interfere/constants": "^9.0.3",
97
- "@interfere/helpers": "^9.0.3",
98
- "@interfere/react": "^11.0.5",
99
- "@interfere/sdk": "^11.0.5",
100
- "@interfere/types": "^10.0.2",
96
+ "@interfere/constants": "^9.0.4",
97
+ "@interfere/helpers": "^9.1.0",
98
+ "@interfere/react": "^11.1.0",
99
+ "@interfere/sdk": "^11.1.0",
100
+ "@interfere/types": "^10.1.0",
101
101
  "@opentelemetry/api": "^1.9.1",
102
- "@opentelemetry/api-logs": "^0.219.0",
102
+ "@opentelemetry/api-logs": "^0.221.0",
103
103
  "@opentelemetry/baggage-span-processor": "^0.5.0",
104
104
  "@opentelemetry/context-async-hooks": "^2.7.1",
105
105
  "@opentelemetry/core": "^2.7.0",
106
- "@opentelemetry/exporter-logs-otlp-http": "^0.219.0",
107
- "@opentelemetry/exporter-trace-otlp-http": "^0.219.0",
108
- "@opentelemetry/instrumentation": "^0.219.0",
109
- "@opentelemetry/otlp-exporter-base": "^0.219.0",
110
- "@opentelemetry/otlp-transformer": "^0.219.0",
106
+ "@opentelemetry/exporter-logs-otlp-http": "^0.221.0",
107
+ "@opentelemetry/exporter-trace-otlp-http": "^0.221.0",
108
+ "@opentelemetry/instrumentation": "^0.221.0",
109
+ "@opentelemetry/otlp-exporter-base": "^0.221.0",
110
+ "@opentelemetry/otlp-transformer": "^0.221.0",
111
111
  "@opentelemetry/resources": "^2.7.0",
112
- "@opentelemetry/sdk-logs": "^0.219.0",
112
+ "@opentelemetry/sdk-logs": "^0.221.0",
113
113
  "@opentelemetry/sdk-trace-base": "^2.7.0",
114
114
  "@opentelemetry/sdk-trace-node": "^2.7.1",
115
- "chalk": "^5.6.2"
115
+ "chalk": "^6.0.0"
116
116
  },
117
117
  "peerDependencies": {
118
118
  "next": "^15.3.0 || ^16.0.0",
@@ -131,21 +131,21 @@
131
131
  }
132
132
  },
133
133
  "devDependencies": {
134
- "@interfere/test-utils": "^9.0.4",
135
- "@interfere/typescript-config": "^9.0.1",
136
- "@types/node": "^26.1.0",
137
- "@types/react": "19.2.17",
138
- "@types/react-dom": "19.2.3",
139
- "@typescript/native-preview": "7.0.0-dev.20260701.1",
140
- "@vitest/browser": "4.1.9",
141
- "@vitest/browser-playwright": "4.1.9",
142
- "@vitest/coverage-v8": "4.1.9",
143
- "next": "^16.2.4",
144
- "playwright": "^1.61.1",
134
+ "@interfere/test-utils": "^9.1.0",
135
+ "@interfere/typescript-config": "^9.0.2",
136
+ "@types/node": "^26.2.0",
137
+ "@types/react": "19.2.18",
138
+ "@types/react-dom": "19.2.4",
139
+ "@vitest/browser": "4.1.10",
140
+ "@vitest/browser-playwright": "4.1.10",
141
+ "@vitest/coverage-v8": "4.1.10",
142
+ "next": "^16.3.0",
143
+ "playwright": "^1.62.1",
145
144
  "react": "^19.2.6",
146
- "react-dom": "^19.2.6",
145
+ "react-dom": "19.2.8",
147
146
  "tsdown": "^0.22.2",
148
- "vitest": "4.1.9",
147
+ "typescript": "^7.0.2",
148
+ "vitest": "4.1.10",
149
149
  "vitest-browser-react": "2.2.0"
150
150
  }
151
151
  }