@daloyjs/core 0.39.1 → 0.42.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/dist/docs.d.ts CHANGED
@@ -226,6 +226,24 @@ export interface DocsAssetOptions {
226
226
  * @since 0.39.0
227
227
  */
228
228
  redocScriptIntegrity?: string;
229
+ /** Override the AsyncAPI React standalone bundle URL (useful for self-hosting). */
230
+ asyncapiScriptUrl?: string;
231
+ /**
232
+ * SRI hash for {@link asyncapiScriptUrl}. One or more space-separated
233
+ * `sha256-`/`sha384-`/`sha512-` base64 digests. Invalid values throw.
234
+ *
235
+ * @since 0.42.0
236
+ */
237
+ asyncapiScriptIntegrity?: string;
238
+ /** Override the AsyncAPI React component stylesheet URL (useful for self-hosting). */
239
+ asyncapiStyleUrl?: string;
240
+ /**
241
+ * SRI hash for {@link asyncapiStyleUrl}. One or more space-separated
242
+ * `sha256-`/`sha384-`/`sha512-` base64 digests. Invalid values throw.
243
+ *
244
+ * @since 0.42.0
245
+ */
246
+ asyncapiStyleIntegrity?: string;
229
247
  /**
230
248
  * `crossorigin` attribute value emitted alongside any pinned integrity
231
249
  * hash. SRI on a cross-origin asset requires CORS, so this defaults to
@@ -264,6 +282,20 @@ export interface RedocHtmlOptions extends DocsOptions {
264
282
  /** Forwarded as the options object to `Redoc.init(specUrl, configuration, element)`. */
265
283
  configuration?: RedocConfiguration;
266
284
  }
285
+ /**
286
+ * Options for {@link asyncapiHtml}; adds AsyncAPI-specific UI configuration.
287
+ *
288
+ * @since 0.42.0
289
+ */
290
+ export interface AsyncApiHtmlOptions extends DocsOptions {
291
+ /**
292
+ * Forwarded as the `config` object to `AsyncApiStandalone.render({ schema, config }, el)`.
293
+ * Defaults to showing the sidebar and inline errors.
294
+ */
295
+ configuration?: {
296
+ [key: string]: ScalarJsonValue | undefined;
297
+ };
298
+ }
267
299
  /** Options for {@link docsContentSecurityPolicy}. */
268
300
  export interface DocsContentSecurityPolicyOptions {
269
301
  /** Extra origins to allow for `script-src` / `style-src` (defaults to jsDelivr). */
@@ -316,6 +348,23 @@ export declare function swaggerUiHtml(opts: DocsOptions): string;
316
348
  * @since 0.39.0
317
349
  */
318
350
  export declare function redocHtml(opts: RedocHtmlOptions): string;
351
+ /**
352
+ * Render an AsyncAPI HTML page that loads `opts.specUrl` (an AsyncAPI 3.0
353
+ * document) into the official AsyncAPI React component. Same shape as
354
+ * {@link redocHtml}: a prebuilt standalone bundle is loaded from a CDN via a
355
+ * `<script>` tag (no build step, no extra deps) and the spec URL is handed to
356
+ * `AsyncApiStandalone.render(...)`. This is the AsyncAPI equivalent of the
357
+ * Scalar / Swagger UI / Redoc OpenAPI viewers.
358
+ *
359
+ * Serve it with the same CSP as the OpenAPI docs UIs ({@link docsContentSecurityPolicy}):
360
+ * it needs the asset origin (jsDelivr by default) in `script-src` / `style-src`
361
+ * and `connect-src 'self'` so the component can `fetch` the spec. The spec URL
362
+ * and configuration are embedded with `<`-escaped JSON so an attacker-controlled
363
+ * value cannot break out of the inline `<script>`.
364
+ *
365
+ * @since 0.42.0
366
+ */
367
+ export declare function asyncapiHtml(opts: AsyncApiHtmlOptions): string;
319
368
  /**
320
369
  * Build a Content-Security-Policy string compatible with the docs HTML
321
370
  * produced by {@link scalarHtml} / {@link swaggerUiHtml}.
package/dist/docs.js CHANGED
@@ -123,6 +123,45 @@ export function redocHtml(opts) {
123
123
  <script${nonce}>Redoc.init(${specArg},${optionsArg},document.getElementById("redoc"));</script>
124
124
  </body></html>`;
125
125
  }
126
+ /**
127
+ * Render an AsyncAPI HTML page that loads `opts.specUrl` (an AsyncAPI 3.0
128
+ * document) into the official AsyncAPI React component. Same shape as
129
+ * {@link redocHtml}: a prebuilt standalone bundle is loaded from a CDN via a
130
+ * `<script>` tag (no build step, no extra deps) and the spec URL is handed to
131
+ * `AsyncApiStandalone.render(...)`. This is the AsyncAPI equivalent of the
132
+ * Scalar / Swagger UI / Redoc OpenAPI viewers.
133
+ *
134
+ * Serve it with the same CSP as the OpenAPI docs UIs ({@link docsContentSecurityPolicy}):
135
+ * it needs the asset origin (jsDelivr by default) in `script-src` / `style-src`
136
+ * and `connect-src 'self'` so the component can `fetch` the spec. The spec URL
137
+ * and configuration are embedded with `<`-escaped JSON so an attacker-controlled
138
+ * value cannot break out of the inline `<script>`.
139
+ *
140
+ * @since 0.42.0
141
+ */
142
+ export function asyncapiHtml(opts) {
143
+ const title = escapeHtml(opts.title ?? "AsyncAPI");
144
+ const scriptUrl = escapeHtml(opts.assets?.asyncapiScriptUrl ??
145
+ `${JSDELIVR_ORIGIN}/npm/@asyncapi/react-component/browser/standalone/index.js`);
146
+ const styleUrl = escapeHtml(opts.assets?.asyncapiStyleUrl ??
147
+ `${JSDELIVR_ORIGIN}/npm/@asyncapi/react-component/styles/default.min.css`);
148
+ const scriptSri = integrityAttr(opts.assets?.asyncapiScriptIntegrity, opts.assets?.crossOrigin);
149
+ const styleSri = integrityAttr(opts.assets?.asyncapiStyleIntegrity, opts.assets?.crossOrigin);
150
+ const nonce = nonceAttr(opts.scriptNonce);
151
+ const specArg = jsonForScript(opts.specUrl);
152
+ const configArg = jsonForScript(opts.configuration ?? { show: { sidebar: true, errors: true } });
153
+ return `<!doctype html>
154
+ <html><head>
155
+ <meta charset="utf-8" />
156
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
157
+ <title>${title}</title>
158
+ <link rel="stylesheet" href="${styleUrl}"${styleSri} />
159
+ </head><body>
160
+ <div id="asyncapi"></div>
161
+ <script src="${scriptUrl}"${scriptSri}${nonce}></script>
162
+ <script${nonce}>AsyncApiStandalone.render({schema:{url:${specArg},options:{method:"GET"}},config:${configArg}},document.getElementById("asyncapi"));</script>
163
+ </body></html>`;
164
+ }
126
165
  /**
127
166
  * Build a Content-Security-Policy string compatible with the docs HTML
128
167
  * produced by {@link scalarHtml} / {@link swaggerUiHtml}.
@@ -31,7 +31,7 @@
31
31
  * @module
32
32
  * @since 0.37.0
33
33
  */
34
- import type { Hooks } from "./types.js";
34
+ import type { BaseContext, Hooks } from "./types.js";
35
35
  /**
36
36
  * Test-only helper that clears the process-wide shared stores used by
37
37
  * `idempotency({ groupId })`. Not part of the documented public API.
@@ -149,6 +149,24 @@ export interface IdempotencyOptions {
149
149
  * store; supply an explicit `store` to coordinate across processes.
150
150
  */
151
151
  groupId?: string;
152
+ /**
153
+ * Namespace idempotency keys by the calling principal so one client can
154
+ * never replay another client's stored response by reusing the same key
155
+ * (CWE-524 — cross-tenant cached-response disclosure). The returned string
156
+ * is mixed into the store key, so two principals using the *same*
157
+ * `Idempotency-Key` get independent reservations.
158
+ *
159
+ * Defaults to the request's `Authorization` header value, which scopes the
160
+ * common bearer- / API-key-authenticated case (Stripe-style idempotency)
161
+ * out of the box. Override it when identity lives elsewhere, e.g.
162
+ * `scope: (ctx) => ctx.state.session?.id` for cookie-based sessions, or
163
+ * return `undefined` to opt a request out of scoping (e.g. truly public,
164
+ * unauthenticated idempotent writes). Returning a stable per-user id is
165
+ * preferable to the raw credential when tokens rotate between retries.
166
+ *
167
+ * @since 0.40.0
168
+ */
169
+ scope?: (ctx: BaseContext<any, any>) => string | undefined | Promise<string | undefined>;
152
170
  }
153
171
  /**
154
172
  * In-memory {@link IdempotencyStore}. Suitable for tests and single-process
@@ -157,10 +175,14 @@ export interface IdempotencyOptions {
157
175
  */
158
176
  export declare class MemoryIdempotencyStore implements IdempotencyStore {
159
177
  private readonly map;
178
+ /**
179
+ * @inheritDoc
180
+ * `_ttlMs` is part of the {@link IdempotencyStore} contract but unused here:
181
+ * the in-memory store derives expiry from `record.expiresAt`.
182
+ */
183
+ reserve(key: string, record: IdempotencyRecord, _ttlMs?: number): IdempotencyRecord | null;
160
184
  /** @inheritDoc */
161
- reserve(key: string, record: IdempotencyRecord): IdempotencyRecord | null;
162
- /** @inheritDoc */
163
- complete(key: string, record: IdempotencyRecord): void;
185
+ complete(key: string, record: IdempotencyRecord, _ttlMs?: number): void;
164
186
  /** @inheritDoc */
165
187
  release(key: string): void;
166
188
  private read;
@@ -61,8 +61,12 @@ export function _resetSharedIdempotencyStoresForTests() {
61
61
  */
62
62
  export class MemoryIdempotencyStore {
63
63
  map = new Map();
64
- /** @inheritDoc */
65
- reserve(key, record) {
64
+ /**
65
+ * @inheritDoc
66
+ * `_ttlMs` is part of the {@link IdempotencyStore} contract but unused here:
67
+ * the in-memory store derives expiry from `record.expiresAt`.
68
+ */
69
+ reserve(key, record, _ttlMs) {
66
70
  const existing = this.read(key);
67
71
  if (existing)
68
72
  return existing;
@@ -72,7 +76,7 @@ export class MemoryIdempotencyStore {
72
76
  return null;
73
77
  }
74
78
  /** @inheritDoc */
75
- complete(key, record) {
79
+ complete(key, record, _ttlMs) {
76
80
  this.map.set(key, record);
77
81
  }
78
82
  /** @inheritDoc */
@@ -154,7 +158,16 @@ function stableStringify(value) {
154
158
  async function computeFingerprint(method, ctx) {
155
159
  const url = new URL(ctx.request.url);
156
160
  const material = `${method}\n${url.pathname}${url.search}\n${stableStringify(ctx.body)}`;
157
- const digest = new Uint8Array(await getSubtle().digest("SHA-256", enc.encode(material)));
161
+ return sha256Hex(material);
162
+ }
163
+ /**
164
+ * SHA-256 hex of an arbitrary string. Used to fingerprint requests and to
165
+ * derive a fixed-length, delimiter-safe tag for the caller-scope namespace so
166
+ * a long or attacker-controlled `Authorization` value cannot inject into or
167
+ * bloat the store key.
168
+ */
169
+ async function sha256Hex(input) {
170
+ const digest = new Uint8Array(await getSubtle().digest("SHA-256", enc.encode(input)));
158
171
  return bytesToHex(digest);
159
172
  }
160
173
  // Printable ASCII only (no control chars / whitespace). Anchored + bounded to
@@ -271,7 +284,14 @@ export function idempotency(opts = {}) {
271
284
  const key = rawKey.trim();
272
285
  validateKey(key, headerName, maxKeyLength);
273
286
  const fingerprint = await computeFingerprint(method, ctx);
274
- const storeKey = `${keyPrefix}${key}`;
287
+ // Namespace the key by the calling principal so client B can never
288
+ // replay client A's stored response by reusing the same Idempotency-Key
289
+ // (CWE-524). Defaults to the Authorization header; `scope` overrides.
290
+ const scopeRaw = opts.scope
291
+ ? await opts.scope(ctx)
292
+ : (ctx.request.headers.get("authorization") ?? undefined);
293
+ const scopeTag = scopeRaw ? `${await sha256Hex(scopeRaw)}:` : "";
294
+ const storeKey = `${keyPrefix}${scopeTag}${key}`;
275
295
  const now = Date.now();
276
296
  const record = {
277
297
  fingerprint,
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  export { App } from "./app.js";
2
2
  export { createApp } from "./app.js";
3
+ export { findRoutesMissingResponseBodySchema } from "./app.js";
3
4
  export { _resetPackageJsonCacheForTests } from "./app.js";
4
5
  export { _resetCrashHandlersForTests } from "./app.js";
5
6
  export { _resetInsecureDefaultsLogForTests } from "./app.js";
6
- export type { AppOptions, AppOpenAPIOptions, DocsRouteOptions, HealthRouteOptions, CspReportRouteOptions, MetricsRouteOptions, IntrospectedRoute, PluginInstalledEvent, PluginExtension, ShutdownEvent, SecurityPreset, } from "./app.js";
7
+ export type { AppOptions, AppOpenAPIOptions, DocsRouteOptions, AsyncAPIRouteOptions, HealthRouteOptions, CspReportRouteOptions, MetricsRouteOptions, IntrospectedRoute, PluginInstalledEvent, PluginExtension, ShutdownEvent, SecurityPreset, } from "./app.js";
7
8
  export { getConnInfo, setConnInfo, assertBehindProxy, resolveClientIp, readRemoteAddress, readRemotePort, pickForwardedForByHops, } from "./conn-info.js";
8
9
  export type { BehindProxyConfig, ConnInfo } from "./conn-info.js";
9
10
  export { subdomains, PSL_SNAPSHOT_DATE, PSL_PUBLIC_SUFFIXES, MAX_SNAPSHOT_AGE_DAYS, } from "./subdomains.js";
@@ -72,7 +73,7 @@ export type { RequestIdOptions, SecureHeadersOptions, CspDirectivesOptions, Cors
72
73
  export type { BearerAuthOptions, BearerAuthVerifyHook } from "./middleware.js";
73
74
  export { createLogger, noopLogger, DEFAULT_REDACT_KEYS } from "./logger.js";
74
75
  export type { Logger, LogLevel, ConsoleLoggerOptions, LoggerRedactionOptions, } from "./logger.js";
75
- export type { ScalarJsonPrimitive, ScalarJsonValue, ScalarReferenceConfiguration, ScalarTheme, RedocConfiguration, RedocHtmlOptions, DocsAssetOptions, } from "./docs.js";
76
+ export type { ScalarJsonPrimitive, ScalarJsonValue, ScalarReferenceConfiguration, ScalarTheme, RedocConfiguration, RedocHtmlOptions, AsyncApiHtmlOptions, DocsAssetOptions, } from "./docs.js";
76
77
  export { formatStartupBanner, printStartupBanner } from "./banner.js";
77
78
  export type { StartupBannerLink, StartupBannerOptions } from "./banner.js";
78
79
  export { sseStream, sseResponse, ndjsonStream, ndjsonResponse, } from "./streaming.js";
@@ -95,5 +96,7 @@ export { fileField, multipartObject, isFileFieldSchema, isMultipartObjectSchema,
95
96
  export type { FileFieldSchema, FileFieldOptions, FileMagicBytesOption, FileMagicBytesSignature, MultipartObjectOptions, MultipartShape, UploadedFile, } from "./multipart.js";
96
97
  export { otelTracing, TRACING_SPAN_KIND_SERVER, TRACING_SPAN_STATUS_UNSET, TRACING_SPAN_STATUS_OK, TRACING_SPAN_STATUS_ERROR, } from "./tracing.js";
97
98
  export type { OtelTracingOptions, TracingAttributes, TracingAttributeValue, TracingSpan, TracingStartSpanOptions, TracingTracer, } from "./tracing.js";
99
+ export { tenancy, tenantScope, tenantFromSubdomain, tenantFromHeader, tenantFromPathPrefix, tenantFromClaim, defaultTenantNormalize, } from "./tenancy.js";
100
+ export type { TenancyOptions, TenantResolver, TenantScopeOptions, SubdomainTenantOptions, PathPrefixTenantOptions, ClaimTenantOptions, UnresolvedStatus, InvalidStatus, } from "./tenancy.js";
98
101
  export { defineWebSocket, WebSocketRegistry, WebSocketProtocolError, WebSocketPayloadTooLargeError, WS_GUID, WS_READY_STATE, WS_OPCODE, WS_CLOSE_CODE, WS_MAX_CONTROL_PAYLOAD, DEFAULT_WS_BACKPRESSURE_LIMIT, DEFAULT_WS_MAX_PAYLOAD_LENGTH, DEFAULT_WS_IDLE_TIMEOUT_SECONDS, computeAcceptKey, parseSubprotocols, validateSelectedSubprotocol, validateUpgrade, checkWebSocketOrigin, parseFrame, encodeFrame, encodeClosePayload, decodeClosePayload, encodeSendPayload, normalizeWebSocketOptions, wsRateLimit, FrameSink, FRAME_INCOMPLETE, } from "./websocket.js";
99
102
  export type { WebSocketConnection, WebSocketContext, WebSocketHandler, WebSocketMeta, WebSocketRouteEntry, NormalizedWebSocketOptions, WebSocketBeforeUpgrade, HandshakeResult, ParsedFrame, MessageEvent as WebSocketMessageEvent, FrameSinkEvents, } from "./websocket.js";
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { App } from "./app.js";
2
2
  export { createApp } from "./app.js";
3
+ export { findRoutesMissingResponseBodySchema } from "./app.js";
3
4
  export { _resetPackageJsonCacheForTests } from "./app.js";
4
5
  export { _resetCrashHandlersForTests } from "./app.js";
5
6
  export { _resetInsecureDefaultsLogForTests } from "./app.js";
@@ -47,4 +48,5 @@ export { encodeCursor, decodeCursor, buildLinkHeader, buildPageLinks, pagination
47
48
  export { MetricsRegistry, Counter, Gauge, Histogram, httpMetrics, DEFAULT_DURATION_BUCKETS, PROMETHEUS_CONTENT_TYPE, } from "./metrics.js";
48
49
  export { fileField, multipartObject, isFileFieldSchema, isMultipartObjectSchema, } from "./multipart.js";
49
50
  export { otelTracing, TRACING_SPAN_KIND_SERVER, TRACING_SPAN_STATUS_UNSET, TRACING_SPAN_STATUS_OK, TRACING_SPAN_STATUS_ERROR, } from "./tracing.js";
51
+ export { tenancy, tenantScope, tenantFromSubdomain, tenantFromHeader, tenantFromPathPrefix, tenantFromClaim, defaultTenantNormalize, } from "./tenancy.js";
50
52
  export { defineWebSocket, WebSocketRegistry, WebSocketProtocolError, WebSocketPayloadTooLargeError, WS_GUID, WS_READY_STATE, WS_OPCODE, WS_CLOSE_CODE, WS_MAX_CONTROL_PAYLOAD, DEFAULT_WS_BACKPRESSURE_LIMIT, DEFAULT_WS_MAX_PAYLOAD_LENGTH, DEFAULT_WS_IDLE_TIMEOUT_SECONDS, computeAcceptKey, parseSubprotocols, validateSelectedSubprotocol, validateUpgrade, checkWebSocketOrigin, parseFrame, encodeFrame, encodeClosePayload, decodeClosePayload, encodeSendPayload, normalizeWebSocketOptions, wsRateLimit, FrameSink, FRAME_INCOMPLETE, } from "./websocket.js";
@@ -141,6 +141,26 @@ export interface ResponseCacheOptions {
141
141
  * store.
142
142
  */
143
143
  groupId?: string;
144
+ /**
145
+ * Whether to cache responses to requests that carry an `Authorization`
146
+ * header. Default: `false`.
147
+ *
148
+ * A shared response cache keyed on method + URL (the default) does not
149
+ * include the credential, so caching an authenticated response would serve
150
+ * one user's private data to the next user requesting the same URL
151
+ * (CWE-524 — cross-tenant cached-response disclosure). For that reason, and
152
+ * per RFC 9111 §3.5 (a shared cache MUST NOT reuse a response to an
153
+ * `Authorization`-bearing request unless explicitly permitted), such
154
+ * requests bypass the cache entirely by default.
155
+ *
156
+ * Set this to `true` only when the response is genuinely shareable across
157
+ * principals (e.g. public reference data served behind a bearer gate) — and
158
+ * then also add the credential to {@link varyHeaders} or a custom
159
+ * {@link keyGenerator} so distinct callers cannot collide.
160
+ *
161
+ * @since 0.40.0
162
+ */
163
+ cacheAuthenticatedRequests?: boolean;
144
164
  }
145
165
  /**
146
166
  * In-memory {@link ResponseCacheStore}. Suitable for tests and single-process
@@ -151,8 +171,12 @@ export declare class MemoryResponseCacheStore implements ResponseCacheStore {
151
171
  private readonly map;
152
172
  /** @inheritDoc */
153
173
  get(key: string): CachedResponse | null;
154
- /** @inheritDoc */
155
- set(key: string, entry: CachedResponse): void;
174
+ /**
175
+ * @inheritDoc
176
+ * `_ttlMs` is part of the {@link ResponseCacheStore} contract but unused
177
+ * here: the in-memory store derives freshness from `entry.freshUntil`.
178
+ */
179
+ set(key: string, entry: CachedResponse, _ttlMs?: number): void;
156
180
  /** @inheritDoc */
157
181
  delete(key: string): void;
158
182
  private prune;
@@ -76,8 +76,12 @@ export class MemoryResponseCacheStore {
76
76
  }
77
77
  return entry;
78
78
  }
79
- /** @inheritDoc */
80
- set(key, entry) {
79
+ /**
80
+ * @inheritDoc
81
+ * `_ttlMs` is part of the {@link ResponseCacheStore} contract but unused
82
+ * here: the in-memory store derives freshness from `entry.freshUntil`.
83
+ */
84
+ set(key, entry, _ttlMs) {
81
85
  this.map.set(key, entry);
82
86
  if (this.map.size > 10_000)
83
87
  this.prune();
@@ -245,6 +249,7 @@ export function responseCache(opts = {}) {
245
249
  throw new Error("responseCache(): maxBodyBytes must be a positive integer.");
246
250
  }
247
251
  const methods = new Set((opts.methods ?? ["GET", "HEAD"]).map((m) => m.toUpperCase()));
252
+ const cacheAuthenticatedRequests = opts.cacheAuthenticatedRequests === true;
248
253
  const cacheableStatus = opts.cacheableStatus ?? ((status) => status === 200);
249
254
  const varyHeaders = (opts.varyHeaders ?? []).map((h) => h.toLowerCase());
250
255
  const statusHeaderName = opts.statusHeaderName === null ? null : (opts.statusHeaderName ?? "x-cache").toLowerCase();
@@ -289,6 +294,13 @@ export function responseCache(opts = {}) {
289
294
  const method = ctx.request.method.toUpperCase();
290
295
  if (!methods.has(method))
291
296
  return undefined;
297
+ // RFC 9111 §3.5 / CWE-524: a shared cache keyed on method+URL must not
298
+ // store or reuse a response to an Authorization-bearing request, or it
299
+ // would serve one principal's private data to the next caller. Opt in
300
+ // via `cacheAuthenticatedRequests` for genuinely shareable content.
301
+ if (!cacheAuthenticatedRequests && ctx.request.headers.has("authorization")) {
302
+ return undefined;
303
+ }
292
304
  const reqCc = parseCacheControl(ctx.request.headers.get("cache-control"));
293
305
  if (reqCc.has("no-store"))
294
306
  return undefined;
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.5",
4
- "serialNumber": "urn:uuid:67351bdb-989b-5f0b-81f1-020a4c493489",
4
+ "serialNumber": "urn:uuid:c3e0bc4b-403c-5789-b2e4-dbafa73b03ee",
5
5
  "version": 1,
6
6
  "metadata": {
7
- "timestamp": "2026-06-17T18:34:55.006Z",
7
+ "timestamp": "2026-06-19T08:56:49.249Z",
8
8
  "tools": [
9
9
  {
10
10
  "vendor": "DaloyJS",
11
11
  "name": "daloy-generate-sbom",
12
- "version": "0.39.1"
12
+ "version": "0.42.0"
13
13
  }
14
14
  ],
15
15
  "authors": [
@@ -19,11 +19,11 @@
19
19
  ],
20
20
  "component": {
21
21
  "type": "library",
22
- "bom-ref": "pkg:npm/@daloyjs/core@0.39.1",
22
+ "bom-ref": "pkg:npm/@daloyjs/core@0.42.0",
23
23
  "name": "@daloyjs/core",
24
- "version": "0.39.1",
24
+ "version": "0.42.0",
25
25
  "description": "DaloyJS is a runtime-portable, contract-first TypeScript web framework with built-in OpenAPI (Hey API), typed client generation, large-scale maintainability, and security-first defaults. Hono-grade portability, Elysia-grade DX, FastAPI-grade docs, Fastify-grade ops — distributed via pnpm.",
26
- "purl": "pkg:npm/@daloyjs/core@0.39.1",
26
+ "purl": "pkg:npm/@daloyjs/core@0.42.0",
27
27
  "licenses": [
28
28
  {
29
29
  "license": {
@@ -46,9 +46,9 @@
46
46
  }
47
47
  ],
48
48
  "swid": {
49
- "tagId": "swidtag--daloyjs-core-0.39.1",
49
+ "tagId": "swidtag--daloyjs-core-0.42.0",
50
50
  "name": "@daloyjs/core",
51
- "version": "0.39.1",
51
+ "version": "0.42.0",
52
52
  "tagVersion": 0,
53
53
  "patch": false
54
54
  }
@@ -57,7 +57,7 @@
57
57
  "components": [],
58
58
  "dependencies": [
59
59
  {
60
- "ref": "pkg:npm/@daloyjs/core@0.39.1",
60
+ "ref": "pkg:npm/@daloyjs/core@0.42.0",
61
61
  "dependsOn": []
62
62
  }
63
63
  ]
@@ -2,10 +2,10 @@
2
2
  "spdxVersion": "SPDX-2.3",
3
3
  "dataLicense": "CC0-1.0",
4
4
  "SPDXID": "SPDXRef-DOCUMENT",
5
- "name": "@daloyjs/core-0.39.1",
6
- "documentNamespace": "https://github.com/daloyjs/daloy/sbom/@daloyjs/core-0.39.1-67351bdb-989b-5f0b-81f1-020a4c493489",
5
+ "name": "@daloyjs/core-0.42.0",
6
+ "documentNamespace": "https://github.com/daloyjs/daloy/sbom/@daloyjs/core-0.42.0-c3e0bc4b-403c-5789-b2e4-dbafa73b03ee",
7
7
  "creationInfo": {
8
- "created": "2026-06-17T18:34:55.006Z",
8
+ "created": "2026-06-19T08:56:49.249Z",
9
9
  "creators": [
10
10
  "Tool: daloy-generate-sbom",
11
11
  "Organization: DaloyJS"
@@ -16,7 +16,7 @@
16
16
  {
17
17
  "SPDXID": "SPDXRef-Package--daloyjs-core",
18
18
  "name": "@daloyjs/core",
19
- "versionInfo": "0.39.1",
19
+ "versionInfo": "0.42.0",
20
20
  "downloadLocation": "https://github.com/daloyjs/daloy",
21
21
  "filesAnalyzed": false,
22
22
  "licenseConcluded": "MIT",
@@ -27,7 +27,7 @@
27
27
  {
28
28
  "referenceCategory": "PACKAGE-MANAGER",
29
29
  "referenceType": "purl",
30
- "referenceLocator": "pkg:npm/@daloyjs/core@0.39.1"
30
+ "referenceLocator": "pkg:npm/@daloyjs/core@0.42.0"
31
31
  }
32
32
  ]
33
33
  }