@btravstack/core 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -112,6 +112,22 @@ and turns the outcome into a process exit code — one call, and the whole of a
112
112
  `TickerApp` that does not export `Greeter` is a type error at the call, and so
113
113
  is a module that exports no runtime port at all.
114
114
 
115
+ ## For a runtime author
116
+
117
+ Two helpers sit beside the `Runtime` contract, because every transport needs
118
+ them and none should own a private copy:
119
+
120
+ - **`releasedBy(signal, running)`** — `running`, but no later than the kernel's
121
+ drain deadline, for a `Serving.drain` whose work settles on somebody else's
122
+ clock.
123
+ - **`traceIdOfTraceparent(header)`** — the trace-id field of a W3C
124
+ `traceparent`, and nothing else of it: the parent's span id is dropped, since
125
+ `UnitMeta.traceId` is a correlation id rather than a span context. Answers
126
+ `undefined` for anything the specification calls invalid — a malformed
127
+ header, an all-zero trace id, an all-zero parent id, the reserved version
128
+ `ff` — so your runtime falls back to its own id instead of adopting one that
129
+ means nothing. A higher version's extra fields are read rather than refused.
130
+
115
131
  ## What you get
116
132
 
117
133
  - **A drain that survives Kubernetes.** On SIGTERM: readiness flips false, the
@@ -132,7 +148,7 @@ is a module that exports no runtime port at all.
132
148
  - **A per-unit scope no handler manages** — pass a module as
133
149
  `StartOptions.unit` and the kernel forks it around every unit.
134
150
  - **An ambient record, not an ambient container** — `currentUnit()` reads
135
- `{ unitId, traceId, tenantId, deadline, signal }`; services never travel
151
+ `{ unitId, traceId, tenantId, signal }`; services never travel
136
152
  there. `signal` is the very `AbortSignal` the unit's work callback is handed,
137
153
  so a runtime whose work is a library's `next()` — a Temporal activity, an
138
154
  AMQP delivery — can still honour the drain deadline.
package/dist/index.cjs CHANGED
@@ -206,6 +206,39 @@ var RuntimeStartFailed = class extends (0, unthrown.TaggedError)("RuntimeStartFa
206
206
  */
207
207
  const RuntimePort = (0, _btravstack_di.Port)("Runtime");
208
208
  /**
209
+ * The trace id inside a W3C `traceparent` header, and nothing else of it.
210
+ *
211
+ * @remarks
212
+ * The parent's **span id is dropped**, deliberately: `UnitMeta.traceId` is a
213
+ * correlation id rather than a span context, and half-carrying one would
214
+ * suggest a parent-child link nothing here maintains.
215
+ *
216
+ * Three things the specification calls invalid are refused like a malformed
217
+ * header, because adopting one would replace a runtime's own usable id with a
218
+ * value that means nothing: an **all-zero trace id**, an **all-zero parent
219
+ * id** (the header is well-formed and names no span), and **version `ff`**,
220
+ * which is reserved and never a version a caller may send.
221
+ *
222
+ * It is here rather than in a runtime because **every** transport carrying an
223
+ * inbound trace needs the same answer, and two copies of a parser is two
224
+ * places for the all-zero rule to be forgotten. A runtime pairs it with the
225
+ * adopt-only-a-non-blank-inbound-id rule its own headers need:
226
+ * `UnitMeta.traceId` defaults to `meta.id` when it is nullish and `""` is not,
227
+ * so an empty header would hand a caller's every unit the same blank id.
228
+ *
229
+ * @example
230
+ * ```ts
231
+ * const parent = request.headers["traceparent"];
232
+ * const traceId = typeof parent === "string" ? traceIdOfTraceparent(parent) : undefined;
233
+ * ```
234
+ */
235
+ const traceIdOfTraceparent = (header) => {
236
+ const [, version, traceId, parentId, extra] = /^(?!ff)([\da-f]{2})-([\da-f]{32})-([\da-f]{16})-[\da-f]{2}(-.*)?$/.exec(header.trim()) ?? [];
237
+ if (traceId === void 0 || parentId === void 0) return void 0;
238
+ if (version === "00" && extra !== void 0) return void 0;
239
+ return /^0+$/.test(traceId) || /^0+$/.test(parentId) ? void 0 : traceId;
240
+ };
241
+ /**
209
242
  * `running`, but no later than the kernel's drain deadline — the primitive a
210
243
  * `Serving.drain` needs when the work it awaits settles on somebody else's
211
244
  * clock (Temporal's `shutdownForceTime`, a broker library's close) and so
@@ -386,7 +419,6 @@ const createUnitRegistry = () => {
386
419
  unitId: nextId(),
387
420
  traceId: meta.traceId ?? meta.id,
388
421
  tenantId: meta.tenantId,
389
- deadline: meta.deadline,
390
422
  signal: controller.signal
391
423
  };
392
424
  return (0, unthrown.fromSafePromise)(runWithUnit(record, async () => {
@@ -710,3 +742,4 @@ exports.runMain = runMain;
710
742
  exports.start = start;
711
743
  exports.stderrSink = stderrSink;
712
744
  exports.systemClock = systemClock;
745
+ exports.traceIdOfTraceparent = traceIdOfTraceparent;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AsyncResult, Result } from "unthrown";
2
- import { AnyPort, Context, Module, PortClass, Scope, ServiceOf } from "@btravstack/di";
2
+ import { AnyPort, Context, Module, PortClass, PortInstance, Scope, ServiceOf } from "@btravstack/di";
3
3
  import { Env, Environment } from "@btravstack/config";
4
4
  //#region src/instrumentation.d.ts
5
5
  /**
@@ -315,7 +315,6 @@ type UnitRecord = {
315
315
  readonly unitId: string;
316
316
  readonly traceId: string;
317
317
  readonly tenantId: string | undefined;
318
- readonly deadline: number | undefined;
319
318
  readonly signal: AbortSignal;
320
319
  };
321
320
  declare const currentUnit: () => UnitRecord | undefined;
@@ -339,7 +338,6 @@ type UnitMeta = {
339
338
  readonly id: string;
340
339
  readonly traceId?: string;
341
340
  readonly tenantId?: string;
342
- readonly deadline?: number;
343
341
  };
344
342
  type UnitWork<T, E> = (signal: AbortSignal) => AsyncResult<T, E> | Promise<Result<T, E>> | Result<T, E>;
345
343
  type UnitRegistry = {
@@ -434,6 +432,34 @@ type RuntimeInstance = InstanceType<PortClass<"Runtime">>;
434
432
  type RuntimeOf<X> = ServiceOf<Extract<X, RuntimeInstance>>;
435
433
  type RuntimeResolvesOf<X> = RuntimeOf<X> extends Runtime<infer Resolves, unknown> ? Resolves : never;
436
434
  type RuntimeInfoOf<X> = RuntimeOf<X> extends Runtime<AnyPort, infer Info> ? Info : never;
435
+ /**
436
+ * The trace id inside a W3C `traceparent` header, and nothing else of it.
437
+ *
438
+ * @remarks
439
+ * The parent's **span id is dropped**, deliberately: `UnitMeta.traceId` is a
440
+ * correlation id rather than a span context, and half-carrying one would
441
+ * suggest a parent-child link nothing here maintains.
442
+ *
443
+ * Three things the specification calls invalid are refused like a malformed
444
+ * header, because adopting one would replace a runtime's own usable id with a
445
+ * value that means nothing: an **all-zero trace id**, an **all-zero parent
446
+ * id** (the header is well-formed and names no span), and **version `ff`**,
447
+ * which is reserved and never a version a caller may send.
448
+ *
449
+ * It is here rather than in a runtime because **every** transport carrying an
450
+ * inbound trace needs the same answer, and two copies of a parser is two
451
+ * places for the all-zero rule to be forgotten. A runtime pairs it with the
452
+ * adopt-only-a-non-blank-inbound-id rule its own headers need:
453
+ * `UnitMeta.traceId` defaults to `meta.id` when it is nullish and `""` is not,
454
+ * so an empty header would hand a caller's every unit the same blank id.
455
+ *
456
+ * @example
457
+ * ```ts
458
+ * const parent = request.headers["traceparent"];
459
+ * const traceId = typeof parent === "string" ? traceIdOfTraceparent(parent) : undefined;
460
+ * ```
461
+ */
462
+ declare const traceIdOfTraceparent: (header: string) => string | undefined;
437
463
  /**
438
464
  * `running`, but no later than the kernel's drain deadline — the primitive a
439
465
  * `Serving.drain` needs when the work it awaits settles on somebody else's
@@ -600,18 +626,38 @@ type RunningApp<E, Info = never> = {
600
626
  };
601
627
  /**
602
628
  * The phantom marker `start`, `runMain` and `Boot` all intersect onto their
603
- * `module` parameter: `unknown` — and invisible — when the module exports a
604
- * runtime, its exports cover what that runtime resolves and they cover the
605
- * unit module's needs; one of three sentences otherwise, printed at the call
606
- * site as the parameter type the argument did not match.
629
+ * `module` parameter: `unknown` — and invisible — when nothing the module
630
+ * needs is unprovided, it exports a runtime, its exports cover what that
631
+ * runtime resolves and they cover the unit module's needs; a diagnostic
632
+ * otherwise, printed at the call site as the parameter type the argument did
633
+ * not match.
607
634
  *
608
635
  * `unknown` is the satisfied arm because intersecting it leaves the module
609
636
  * type untouched. A runtime's `resolves` is checked against the module's
610
637
  * exports only, never the unit module's: `RuntimeHost.ctx` is the application
611
638
  * context, so a unit-only port would resolve to nothing there.
639
+ *
640
+ * **Unmet needs are checked FIRST, and answered in di's own words rather than
641
+ * a sentence of the kernel's.** A root that forgot `provides: [router]` used
642
+ * to be told `Type 'HttpRouterPort' is not assignable to type 'Scope'` — an
643
+ * internal phantom nobody has heard of — or, when the port was missing from
644
+ * `exports` too, `UNSATISFIED RUNTIME PORTS`, which is a correct diagnosis of
645
+ * the second mistake that reads as a wrong one of the first and steers the fix
646
+ * into the wrong list. It is the same defect `Module.build` reports, so it
647
+ * prints the same sentence and ends on the port that is missing.
612
648
  */
613
- type StartGate<X, UnitNeeds = never> = [Extract<X, RuntimeInstance>] extends [never] ? "NO RUNTIME — the module exports no port declared over RuntimePort" : [InstanceType<RuntimeResolvesOf<X>>] extends [X] ? [Exclude<UnitNeeds, X | Scope | Env>] extends [never] ? unknown : "UNSATISFIED UNIT NEEDS — the unit module needs a port the module does not export" : "UNSATISFIED RUNTIME PORTS — the runtime resolves a port the module does not export";
614
- declare const start: <X, E, UnitX = never, UnitNeeds = never>(module: Module<X, E, Scope | Env> & StartGate<X, UnitNeeds>, options?: StartOptions<UnitX, UnitNeeds>) => RunningApp<E, RuntimeInfoOf<X>>;
649
+ /**
650
+ * A port's declared id, which is what a marker names it by: an id is the short
651
+ * string the application wrote in `Port("…")`, where the port TYPE of a
652
+ * starter's own generic port — `AmqpHandlers` over a contract — expands to
653
+ * hundreds of characters of the caller's own schema and truncates before the
654
+ * name is reached.
655
+ */
656
+ type PortIdOf<P> = P extends PortInstance<infer Id, infer _Service> ? Id : P;
657
+ type StartGate<X, UnitNeeds = never, N = never> = [Exclude<N, Scope | Env>] extends [never] ? [Extract<X, RuntimeInstance>] extends [never] ? "NO RUNTIME — the module exports no port declared over RuntimePort" : [InstanceType<RuntimeResolvesOf<X>>] extends [X] ? [Exclude<UnitNeeds, X | Scope | Env>] extends [never] ? unknown : "UNSATISFIED UNIT NEEDS — the unit module needs a port the module does not export" : "UNSATISFIED RUNTIME PORTS — the runtime resolves a port the module does not export" : {
658
+ readonly "UNSATISFIED DEPENDENCIES — nothing provides": PortIdOf<Exclude<N, Scope | Env>>;
659
+ };
660
+ declare const start: <X, E, N, UnitX = never, UnitNeeds = never>(module: Module<X, E, N> & StartGate<X, UnitNeeds, N>, options?: StartOptions<UnitX, UnitNeeds>) => RunningApp<E, RuntimeInfoOf<X>>;
615
661
  //#endregion
616
662
  //#region src/run-main.d.ts
617
663
  /**
@@ -646,6 +692,6 @@ declare const start: <X, E, UnitX = never, UnitNeeds = never>(module: Module<X,
646
692
  * await runMain(OrderApi);
647
693
  * ```
648
694
  */
649
- declare const runMain: <X, E, UnitX = never, UnitNeeds = never>(module: Module<X, E, Scope | Env> & StartGate<X, UnitNeeds>, options?: StartOptions<UnitX, UnitNeeds>, exit?: (code: number) => void) => Promise<void>;
695
+ declare const runMain: <X, E, N, UnitX = never, UnitNeeds = never>(module: Module<X, E, N> & StartGate<X, UnitNeeds, N>, options?: StartOptions<UnitX, UnitNeeds>, exit?: (code: number) => void) => Promise<void>;
650
696
  //#endregion
651
- export { type Attributes, type Clock, type ComponentHealth, type Counter, type DrainReport, type EventSink, type ExitReport, type HealthCheck, HealthCheckFailed, HealthChecks, type HealthReport, type Histogram, type InstrumentationLoader, Instrumentations, type KernelEvent, LEVELS, type Level, Logger, type LoggerService, Meter, type MeterService, Observers, type Operation, type Phase, type RunUnit, type RunningApp, type Runtime, type RuntimeHost, type RuntimeInfoOf, RuntimePort, RuntimeStartFailed, SPAN_STATUS, type Serving, type Settle, type Settled, type Span, type SpanStatusCode, type StartGate, type StartOptions, type TeardownError, Tracer, type TracerService, type UnitMeta, type UnitRecord, type UnitRegistry, type UnitWork, currentUnit, noObserver, observe, releasedBy, runHealthChecks, runMain, start, stderrSink, systemClock };
697
+ export { type Attributes, type Clock, type ComponentHealth, type Counter, type DrainReport, type EventSink, type ExitReport, type HealthCheck, HealthCheckFailed, HealthChecks, type HealthReport, type Histogram, type InstrumentationLoader, Instrumentations, type KernelEvent, LEVELS, type Level, Logger, type LoggerService, Meter, type MeterService, Observers, type Operation, type Phase, type RunUnit, type RunningApp, type Runtime, type RuntimeHost, type RuntimeInfoOf, RuntimePort, RuntimeStartFailed, SPAN_STATUS, type Serving, type Settle, type Settled, type Span, type SpanStatusCode, type StartGate, type StartOptions, type TeardownError, Tracer, type TracerService, type UnitMeta, type UnitRecord, type UnitRegistry, type UnitWork, currentUnit, noObserver, observe, releasedBy, runHealthChecks, runMain, start, stderrSink, systemClock, traceIdOfTraceparent };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { AnyPort, Context, Module, PortClass, Scope, ServiceOf } from "@btravstack/di";
1
+ import { AnyPort, Context, Module, PortClass, PortInstance, Scope, ServiceOf } from "@btravstack/di";
2
2
  import { AsyncResult, Result } from "unthrown";
3
3
  import { Env, Environment } from "@btravstack/config";
4
4
  //#region src/instrumentation.d.ts
@@ -315,7 +315,6 @@ type UnitRecord = {
315
315
  readonly unitId: string;
316
316
  readonly traceId: string;
317
317
  readonly tenantId: string | undefined;
318
- readonly deadline: number | undefined;
319
318
  readonly signal: AbortSignal;
320
319
  };
321
320
  declare const currentUnit: () => UnitRecord | undefined;
@@ -339,7 +338,6 @@ type UnitMeta = {
339
338
  readonly id: string;
340
339
  readonly traceId?: string;
341
340
  readonly tenantId?: string;
342
- readonly deadline?: number;
343
341
  };
344
342
  type UnitWork<T, E> = (signal: AbortSignal) => AsyncResult<T, E> | Promise<Result<T, E>> | Result<T, E>;
345
343
  type UnitRegistry = {
@@ -434,6 +432,34 @@ type RuntimeInstance = InstanceType<PortClass<"Runtime">>;
434
432
  type RuntimeOf<X> = ServiceOf<Extract<X, RuntimeInstance>>;
435
433
  type RuntimeResolvesOf<X> = RuntimeOf<X> extends Runtime<infer Resolves, unknown> ? Resolves : never;
436
434
  type RuntimeInfoOf<X> = RuntimeOf<X> extends Runtime<AnyPort, infer Info> ? Info : never;
435
+ /**
436
+ * The trace id inside a W3C `traceparent` header, and nothing else of it.
437
+ *
438
+ * @remarks
439
+ * The parent's **span id is dropped**, deliberately: `UnitMeta.traceId` is a
440
+ * correlation id rather than a span context, and half-carrying one would
441
+ * suggest a parent-child link nothing here maintains.
442
+ *
443
+ * Three things the specification calls invalid are refused like a malformed
444
+ * header, because adopting one would replace a runtime's own usable id with a
445
+ * value that means nothing: an **all-zero trace id**, an **all-zero parent
446
+ * id** (the header is well-formed and names no span), and **version `ff`**,
447
+ * which is reserved and never a version a caller may send.
448
+ *
449
+ * It is here rather than in a runtime because **every** transport carrying an
450
+ * inbound trace needs the same answer, and two copies of a parser is two
451
+ * places for the all-zero rule to be forgotten. A runtime pairs it with the
452
+ * adopt-only-a-non-blank-inbound-id rule its own headers need:
453
+ * `UnitMeta.traceId` defaults to `meta.id` when it is nullish and `""` is not,
454
+ * so an empty header would hand a caller's every unit the same blank id.
455
+ *
456
+ * @example
457
+ * ```ts
458
+ * const parent = request.headers["traceparent"];
459
+ * const traceId = typeof parent === "string" ? traceIdOfTraceparent(parent) : undefined;
460
+ * ```
461
+ */
462
+ declare const traceIdOfTraceparent: (header: string) => string | undefined;
437
463
  /**
438
464
  * `running`, but no later than the kernel's drain deadline — the primitive a
439
465
  * `Serving.drain` needs when the work it awaits settles on somebody else's
@@ -600,18 +626,38 @@ type RunningApp<E, Info = never> = {
600
626
  };
601
627
  /**
602
628
  * The phantom marker `start`, `runMain` and `Boot` all intersect onto their
603
- * `module` parameter: `unknown` — and invisible — when the module exports a
604
- * runtime, its exports cover what that runtime resolves and they cover the
605
- * unit module's needs; one of three sentences otherwise, printed at the call
606
- * site as the parameter type the argument did not match.
629
+ * `module` parameter: `unknown` — and invisible — when nothing the module
630
+ * needs is unprovided, it exports a runtime, its exports cover what that
631
+ * runtime resolves and they cover the unit module's needs; a diagnostic
632
+ * otherwise, printed at the call site as the parameter type the argument did
633
+ * not match.
607
634
  *
608
635
  * `unknown` is the satisfied arm because intersecting it leaves the module
609
636
  * type untouched. A runtime's `resolves` is checked against the module's
610
637
  * exports only, never the unit module's: `RuntimeHost.ctx` is the application
611
638
  * context, so a unit-only port would resolve to nothing there.
639
+ *
640
+ * **Unmet needs are checked FIRST, and answered in di's own words rather than
641
+ * a sentence of the kernel's.** A root that forgot `provides: [router]` used
642
+ * to be told `Type 'HttpRouterPort' is not assignable to type 'Scope'` — an
643
+ * internal phantom nobody has heard of — or, when the port was missing from
644
+ * `exports` too, `UNSATISFIED RUNTIME PORTS`, which is a correct diagnosis of
645
+ * the second mistake that reads as a wrong one of the first and steers the fix
646
+ * into the wrong list. It is the same defect `Module.build` reports, so it
647
+ * prints the same sentence and ends on the port that is missing.
612
648
  */
613
- type StartGate<X, UnitNeeds = never> = [Extract<X, RuntimeInstance>] extends [never] ? "NO RUNTIME — the module exports no port declared over RuntimePort" : [InstanceType<RuntimeResolvesOf<X>>] extends [X] ? [Exclude<UnitNeeds, X | Scope | Env>] extends [never] ? unknown : "UNSATISFIED UNIT NEEDS — the unit module needs a port the module does not export" : "UNSATISFIED RUNTIME PORTS — the runtime resolves a port the module does not export";
614
- declare const start: <X, E, UnitX = never, UnitNeeds = never>(module: Module<X, E, Scope | Env> & StartGate<X, UnitNeeds>, options?: StartOptions<UnitX, UnitNeeds>) => RunningApp<E, RuntimeInfoOf<X>>;
649
+ /**
650
+ * A port's declared id, which is what a marker names it by: an id is the short
651
+ * string the application wrote in `Port("…")`, where the port TYPE of a
652
+ * starter's own generic port — `AmqpHandlers` over a contract — expands to
653
+ * hundreds of characters of the caller's own schema and truncates before the
654
+ * name is reached.
655
+ */
656
+ type PortIdOf<P> = P extends PortInstance<infer Id, infer _Service> ? Id : P;
657
+ type StartGate<X, UnitNeeds = never, N = never> = [Exclude<N, Scope | Env>] extends [never] ? [Extract<X, RuntimeInstance>] extends [never] ? "NO RUNTIME — the module exports no port declared over RuntimePort" : [InstanceType<RuntimeResolvesOf<X>>] extends [X] ? [Exclude<UnitNeeds, X | Scope | Env>] extends [never] ? unknown : "UNSATISFIED UNIT NEEDS — the unit module needs a port the module does not export" : "UNSATISFIED RUNTIME PORTS — the runtime resolves a port the module does not export" : {
658
+ readonly "UNSATISFIED DEPENDENCIES — nothing provides": PortIdOf<Exclude<N, Scope | Env>>;
659
+ };
660
+ declare const start: <X, E, N, UnitX = never, UnitNeeds = never>(module: Module<X, E, N> & StartGate<X, UnitNeeds, N>, options?: StartOptions<UnitX, UnitNeeds>) => RunningApp<E, RuntimeInfoOf<X>>;
615
661
  //#endregion
616
662
  //#region src/run-main.d.ts
617
663
  /**
@@ -646,6 +692,6 @@ declare const start: <X, E, UnitX = never, UnitNeeds = never>(module: Module<X,
646
692
  * await runMain(OrderApi);
647
693
  * ```
648
694
  */
649
- declare const runMain: <X, E, UnitX = never, UnitNeeds = never>(module: Module<X, E, Scope | Env> & StartGate<X, UnitNeeds>, options?: StartOptions<UnitX, UnitNeeds>, exit?: (code: number) => void) => Promise<void>;
695
+ declare const runMain: <X, E, N, UnitX = never, UnitNeeds = never>(module: Module<X, E, N> & StartGate<X, UnitNeeds, N>, options?: StartOptions<UnitX, UnitNeeds>, exit?: (code: number) => void) => Promise<void>;
650
696
  //#endregion
651
- export { type Attributes, type Clock, type ComponentHealth, type Counter, type DrainReport, type EventSink, type ExitReport, type HealthCheck, HealthCheckFailed, HealthChecks, type HealthReport, type Histogram, type InstrumentationLoader, Instrumentations, type KernelEvent, LEVELS, type Level, Logger, type LoggerService, Meter, type MeterService, Observers, type Operation, type Phase, type RunUnit, type RunningApp, type Runtime, type RuntimeHost, type RuntimeInfoOf, RuntimePort, RuntimeStartFailed, SPAN_STATUS, type Serving, type Settle, type Settled, type Span, type SpanStatusCode, type StartGate, type StartOptions, type TeardownError, Tracer, type TracerService, type UnitMeta, type UnitRecord, type UnitRegistry, type UnitWork, currentUnit, noObserver, observe, releasedBy, runHealthChecks, runMain, start, stderrSink, systemClock };
697
+ export { type Attributes, type Clock, type ComponentHealth, type Counter, type DrainReport, type EventSink, type ExitReport, type HealthCheck, HealthCheckFailed, HealthChecks, type HealthReport, type Histogram, type InstrumentationLoader, Instrumentations, type KernelEvent, LEVELS, type Level, Logger, type LoggerService, Meter, type MeterService, Observers, type Operation, type Phase, type RunUnit, type RunningApp, type Runtime, type RuntimeHost, type RuntimeInfoOf, RuntimePort, RuntimeStartFailed, SPAN_STATUS, type Serving, type Settle, type Settled, type Span, type SpanStatusCode, type StartGate, type StartOptions, type TeardownError, Tracer, type TracerService, type UnitMeta, type UnitRecord, type UnitRegistry, type UnitWork, currentUnit, noObserver, observe, releasedBy, runHealthChecks, runMain, start, stderrSink, systemClock, traceIdOfTraceparent };
package/dist/index.mjs CHANGED
@@ -205,6 +205,39 @@ var RuntimeStartFailed = class extends TaggedError("RuntimeStartFailed") {
205
205
  */
206
206
  const RuntimePort = Port("Runtime");
207
207
  /**
208
+ * The trace id inside a W3C `traceparent` header, and nothing else of it.
209
+ *
210
+ * @remarks
211
+ * The parent's **span id is dropped**, deliberately: `UnitMeta.traceId` is a
212
+ * correlation id rather than a span context, and half-carrying one would
213
+ * suggest a parent-child link nothing here maintains.
214
+ *
215
+ * Three things the specification calls invalid are refused like a malformed
216
+ * header, because adopting one would replace a runtime's own usable id with a
217
+ * value that means nothing: an **all-zero trace id**, an **all-zero parent
218
+ * id** (the header is well-formed and names no span), and **version `ff`**,
219
+ * which is reserved and never a version a caller may send.
220
+ *
221
+ * It is here rather than in a runtime because **every** transport carrying an
222
+ * inbound trace needs the same answer, and two copies of a parser is two
223
+ * places for the all-zero rule to be forgotten. A runtime pairs it with the
224
+ * adopt-only-a-non-blank-inbound-id rule its own headers need:
225
+ * `UnitMeta.traceId` defaults to `meta.id` when it is nullish and `""` is not,
226
+ * so an empty header would hand a caller's every unit the same blank id.
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * const parent = request.headers["traceparent"];
231
+ * const traceId = typeof parent === "string" ? traceIdOfTraceparent(parent) : undefined;
232
+ * ```
233
+ */
234
+ const traceIdOfTraceparent = (header) => {
235
+ const [, version, traceId, parentId, extra] = /^(?!ff)([\da-f]{2})-([\da-f]{32})-([\da-f]{16})-[\da-f]{2}(-.*)?$/.exec(header.trim()) ?? [];
236
+ if (traceId === void 0 || parentId === void 0) return void 0;
237
+ if (version === "00" && extra !== void 0) return void 0;
238
+ return /^0+$/.test(traceId) || /^0+$/.test(parentId) ? void 0 : traceId;
239
+ };
240
+ /**
208
241
  * `running`, but no later than the kernel's drain deadline — the primitive a
209
242
  * `Serving.drain` needs when the work it awaits settles on somebody else's
210
243
  * clock (Temporal's `shutdownForceTime`, a broker library's close) and so
@@ -385,7 +418,6 @@ const createUnitRegistry = () => {
385
418
  unitId: nextId(),
386
419
  traceId: meta.traceId ?? meta.id,
387
420
  tenantId: meta.tenantId,
388
- deadline: meta.deadline,
389
421
  signal: controller.signal
390
422
  };
391
423
  return fromSafePromise(runWithUnit(record, async () => {
@@ -689,4 +721,4 @@ const runMain = async (module, options = {}, exit = (code) => {
689
721
  await awaitExit(start(module, options), exit);
690
722
  };
691
723
  //#endregion
692
- export { HealthCheckFailed, HealthChecks, Instrumentations, LEVELS, Logger, Meter, Observers, RuntimePort, RuntimeStartFailed, SPAN_STATUS, Tracer, currentUnit, noObserver, observe, releasedBy, runHealthChecks, runMain, start, stderrSink, systemClock };
724
+ export { HealthCheckFailed, HealthChecks, Instrumentations, LEVELS, Logger, Meter, Observers, RuntimePort, RuntimeStartFailed, SPAN_STATUS, Tracer, currentUnit, noObserver, observe, releasedBy, runHealthChecks, runMain, start, stderrSink, systemClock, traceIdOfTraceparent };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/core",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "The application kernel: boot a di module into a running process, and stop it without losing work",
5
5
  "keywords": [
6
6
  "application",
@@ -53,13 +53,13 @@
53
53
  "typescript": "7.0.2",
54
54
  "unthrown": "5.7.0",
55
55
  "vitest": "4.1.11",
56
- "@btravstack/config": "0.10.0",
57
- "@btravstack/di": "0.10.0"
56
+ "@btravstack/config": "0.12.0",
57
+ "@btravstack/di": "0.12.0"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "unthrown": "^5.0.0",
61
- "@btravstack/config": "^0.10.0",
62
- "@btravstack/di": "^0.10.0"
61
+ "@btravstack/config": "^0.12.0",
62
+ "@btravstack/di": "^0.12.0"
63
63
  },
64
64
  "engines": {
65
65
  "node": ">=22"