@glasstrace/sdk 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/async-context/index.cjs +53 -4
  2. package/dist/async-context/index.cjs.map +1 -1
  3. package/dist/async-context/index.js +2 -2
  4. package/dist/{chunk-JHUNLPSS.js → chunk-6RKS3DNA.js} +45 -1
  5. package/dist/{chunk-JHUNLPSS.js.map → chunk-6RKS3DNA.js.map} +1 -1
  6. package/dist/{chunk-HD6JIFKN.js → chunk-BSVWJSVX.js} +2 -2
  7. package/dist/{chunk-QHV7NFON.js → chunk-D54FMQHF.js} +49 -40
  8. package/dist/chunk-D54FMQHF.js.map +1 -0
  9. package/dist/chunk-I2DVVSKW.js +419 -0
  10. package/dist/chunk-I2DVVSKW.js.map +1 -0
  11. package/dist/{chunk-H6WJ63X2.js → chunk-M5GO2SSO.js} +2 -2
  12. package/dist/{chunk-XEPC4NFL.js → chunk-OXA4IHQX.js} +39 -405
  13. package/dist/chunk-OXA4IHQX.js.map +1 -0
  14. package/dist/{chunk-RQ5BIWDT.js → chunk-OXM2BZMF.js} +11 -6
  15. package/dist/{chunk-RQ5BIWDT.js.map → chunk-OXM2BZMF.js.map} +1 -1
  16. package/dist/{chunk-M6EWJCAT.js → chunk-QVTONMVZ.js} +2 -2
  17. package/dist/{chunk-DKV53A2C.js → chunk-RL43PU2X.js} +2 -2
  18. package/dist/{chunk-GWIEUBFR.js → chunk-UMGZJYC4.js} +3 -3
  19. package/dist/{chunk-QXITSNYM.js → chunk-XG6WR2KS.js} +3 -3
  20. package/dist/cli/init.cjs +4 -4
  21. package/dist/cli/init.cjs.map +1 -1
  22. package/dist/cli/init.js +7 -7
  23. package/dist/cli/init.js.map +1 -1
  24. package/dist/cli/mcp-add.cjs +1 -1
  25. package/dist/cli/mcp-add.cjs.map +1 -1
  26. package/dist/cli/mcp-add.js +3 -3
  27. package/dist/cli/mcp-add.js.map +1 -1
  28. package/dist/cli/uninit.js +3 -3
  29. package/dist/cli/upgrade-instructions.cjs +1 -1
  30. package/dist/cli/upgrade-instructions.cjs.map +1 -1
  31. package/dist/cli/upgrade-instructions.js +3 -3
  32. package/dist/cli/upgrade-instructions.js.map +1 -1
  33. package/dist/cli/validate.cjs.map +1 -1
  34. package/dist/cli/validate.js +2 -2
  35. package/dist/edge-entry.cjs +100 -42
  36. package/dist/edge-entry.cjs.map +1 -1
  37. package/dist/edge-entry.js +4 -4
  38. package/dist/index.cjs +58 -5
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.js +10 -8
  41. package/dist/index.js.map +1 -1
  42. package/dist/middleware/index.cjs +91 -38
  43. package/dist/middleware/index.cjs.map +1 -1
  44. package/dist/middleware/index.d.cts +8 -0
  45. package/dist/middleware/index.d.ts +8 -0
  46. package/dist/middleware/index.js +2 -2
  47. package/dist/node-entry.cjs +58 -5
  48. package/dist/node-entry.cjs.map +1 -1
  49. package/dist/node-entry.js +12 -10
  50. package/dist/node-subpath.cjs.map +1 -1
  51. package/dist/node-subpath.js +3 -3
  52. package/dist/{source-map-uploader-MMJ2WCL4.js → source-map-uploader-CLYCE2TZ.js} +3 -3
  53. package/dist/trpc/index.cjs +15164 -503
  54. package/dist/trpc/index.cjs.map +1 -1
  55. package/dist/trpc/index.d.cts +62 -1
  56. package/dist/trpc/index.d.ts +62 -1
  57. package/dist/trpc/index.js +200 -1
  58. package/dist/trpc/index.js.map +1 -1
  59. package/package.json +1 -1
  60. package/dist/chunk-QHV7NFON.js.map +0 -1
  61. package/dist/chunk-XEPC4NFL.js.map +0 -1
  62. /package/dist/{chunk-HD6JIFKN.js.map → chunk-BSVWJSVX.js.map} +0 -0
  63. /package/dist/{chunk-H6WJ63X2.js.map → chunk-M5GO2SSO.js.map} +0 -0
  64. /package/dist/{chunk-M6EWJCAT.js.map → chunk-QVTONMVZ.js.map} +0 -0
  65. /package/dist/{chunk-DKV53A2C.js.map → chunk-RL43PU2X.js.map} +0 -0
  66. /package/dist/{chunk-GWIEUBFR.js.map → chunk-UMGZJYC4.js.map} +0 -0
  67. /package/dist/{chunk-QXITSNYM.js.map → chunk-XG6WR2KS.js.map} +0 -0
  68. /package/dist/{source-map-uploader-MMJ2WCL4.js.map → source-map-uploader-CLYCE2TZ.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createBuildHash
3
- } from "./chunk-JHUNLPSS.js";
3
+ } from "./chunk-6RKS3DNA.js";
4
4
 
5
5
  // src/import-graph.ts
6
6
  import * as fs from "node:fs/promises";
@@ -175,4 +175,4 @@ export {
175
175
  extractImports,
176
176
  buildImportGraph
177
177
  };
178
- //# sourceMappingURL=chunk-HD6JIFKN.js.map
178
+ //# sourceMappingURL=chunk-BSVWJSVX.js.map
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-DQ25VOKK.js";
8
8
  import {
9
9
  GLASSTRACE_ATTRIBUTE_NAMES
10
- } from "./chunk-JHUNLPSS.js";
10
+ } from "./chunk-6RKS3DNA.js";
11
11
 
12
12
  // src/middleware/index.ts
13
13
  var ATTR = GLASSTRACE_ATTRIBUTE_NAMES;
@@ -58,49 +58,58 @@ function tracedRequestMiddleware(options, handler) {
58
58
  }
59
59
  const wrapped = ((req, ...rest) => {
60
60
  const tracer = trace.getTracer(TRACER_NAME);
61
- return tracer.startActiveSpan(options.name, (span) => {
62
- if (isNoopSpan(span)) {
63
- if (!_skippedUninstalledEmitted) {
64
- _skippedUninstalledEmitted = true;
65
- tryEmitLifecycleEvent("middleware:skipped_uninstalled", {});
61
+ let callbackInvoked = false;
62
+ try {
63
+ return tracer.startActiveSpan(options.name, (span) => {
64
+ callbackInvoked = true;
65
+ if (isNoopSpan(span)) {
66
+ if (!_skippedUninstalledEmitted) {
67
+ _skippedUninstalledEmitted = true;
68
+ tryEmitLifecycleEvent("middleware:skipped_uninstalled", {});
69
+ }
70
+ endSpanSafely(span);
71
+ return handler(req, ...rest);
66
72
  }
67
- endSpanSafely(span);
68
- return handler(req, ...rest);
69
- }
70
- try {
71
- if (options.attributes) {
72
- span.setAttributes(options.attributes);
73
+ try {
74
+ if (options.attributes) {
75
+ span.setAttributes(options.attributes);
76
+ }
77
+ const path = extractRequestPath(req);
78
+ if (path !== void 0) {
79
+ span.setAttribute(ATTR.CAUSAL_MIDDLEWARE_FOR_REQUEST, path);
80
+ }
81
+ } catch {
73
82
  }
74
- const path = extractRequestPath(req);
75
- if (path !== void 0) {
76
- span.setAttribute(ATTR.CAUSAL_MIDDLEWARE_FOR_REQUEST, path);
83
+ let result;
84
+ try {
85
+ result = handler(req, ...rest);
86
+ } catch (error) {
87
+ recordSpanError(span, error);
88
+ endSpanSafely(span);
89
+ throw error;
90
+ }
91
+ if (result !== null && typeof result === "object" && typeof result.then === "function") {
92
+ return result.then(
93
+ (value) => {
94
+ endSpanSafely(span);
95
+ return value;
96
+ },
97
+ (error) => {
98
+ recordSpanError(span, error);
99
+ endSpanSafely(span);
100
+ throw error;
101
+ }
102
+ );
77
103
  }
78
- } catch {
79
- }
80
- let result;
81
- try {
82
- result = handler(req, ...rest);
83
- } catch (error) {
84
- recordSpanError(span, error);
85
104
  endSpanSafely(span);
86
- throw error;
87
- }
88
- if (result !== null && typeof result === "object" && typeof result.then === "function") {
89
- return result.then(
90
- (value) => {
91
- endSpanSafely(span);
92
- return value;
93
- },
94
- (error) => {
95
- recordSpanError(span, error);
96
- endSpanSafely(span);
97
- throw error;
98
- }
99
- );
105
+ return result;
106
+ });
107
+ } catch (err) {
108
+ if (callbackInvoked) {
109
+ throw err;
100
110
  }
101
- endSpanSafely(span);
102
- return result;
103
- });
111
+ return handler(req, ...rest);
112
+ }
104
113
  });
105
114
  return wrapped;
106
115
  }
@@ -127,4 +136,4 @@ export {
127
136
  _resetForTesting,
128
137
  tracedRequestMiddleware
129
138
  };
130
- //# sourceMappingURL=chunk-QHV7NFON.js.map
139
+ //# sourceMappingURL=chunk-D54FMQHF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware/index.ts"],"sourcesContent":["/**\n * Request-middleware-ownership instrumentation for Glasstrace.\n *\n * Subpath: `@glasstrace/sdk/middleware`\n *\n * This module exposes {@link tracedRequestMiddleware}, a wrapper that\n * turns a Next.js `middleware.ts` function (or any generic\n * `Request → Response`-shaped handler) into a span-emitting middleware\n * function. Each invocation opens a child span and tags it with the\n * `glasstrace.causal.middleware_for_request` causal-evidence attribute\n * carrying the originating request's normalized path so the\n * product-side trace-summary transform can link the middleware span\n * to the owning HTTP request trace (DISC-1537 / SDK-046).\n *\n * Edge-runtime safety\n * -------------------\n * The wrapper is included in the SDK's edge bundle\n * (`packages/sdk/src/edge-entry.ts`). Its closure imports only the\n * OTel API, the protocol constants, and the\n * `./optional-lifecycle.js` bridge — none of which reach into\n * `node:*` built-ins or the `process` global. The F003 closure scan\n * (`packages/sdk/scripts/check-edge-bundle.mjs`) enforces this on\n * every build.\n *\n * Causal-evidence form\n * --------------------\n * The wrapper attaches the originating request path as a span\n * attribute (`glasstrace.causal.middleware_for_request`). It does NOT\n * emit an OTel `Link`. Reasons:\n *\n * 1. The Next.js Edge runtime does not propagate AsyncLocalStorage\n * into `middleware.ts`, so there is no in-process\n * `SpanContext` to link to in that environment. Attribute-only\n * causality works in both Node and Edge runtimes; a Link would\n * degrade to a no-op (no parent context) on Edge.\n * 2. The product-side trace-summary transform reconstructs\n * ownership from `glasstrace.causal.*` attributes per\n * DISC-1539 §51-58; it does not require a Link.\n *\n * Invariants\n * ----------\n *\n * - The wrapped function preserves the user's call-site type so\n * Next.js's `middleware` export contract (`(req: NextRequest) =>\n * NextResponse | Response`) flows through unchanged.\n * - The middleware span MUST NOT overwrite `glasstrace.route`,\n * `glasstrace.http.status_code`, or `glasstrace.http.duration_ms`\n * on the parent HTTP span — root-request semantics are owned by\n * the enriching exporter (`packages/sdk/src/enriching-exporter.ts`).\n * - On a thrown handler error: span ends with `ERROR` status +\n * `recordException`; rethrows. The exception is normalized to\n * `Error | string` first so non-Error throwables (number, plain\n * object) do not crash `recordException`.\n * - Always ends the span (`finally`), even on `throw`.\n *\n * @module @glasstrace/sdk/middleware\n */\n\nimport {\n trace,\n SpanStatusCode,\n type AttributeValue,\n} from \"@opentelemetry/api\";\nimport { GLASSTRACE_ATTRIBUTE_NAMES } from \"@glasstrace/protocol\";\nimport { tryEmitLifecycleEvent } from \"../optional-lifecycle.js\";\n\nconst ATTR = GLASSTRACE_ATTRIBUTE_NAMES;\n\n/**\n * Module-level OTel tracer name for the middleware subpath. Resolves\n * through the global `ProxyTracerProvider` so the wrapper picks up\n * whatever provider the SDK has detected or registered (the SDK's\n * own enriching exporter, Sentry's processor in coexistence mode,\n * etc.). Re-resolved on every call site rather than cached at module\n * top level so test harnesses can install a provider after this\n * module is imported. This mirrors the tRPC subpath at\n * `packages/sdk/src/trpc/index.ts:128`.\n */\nconst TRACER_NAME = \"@glasstrace/sdk/middleware\";\n\n/**\n * Module-level once-flag for the\n * `middleware:skipped_uninstalled` lifecycle event. The flag is\n * exported via {@link _resetForTesting} so unit tests can re-arm it\n * between scenarios.\n */\nlet _skippedUninstalledEmitted = false;\n\n/**\n * INTERNAL — clears the once-flag for the\n * `middleware:skipped_uninstalled` lifecycle event. Invoked by\n * Vitest fixtures only; not part of the public surface.\n */\nexport function _resetForTesting(): void {\n _skippedUninstalledEmitted = false;\n}\n\n/**\n * Permissive structural bound for a request-middleware function. The\n * shape is the intersection of Next.js's `middleware.ts` export\n * (`(req: NextRequest, event?: NextFetchEvent) => NextResponse |\n * Response | Promise<NextResponse | Response> | undefined`) and the\n * generic Web Fetch API (`(req: Request, ...rest: any[]) => Response\n * | Promise<Response>`). The parameter list is typed with `any[]` for\n * the rest position so any caller-narrowed signature is assignable\n * without the wrapper having to import `next/server` types.\n *\n * Exported so consumers can reference it for type-inference assertions\n * (e.g., proving a strongly-typed handler fits the bound). The\n * runtime contract is fixed by the Web Fetch API: the first argument\n * is a `Request`-shaped object and the return is a `Response`-shaped\n * value (or a Promise of one).\n */\n// The `any[]` in the rest position is load-bearing: a tighter bound\n// (e.g. `unknown[]`) would reject `(req, event?) => ...` because\n// `unknown` cannot be passed in the contravariant parameter position\n// without an explicit cast at every call site. Capturing\n// `H extends RequestMiddlewareFunction` preserves caller types\n// through the wrapper's `: H` return.\n//\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type RequestMiddlewareFunction = (req: any, ...rest: any[]) => unknown;\n\n/**\n * Options for {@link tracedRequestMiddleware}.\n *\n * @example\n * ```ts\n * import { tracedRequestMiddleware } from \"@glasstrace/sdk/middleware\";\n * import type { NextRequest } from \"next/server\";\n *\n * export const middleware = tracedRequestMiddleware(\n * { name: \"auth-middleware\", attributes: { \"auth.required\": true } },\n * async (req: NextRequest) => {\n * // … your auth logic here …\n * return NextResponse.next();\n * },\n * );\n * ```\n */\nexport interface TracedRequestMiddlewareOptions {\n /**\n * Span name. Required, non-empty string. Used as the OTel span name\n * and appears in trace timelines. Names should be stable across\n * runs so the product-side transform can reason about middleware\n * identity (e.g., \"auth-middleware\", \"rate-limiter\"); avoid\n * embedding request data in the name.\n */\n name: string;\n /**\n * Optional attributes attached to the span before the wrapped\n * handler runs. Forwarded to OTel as-is via `span.setAttributes()`.\n * The SDK does not redact, sanitize, or scan values here — callers\n * MUST avoid placing tokens, credentials, or other sensitive data\n * in `attributes`.\n *\n * Sensitive request/response data is captured through gated SDK\n * paths (e.g., `glasstrace.error.response_body`), not through this\n * surface.\n */\n attributes?: Record<string, AttributeValue>;\n}\n\n/**\n * Extract the originating request path from a Fetch-API `Request` or\n * `NextRequest`-shaped object. Preference order:\n *\n * 1. `req.nextUrl.pathname` — present on `NextRequest`. This is\n * Next.js's parsed URL and is the most reliable source on the\n * Next.js Edge runtime, where `req.url` may be a relative form\n * depending on framework-internal rewrites.\n * 2. `new URL(req.url).pathname` — present on the generic Fetch\n * `Request`. The URL constructor accepts an absolute URL; if\n * `req.url` is relative we synthesize a base of\n * `http://localhost` to make parsing succeed (the host is\n * discarded — only the path is used).\n * 3. `undefined` — when neither field exists or both fail to\n * parse, the wrapper omits the causal attribute rather than\n * emitting a guessed value, per the SDK-046 product brief's\n * \"missing or unknown evidence is preferable to guessed\n * evidence\" rule (DISC-1537 / DISC-1539 product handoff).\n *\n * This function never throws.\n */\nfunction extractRequestPath(req: unknown): string | undefined {\n if (req === null || typeof req !== \"object\") return undefined;\n try {\n // NextRequest.nextUrl — already a URL-like object with .pathname.\n const nextUrl = (req as { nextUrl?: unknown }).nextUrl;\n if (nextUrl !== null && typeof nextUrl === \"object\") {\n const pathname = (nextUrl as { pathname?: unknown }).pathname;\n if (typeof pathname === \"string\" && pathname.length > 0) {\n return pathname;\n }\n }\n // Fall back to req.url. On Edge / Web Fetch this is always\n // absolute; on some Node frameworks it can be relative\n // (`/api/foo?x=1`), so synthesize a base if the URL constructor\n // throws on the absolute parse.\n const url = (req as { url?: unknown }).url;\n if (typeof url === \"string\" && url.length > 0) {\n try {\n return new URL(url).pathname;\n } catch {\n try {\n return new URL(url, \"http://localhost\").pathname;\n } catch {\n return undefined;\n }\n }\n }\n } catch {\n // Defensive: any unexpected shape failure returns undefined.\n }\n return undefined;\n}\n\n/**\n * Sentinel trace ID returned by the OTel API's noop tracer\n * (`@opentelemetry/api`'s `NonRecordingSpan`). Per the OTel\n * specification's noop semantics, the noop SpanContext exposes\n * `traceId === \"00000000000000000000000000000000\"`. Used by\n * {@link isNoopSpan} below to discriminate \"no provider registered\"\n * from \"real provider whose sampler dropped this span\" — the latter\n * also returns `isRecording() === false` but produces a valid\n * 32-char hex trace ID because the SDK assigns one before sampler\n * invocation for propagation purposes.\n */\nconst INVALID_TRACE_ID = \"00000000000000000000000000000000\";\n\n/**\n * Type guard for OTel spans created by the noop tracer. The OTel\n * API's noop SpanContext returns the all-zeros sentinel for\n * `traceId`; real SDK-emitted spans always have a valid 32-char hex\n * trace ID (even when a sampler decided to DROP the span). Using\n * the SpanContext discriminator keeps the SDK-not-registered fast\n * path from misfiring under normal head sampling configurations\n * (Copilot review 2026-05-08).\n *\n * Returning `true` here means the caller should NOT proceed with\n * span enrichment; the noop tracer would discard everything anyway.\n */\nfunction isNoopSpan(\n span: ReturnType<ReturnType<typeof trace.getTracer>[\"startSpan\"]>,\n): boolean {\n try {\n return span.spanContext().traceId === INVALID_TRACE_ID;\n } catch {\n // Defensive: treat \"could not determine\" as not-noop so we\n // continue down the enrichment path. The noop tracer itself\n // never throws from `spanContext()`.\n return false;\n }\n}\n\n/**\n * Wrap a Next.js / generic-fetch request-middleware function in an\n * OTel span tagged with `glasstrace.causal.middleware_for_request`.\n *\n * **Privacy:** the value of\n * `glasstrace.causal.middleware_for_request` is the raw URL\n * pathname. Pathnames can carry user-controlled data (IDs, emails,\n * opaque keys). The SDK does NOT redact this attribute. Callers MUST\n * NOT place secrets, tokens, or other sensitive data in URL paths;\n * the same general HTTP best practice that keeps secrets out of\n * server logs keeps them out of Glasstrace trace evidence.\n *\n * Each call to the returned function:\n *\n * 1. Detects the SDK's registration state. When the OTel API is\n * still on the noop tracer (SDK not registered, or\n * `OtelState.UNCONFIGURED`), runs the wrapped handler directly\n * and emits a `middleware:skipped_uninstalled` lifecycle event\n * (at most once per process). No span is opened.\n * 2. Otherwise opens a span named `options.name` under the active\n * OTel context (typically the HTTP server span on Node;\n * detached on Edge where AsyncLocalStorage is not available).\n * Sets `options.attributes` first, then attaches the originating\n * request's path (via {@link extractRequestPath}) as\n * `glasstrace.causal.middleware_for_request`. The path is\n * omitted when extraction returns `undefined` so absent evidence\n * is preferred over guessed evidence.\n * 3. Awaits the wrapped handler.\n * 4. On a thrown error: normalizes the throwable to `Error | string`\n * so `recordException` does not throw on non-Error values; sets\n * `span.status` to `ERROR` with the error's message; rethrows the\n * original (un-normalized) error verbatim.\n * 5. On a successful return: leaves the span status `UNSET` per OTel\n * instrumentation-library guidance (explicit `OK` would shadow\n * downstream consumers' error transitions).\n * 6. Always ends the span, even on `throw` or `return`.\n *\n * Type-inference: the returned function preserves the input function's\n * type `H`, so caller-narrowed signatures (e.g., `(req: NextRequest)\n * => NextResponse`) flow through unchanged.\n *\n * @param options - Span name and optional pre-start attributes.\n * @param handler - The user's middleware handler. Must accept a\n * request-shaped object as its first argument and return (or\n * resolve to) a response-shaped value.\n * @returns The wrapped handler with the same call signature and\n * return type as `handler`.\n *\n * @example Next.js middleware.ts\n * ```ts\n * import { tracedRequestMiddleware } from \"@glasstrace/sdk/middleware\";\n * import { NextResponse, type NextRequest } from \"next/server\";\n *\n * export const middleware = tracedRequestMiddleware(\n * { name: \"auth-middleware\" },\n * async (req: NextRequest) => {\n * if (!req.cookies.get(\"session\")) {\n * return NextResponse.redirect(new URL(\"/login\", req.url));\n * }\n * return NextResponse.next();\n * },\n * );\n *\n * export const config = { matcher: [\"/dashboard/:path*\"] };\n * ```\n */\nexport function tracedRequestMiddleware<H extends RequestMiddlewareFunction>(\n options: TracedRequestMiddlewareOptions,\n handler: H,\n): H {\n // Eager validation: a mis-typed call site fails at wrapper-\n // construction time (typically at module load) rather than at\n // first request, when the failure is harder to diagnose.\n if (typeof options.name !== \"string\" || options.name.length === 0) {\n throw new TypeError(\n \"tracedRequestMiddleware: options.name must be a non-empty string\",\n );\n }\n\n // Capture options + handler lexically. Do not read from `this` —\n // Next.js's middleware loader invokes this as a plain function, not\n // a method, so `this` is undefined.\n const wrapped = ((req: Parameters<H>[0], ...rest: unknown[]): unknown => {\n const tracer = trace.getTracer(TRACER_NAME);\n // Defensive wrap around `tracer.startActiveSpan` itself.\n // OTel's noop tracer never throws; a real provider could\n // (e.g., a misbehaving custom processor in coexistence). If the\n // tracer call throws BEFORE invoking our callback, fall back to\n // running the handler directly so instrumentation does not break\n // the user's middleware.\n //\n // CRITICAL: the fallback runs ONLY when the tracer failed\n // pre-callback. The callback itself rethrows handler errors\n // (`recordSpanError` + `throw error`) which would otherwise be\n // intercepted here and cause the handler to run a second time\n // (Codex P1, 2026-05-08). The `callbackInvoked` flag\n // distinguishes pre-callback tracer failure from post-callback\n // handler-error rethrow.\n let callbackInvoked = false;\n try {\n return tracer.startActiveSpan(options.name, (span) => {\n callbackInvoked = true;\n // SDK-not-registered fast path. Detecting via the public\n // `isRecording()` method on the started span is the canonical\n // OTel-API-only probe — the noop tracer's `NonRecordingSpan`\n // returns `false`, real SDK-emitted spans return `true`. This\n // avoids the more expensive workaround of opening a probe span\n // ahead of time, which would emit a useless span on every\n // request when a real provider is registered.\n if (isNoopSpan(span)) {\n if (!_skippedUninstalledEmitted) {\n _skippedUninstalledEmitted = true;\n tryEmitLifecycleEvent(\"middleware:skipped_uninstalled\", {});\n }\n // The noop span needs no enrichment and no end() because the\n // noop implementation is a no-op for both, but call end()\n // anyway for symmetry with the real-span path.\n endSpanSafely(span);\n return (handler as (...args: unknown[]) => unknown)(req, ...rest);\n }\n\n // Set caller-supplied attributes first so they appear on the\n // span before any internal attribute we add below.\n try {\n if (options.attributes) {\n span.setAttributes(options.attributes);\n }\n const path = extractRequestPath(req);\n if (path !== undefined) {\n span.setAttribute(ATTR.CAUSAL_MIDDLEWARE_FOR_REQUEST, path);\n }\n } catch {\n // Attribute-setting failures are advisory; never block the\n // wrapped handler from running.\n }\n\n let result: unknown;\n try {\n result = (handler as (...args: unknown[]) => unknown)(req, ...rest);\n } catch (error) {\n recordSpanError(span, error);\n endSpanSafely(span);\n throw error;\n }\n\n // The handler may be sync or async. If async, attach the\n // span-end + error-recording on the promise chain; otherwise\n // end the span synchronously and return the value.\n if (\n result !== null &&\n typeof result === \"object\" &&\n typeof (result as Promise<unknown>).then === \"function\"\n ) {\n return (result as Promise<unknown>).then(\n (value) => {\n endSpanSafely(span);\n return value;\n },\n (error: unknown) => {\n recordSpanError(span, error);\n endSpanSafely(span);\n throw error;\n },\n );\n }\n\n endSpanSafely(span);\n return result;\n });\n } catch (err) {\n if (callbackInvoked) {\n // The tracer's callback ran and our code (or the user's\n // handler via our rethrow) threw. That error is intentional;\n // propagate it without invoking the handler again.\n throw err;\n }\n // `tracer.startActiveSpan` failed BEFORE invoking our callback.\n // Drop instrumentation for this invocation and run the user's\n // handler directly so the request does not break.\n return (handler as (...args: unknown[]) => unknown)(req, ...rest);\n }\n }) as H;\n\n return wrapped;\n}\n\n/**\n * Records an exception on a span and sets the span status to `ERROR`.\n * Both calls are independently guarded so a failing `recordException`\n * cannot prevent the status transition, and vice versa. The user's\n * original error value is preserved verbatim — wrapping is purely a\n * span-side normalization.\n */\nfunction recordSpanError(\n span: ReturnType<ReturnType<typeof trace.getTracer>[\"startSpan\"]>,\n error: unknown,\n): void {\n const normalized: Error | string =\n error instanceof Error\n ? error\n : typeof error === \"string\"\n ? error\n : new Error(String(error));\n const statusMessage =\n normalized instanceof Error ? normalized.message : normalized;\n try {\n span.recordException(normalized);\n } catch {\n // Swallow: instrumentation must never replace the user's error.\n }\n try {\n span.setStatus({ code: SpanStatusCode.ERROR, message: statusMessage });\n } catch {\n // Swallow: independent from recordException so a failing\n // recordException does not prevent the ERROR status.\n }\n}\n\n/**\n * Ends a span, swallowing any throw from the OTel implementation. A\n * misbehaving `span.end()` must not replace the wrapped handler's\n * return value or thrown error with an unrelated one.\n */\nfunction endSpanSafely(\n span: ReturnType<ReturnType<typeof trace.getTracer>[\"startSpan\"]>,\n): void {\n try {\n span.end();\n } catch {\n // Span lifecycle errors are always non-fatal at this layer.\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,419 @@
1
+ import {
2
+ _registerLifecycleEmitForBridge
3
+ } from "./chunk-CL3OVHPO.js";
4
+
5
+ // src/lifecycle.ts
6
+ import { EventEmitter } from "node:events";
7
+
8
+ // src/signal-handler.ts
9
+ var coexistenceState = "unknown";
10
+ function setCoexistenceState(s) {
11
+ coexistenceState = s;
12
+ }
13
+ function getCoexistenceState() {
14
+ return coexistenceState;
15
+ }
16
+
17
+ // src/lifecycle.ts
18
+ var CoreState = {
19
+ IDLE: "IDLE",
20
+ REGISTERING: "REGISTERING",
21
+ KEY_PENDING: "KEY_PENDING",
22
+ KEY_RESOLVED: "KEY_RESOLVED",
23
+ ACTIVE: "ACTIVE",
24
+ ACTIVE_DEGRADED: "ACTIVE_DEGRADED",
25
+ SHUTTING_DOWN: "SHUTTING_DOWN",
26
+ SHUTDOWN: "SHUTDOWN",
27
+ PRODUCTION_DISABLED: "PRODUCTION_DISABLED",
28
+ REGISTRATION_FAILED: "REGISTRATION_FAILED"
29
+ };
30
+ var AuthState = {
31
+ ANONYMOUS: "ANONYMOUS",
32
+ AUTHENTICATED: "AUTHENTICATED",
33
+ CLAIMING: "CLAIMING",
34
+ CLAIMED: "CLAIMED"
35
+ };
36
+ var OtelState = {
37
+ UNCONFIGURED: "UNCONFIGURED",
38
+ CONFIGURING: "CONFIGURING",
39
+ OWNS_PROVIDER: "OWNS_PROVIDER",
40
+ AUTO_ATTACHED: "AUTO_ATTACHED",
41
+ PROCESSOR_PRESENT: "PROCESSOR_PRESENT",
42
+ COEXISTENCE_FAILED: "COEXISTENCE_FAILED"
43
+ };
44
+ var VALID_CORE_TRANSITIONS = {
45
+ [CoreState.IDLE]: [CoreState.REGISTERING, CoreState.REGISTRATION_FAILED, CoreState.SHUTTING_DOWN],
46
+ [CoreState.REGISTERING]: [
47
+ CoreState.KEY_PENDING,
48
+ CoreState.PRODUCTION_DISABLED,
49
+ CoreState.REGISTRATION_FAILED,
50
+ CoreState.SHUTTING_DOWN
51
+ ],
52
+ [CoreState.KEY_PENDING]: [
53
+ CoreState.KEY_RESOLVED,
54
+ CoreState.REGISTRATION_FAILED,
55
+ CoreState.SHUTTING_DOWN
56
+ ],
57
+ [CoreState.KEY_RESOLVED]: [
58
+ CoreState.ACTIVE,
59
+ CoreState.ACTIVE_DEGRADED,
60
+ CoreState.SHUTTING_DOWN
61
+ ],
62
+ [CoreState.ACTIVE]: [
63
+ CoreState.ACTIVE_DEGRADED,
64
+ CoreState.SHUTTING_DOWN
65
+ ],
66
+ [CoreState.ACTIVE_DEGRADED]: [
67
+ CoreState.ACTIVE,
68
+ CoreState.SHUTTING_DOWN
69
+ ],
70
+ [CoreState.SHUTTING_DOWN]: [CoreState.SHUTDOWN],
71
+ [CoreState.SHUTDOWN]: [],
72
+ [CoreState.PRODUCTION_DISABLED]: [],
73
+ [CoreState.REGISTRATION_FAILED]: []
74
+ };
75
+ var VALID_AUTH_TRANSITIONS = {
76
+ [AuthState.ANONYMOUS]: [AuthState.CLAIMING],
77
+ [AuthState.AUTHENTICATED]: [AuthState.CLAIMING],
78
+ [AuthState.CLAIMING]: [AuthState.CLAIMED],
79
+ [AuthState.CLAIMED]: [AuthState.CLAIMING]
80
+ };
81
+ var VALID_OTEL_TRANSITIONS = {
82
+ [OtelState.UNCONFIGURED]: [OtelState.CONFIGURING],
83
+ [OtelState.CONFIGURING]: [
84
+ OtelState.OWNS_PROVIDER,
85
+ OtelState.AUTO_ATTACHED,
86
+ OtelState.PROCESSOR_PRESENT,
87
+ OtelState.COEXISTENCE_FAILED
88
+ ],
89
+ [OtelState.OWNS_PROVIDER]: [],
90
+ [OtelState.AUTO_ATTACHED]: [],
91
+ [OtelState.PROCESSOR_PRESENT]: [],
92
+ [OtelState.COEXISTENCE_FAILED]: []
93
+ };
94
+ var _coreState = CoreState.IDLE;
95
+ var _authState = AuthState.ANONYMOUS;
96
+ var _otelState = OtelState.UNCONFIGURED;
97
+ var _emitter = new EventEmitter();
98
+ var _logger = null;
99
+ var _initialized = false;
100
+ var _initWarned = false;
101
+ var _coreReadyEmitted = false;
102
+ var _authInitialized = false;
103
+ var _emitting = false;
104
+ function initLifecycle(options) {
105
+ if (_initialized) {
106
+ options.logger("warn", "[glasstrace] initLifecycle() called twice \u2014 ignored.");
107
+ return;
108
+ }
109
+ _logger = options.logger;
110
+ _initialized = true;
111
+ _registerLifecycleEmitForBridge((event, payload) => {
112
+ emitLifecycleEvent(
113
+ event,
114
+ payload
115
+ );
116
+ });
117
+ }
118
+ function warnIfNotInitialized() {
119
+ if (!_initialized && !_initWarned) {
120
+ _initWarned = true;
121
+ console.warn(
122
+ "[glasstrace] Lifecycle state changed before initLifecycle() was called. Logger not available \u2014 errors will be silent."
123
+ );
124
+ }
125
+ }
126
+ function setCoreState(to) {
127
+ warnIfNotInitialized();
128
+ const from = _coreState;
129
+ if (from === to) return;
130
+ const valid = VALID_CORE_TRANSITIONS[from];
131
+ if (!valid.includes(to)) {
132
+ _logger?.(
133
+ "warn",
134
+ `[glasstrace] Invalid core state transition: ${from} \u2192 ${to}. Ignored.`
135
+ );
136
+ return;
137
+ }
138
+ _coreState = to;
139
+ if (_emitting) return;
140
+ _emitting = true;
141
+ try {
142
+ emitSafe("core:state_changed", { from, to });
143
+ const current = _coreState;
144
+ if (!_coreReadyEmitted && (current === CoreState.ACTIVE || current === CoreState.ACTIVE_DEGRADED)) {
145
+ _coreReadyEmitted = true;
146
+ emitSafe("core:ready", {});
147
+ }
148
+ if (current === CoreState.SHUTTING_DOWN) {
149
+ emitSafe("core:shutdown_started", {});
150
+ }
151
+ if (current === CoreState.SHUTDOWN) {
152
+ emitSafe("core:shutdown_completed", {});
153
+ }
154
+ } finally {
155
+ _emitting = false;
156
+ }
157
+ if (to === CoreState.ACTIVE && _degradationSources.size > 0) {
158
+ recomputeCoreFromDegradationSources();
159
+ }
160
+ }
161
+ function initAuthState(state) {
162
+ if (_authInitialized) {
163
+ _logger?.(
164
+ "warn",
165
+ "[glasstrace] initAuthState() called after auth state already initialized. Ignored."
166
+ );
167
+ return;
168
+ }
169
+ _authInitialized = true;
170
+ _authState = state;
171
+ }
172
+ function setAuthState(to) {
173
+ warnIfNotInitialized();
174
+ const from = _authState;
175
+ if (from === to) return;
176
+ const valid = VALID_AUTH_TRANSITIONS[from];
177
+ if (!valid.includes(to)) {
178
+ _logger?.(
179
+ "warn",
180
+ `[glasstrace] Invalid auth state transition: ${from} \u2192 ${to}. Ignored.`
181
+ );
182
+ return;
183
+ }
184
+ _authState = to;
185
+ }
186
+ function setOtelState(to) {
187
+ warnIfNotInitialized();
188
+ const from = _otelState;
189
+ if (from === to) return;
190
+ const valid = VALID_OTEL_TRANSITIONS[from];
191
+ if (!valid.includes(to)) {
192
+ _logger?.(
193
+ "warn",
194
+ `[glasstrace] Invalid OTel state transition: ${from} \u2192 ${to}. Ignored.`
195
+ );
196
+ return;
197
+ }
198
+ _otelState = to;
199
+ }
200
+ var _degradationSources = /* @__PURE__ */ new Set();
201
+ function pushDegradationSource(key) {
202
+ _degradationSources.add(key);
203
+ recomputeCoreFromDegradationSources();
204
+ }
205
+ function clearDegradationSource(key) {
206
+ _degradationSources.delete(key);
207
+ recomputeCoreFromDegradationSources();
208
+ }
209
+ function recomputeCoreFromDegradationSources() {
210
+ const hasDegradation = _degradationSources.size > 0;
211
+ if (hasDegradation && _coreState === CoreState.ACTIVE) {
212
+ setCoreState(CoreState.ACTIVE_DEGRADED);
213
+ return;
214
+ }
215
+ if (!hasDegradation && _coreState === CoreState.ACTIVE_DEGRADED) {
216
+ setCoreState(CoreState.ACTIVE);
217
+ }
218
+ }
219
+ function getCoreState() {
220
+ return _coreState;
221
+ }
222
+ function getSdkState() {
223
+ return {
224
+ core: _coreState,
225
+ auth: _authState,
226
+ otel: _otelState
227
+ };
228
+ }
229
+ function onLifecycleEvent(event, listener) {
230
+ _emitter.on(event, listener);
231
+ }
232
+ function emitLifecycleEvent(event, payload) {
233
+ emitSafe(event, payload);
234
+ }
235
+ function offLifecycleEvent(event, listener) {
236
+ _emitter.off(event, listener);
237
+ }
238
+ function emitSafe(event, payload) {
239
+ const listeners = _emitter.listeners(event);
240
+ for (const listener of listeners) {
241
+ try {
242
+ const result = listener(payload);
243
+ if (result && typeof result.catch === "function") {
244
+ result.catch((err) => {
245
+ _logger?.(
246
+ "error",
247
+ `[glasstrace] Async error in lifecycle event listener for "${event}": ${err instanceof Error ? err.message : String(err)}`
248
+ );
249
+ });
250
+ }
251
+ } catch (err) {
252
+ _logger?.(
253
+ "error",
254
+ `[glasstrace] Error in lifecycle event listener for "${event}": ${err instanceof Error ? err.message : String(err)}`
255
+ );
256
+ }
257
+ }
258
+ }
259
+ function isReady() {
260
+ return _coreState === CoreState.ACTIVE || _coreState === CoreState.ACTIVE_DEGRADED;
261
+ }
262
+ function waitForReady(timeoutMs = 3e4) {
263
+ if (isReady()) {
264
+ return Promise.resolve();
265
+ }
266
+ if (_coreState === CoreState.PRODUCTION_DISABLED || _coreState === CoreState.REGISTRATION_FAILED || _coreState === CoreState.SHUTTING_DOWN || _coreState === CoreState.SHUTDOWN) {
267
+ return Promise.reject(new Error(`SDK is in terminal state: ${_coreState}`));
268
+ }
269
+ return new Promise((resolve, reject) => {
270
+ let settled = false;
271
+ const listener = ({ to }) => {
272
+ if (settled) return;
273
+ if (to === CoreState.ACTIVE || to === CoreState.ACTIVE_DEGRADED) {
274
+ settled = true;
275
+ offLifecycleEvent("core:state_changed", listener);
276
+ resolve();
277
+ } else if (to === CoreState.PRODUCTION_DISABLED || to === CoreState.REGISTRATION_FAILED || to === CoreState.SHUTTING_DOWN || to === CoreState.SHUTDOWN) {
278
+ settled = true;
279
+ offLifecycleEvent("core:state_changed", listener);
280
+ reject(new Error(`SDK reached terminal state: ${to}`));
281
+ }
282
+ };
283
+ onLifecycleEvent("core:state_changed", listener);
284
+ if (timeoutMs > 0) {
285
+ const timer = setTimeout(() => {
286
+ if (settled) return;
287
+ settled = true;
288
+ offLifecycleEvent("core:state_changed", listener);
289
+ reject(new Error(`waitForReady timed out after ${timeoutMs}ms (state: ${_coreState})`));
290
+ }, timeoutMs);
291
+ if (typeof timer === "object" && "unref" in timer) {
292
+ timer.unref();
293
+ }
294
+ }
295
+ });
296
+ }
297
+ function getStatus() {
298
+ let mode;
299
+ if (_coreState === CoreState.PRODUCTION_DISABLED) {
300
+ mode = "disabled";
301
+ } else if (_authState === AuthState.CLAIMING || _authState === AuthState.CLAIMED) {
302
+ mode = "claiming";
303
+ } else if (_authState === AuthState.AUTHENTICATED) {
304
+ mode = "authenticated";
305
+ } else {
306
+ mode = "anonymous";
307
+ }
308
+ let tracing;
309
+ if (_otelState === OtelState.COEXISTENCE_FAILED || _otelState === OtelState.UNCONFIGURED || _otelState === OtelState.CONFIGURING) {
310
+ tracing = "not-configured";
311
+ } else if (_coreState === CoreState.ACTIVE_DEGRADED) {
312
+ tracing = "degraded";
313
+ } else if (_otelState === OtelState.AUTO_ATTACHED || _otelState === OtelState.PROCESSOR_PRESENT) {
314
+ tracing = "coexistence";
315
+ } else {
316
+ tracing = "active";
317
+ }
318
+ return {
319
+ ready: isReady(),
320
+ mode,
321
+ tracing
322
+ };
323
+ }
324
+ var _shutdownHooks = [];
325
+ var _signalHandlersRegistered = false;
326
+ var _signalHandler = null;
327
+ var _beforeExitRegistered = false;
328
+ var _beforeExitHandler = null;
329
+ var _shutdownExecuted = false;
330
+ function registerShutdownHook(hook) {
331
+ _shutdownHooks.push(hook);
332
+ _shutdownHooks.sort((a, b) => a.priority - b.priority);
333
+ }
334
+ async function executeShutdown(timeoutMs = 5e3) {
335
+ if (_shutdownExecuted) return;
336
+ _shutdownExecuted = true;
337
+ setCoreState(CoreState.SHUTTING_DOWN);
338
+ for (const hook of _shutdownHooks) {
339
+ try {
340
+ const hookPromise = hook.fn();
341
+ hookPromise.catch(() => {
342
+ });
343
+ await Promise.race([
344
+ hookPromise,
345
+ new Promise((_, reject) => {
346
+ const timer = setTimeout(() => reject(new Error(`Shutdown hook "${hook.name}" timed out`)), timeoutMs);
347
+ if (typeof timer === "object" && "unref" in timer) {
348
+ timer.unref();
349
+ }
350
+ })
351
+ ]);
352
+ } catch (err) {
353
+ _logger?.(
354
+ "warn",
355
+ `[glasstrace] Shutdown hook "${hook.name}" failed: ${err instanceof Error ? err.message : String(err)}`
356
+ );
357
+ }
358
+ }
359
+ setCoreState(CoreState.SHUTDOWN);
360
+ }
361
+ function registerSignalHandlers() {
362
+ if (_signalHandlersRegistered) return;
363
+ if (typeof process === "undefined" || typeof process.once !== "function") return;
364
+ _signalHandlersRegistered = true;
365
+ const otherSigtermListeners = process.listenerCount("SIGTERM");
366
+ const otherSigintListeners = process.listenerCount("SIGINT");
367
+ const handler = (signal) => {
368
+ void executeShutdown().finally(() => {
369
+ if (_signalHandler) {
370
+ process.removeListener("SIGTERM", _signalHandler);
371
+ process.removeListener("SIGINT", _signalHandler);
372
+ }
373
+ const otherListeners = signal === "SIGTERM" ? otherSigtermListeners : otherSigintListeners;
374
+ const otherProviderOwnsSignal = getCoexistenceState() === "coexisting" && otherListeners > 0;
375
+ if (!otherProviderOwnsSignal) {
376
+ process.kill(process.pid, signal);
377
+ }
378
+ });
379
+ };
380
+ _signalHandler = handler;
381
+ process.once("SIGTERM", handler);
382
+ process.once("SIGINT", handler);
383
+ }
384
+ function registerBeforeExitTrigger() {
385
+ if (_beforeExitRegistered) return;
386
+ if (typeof process === "undefined" || typeof process.once !== "function") return;
387
+ _beforeExitRegistered = true;
388
+ const handler = () => {
389
+ void executeShutdown();
390
+ };
391
+ _beforeExitHandler = handler;
392
+ process.once("beforeExit", handler);
393
+ }
394
+
395
+ export {
396
+ setCoexistenceState,
397
+ CoreState,
398
+ AuthState,
399
+ OtelState,
400
+ initLifecycle,
401
+ setCoreState,
402
+ initAuthState,
403
+ setAuthState,
404
+ setOtelState,
405
+ pushDegradationSource,
406
+ clearDegradationSource,
407
+ getCoreState,
408
+ getSdkState,
409
+ onLifecycleEvent,
410
+ emitLifecycleEvent,
411
+ isReady,
412
+ waitForReady,
413
+ getStatus,
414
+ registerShutdownHook,
415
+ executeShutdown,
416
+ registerSignalHandlers,
417
+ registerBeforeExitTrigger
418
+ };
419
+ //# sourceMappingURL=chunk-I2DVVSKW.js.map