@interfere/next 11.0.0-canary.3 → 11.0.0-canary.5

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/README.md CHANGED
@@ -97,13 +97,13 @@ export default function RootLayout({
97
97
 
98
98
  | Variable | Required | Description |
99
99
  | --- | --- | --- |
100
- | `INTERFERE_PUBLIC_KEY` | Yes | Surface public key in the `interfere_pk_*` format. Public by design; used for ingestion. |
101
- | `INTERFERE_API_KEY` | Yes for release metadata | Interfere API key in the `interfere_ak_*` format. Server-side build credential; never expose in browser code. |
100
+ | `INTERFERE_PUBLIC_KEY` | Yes | Surface publishable key in the `interfere_pub_us_*` or `interfere_pub_eu_*` format. Public by design; used for ingestion. |
101
+ | `INTERFERE_API_KEY` | Yes for release metadata | Interfere secret key in the `interfere_secret_us_*` or `interfere_secret_eu_*` format. Server-side build credential; never expose in browser code. |
102
102
  | `NEXT_PUBLIC_INTERFERE_ROUTE_PREFIX` | No | Override the proxy route prefix (default: `/api/interfere`). Must match the path you mount the route handler at — e.g. set this to `/__telemetry` and mount the handler at `app/__telemetry/[[...path]]/route.ts`. Read by both the server route handler and the client SDK. |
103
103
 
104
104
  ### Migrating From 0.x
105
105
 
106
- Upgrade all `@interfere/*` SDK packages together. Keep the env var names, but replace old `int_pub_*` values with the dashboard's new `interfere_pk_*` public key, and replace old `ak_*` build keys with the `interfere_ak_*` Interfere API key.
106
+ Upgrade all `@interfere/*` SDK packages together. Keep the env var names, but replace old `int_pub_*` / `interfere_pk_*` values with the dashboard's regional publishable key, and replace old `ak_*` / `interfere_ak_*` build keys with the regional Interfere secret key.
107
107
 
108
108
  ## Custom Route Prefix
109
109
 
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{omitUndefined}from"@interfere/helpers/omit-undefined";import{LOCAL_DEV_RELEASE_SLUG}from"@interfere/types/releases/slug";import{resolveDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{PHASE_PRODUCTION_BUILD}from"next/constants.js";function withInterfere(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(),forceEnable=!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE,build=configureBuild({existingWebpack:webpack,existingTurbopack:turbopack,projectDir,values:{__INTERFERE_RELEASE_SLUG__:forceEnable?LOCAL_DEV_RELEASE_SLUG:config.releaseSlug,...config.publicKey&&{__INTERFERE_PROXY_MODE__:!0,__INTERFERE_PUBLIC_KEY__:config.publicKey},...config.environment&&{__INTERFERE_ENVIRONMENT__:config.environment},...forceEnable&&{__INTERFERE_FORCE_ENABLE__:!0}}});if(config.publicKey!==null&&!build.webpack&&!build.turbopack)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 nextMajor=readNextMajorVersion(projectDir),needsInstrumentationHookFlag=nextMajor===null||nextMajor<=14,existingHook=compiler?.runAfterProductionCompile,browserSourceMaps=config.apiKey===null?productionBrowserSourceMaps:!0;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 evidence when generating insights.`,`Error: ${message}`])}}},...omitUndefined({productionBrowserSourceMaps:browserSourceMaps,turbopack:build.turbopack,webpack:build.webpack}),...needsInstrumentationHookFlag?{experimental:{...rest.experimental??{},instrumentationHook:!0}}:{}}}function resolveBuildConfig(){let{apiKey,apiUrl,publicKey}=readInterfereEnv(),{commitSha,slug}=resolveReleaseSlug(),environment=process.env.NEXT_PHASE===PHASE_PRODUCTION_BUILD?resolveDeployEnvironment(process.env):null;return{apiKey:apiKey??null,apiUrl,buildId:commitSha,environment,publicKey:publicKey??null,releaseSlug:slug}}async function runBuildReleasePipeline(context,config){let{apiKey,buildId,releaseSlug}=config;if(!apiKey)return log.fatal(`API key not set`,[`withInterfere() requires an API 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://support.interfere.com/docs/guides/next-js`]);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);log.warn(`Skipping release pipeline`,[`Interfere failed to process this release.`,`Events from this release will be ingested, but ignored as evidence when generating insights.`,`Please check https://status.interfere.com for any outages, or contact support@interfere.com if the problem persists.`,`Error: ${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{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{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 withInterfere(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(),forceEnable=!!process.env.NEXT_PUBLIC_INTERFERE_FORCE_ENABLE,build=configureBuild({existingWebpack:webpack,existingTurbopack:turbopack,projectDir,values:{__INTERFERE_RELEASE_SLUG__:forceEnable?LOCAL_DEV_RELEASE_SLUG:config.releaseSlug,...config.publicKey&&{__INTERFERE_PROXY_MODE__:!0,__INTERFERE_PUBLIC_KEY__:config.publicKey},...config.environment&&{__INTERFERE_ENVIRONMENT__:config.environment},...forceEnable&&{__INTERFERE_FORCE_ENABLE__:!0}}});if(config.publicKey!==null&&!build.webpack&&!build.turbopack)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 nextMajor=readNextMajorVersion(projectDir),experimental=interfereExperimentalConfig({existing:rest.experimental,instrumentationHook:nextMajor===null||nextMajor<=14,traceMetadata:config.publicKey!==null||forceEnable}),existingHook=compiler?.runAfterProductionCompile,browserSourceMaps=config.apiKey===null?productionBrowserSourceMaps:!0;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 resolveBuildConfig(){let{apiKey,apiUrl,publicKey}=readInterfereEnv(),{commitSha,slug}=resolveReleaseSlug(),environment=process.env.NEXT_PHASE===PHASE_PRODUCTION_BUILD?resolveDeployEnvironment(process.env):null;return{apiKey:apiKey??null,apiUrl,buildId:commitSha,environment,publicKey:publicKey??null,releaseSlug:slug}}async function runBuildReleasePipeline(context,config){let{apiKey,buildId,releaseSlug}=config;if(!apiKey)return log.fatal(`API key not set`,[`withInterfere() requires an API 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://support.interfere.com/docs/guides/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 +1 @@
1
- import{detectActiveBundler}from"./detect-bundler.mjs";import{resolveReleaseRequest}from"./release/index.mjs";import{discoverSourceMaps}from"./source-maps/discover.mjs";import{uploadSourceMaps}from"./source-maps/upload.mjs";import{cleanupSourceMaps}from"./source-maps/index.mjs";import{releaseSlugSchema}from"@interfere/types/releases/slug";import{HTTPClient,Interfere}from"@interfere/sdk";async function timed(fn){let start=performance.now();return[await fn(),Math.round(performance.now()-start)]}async function runBuildPipeline(context,metadata){let{apiUrl,apiKey}=metadata,httpClient=new HTTPClient;httpClient.addHook(`beforeRequest`,request=>{let nextRequest=new Request(request);return nextRequest.headers.set(`Authorization`,`Bearer ${apiKey}`),nextRequest});let sdk=new Interfere({serverURL:apiUrl,httpClient}),security={apiKey},start=performance.now(),bundler=detectActiveBundler(),[{discovered,config},discoverMs]=await timed(async()=>{let[discovered,config]=await Promise.all([discoverSourceMaps({bundler,projectDir:context.projectDir,distDir:context.distDir}),sdk.releases.getConfig(security)]);return{discovered,config}});if(discovered.files.length===0)return{ready:!1,reason:`no_source_maps`,fileCount:0};let releaseRequest=resolveReleaseRequest(metadata.buildId,metadata.releaseSlug,config),[release,createReleaseMs]=await timed(()=>sdk.releases.create(security,releaseRequest)),releaseSlug=releaseSlugSchema.parse(release.destination.slug),buildId=release.build.hash??metadata.buildId,[{totalBytes},uploadMs]=await timed(()=>uploadSourceMaps({apiUrl,bundler,discovered,httpClient,releaseSlug})),[,preflightMs]=await timed(()=>sdk.releases.preflight(security,{releaseSlug})),[,cleanupMs]=await timed(()=>cleanupSourceMaps(discovered.files)),timing={discover:discoverMs,createRelease:createReleaseMs,upload:uploadMs,preflight:preflightMs,cleanup:cleanupMs,total:Math.round(performance.now()-start),fileCount:discovered.files.length,totalBytes};return{ready:!0,fileCount:discovered.files.length,release:{...release,destination:{...release.destination,slug:releaseSlug}},config,buildId,timing}}export{runBuildPipeline};
1
+ import{detectActiveBundler}from"./detect-bundler.mjs";import{resolveReleaseRequest}from"./release/index.mjs";import{discoverSourceMaps}from"./source-maps/discover.mjs";import{uploadSourceMaps}from"./source-maps/upload.mjs";import{cleanupSourceMaps}from"./source-maps/index.mjs";import{releaseSlugSchema}from"@interfere/types/releases/slug";import{HTTPClient,Interfere}from"@interfere/sdk";async function timed(fn){let start=performance.now();return[await fn(),Math.round(performance.now()-start)]}async function runBuildPipeline(context,metadata){let{apiUrl,apiKey}=metadata,httpClient=new HTTPClient;httpClient.addHook(`beforeRequest`,request=>{let nextRequest=new Request(request);return nextRequest.headers.set(`Authorization`,`Bearer ${apiKey}`),nextRequest});let sdk=new Interfere({serverURL:apiUrl,httpClient}),security={apiKey},start=performance.now(),bundler=detectActiveBundler(),[{discovered,config},discoverMs]=await timed(async()=>{let[discovered,config]=await Promise.all([discoverSourceMaps({bundler,projectDir:context.projectDir,distDir:context.distDir}),sdk.releases.getConfig(security)]);return{discovered,config}});if(discovered.files.length===0)return{ready:!1,reason:`no_source_maps`,fileCount:0};let releaseRequest=resolveReleaseRequest(metadata.buildId,metadata.environment,metadata.releaseSlug,config),[release,createReleaseMs]=await timed(()=>sdk.releases.create(security,releaseRequest)),releaseSlug=releaseSlugSchema.parse(release.destination.slug),buildId=release.build.hash??metadata.buildId,[{totalBytes},uploadMs]=await timed(()=>uploadSourceMaps({apiUrl,bundler,discovered,httpClient,releaseSlug})),[,preflightMs]=await timed(()=>sdk.releases.preflight(security,{releaseSlug})),[,cleanupMs]=await timed(()=>cleanupSourceMaps(discovered.files)),timing={discover:discoverMs,createRelease:createReleaseMs,upload:uploadMs,preflight:preflightMs,cleanup:cleanupMs,total:Math.round(performance.now()-start),fileCount:discovered.files.length,totalBytes};return{ready:!0,fileCount:discovered.files.length,release:{...release,destination:{...release.destination,slug:releaseSlug}},config,buildId,timing}}export{runBuildPipeline};
@@ -3,6 +3,6 @@ import { ReleasesConfigResponse } from "@interfere/sdk/models/releases-config-re
3
3
  import { CreateReleaseRequest } from "@interfere/types/releases/definition";
4
4
 
5
5
  //#region src/internal/build/release/index.d.ts
6
- declare function resolveReleaseRequest(buildId: string, releaseSlug: ReleaseSlug, config: ReleasesConfigResponse): CreateReleaseRequest;
6
+ declare function resolveReleaseRequest(buildId: string, environment: string | null, releaseSlug: ReleaseSlug, config: ReleasesConfigResponse): CreateReleaseRequest;
7
7
  //#endregion
8
8
  export { resolveReleaseRequest };
@@ -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{releaseDestinationProviderSchema}from"@interfere/types/integrations";function resolveReleaseRequest(buildId,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:destinations[destinationProvider.data](releaseSlug),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{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};
package/dist/package.mjs CHANGED
@@ -1 +1 @@
1
- var name=`@interfere/next`,version=`11.0.0-canary.3`;export{name,version};
1
+ var name=`@interfere/next`,version=`11.0.0-canary.5`;export{name,version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interfere/next",
3
- "version": "11.0.0-canary.3",
3
+ "version": "11.0.0-canary.5",
4
4
  "license": "MIT",
5
5
  "description": "Build software that never breaks.",
6
6
  "keywords": [
@@ -100,8 +100,8 @@
100
100
  "dependencies": {
101
101
  "@interfere/constants": "^9.0.2-canary.0",
102
102
  "@interfere/helpers": "^9.0.0",
103
- "@interfere/react": "^11.0.0-canary.3",
104
- "@interfere/sdk": "^11.0.0-canary.3",
103
+ "@interfere/react": "^11.0.0-canary.4",
104
+ "@interfere/sdk": "^11.0.0-canary.4",
105
105
  "@interfere/types": "^9.0.3-canary.2",
106
106
  "@opentelemetry/api": "^1.9.1",
107
107
  "@opentelemetry/api-logs": "^0.219.0",
@@ -140,15 +140,15 @@
140
140
  "devDependencies": {
141
141
  "@interfere/test-utils": "^9.0.0",
142
142
  "@interfere/typescript-config": "^9.0.0",
143
- "@types/node": "^25.9.3",
143
+ "@types/node": "^26.0.0",
144
144
  "@types/react": "19.2.17",
145
145
  "@types/react-dom": "19.2.3",
146
- "@typescript/native-preview": "7.0.0-dev.20260617.2",
146
+ "@typescript/native-preview": "7.0.0-dev.20260623.1",
147
147
  "@vitest/browser": "4.1.9",
148
148
  "@vitest/browser-playwright": "4.1.9",
149
149
  "@vitest/coverage-v8": "4.1.9",
150
150
  "next": "^16.2.4",
151
- "playwright": "^1.60.0",
151
+ "playwright": "^1.61.1",
152
152
  "react": "^19.2.6",
153
153
  "react-dom": "^19.2.6",
154
154
  "tsdown": "^0.22.2",