@interfere/vite 12.3.0 → 12.3.4
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/internal/server/register.mjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/plugin.mjs +1 -1
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PRODUCER_VERSION}from"../../version.mjs";import{resolveReleaseSlug}from"../release-slug.mjs";import{readInterfereServerEnv}from"./env.mjs";import{fetchAndCacheRemoteConfig}from"./remote-config.mjs";import{bridgeConsoleToOtel}from"./console-bridge.mjs";import{FreshnessStampingPropagator}from"./freshness-propagator.mjs";import{drainUrl}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{metrics,propagation}from"@opentelemetry/api";import{resolveLogSourcingMode}from"@interfere/types/sdk/log-sourcing";import{VERCEL_EXPORT_TIMEOUT_MS,resolveServerTracing}from"@interfere/types/sdk/server-tracing";import{BaggageSpanProcessor}from"@opentelemetry/baggage-span-processor";import{AsyncLocalStorageContextManager}from"@opentelemetry/context-async-hooks";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator,getStringFromEnv}from"@opentelemetry/core";import{OTLPLogExporter}from"@opentelemetry/exporter-logs-otlp-http";import{AggregationTemporalityPreference,OTLPMetricExporter}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter}from"@opentelemetry/exporter-trace-otlp-http";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{UndiciInstrumentation}from"@opentelemetry/instrumentation-undici";import{defaultServiceName,resourceFromAttributes}from"@opentelemetry/resources";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{MeterProvider,PeriodicExportingMetricReader}from"@opentelemetry/sdk-metrics";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{NodeTracerProvider}from"@opentelemetry/sdk-trace-node";let registered=!1;function matchesAny(url,patterns){for(let pattern of patterns)if(pattern instanceof RegExp?pattern.test(url):url.includes(pattern))return!0;return!1}async function register(opts={}){if(registered)return;let env=readInterfereServerEnv();if(!env.publicKey)return;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{publicKey}=env,tracesUrl=drainUrl(env.apiUrl,`traces`,publicKey),logsUrl=drainUrl(env.apiUrl,`logs`,publicKey),metricsUrl=drainUrl(env.apiUrl,`metrics`,publicKey),ignoreUrls=[tracesUrl,logsUrl,metricsUrl,...opts.ignoreUrls??[]],propagateContextUrls=opts.propagateContextUrls??[],tracing=resolveServerTracing({injected:import.meta.env?.VITE_INTERFERE_SERVER_TRACING}),isLogDrainMode=resolveLogSourcingMode(import.meta.env?.VITE_INTERFERE_LOG_SOURCING)===`drain`,exportTimeout=tracing.vercel?{timeoutMillis:VERCEL_EXPORT_TIMEOUT_MS}:{},batchTimeout=tracing.vercel?{exportTimeoutMillis:VERCEL_EXPORT_TIMEOUT_MS}:{},exporterHeaders={"x-interfere-producer-version":PRODUCER_VERSION},resourceAttributes=omitUndefined({"deployment.environment.name":env.nodeEnvironment,"interfere.sdk.name":`@interfere/vite`,"interfere.sdk.version":PRODUCER_VERSION,"service.name":opts.serviceName||getStringFromEnv(`OTEL_SERVICE_NAME`)||import.meta.env.VITE_INTERFERE_SERVICE_NAME||defaultServiceName(),"service.namespace":opts.serviceNamespace,"telemetry.sdk.language":`nodejs`,"release.slug":releaseSlug||void 0}),resource=resourceFromAttributes(resourceAttributes),isDrainMode=tracing.mode===`drain`,tracerProvider=new NodeTracerProvider({resource,spanProcessors:[new BaggageSpanProcessor(()=>!0),...isDrainMode?[]:[new BatchSpanProcessor(new OTLPTraceExporter({...exportTimeout,headers:exporterHeaders,url:tracesUrl}),batchTimeout)]]});if(propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,new FreshnessStampingPropagator,new W3CBaggagePropagator]})),tracerProvider.register({contextManager:new AsyncLocalStorageContextManager().enable()}),!isLogDrainMode){let loggerProvider=new LoggerProvider({processors:[new BatchLogRecordProcessor({...batchTimeout,exporter:new OTLPLogExporter({...exportTimeout,url:logsUrl,headers:exporterHeaders})})],resource}),{logs:logsApi}=await import(`@opentelemetry/api-logs`);logsApi.setGlobalLoggerProvider(loggerProvider)}let meterProvider=new MeterProvider({readers:[new PeriodicExportingMetricReader({exporter:new OTLPMetricExporter({url:metricsUrl,headers:exporterHeaders,temporalityPreference:AggregationTemporalityPreference.DELTA}),exportIntervalMillis:3e4})],resource});metrics.setGlobalMeterProvider(meterProvider),isDrainMode?console.info(`[interfere] server tracing in drain mode; SDK trace exporter + outbound HTTP instrumentation disabled — server traces come from the platform trace drain.`):registerInstrumentations({instrumentations:[new UndiciInstrumentation({ignoreRequestHook:req=>matchesAny(`${req.origin}${req.path}`,ignoreUrls),requestHook:(span,req)=>{matchesAny(`${req.origin}${req.path}`,propagateContextUrls)&&span.setAttribute(`interfere.propagated`,!0)}})],meterProvider,tracerProvider}),!isLogDrainMode&&opts.consoleBridge!==!1&&bridgeConsoleToOtel(),registered=!0,await fetchAndCacheRemoteConfig()}export{register};
|
|
1
|
+
import{PRODUCER_VERSION}from"../../version.mjs";import{resolveReleaseSlug}from"../release-slug.mjs";import{readInterfereServerEnv}from"./env.mjs";import{fetchAndCacheRemoteConfig}from"./remote-config.mjs";import{bridgeConsoleToOtel}from"./console-bridge.mjs";import{FreshnessStampingPropagator}from"./freshness-propagator.mjs";import{drainUrl}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{metrics,propagation}from"@opentelemetry/api";import{resolveLogSourcingMode}from"@interfere/types/sdk/log-sourcing";import{VERCEL_EXPORT_TIMEOUT_MS,resolveServerTracing}from"@interfere/types/sdk/server-tracing";import{BaggageSpanProcessor}from"@opentelemetry/baggage-span-processor";import{AsyncLocalStorageContextManager}from"@opentelemetry/context-async-hooks";import{CompositePropagator,W3CBaggagePropagator,W3CTraceContextPropagator,getStringFromEnv}from"@opentelemetry/core";import{OTLPLogExporter}from"@opentelemetry/exporter-logs-otlp-http";import{AggregationTemporalityPreference,OTLPMetricExporter}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter}from"@opentelemetry/exporter-trace-otlp-http";import{registerInstrumentations}from"@opentelemetry/instrumentation";import{UndiciInstrumentation}from"@opentelemetry/instrumentation-undici";import{defaultServiceName,resourceFromAttributes}from"@opentelemetry/resources";import{BatchLogRecordProcessor,LoggerProvider}from"@opentelemetry/sdk-logs";import{MeterProvider,PeriodicExportingMetricReader}from"@opentelemetry/sdk-metrics";import{BatchSpanProcessor}from"@opentelemetry/sdk-trace-base";import{NodeTracerProvider}from"@opentelemetry/sdk-trace-node";let registered=!1;function matchesAny(url,patterns){for(let pattern of patterns)if(pattern instanceof RegExp?pattern.test(url):url.includes(pattern))return!0;return!1}async function register(opts={}){if(registered)return;let env=readInterfereServerEnv();if(!env.publicKey)return;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{publicKey}=env,tracesUrl=drainUrl(env.apiUrl,`traces`,publicKey),logsUrl=drainUrl(env.apiUrl,`logs`,publicKey),metricsUrl=drainUrl(env.apiUrl,`metrics`,publicKey),ignoreUrls=[tracesUrl,logsUrl,metricsUrl,...opts.ignoreUrls??[]],propagateContextUrls=opts.propagateContextUrls??[],tracing=resolveServerTracing({injected:import.meta.env?.VITE_INTERFERE_SERVER_TRACING,platform:import.meta.env?.VITE_INTERFERE_PLATFORM}),isLogDrainMode=resolveLogSourcingMode(import.meta.env?.VITE_INTERFERE_LOG_SOURCING)===`drain`,exportTimeout=tracing.vercel?{timeoutMillis:VERCEL_EXPORT_TIMEOUT_MS}:{},batchTimeout=tracing.vercel?{exportTimeoutMillis:VERCEL_EXPORT_TIMEOUT_MS}:{},exporterHeaders={"x-interfere-producer-version":PRODUCER_VERSION},resourceAttributes=omitUndefined({"deployment.environment.name":env.nodeEnvironment,"interfere.sdk.name":`@interfere/vite`,"interfere.sdk.version":PRODUCER_VERSION,"service.name":opts.serviceName||getStringFromEnv(`OTEL_SERVICE_NAME`)||import.meta.env.VITE_INTERFERE_SERVICE_NAME||defaultServiceName(),"service.namespace":opts.serviceNamespace,"telemetry.sdk.language":`nodejs`,"release.slug":releaseSlug||void 0}),resource=resourceFromAttributes(resourceAttributes),isDrainMode=tracing.mode===`drain`,tracerProvider=new NodeTracerProvider({resource,spanProcessors:[new BaggageSpanProcessor(()=>!0),...isDrainMode?[]:[new BatchSpanProcessor(new OTLPTraceExporter({...exportTimeout,headers:exporterHeaders,url:tracesUrl}),batchTimeout)]]});if(propagation.fields().length===0&&propagation.setGlobalPropagator(new CompositePropagator({propagators:[new W3CTraceContextPropagator,new FreshnessStampingPropagator,new W3CBaggagePropagator]})),tracerProvider.register({contextManager:new AsyncLocalStorageContextManager().enable()}),!isLogDrainMode){let loggerProvider=new LoggerProvider({processors:[new BatchLogRecordProcessor({...batchTimeout,exporter:new OTLPLogExporter({...exportTimeout,url:logsUrl,headers:exporterHeaders})})],resource}),{logs:logsApi}=await import(`@opentelemetry/api-logs`);logsApi.setGlobalLoggerProvider(loggerProvider)}let meterProvider=new MeterProvider({readers:[new PeriodicExportingMetricReader({exporter:new OTLPMetricExporter({url:metricsUrl,headers:exporterHeaders,temporalityPreference:AggregationTemporalityPreference.DELTA}),exportIntervalMillis:3e4})],resource});metrics.setGlobalMeterProvider(meterProvider),isDrainMode?console.info(`[interfere] server tracing in drain mode; SDK trace exporter + outbound HTTP instrumentation disabled — server traces come from the platform trace drain.`):registerInstrumentations({instrumentations:[new UndiciInstrumentation({ignoreRequestHook:req=>matchesAny(`${req.origin}${req.path}`,ignoreUrls),requestHook:(span,req)=>{matchesAny(`${req.origin}${req.path}`,propagateContextUrls)&&span.setAttribute(`interfere.propagated`,!0)}})],meterProvider,tracerProvider}),!isLogDrainMode&&opts.consoleBridge!==!1&&bridgeConsoleToOtel(),registered=!0,await fetchAndCacheRemoteConfig()}export{register};
|
package/dist/package.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var name=`@interfere/vite`,version=`12.3.
|
|
1
|
+
var name=`@interfere/vite`,version=`12.3.4`;export{name,version};
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{PRODUCER_VERSION}from"./version.mjs";import{runGitCommand}from"./internal/build/git.mjs";import{rejectRemovedOptions}from"./internal/plugin-options.mjs";import{createBuildReceipt}from"./internal/build/build-receipt.mjs";import{runReleasePipeline}from"./internal/build/pipeline.mjs";import{renderDebugId}from"./internal/build/render-debug-id.mjs";import{discoverByPairing}from"./internal/build/source-maps.mjs";import{resolveCommitSha}from"./internal/release-slug.mjs";import{cleanupSourceMaps}from"@interfere/build/cleanup-source-maps";import{resolveBuildServiceName}from"@interfere/build/service-name";import{sourceMapUploadFetch}from"@interfere/build/source-map-upload-fetch";import{InterfereClient}from"@interfere/javascript";import{createBuildConfigResolver}from"@interfere/build/config";import{API_URL,PUBLIC_KEY_HEADER}from"@interfere/constants/api";import{omitUndefined}from"@interfere/helpers/omit-undefined";import{deriveReleaseSlug}from"@interfere/types/releases/slug";import{checkReleaseConfig,diagnoseRelease}from"@interfere/types/sdk/build-diagnostics";import{resolveDeployEnvironment}from"@interfere/types/sdk/deploy-environment";import{createHash}from"node:crypto";import{existsSync,readdirSync,statSync}from"node:fs";import path from"node:path";import{loadEnv}from"vite";const SERVER_RUNTIME_PLUGIN_HINTS=[`tanstack-start`,`nitro`,`@tanstack/react-start`],DIAGNOSTIC_CONTEXT={publicKeyEnvVar:`VITE_INTERFERE_PUBLIC_KEY`,docsUrl:`https://interfere.com/docs/sdk/vite`};function buildError(title,details){return Error([`Interfere: ${title}`,...details].join(`
|
|
2
|
-
`))}function logDiagnostic(logger,diagnostic){for(let line of[diagnostic.title,...diagnostic.details])logger[diagnostic.severity](`[interfere] ${line}`)}function isTestEnv(){return!!(process.env.VITEST||process.env.VITEST_WORKER_ID)}function pickEnvValue(env,key){let value=env[key];return value&&value.length>0?value:void 0}function hasServerRuntimePlugin(pluginNames){return pluginNames.some(name=>SERVER_RUNTIME_PLUGIN_HINTS.some(hint=>name.includes(hint)))}function normalizeOrigin(host){try{return new URL(host).origin}catch{return null}}function resolveApiHost(options,env){let host=options.apiHost??env.VITE_INTERFERE_API_URL;if(!host)return;let origin=normalizeOrigin(host);if(!origin)throw Error(`interfere({ apiHost }) requires a full URL, e.g. apiHost: "https://in.yourapp.com"`);return origin}function resolveBrowserConfig(options,env,command,root){let commitSha=options.commitSha??env.VITE_INTERFERE_COMMIT_SHA??resolveCommitSha(runGitCommand);return{apiHost:resolveApiHost(options,env),commitSha,environment:command===`build`?resolveDeployEnvironment({...env,...process.env}):null,publicKey:env.VITE_INTERFERE_PUBLIC_KEY,serviceName:resolveBuildServiceName({option:options.serviceName,env,root,legacyEnvName:`VITE_INTERFERE_SERVICE_NAME`}),releaseSlug:commitSha?deriveReleaseSlug(options.buildVariant?createHash(`sha256`).update(JSON.stringify([commitSha,options.buildVariant])).digest(`hex`):commitSha):null}}function browserDefine(browser){return{"import.meta.env.VITE_INTERFERE_API_HOST":JSON.stringify(browser.apiHost??null),"import.meta.env.VITE_INTERFERE_ENVIRONMENT":JSON.stringify(browser.environment),"import.meta.env.VITE_INTERFERE_RELEASE_SLUG":JSON.stringify(browser.releaseSlug),"import.meta.env.VITE_INTERFERE_SERVICE_NAME":JSON.stringify(browser.serviceName??null)}}function hasFreshServerSourceMaps(root,sinceMs){if(!existsSync(root))return!1;let entries=readdirSync(root,{withFileTypes:!0});for(let entry of entries){let absolute=path.join(root,entry.name);if(entry.isDirectory()){if(hasFreshServerSourceMaps(absolute,sinceMs))return!0;continue}if(entry.name.endsWith(`.map`)&&statSync(absolute).mtimeMs>=sinceMs)return!0}return!1}function isReleaseReady(state){return!!(state.releaseEnabled&&state.apiKey&&state.releaseSlug&&state.commitSha&&!state.releaseStarted)}function shouldWaitForServerOutput(state){return state.uploadSourceMaps&&state.serverBuild&&!hasFreshServerSourceMaps(state.serverSourcemapsDir,state.buildStartedAt)}function logSkippedRelease(logger,failure){if(failure.kind===`missing_source_provider`){logger.warn(`[interfere] release skipped: this surface has no version control provider configured. Configure one at https://interfere.com/~/${failure.config.org.slug}/apps/${failure.config.surface.slug}.`);return}logger.warn(`[interfere] release skipped: this surface has no deployment target configured. Configure one at https://interfere.com/~/${failure.config.org.slug}/apps/${failure.config.surface.slug}.`)}function logCleanupFailures(logger,failures){for(let failure of failures)logger.warn(`[interfere] cleanup left ${failure.absolute} on disk: ${failure.code??failure.message}`)}async function discoverUploadableSourceMaps(state){let discovered;try{discovered=await discoverByPairing({distDir:state.uploadOutDir,projectDir:state.projectDir,publicPathRewrites:[{from:`public`,to:``}],subtrees:[`.`]})}catch(error){return logDiagnostic(state.logger,diagnoseRelease(DIAGNOSTIC_CONTEXT,error)),null}return discovered.missingSourceMapCount>0&&state.logger.warn(`[interfere] ${discovered.missingSourceMapCount} referenced source map(s) not found. Errors in those chunks will not resolve to source.`),discovered.files.length===0?(state.logger.warn(`[interfere] No source maps found; the release remains unready. Enable source-map generation and upload them during the build.`),null):discovered}async function publishRelease(state,discovered){let{apiKey,apiUrl,releaseSlug,commitSha,logger,publicKey}=state,client=new InterfereClient({fetch:sourceMapUploadFetch,baseUrl:apiUrl,apiKey:{token:apiKey},headers:{"user-agent":PRODUCER_VERSION,[PUBLIC_KEY_HEADER]:publicKey},maxRetries:4,timeoutInSeconds:10}),releasesConfig=await client.releases.getReleasesConfig({abortSignal:AbortSignal.timeout(6e4)}),result=await runReleasePipeline({client,buildId:commitSha,bundler:`rollup`,discovery:discovered,environment:state.environment,producerVersion:PRODUCER_VERSION,releaseSlug,releasesConfig,capturePublication:state.receipt!==void 0,uploadSourceMaps:state.uploadSourceMaps});if(!result.ok){logSkippedRelease(logger,result.failure);return}if(logCleanupFailures(logger,result.data.cleanupFailures),result.data.publication&&state.receipt?.recordPublication(result.data.publication),!result.data.timing){logger.info(`[interfere] release ${result.data.releaseSlug} registered without source maps.`);return}logger.info(`[interfere] source-map stages (ms): create=${result.data.timing.createRelease}, sign=${result.data.timing.sign}, session=${result.data.timing.session}, upload=${result.data.timing.upload}, finalize=${result.data.timing.finalize}, receipt=${result.data.timing.receipt}, cleanup=${result.data.timing.cleanup}; bytes=${result.data.timing.totalBytes}.`),state.uploadComplete=!0,logger.info(`[interfere] release ${result.data.releaseSlug} confirmed — ${result.data.fileCount} maps, ${result.data.timing.total}ms.`)}async function releaseBuild(state){let{logger,releaseSlug}=state;logger.info(state.uploadSourceMaps?`[interfere] uploading source maps for release ${releaseSlug}…`:`[interfere] registering release ${releaseSlug} without source maps…`);let discovered=state.uploadSourceMaps?await discoverUploadableSourceMaps(state):{files:[],missingSourceMapCount:0,sourceFileCount:0};if(discovered){try{await publishRelease(state,discovered)}catch(error){logDiagnostic(logger,diagnoseRelease(DIAGNOSTIC_CONTEXT,error))}state.uploadComplete||logCleanupFailures(logger,await cleanupSourceMaps(discovered.files))}}async function releaseBuildWhenReady(state){if(isReleaseReady(state)){if(shouldWaitForServerOutput(state)){state.logger.info(`[interfere] waiting for server build output in ${path.relative(state.projectDir,state.serverSourcemapsDir)} before uploading source maps.`);return}state.releaseStarted=!0,await releaseBuild(state)}}function resolveReleaseEnv(config){return{...loadEnv(config.mode,config.envDir,``),...process.env}}function buildPluginState(options,config,browser){let{logger}=config,isProductionBuild=config.command===`build`,releaseEnv=resolveReleaseEnv(config),apiKey=pickEnvValue(releaseEnv,`INTERFERE_API_KEY`),apiUrl=pickEnvValue(releaseEnv,`INTERFERE_API_URL`)??API_URL,retainSourceMaps=isProductionBuild&&options.sourceMaps?.retain===!0,release=isProductionBuild&&!retainSourceMaps?checkReleaseConfig(DIAGNOSTIC_CONTEXT,{apiKey,commitSha:browser.commitSha,releaseSlug:browser.releaseSlug}):null;if(release?.status===`fail`)throw buildError(release.title,release.details);let releaseEnabled=release?.status===`ok`,uploadOutDir=path.resolve(config.root,config.build.outDir),serverSourcemapsDir=options.serverSourcemapsDir?path.resolve(config.root,options.serverSourcemapsDir):path.join(uploadOutDir,`server`),serverBuild=hasServerRuntimePlugin(config.plugins.map(p=>p.name))||!!config.build.ssr;return{apiHost:browser.apiHost,apiKey,apiUrl,buildStartedAt:Math.floor(Date.now()/1e3)*1e3,commitSha:browser.commitSha,releaseEnabled,retainSourceMaps,skippedRelease:release?.status===`skip`?release:null,uploadSourceMaps:releaseEnabled&&options.sourceMaps?.upload!==!1,environment:browser.environment,isProductionBuild,logger,projectDir:config.root,publicKey:browser.publicKey,releaseSlug:browser.releaseSlug,serverBuild,serverSourcemapsDir,uploadOutDir,releaseStarted:!1,uploadComplete:!1}}function announceSetup(state){if(state.logger.info(`[interfere] ingest → ${state.apiHost??`Interfere (default)`}`),!state.apiHost&&state.serverBuild&&state.logger.warn(`[interfere] Telemetry posts directly to Interfere. On a server-rendered app, set interfere({ apiHost }) to a subdomain of your own site to survive ad-blockers.`),state.isProductionBuild&&!state.publicKey&&state.logger.warn(`[interfere] VITE_INTERFERE_PUBLIC_KEY is not set, so this build sends no events. Set it on builds that you deploy.`),state.retainSourceMaps&&state.logger.info(`[interfere] source maps are retained in the build output for a release step to upload per environment.`),state.skippedRelease)for(let line of[state.skippedRelease.title,...state.skippedRelease.details])state.logger.warn(`[interfere] ${line}`)}function mirrorPublicKeyForDevServer(command,env){if(command!==`serve`)return;let publicKey=env.VITE_INTERFERE_PUBLIC_KEY;publicKey&&!process.env.VITE_INTERFERE_PUBLIC_KEY&&(process.env.VITE_INTERFERE_PUBLIC_KEY=publicKey)}function resolveRoot(userConfig){return userConfig.root?path.resolve(process.cwd(),userConfig.root):process.cwd()}function resolveEnvDir(userConfig){let root=resolveRoot(userConfig);return userConfig.envDir===!1||userConfig.envDir===void 0||userConfig.envDir===``?root:path.resolve(root,userConfig.envDir)}function forceSourcemapForUpload(userConfig,options,command,env){if(!(command===`build`&&(options.sourceMaps?.retain===!0||options.sourceMaps?.upload!==!1&&pickEnvValue(env,`INTERFERE_API_KEY`))))return;let previous=userConfig.build?.sourcemap;return userConfig.build={...userConfig.build,sourcemap:!0},previous===void 0||previous===!0?void 0:previous}function carryOverUploadProgress(previous,next){previous?.serverBuild&&next.serverBuild&&(next.uploadOutDir=previous.uploadOutDir,next.serverSourcemapsDir=previous.serverSourcemapsDir,next.releaseStarted=previous.releaseStarted,next.uploadComplete=previous.uploadComplete,next.buildStartedAt=previous.buildStartedAt)}function warnForcedSourcemap(logger,overridden){overridden!==void 0&&logger.warn(`[interfere] Forced build.sourcemap to true (was ${JSON.stringify(overridden)}). Source maps are required to symbolicate errors; they are uploaded then deleted from the build output, so they are never served. Pass interfere({ sourceMaps: { upload: false } }) to opt out.`)}function disabledPlugin(){return{name:`interfere`,config(){return{define:{"import.meta.env.VITE_INTERFERE_DISABLED":JSON.stringify(`true`)},ssr:{noExternal:[`@interfere/vite`]}}}}}function interfere(options={}){if(rejectRemovedOptions(options),options.disable)return disabledPlugin();let receipt=options.buildReceipt?createBuildReceipt(options.buildReceipt):void 0,remoteConfigFallback=!1,resolveBuildConfig=createBuildConfigResolver(result=>{receipt?.observeConfig(result),remoteConfigFallback||=result.status===`fallback`}),state=null,overriddenSourcemap,announced=!1,uploadAfterAppBuild=!1,writeReceipt=async()=>{try{await receipt?.write()}catch{state?.logger.warn(`[interfere] Private build receipt could not be written.`)}};return{buildApp:{order:`post`,async handler(builder){if(!state)return;uploadAfterAppBuild=!0;let environments=Object.values(builder.environments);if(environments.every(environment=>!environment.isBuilt))for(let environment of environments)await builder.build(environment);isReleaseReady(state)&&(state.releaseStarted=!0,await releaseBuild(state)),await writeReceipt()}},buildStart(){state&&!announced&&(announceSetup(state),warnForcedSourcemap(state.logger,overriddenSourcemap),remoteConfigFallback&&state.logger.warn(`[interfere] Could not load SDK settings from Interfere. The build uses the default settings.`),announced=!0)},async closeBundle(){state&&!uploadAfterAppBuild&&await releaseBuildWhenReady(state),await writeReceipt()},async writeBundle(output,bundle){output.dir&&await receipt?.recordOutput(output.dir,Object.keys(bundle))},outputOptions(output){return state?.uploadSourceMaps||state?.retainSourceMaps?{...output,sourcemapDebugIds:!1}:null},renderChunk:{order:`post`,handler(code){return state?.uploadSourceMaps||state?.retainSourceMaps?renderDebugId(code):null}},async config(userConfig,{command,mode}){let env=loadEnv(mode,resolveEnvDir(userConfig),``);mirrorPublicKeyForDevServer(command,env),overriddenSourcemap=forceSourcemapForUpload(userConfig,options,command,env);let browser=resolveBrowserConfig(options,env,command,resolveRoot(userConfig)),baked=command===`build`&&browser.publicKey&&!isTestEnv()?await resolveBuildConfig(browser.apiHost??API_URL,browser.publicKey):null;return{define:omitUndefined({...browserDefine(browser),"import.meta.env.VITE_INTERFERE_INGEST_URL":baked?.ingestUrl?JSON.stringify(baked.ingestUrl):void 0,"import.meta.env.VITE_INTERFERE_SERVER_TRACING":JSON.stringify(baked?.serverTracing??null),"import.meta.env.VITE_INTERFERE_LOG_SOURCING":JSON.stringify(baked?.logSourcing??null),"import.meta.env.VITE_INTERFERE_PLUGINS":baked?.plugins?JSON.stringify(JSON.stringify(baked.plugins)):void 0}),ssr:{noExternal:[`@interfere/vite`]}}},async configResolved(config){let browser=resolveBrowserConfig(options,config.env,config.command,config.root),next=buildPluginState(options,config,browser);carryOverUploadProgress(state,next),state={...next,receipt},uploadAfterAppBuild||=config.builder!==void 0,config.command===`build`&&await receipt?.configure(config,{commitSha:browser.commitSha,releaseSlug:browser.releaseSlug,environment:browser.environment,publicKey:browser.publicKey,apiOrigin:browser.apiHost??API_URL,producerVersion:PRODUCER_VERSION})},enforce:`pre`,name:`interfere`,sharedDuringBuild:!0}}export{interfere};
|
|
2
|
+
`))}function logDiagnostic(logger,diagnostic){for(let line of[diagnostic.title,...diagnostic.details])logger[diagnostic.severity](`[interfere] ${line}`)}function isTestEnv(){return!!(process.env.VITEST||process.env.VITEST_WORKER_ID)}function pickEnvValue(env,key){let value=env[key];return value&&value.length>0?value:void 0}function hasServerRuntimePlugin(pluginNames){return pluginNames.some(name=>SERVER_RUNTIME_PLUGIN_HINTS.some(hint=>name.includes(hint)))}function normalizeOrigin(host){try{return new URL(host).origin}catch{return null}}function resolveApiHost(options,env){let host=options.apiHost??env.VITE_INTERFERE_API_URL;if(!host)return;let origin=normalizeOrigin(host);if(!origin)throw Error(`interfere({ apiHost }) requires a full URL, e.g. apiHost: "https://in.yourapp.com"`);return origin}function resolveBrowserConfig(options,env,command,root){let commitSha=options.commitSha??env.VITE_INTERFERE_COMMIT_SHA??resolveCommitSha(runGitCommand);return{apiHost:resolveApiHost(options,env),commitSha,environment:command===`build`?resolveDeployEnvironment({...env,...process.env}):null,publicKey:env.VITE_INTERFERE_PUBLIC_KEY,serviceName:resolveBuildServiceName({option:options.serviceName,env,root,legacyEnvName:`VITE_INTERFERE_SERVICE_NAME`}),releaseSlug:commitSha?deriveReleaseSlug(options.buildVariant?createHash(`sha256`).update(JSON.stringify([commitSha,options.buildVariant])).digest(`hex`):commitSha):null}}function browserDefine(browser){return{"import.meta.env.VITE_INTERFERE_API_HOST":JSON.stringify(browser.apiHost??null),"import.meta.env.VITE_INTERFERE_ENVIRONMENT":JSON.stringify(browser.environment),"import.meta.env.VITE_INTERFERE_RELEASE_SLUG":JSON.stringify(browser.releaseSlug),"import.meta.env.VITE_INTERFERE_SERVICE_NAME":JSON.stringify(browser.serviceName??null)}}function hasFreshServerSourceMaps(root,sinceMs){if(!existsSync(root))return!1;let entries=readdirSync(root,{withFileTypes:!0});for(let entry of entries){let absolute=path.join(root,entry.name);if(entry.isDirectory()){if(hasFreshServerSourceMaps(absolute,sinceMs))return!0;continue}if(entry.name.endsWith(`.map`)&&statSync(absolute).mtimeMs>=sinceMs)return!0}return!1}function isReleaseReady(state){return!!(state.releaseEnabled&&state.apiKey&&state.releaseSlug&&state.commitSha&&!state.releaseStarted)}function shouldWaitForServerOutput(state){return state.uploadSourceMaps&&state.serverBuild&&!hasFreshServerSourceMaps(state.serverSourcemapsDir,state.buildStartedAt)}function logSkippedRelease(logger,failure){if(failure.kind===`missing_source_provider`){logger.warn(`[interfere] release skipped: this surface has no version control provider configured. Configure one at https://interfere.com/~/${failure.config.org.slug}/apps/${failure.config.surface.slug}.`);return}logger.warn(`[interfere] release skipped: this surface has no deployment target configured. Configure one at https://interfere.com/~/${failure.config.org.slug}/apps/${failure.config.surface.slug}.`)}function logCleanupFailures(logger,failures){for(let failure of failures)logger.warn(`[interfere] cleanup left ${failure.absolute} on disk: ${failure.code??failure.message}`)}async function discoverUploadableSourceMaps(state){let discovered;try{discovered=await discoverByPairing({distDir:state.uploadOutDir,projectDir:state.projectDir,publicPathRewrites:[{from:`public`,to:``}],subtrees:[`.`]})}catch(error){return logDiagnostic(state.logger,diagnoseRelease(DIAGNOSTIC_CONTEXT,error)),null}return discovered.missingSourceMapCount>0&&state.logger.warn(`[interfere] ${discovered.missingSourceMapCount} referenced source map(s) not found. Errors in those chunks will not resolve to source.`),discovered.files.length===0?(state.logger.warn(`[interfere] No source maps found; the release remains unready. Enable source-map generation and upload them during the build.`),null):discovered}async function publishRelease(state,discovered){let{apiKey,apiUrl,releaseSlug,commitSha,logger,publicKey}=state,client=new InterfereClient({fetch:sourceMapUploadFetch,baseUrl:apiUrl,apiKey:{token:apiKey},headers:{"user-agent":PRODUCER_VERSION,[PUBLIC_KEY_HEADER]:publicKey},maxRetries:4,timeoutInSeconds:10}),releasesConfig=await client.releases.getReleasesConfig({abortSignal:AbortSignal.timeout(6e4)}),result=await runReleasePipeline({client,buildId:commitSha,bundler:`rollup`,discovery:discovered,environment:state.environment,producerVersion:PRODUCER_VERSION,releaseSlug,releasesConfig,capturePublication:state.receipt!==void 0,uploadSourceMaps:state.uploadSourceMaps});if(!result.ok){logSkippedRelease(logger,result.failure);return}if(logCleanupFailures(logger,result.data.cleanupFailures),result.data.publication&&state.receipt?.recordPublication(result.data.publication),!result.data.timing){logger.info(`[interfere] release ${result.data.releaseSlug} registered without source maps.`);return}logger.info(`[interfere] source-map stages (ms): create=${result.data.timing.createRelease}, sign=${result.data.timing.sign}, session=${result.data.timing.session}, upload=${result.data.timing.upload}, finalize=${result.data.timing.finalize}, receipt=${result.data.timing.receipt}, cleanup=${result.data.timing.cleanup}; bytes=${result.data.timing.totalBytes}.`),state.uploadComplete=!0,logger.info(`[interfere] release ${result.data.releaseSlug} confirmed — ${result.data.fileCount} maps, ${result.data.timing.total}ms.`)}async function releaseBuild(state){let{logger,releaseSlug}=state;logger.info(state.uploadSourceMaps?`[interfere] uploading source maps for release ${releaseSlug}…`:`[interfere] registering release ${releaseSlug} without source maps…`);let discovered=state.uploadSourceMaps?await discoverUploadableSourceMaps(state):{files:[],missingSourceMapCount:0,sourceFileCount:0};if(discovered){try{await publishRelease(state,discovered)}catch(error){logDiagnostic(logger,diagnoseRelease(DIAGNOSTIC_CONTEXT,error))}state.uploadComplete||logCleanupFailures(logger,await cleanupSourceMaps(discovered.files))}}async function releaseBuildWhenReady(state){if(isReleaseReady(state)){if(shouldWaitForServerOutput(state)){state.logger.info(`[interfere] waiting for server build output in ${path.relative(state.projectDir,state.serverSourcemapsDir)} before uploading source maps.`);return}state.releaseStarted=!0,await releaseBuild(state)}}function resolveReleaseEnv(config){return{...loadEnv(config.mode,config.envDir,``),...process.env}}function buildPluginState(options,config,browser){let{logger}=config,isProductionBuild=config.command===`build`,releaseEnv=resolveReleaseEnv(config),apiKey=pickEnvValue(releaseEnv,`INTERFERE_API_KEY`),apiUrl=pickEnvValue(releaseEnv,`INTERFERE_API_URL`)??API_URL,retainSourceMaps=isProductionBuild&&options.sourceMaps?.retain===!0,release=isProductionBuild&&!retainSourceMaps?checkReleaseConfig(DIAGNOSTIC_CONTEXT,{apiKey,commitSha:browser.commitSha,releaseSlug:browser.releaseSlug}):null;if(release?.status===`fail`)throw buildError(release.title,release.details);let releaseEnabled=release?.status===`ok`,uploadOutDir=path.resolve(config.root,config.build.outDir),serverSourcemapsDir=options.serverSourcemapsDir?path.resolve(config.root,options.serverSourcemapsDir):path.join(uploadOutDir,`server`),serverBuild=hasServerRuntimePlugin(config.plugins.map(p=>p.name))||!!config.build.ssr;return{apiHost:browser.apiHost,apiKey,apiUrl,buildStartedAt:Math.floor(Date.now()/1e3)*1e3,commitSha:browser.commitSha,releaseEnabled,retainSourceMaps,skippedRelease:release?.status===`skip`?release:null,uploadSourceMaps:releaseEnabled&&options.sourceMaps?.upload!==!1,environment:browser.environment,isProductionBuild,logger,projectDir:config.root,publicKey:browser.publicKey,releaseSlug:browser.releaseSlug,serverBuild,serverSourcemapsDir,uploadOutDir,releaseStarted:!1,uploadComplete:!1}}function announceSetup(state){if(state.logger.info(`[interfere] ingest → ${state.apiHost??`Interfere (default)`}`),!state.apiHost&&state.serverBuild&&state.logger.warn(`[interfere] Telemetry posts directly to Interfere. On a server-rendered app, set interfere({ apiHost }) to a subdomain of your own site to survive ad-blockers.`),state.isProductionBuild&&!state.publicKey&&state.logger.warn(`[interfere] VITE_INTERFERE_PUBLIC_KEY is not set, so this build sends no events. Set it on builds that you deploy.`),state.retainSourceMaps&&state.logger.info(`[interfere] source maps are retained in the build output for a release step to upload per environment.`),state.skippedRelease)for(let line of[state.skippedRelease.title,...state.skippedRelease.details])state.logger.warn(`[interfere] ${line}`)}function mirrorPublicKeyForDevServer(command,env){if(command!==`serve`)return;let publicKey=env.VITE_INTERFERE_PUBLIC_KEY;publicKey&&!process.env.VITE_INTERFERE_PUBLIC_KEY&&(process.env.VITE_INTERFERE_PUBLIC_KEY=publicKey)}function resolveRoot(userConfig){return userConfig.root?path.resolve(process.cwd(),userConfig.root):process.cwd()}function resolveEnvDir(userConfig){let root=resolveRoot(userConfig);return userConfig.envDir===!1||userConfig.envDir===void 0||userConfig.envDir===``?root:path.resolve(root,userConfig.envDir)}function forceSourcemapForUpload(userConfig,options,command,env){if(!(command===`build`&&(options.sourceMaps?.retain===!0||options.sourceMaps?.upload!==!1&&pickEnvValue(env,`INTERFERE_API_KEY`))))return;let previous=userConfig.build?.sourcemap;return userConfig.build={...userConfig.build,sourcemap:!0},previous===void 0||previous===!0?void 0:previous}function carryOverUploadProgress(previous,next){previous?.serverBuild&&next.serverBuild&&(next.uploadOutDir=previous.uploadOutDir,next.serverSourcemapsDir=previous.serverSourcemapsDir,next.releaseStarted=previous.releaseStarted,next.uploadComplete=previous.uploadComplete,next.buildStartedAt=previous.buildStartedAt)}function warnForcedSourcemap(logger,overridden){overridden!==void 0&&logger.warn(`[interfere] Forced build.sourcemap to true (was ${JSON.stringify(overridden)}). Source maps are required to symbolicate errors; they are uploaded then deleted from the build output, so they are never served. Pass interfere({ sourceMaps: { upload: false } }) to opt out.`)}function disabledPlugin(){return{name:`interfere`,config(){return{define:{"import.meta.env.VITE_INTERFERE_DISABLED":JSON.stringify(`true`)},ssr:{noExternal:[`@interfere/vite`]}}}}}function interfere(options={}){if(rejectRemovedOptions(options),options.disable)return disabledPlugin();let receipt=options.buildReceipt?createBuildReceipt(options.buildReceipt):void 0,remoteConfigFallback=!1,resolveBuildConfig=createBuildConfigResolver(result=>{receipt?.observeConfig(result),remoteConfigFallback||=result.status===`fallback`}),state=null,overriddenSourcemap,announced=!1,uploadAfterAppBuild=!1,writeReceipt=async()=>{try{await receipt?.write()}catch{state?.logger.warn(`[interfere] Private build receipt could not be written.`)}};return{buildApp:{order:`post`,async handler(builder){if(!state)return;uploadAfterAppBuild=!0;let environments=Object.values(builder.environments);if(environments.every(environment=>!environment.isBuilt))for(let environment of environments)await builder.build(environment);isReleaseReady(state)&&(state.releaseStarted=!0,await releaseBuild(state)),await writeReceipt()}},buildStart(){state&&!announced&&(announceSetup(state),warnForcedSourcemap(state.logger,overriddenSourcemap),remoteConfigFallback&&state.logger.warn(`[interfere] Could not load SDK settings from Interfere. The build uses the default settings.`),announced=!0)},async closeBundle(){state&&!uploadAfterAppBuild&&await releaseBuildWhenReady(state),await writeReceipt()},async writeBundle(output,bundle){output.dir&&await receipt?.recordOutput(output.dir,Object.keys(bundle))},outputOptions(output){return state?.uploadSourceMaps||state?.retainSourceMaps?{...output,sourcemapDebugIds:!1}:null},renderChunk:{order:`post`,handler(code){return state?.uploadSourceMaps||state?.retainSourceMaps?renderDebugId(code):null}},async config(userConfig,{command,mode}){let env=loadEnv(mode,resolveEnvDir(userConfig),``);mirrorPublicKeyForDevServer(command,env),overriddenSourcemap=forceSourcemapForUpload(userConfig,options,command,env);let browser=resolveBrowserConfig(options,env,command,resolveRoot(userConfig)),baked=command===`build`&&browser.publicKey&&!isTestEnv()?await resolveBuildConfig(browser.apiHost??API_URL,browser.publicKey):null;return{define:omitUndefined({...browserDefine(browser),"import.meta.env.VITE_INTERFERE_INGEST_URL":baked?.ingestUrl?JSON.stringify(baked.ingestUrl):void 0,"import.meta.env.VITE_INTERFERE_SERVER_TRACING":JSON.stringify(baked?.serverTracing??null),"import.meta.env.VITE_INTERFERE_LOG_SOURCING":JSON.stringify(baked?.logSourcing??null),"import.meta.env.VITE_INTERFERE_PLATFORM":baked?.platform===void 0?`undefined`:JSON.stringify(baked.platform),"import.meta.env.VITE_INTERFERE_PLUGINS":baked?.plugins?JSON.stringify(JSON.stringify(baked.plugins)):void 0}),ssr:{noExternal:[`@interfere/vite`]}}},async configResolved(config){let browser=resolveBrowserConfig(options,config.env,config.command,config.root),next=buildPluginState(options,config,browser);carryOverUploadProgress(state,next),state={...next,receipt},uploadAfterAppBuild||=config.builder!==void 0,config.command===`build`&&await receipt?.configure(config,{commitSha:browser.commitSha,releaseSlug:browser.releaseSlug,environment:browser.environment,publicKey:browser.publicKey,apiOrigin:browser.apiHost??API_URL,producerVersion:PRODUCER_VERSION})},enforce:`pre`,name:`interfere`,sharedDuringBuild:!0}}export{interfere};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interfere/vite",
|
|
3
|
-
"version": "12.3.
|
|
3
|
+
"version": "12.3.4",
|
|
4
4
|
"description": "Vite build plugin and client + server initialization for Interfere.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"error-tracking",
|
|
@@ -63,16 +63,17 @@
|
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
65
|
"build": "tsdown",
|
|
66
|
+
"lint:oxlint": "cd ../../../.. && GOMAXPROCS=2 oxlint --max-warnings=0 --report-unused-disable-directives-severity=error --no-error-on-unmatched-pattern --threads=2 src/packages/public/vite",
|
|
66
67
|
"test": "node ../../private/vitest-config/src/cli.ts run --config ../../../../vitest.config.ts",
|
|
67
68
|
"typecheck": "bun check"
|
|
68
69
|
},
|
|
69
70
|
"dependencies": {
|
|
70
|
-
"@interfere/build": "^0.4.
|
|
71
|
+
"@interfere/build": "^0.4.1",
|
|
71
72
|
"@interfere/constants": "^9.3.0",
|
|
72
73
|
"@interfere/helpers": "^9.3.0",
|
|
73
|
-
"@interfere/javascript": "^0.3.
|
|
74
|
-
"@interfere/react": "^12.3.
|
|
75
|
-
"@interfere/types": "^10.5.
|
|
74
|
+
"@interfere/javascript": "^0.3.1",
|
|
75
|
+
"@interfere/react": "^12.3.4",
|
|
76
|
+
"@interfere/types": "^10.5.1",
|
|
76
77
|
"@opentelemetry/api": "1.9.1",
|
|
77
78
|
"@opentelemetry/api-logs": "0.222.0",
|
|
78
79
|
"@opentelemetry/baggage-span-processor": "0.5.0",
|