@setu-ts/kernel 0.9.0 → 0.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 (38) hide show
  1. package/AGENT_CARD.md +47 -0
  2. package/README.md +13 -5
  3. package/dist/application/application.d.ts +2 -0
  4. package/dist/application/application.d.ts.map +1 -1
  5. package/dist/application/application.js +54 -11
  6. package/dist/application/application.js.map +1 -1
  7. package/dist/application/inject-body.d.ts.map +1 -1
  8. package/dist/application/inject-body.js +2 -2
  9. package/dist/application/inject-body.js.map +1 -1
  10. package/dist/context/response.js.map +1 -1
  11. package/dist/diagnostics/buffer.d.ts.map +1 -1
  12. package/dist/diagnostics/buffer.js +9 -4
  13. package/dist/diagnostics/buffer.js.map +1 -1
  14. package/dist/diagnostics/collector.d.ts.map +1 -1
  15. package/dist/diagnostics/collector.js +1 -3
  16. package/dist/diagnostics/collector.js.map +1 -1
  17. package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
  18. package/dist/lifecycle/lifecycle-manager.js.map +1 -1
  19. package/dist/pipeline/execute-chain.d.ts.map +1 -1
  20. package/dist/pipeline/execute-chain.js.map +1 -1
  21. package/dist/pipeline/middleware-pipeline.d.ts.map +1 -1
  22. package/dist/pipeline/middleware-pipeline.js.map +1 -1
  23. package/dist/registry/service-registry.d.ts.map +1 -1
  24. package/dist/registry/service-registry.js.map +1 -1
  25. package/dist/router/route-matcher.d.ts.map +1 -1
  26. package/dist/router/route-matcher.js +4 -1
  27. package/dist/router/route-matcher.js.map +1 -1
  28. package/package.json +9 -8
  29. package/src/application/application.ts +86 -59
  30. package/src/application/inject-body.ts +8 -9
  31. package/src/context/response.ts +2 -10
  32. package/src/diagnostics/buffer.ts +20 -18
  33. package/src/diagnostics/collector.ts +19 -20
  34. package/src/lifecycle/lifecycle-manager.ts +1 -6
  35. package/src/pipeline/execute-chain.ts +1 -3
  36. package/src/pipeline/middleware-pipeline.ts +1 -3
  37. package/src/registry/service-registry.ts +4 -9
  38. package/src/router/route-matcher.ts +15 -12
@@ -198,11 +198,7 @@ class BufferedResponseSnapshot implements Extract<ResponseSnapshot, { readonly s
198
198
  readonly status: number;
199
199
  readonly body: Uint8Array | string | null;
200
200
 
201
- constructor(
202
- response: ResponseBuilder,
203
- status: number,
204
- body: Uint8Array | string | null,
205
- ) {
201
+ constructor(response: ResponseBuilder, status: number, body: Uint8Array | string | null) {
206
202
  this.#response = response;
207
203
  this.status = status;
208
204
  this.body = body;
@@ -224,11 +220,7 @@ class StreamingResponseSnapshot implements Extract<ResponseSnapshot, { readonly
224
220
  readonly status: number;
225
221
  readonly body: ReadableStream<Uint8Array>;
226
222
 
227
- constructor(
228
- response: ResponseBuilder,
229
- status: number,
230
- body: ReadableStream<Uint8Array>,
231
- ) {
223
+ constructor(response: ResponseBuilder, status: number, body: ReadableStream<Uint8Array>) {
232
224
  this.#response = response;
233
225
  this.status = status;
234
226
  this.body = body;
@@ -59,19 +59,21 @@ const EVENT_SKELETON_BYTES = 220;
59
59
  * @returns `true` when the encoded event is within {@linkcode MAX_EVENT_BYTES}
60
60
  * @since 0.8.0
61
61
  */
62
- export function eventWithinByteCap(
63
- fieldLengths: {
64
- readonly operationId: number;
65
- readonly parentOperationId: number;
66
- readonly nodeId: number;
67
- readonly traceId: number;
68
- readonly spanId: number;
69
- readonly statusCode: boolean;
70
- },
71
- ): boolean {
72
- const bounded = EVENT_SKELETON_BYTES +
73
- fieldLengths.operationId + fieldLengths.parentOperationId + fieldLengths.nodeId +
74
- fieldLengths.traceId + fieldLengths.spanId +
62
+ export function eventWithinByteCap(fieldLengths: {
63
+ readonly operationId: number;
64
+ readonly parentOperationId: number;
65
+ readonly nodeId: number;
66
+ readonly traceId: number;
67
+ readonly spanId: number;
68
+ readonly statusCode: boolean;
69
+ }): boolean {
70
+ const bounded =
71
+ EVENT_SKELETON_BYTES +
72
+ fieldLengths.operationId +
73
+ fieldLengths.parentOperationId +
74
+ fieldLengths.nodeId +
75
+ fieldLengths.traceId +
76
+ fieldLengths.spanId +
75
77
  (fieldLengths.statusCode ? 21 : 0);
76
78
  return bounded <= MAX_EVENT_BYTES;
77
79
  }
@@ -111,15 +113,15 @@ export function validateReadCursor(
111
113
  limit: number | undefined,
112
114
  lastSequence: number,
113
115
  ): { after: number; limit: number } {
114
- if (
115
- typeof after !== 'number' || !Number.isSafeInteger(after) || after < 0
116
- ) {
116
+ if (typeof after !== 'number' || !Number.isSafeInteger(after) || after < 0) {
117
117
  throw new RangeError('Invalid diagnostics cursor: expected a non-negative safe integer.');
118
118
  }
119
119
  const effectiveLimit = limit ?? MAX_READ_LIMIT;
120
120
  if (
121
- typeof effectiveLimit !== 'number' || !Number.isSafeInteger(effectiveLimit) ||
122
- effectiveLimit < 1 || effectiveLimit > MAX_READ_LIMIT
121
+ typeof effectiveLimit !== 'number' ||
122
+ !Number.isSafeInteger(effectiveLimit) ||
123
+ effectiveLimit < 1 ||
124
+ effectiveLimit > MAX_READ_LIMIT
123
125
  ) {
124
126
  throw new RangeError(
125
127
  `Invalid diagnostics read limit: expected an integer from 1 to ${MAX_READ_LIMIT}.`,
@@ -508,9 +508,8 @@ export class DiagnosticsCollector implements IDiagnosticsSource {
508
508
  stages.push(stage);
509
509
  }
510
510
  this.#routeMiddlewareNodes.set(event.entryIndex, stages);
511
- const ownerNode = event.owner === undefined
512
- ? undefined
513
- : this.#pluginNodesByName.get(event.owner);
511
+ const ownerNode =
512
+ event.owner === undefined ? undefined : this.#pluginNodesByName.get(event.owner);
514
513
  if (ownerNode !== undefined) {
515
514
  this.#addEdge(ownerNode.id, id, 'owns');
516
515
  }
@@ -631,9 +630,10 @@ export class DiagnosticsCollector implements IDiagnosticsSource {
631
630
  startedAtMs: number | null;
632
631
  durationMs: number | null;
633
632
  }): void {
634
- const node = parts.scope === 'global'
635
- ? this.#globalMiddlewareNodes[parts.position]?.id
636
- : this.#routeMiddlewareNodes.get(parts.routeEntryIndex ?? -1)?.[parts.position]?.id;
633
+ const node =
634
+ parts.scope === 'global'
635
+ ? this.#globalMiddlewareNodes[parts.position]?.id
636
+ : this.#routeMiddlewareNodes.get(parts.routeEntryIndex ?? -1)?.[parts.position]?.id;
637
637
  this.#emitEvent({
638
638
  kind: 'middleware',
639
639
  stage: parts.scope,
@@ -797,11 +797,7 @@ export class DiagnosticsCollector implements IDiagnosticsSource {
797
797
  this.#snapshotDirty = true;
798
798
  }
799
799
 
800
- #nextNodeId(
801
- prefix: string,
802
- current: number,
803
- assign: (next: number) => void,
804
- ): string | undefined {
800
+ #nextNodeId(prefix: string, current: number, assign: (next: number) => void): string | undefined {
805
801
  // Fixed v1 limit: stop ADDING topology at 1,024 nodes and report the
806
802
  // truncation rather than retaining unbounded metadata.
807
803
  if (this.#nodes.length >= MAX_NODES) {
@@ -926,12 +922,14 @@ export class DiagnosticsCollector implements IDiagnosticsSource {
926
922
  }
927
923
  // Identifiers are carried only when they are well-formed and non-zero —
928
924
  // the W3C all-zero ids mean "invalid", not "anonymous".
929
- const traceId = TRACE_ID_PATTERN.test(context.traceId) && NON_ZERO.test(context.traceId)
930
- ? context.traceId
931
- : undefined;
932
- const spanId = SPAN_ID_PATTERN.test(context.spanId) && NON_ZERO.test(context.spanId)
933
- ? context.spanId
934
- : undefined;
925
+ const traceId =
926
+ TRACE_ID_PATTERN.test(context.traceId) && NON_ZERO.test(context.traceId)
927
+ ? context.traceId
928
+ : undefined;
929
+ const spanId =
930
+ SPAN_ID_PATTERN.test(context.spanId) && NON_ZERO.test(context.spanId)
931
+ ? context.spanId
932
+ : undefined;
935
933
  return {
936
934
  ...(traceId !== undefined ? { traceId } : {}),
937
935
  ...(spanId !== undefined ? { spanId } : {}),
@@ -967,9 +965,10 @@ export class DiagnosticsCollector implements IDiagnosticsSource {
967
965
  // A status is recorded as the application set it — any finite number,
968
966
  // ranged or not — but a non-finite one is omitted, for the same reason a
969
967
  // non-finite priority is: it would serialize to `null` in a `number` field.
970
- const statusCode = parts.statusCode !== undefined && Number.isFinite(parts.statusCode)
971
- ? parts.statusCode
972
- : undefined;
968
+ const statusCode =
969
+ parts.statusCode !== undefined && Number.isFinite(parts.statusCode)
970
+ ? parts.statusCode
971
+ : undefined;
973
972
  const parentLength = parts.parentOperationId?.length ?? 0;
974
973
  const withinCap = eventWithinByteCap({
975
974
  operationId: parts.operationId.length,
@@ -22,12 +22,7 @@ type ErrorHook = (error: Error, ctx: IRequestContext) => void | Promise<void>;
22
22
  * @since 0.8.0
23
23
  */
24
24
  export type LifecycleHookPhase =
25
- | 'register-hook'
26
- | 'init'
27
- | 'bootstrap'
28
- | 'stopping'
29
- | 'shutdown'
30
- | 'close';
25
+ 'register-hook' | 'init' | 'bootstrap' | 'stopping' | 'shutdown' | 'close';
31
26
 
32
27
  /**
33
28
  * One hook invocation observed with its fixed phase plus execution ordinal —
@@ -123,9 +123,7 @@ export async function executeChain(
123
123
  // anonymous function — so `??` never fell back and the message read
124
124
  // "…in middleware " with a blank name. `||` is the correct operator.
125
125
  const label = names?.[position] || fn.name || '<anonymous>';
126
- throw new Error(
127
- `next() called multiple times in middleware ${label}`,
128
- );
126
+ throw new Error(`next() called multiple times in middleware ${label}`);
129
127
  }
130
128
  nextCalled = true;
131
129
  if (observer !== undefined && responseEnded()) {
@@ -71,9 +71,7 @@ export class MiddlewarePipeline implements IMiddlewareApi {
71
71
  if (this.#compiled !== null) {
72
72
  return this.#compiled;
73
73
  }
74
- const sorted = [...this.#entries].sort(
75
- (a, b) => a.priority - b.priority || a.index - b.index,
76
- );
74
+ const sorted = [...this.#entries].sort((a, b) => a.priority - b.priority || a.index - b.index);
77
75
  this.#compiled = sorted.map((entry) => entry.fn);
78
76
  this.#compiledNames = sorted.map((entry) => entry.name);
79
77
  this.#compiledDescriptors = sorted.map((entry, position) => ({
@@ -162,17 +162,11 @@ export class ServiceRegistry implements IServiceRegistry {
162
162
  }
163
163
 
164
164
  /** Installs the application-owned callback for startup-time mutations. */
165
- setObserver(
166
- observer: (kind: 'override' | 'unregister', token: CapabilityToken) => void,
167
- ): void {
165
+ setObserver(observer: (kind: 'override' | 'unregister', token: CapabilityToken) => void): void {
168
166
  this.#observer = observer;
169
167
  }
170
168
 
171
- register<T extends object>(
172
- token: CapabilityToken,
173
- service: T,
174
- options?: RegisterOptions,
175
- ): void {
169
+ register<T extends object>(token: CapabilityToken, service: T, options?: RegisterOptions): void {
176
170
  this.#store(token, { instance: service }, options);
177
171
  }
178
172
 
@@ -187,7 +181,8 @@ export class ServiceRegistry implements IServiceRegistry {
187
181
  get<T extends object>(token: CapabilityToken): T {
188
182
  const registration = this.#lookup(token);
189
183
  if (registration === undefined) {
190
- const advice = this.#missExplanation?.(token) ??
184
+ const advice =
185
+ this.#missExplanation?.(token) ??
191
186
  'Register a plugin that provides it, or check the token spelling against CAPABILITIES.';
192
187
  throw new Error(`No service registered for capability '${token}'. ${advice}`);
193
188
  }
@@ -53,18 +53,21 @@ export function parsePattern(pattern: string): readonly Segment[] {
53
53
  if (normalized === '/') {
54
54
  return [{ type: 'static', value: '' }];
55
55
  }
56
- return normalized.slice(1).split('/').map((part) => {
57
- if (part.startsWith(':')) {
58
- return { type: 'param', name: part.slice(1) };
59
- }
60
- // Exactly `*`, never a segment merely CONTAINING one: `/a*` is not a pattern
61
- // any first-party plugin registers, and treating it as a wildcard would lower
62
- // the specificity of a path that matches literally.
63
- if (part === '*') {
64
- return { type: 'wildcard' };
65
- }
66
- return { type: 'static', value: part };
67
- });
56
+ return normalized
57
+ .slice(1)
58
+ .split('/')
59
+ .map((part) => {
60
+ if (part.startsWith(':')) {
61
+ return { type: 'param', name: part.slice(1) };
62
+ }
63
+ // Exactly `*`, never a segment merely CONTAINING one: `/a*` is not a pattern
64
+ // any first-party plugin registers, and treating it as a wildcard would lower
65
+ // the specificity of a path that matches literally.
66
+ if (part === '*') {
67
+ return { type: 'wildcard' };
68
+ }
69
+ return { type: 'static', value: part };
70
+ });
68
71
  }
69
72
 
70
73
  /**