@daloyjs/core 1.0.0-beta.3 → 1.0.0-beta.5
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 +49 -46
- package/dist/app.d.ts +42 -21
- package/dist/app.js +167 -116
- package/dist/docs.d.ts +44 -0
- package/dist/docs.js +47 -8
- package/dist/index.d.ts +17 -17
- package/dist/index.js +5 -5
- package/dist/sbom.cdx.json +9 -9
- package/dist/sbom.spdx.json +5 -5
- package/dist/tenancy.d.ts +16 -7
- package/dist/tenancy.js +16 -7
- package/dist/types.d.ts +26 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ Most backend code is now written with AI. Non-developers describe an app and shi
|
|
|
36
36
|
|
|
37
37
|
DaloyJS is built for exactly this moment, from two directions at once:
|
|
38
38
|
|
|
39
|
-
- **A secure-by-default runtime.** Body limits, prototype-pollution-safe JSON, path-traversal rejection, request timeouts, header-injection guards, real `405`s, and RFC 9457 problem+json with prod-mode redaction are on in the constructor — the dangerous things are off when nobody remembered to turn them off. The app also
|
|
39
|
+
- **A secure-by-default runtime.** Body limits, prototype-pollution-safe JSON, path-traversal rejection, request timeouts, header-injection guards, real `405`s, and RFC 9457 problem+json with prod-mode redaction are on in the constructor — the dangerous things are off when nobody remembered to turn them off. The app also _refuses to boot_ on unsafe configuration (wildcard CORS with credentials, weak session secrets, a state-changing session route with no CSRF protection, unconfigured `X-Forwarded-*` in production).
|
|
40
40
|
- **A hardened supply chain.** `@daloyjs/core` ships **zero runtime dependencies**, is published with npm provenance and CycloneDX + SPDX SBOMs, and the pnpm posture (`ignore-scripts`, a 24-hour release-age cooldown, source-verified lockfiles) plus the CI `verify:*` gates shrink the blast radius of the campaigns making headlines.
|
|
41
41
|
|
|
42
42
|
The point is that none of this costs you developer experience or portability: you keep contract-first DX in the league of ts-rest, Elysia, and FastAPI, and Hono-grade portability across Node, Bun, Deno, Workers, Vercel, Fastly, and Lambda. The secure path is simply the path of least resistance. See [Vibe Coding Security: what DaloyJS already blocks](https://daloyjs.dev/blog/vibe-coding-security-what-daloyjs-already-blocks) and the [security docs](https://daloyjs.dev/docs/security).
|
|
@@ -45,19 +45,19 @@ The point is that none of this costs you developer experience or portability: yo
|
|
|
45
45
|
|
|
46
46
|
DaloyJS exists to be the framework you'd build if you took the best ideas from each modern stack:
|
|
47
47
|
|
|
48
|
-
| You want
|
|
49
|
-
|
|
|
50
|
-
| Best **OpenAPI ergonomics** | [FastAPI](https://fastapi.tiangolo.com) | OpenAPI 3.1 from a single route definition; `docs: true` mounts `/docs` and `/openapi.json`.
|
|
51
|
-
| Best **Vercel / serverless / edge fit** | [Hono](https://hono.dev/docs/) | Web-standard `Request → Response` core with adapters for Node, Bun, Deno, Cloudflare, Vercel, Fastly, and Lambda.
|
|
52
|
-
| Mature **Swagger / docs / ops** in Node | [Fastify](https://fastify.dev/docs/latest/Reference/) | Encapsulated plugins, structured logger, graceful shutdown, request ids, and lifecycle hooks — all first-party.
|
|
53
|
-
| Modern **TS-first DX**, Bun acceptable | [Elysia](https://elysiajs.com/at-glance.html) | End-to-end typed handlers, typed context, and a typed in-process client — no codegen step required.
|
|
54
|
-
| Best-in-class **typed client codegen** for any consumer | [Hey API](https://heyapi.dev/openapi-ts/get-started) | One `pnpm gen` command emits a fully-typed fetch SDK from your live OpenAPI spec.
|
|
55
|
-
| **Contract-first typed client, no codegen** | [ts-rest](https://ts-rest.com/) | Your route definition
|
|
56
|
-
| Opinionated **DI / module architecture** for large teams | [NestJS](https://docs.nestjs.com/) | Plugin encapsulation, `register()` prefixes, and `defineDependency()` typed-DI with per-request dedup — no decorators.
|
|
57
|
-
| Minimalist **async middleware cascade** | [Koa](https://koajs.com/) | Koa-style `Context` on a web-standard core, with validation, OpenAPI, errors, and security headers in-box.
|
|
58
|
-
| **Services + real-time** API framework | [FeathersJS](https://feathersjs.com/) | First-party `app.ws()` with CSWSH refuse-to-boot guards, plus SSE / NDJSON streaming over explicit OpenAPI routes.
|
|
59
|
-
| Battle-tested **Node middleware compatibility** | [Express v5](https://expressjs.com/en/blog/2024-10-15-v5-release) | Regex-free trie router, schema-validated routes, RFC 9457 problem+json, and refuse-to-boot guards on every runtime.
|
|
60
|
-
| **Portable supply-chain hardening** for the apps you build | [pnpm](https://pnpm.io/motivation) defaults + a zero-runtime-dep core | Hardened `.npmrc`, source-verified lockfiles, zero runtime deps, CycloneDX + SPDX SBOM, and npm provenance attestations.
|
|
48
|
+
| You want | Today's best-of | What DaloyJS gives you |
|
|
49
|
+
| ---------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| Best **OpenAPI ergonomics** | [FastAPI](https://fastapi.tiangolo.com) | OpenAPI 3.1 from a single route definition; `docs: true` mounts `/docs` and `/openapi.json`. |
|
|
51
|
+
| Best **Vercel / serverless / edge fit** | [Hono](https://hono.dev/docs/) | Web-standard `Request → Response` core with adapters for Node, Bun, Deno, Cloudflare, Vercel, Fastly, and Lambda. |
|
|
52
|
+
| Mature **Swagger / docs / ops** in Node | [Fastify](https://fastify.dev/docs/latest/Reference/) | Encapsulated plugins, structured logger, graceful shutdown, request ids, and lifecycle hooks — all first-party. |
|
|
53
|
+
| Modern **TS-first DX**, Bun acceptable | [Elysia](https://elysiajs.com/at-glance.html) | End-to-end typed handlers, typed context, and a typed in-process client — no codegen step required. |
|
|
54
|
+
| Best-in-class **typed client codegen** for any consumer | [Hey API](https://heyapi.dev/openapi-ts/get-started) | One `pnpm gen` command emits a fully-typed fetch SDK from your live OpenAPI spec. |
|
|
55
|
+
| **Contract-first typed client, no codegen** | [ts-rest](https://ts-rest.com/) | Your route definition _is_ the contract: an in-process typed client with zero codegen, plus OpenAPI 3.1 + a Hey API SDK for consumers that can't import your types. |
|
|
56
|
+
| Opinionated **DI / module architecture** for large teams | [NestJS](https://docs.nestjs.com/) | Plugin encapsulation, `register()` prefixes, and `defineDependency()` typed-DI with per-request dedup — no decorators. |
|
|
57
|
+
| Minimalist **async middleware cascade** | [Koa](https://koajs.com/) | Koa-style `Context` on a web-standard core, with validation, OpenAPI, errors, and security headers in-box. |
|
|
58
|
+
| **Services + real-time** API framework | [FeathersJS](https://feathersjs.com/) | First-party `app.ws()` with CSWSH refuse-to-boot guards, plus SSE / NDJSON streaming and raw `Response` passthrough (return a Vercel AI SDK stream straight from a handler) over explicit OpenAPI routes. |
|
|
59
|
+
| Battle-tested **Node middleware compatibility** | [Express v5](https://expressjs.com/en/blog/2024-10-15-v5-release) | Regex-free trie router, schema-validated routes, RFC 9457 problem+json, and refuse-to-boot guards on every runtime. |
|
|
60
|
+
| **Portable supply-chain hardening** for the apps you build | [pnpm](https://pnpm.io/motivation) defaults + a zero-runtime-dep core | Hardened `.npmrc`, source-verified lockfiles, zero runtime deps, CycloneDX + SPDX SBOM, and npm provenance attestations. |
|
|
61
61
|
|
|
62
62
|
```
|
|
63
63
|
framework test suite passing · ≥90% line + function coverage / ≥90% branch coverage · typechecks on TypeScript 6 with `strict: true`
|
|
@@ -164,13 +164,7 @@ For maintainers, the safe rule is: use one publish path per version. Either publ
|
|
|
164
164
|
|
|
165
165
|
```ts
|
|
166
166
|
import { z } from "zod";
|
|
167
|
-
import {
|
|
168
|
-
App,
|
|
169
|
-
NotFoundError,
|
|
170
|
-
secureHeaders,
|
|
171
|
-
rateLimit,
|
|
172
|
-
requestId,
|
|
173
|
-
} from "@daloyjs/core";
|
|
167
|
+
import { App, NotFoundError, secureHeaders, rateLimit, requestId } from "@daloyjs/core";
|
|
174
168
|
import { serve } from "@daloyjs/core/node";
|
|
175
169
|
|
|
176
170
|
const app = new App({ bodyLimitBytes: 1024 * 1024, requestTimeoutMs: 5_000 });
|
|
@@ -282,6 +276,11 @@ new App({
|
|
|
282
276
|
docExpansion: "none",
|
|
283
277
|
displayRequestDuration: true,
|
|
284
278
|
},
|
|
279
|
+
auth: {
|
|
280
|
+
loginUrl: "/login", // or Auth0 / Entra ID / Okta / Clerk / Better Auth
|
|
281
|
+
label: "Sign in",
|
|
282
|
+
target: "popup",
|
|
283
|
+
},
|
|
285
284
|
tags: ["Docs"],
|
|
286
285
|
},
|
|
287
286
|
});
|
|
@@ -311,6 +310,9 @@ HTML helper. The `swagger` option is forwarded to `SwaggerUIBundle` with Daloy
|
|
|
311
310
|
owning `url` / `dom_id`. Redoc spins up a `blob:` Web Worker for search, so the
|
|
312
311
|
auto-mounted `/docs` page widens its CSP with `worker-src 'self' blob:` for
|
|
313
312
|
`ui: "redoc"` only — Scalar and Swagger UI keep the tighter default.
|
|
313
|
+
Add `docs.auth` when you want all three docs UIs to expose the same visible
|
|
314
|
+
authorization launcher; point it at a local login route or any OAuth2/OIDC
|
|
315
|
+
provider entry point.
|
|
314
316
|
|
|
315
317
|
Prefer to mount manually? Import the helpers directly:
|
|
316
318
|
|
|
@@ -354,26 +356,26 @@ path is used. Others are first-party middleware so applications can choose the
|
|
|
354
356
|
right CORS policy, rate-limit key, CSP, session secret, or CSRF rollout for their
|
|
355
357
|
deployment.
|
|
356
358
|
|
|
357
|
-
| Threat
|
|
358
|
-
|
|
|
359
|
-
| **Body-size DoS**
|
|
360
|
-
| **Prototype pollution**
|
|
361
|
-
| **Header / response splitting**
|
|
362
|
-
| **Path traversal**
|
|
363
|
-
| **Slow-loris / hung handlers**
|
|
364
|
-
| **HTTP/2 Bomb / header-count flood** | Core `maxHeaderCount` rejects requests with more than 100 header fields (`431`) before routing; Node adapter sets `server.maxHeadersCount`. See [SECURITY.md](SECURITY.md) for the upstream HTTP/2 mitigations.
|
|
365
|
-
| **MIME sniffing**
|
|
366
|
-
| **Clickjacking**
|
|
367
|
-
| **XSS via injected scripts**
|
|
368
|
-
| **Cross-origin leakage**
|
|
369
|
-
| **CSRF**
|
|
370
|
-
| **Information disclosure (5xx)**
|
|
371
|
-
| **Credential timing attacks**
|
|
372
|
-
| **Brute-force / scraping**
|
|
373
|
-
| **Method confusion**
|
|
374
|
-
| **CORS misconfig**
|
|
375
|
-
| **Request correlation**
|
|
376
|
-
| **Supply chain (portable)**
|
|
359
|
+
| Threat | Built-in behavior |
|
|
360
|
+
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
361
|
+
| **Body-size DoS** | Core-enforced streamed read with a hard cap (default 1 MiB); `Content-Length` checked first. |
|
|
362
|
+
| **Prototype pollution** | Core JSON parser strips `__proto__` / `constructor` / `prototype` via reviver. |
|
|
363
|
+
| **Header / response splitting** | Core header sanitizers reject CRLF + NUL. |
|
|
364
|
+
| **Path traversal** | Core router rejects `..` segments and `//` before walking. |
|
|
365
|
+
| **Slow-loris / hung handlers** | Core `requestTimeoutMs` aborts handlers (default 30 s); Node adapter sets `requestTimeout` + `headersTimeout` + `maxHeaderSize`. |
|
|
366
|
+
| **HTTP/2 Bomb / header-count flood** | Core `maxHeaderCount` rejects requests with more than 100 header fields (`431`) before routing; Node adapter sets `server.maxHeadersCount`. See [SECURITY.md](SECURITY.md) for the upstream HTTP/2 mitigations. |
|
|
367
|
+
| **MIME sniffing** | First-party `secureHeaders()` sets `X-Content-Type-Options: nosniff`; scaffolded apps enable it. |
|
|
368
|
+
| **Clickjacking** | First-party `secureHeaders()` sets `X-Frame-Options: DENY` + CSP `frame-ancestors 'none'`; scaffolded apps enable it. |
|
|
369
|
+
| **XSS via injected scripts** | First-party `secureHeaders()` provides a strict CSP `default-src 'self'` baseline; the directives-object form supports per-request **nonces** and **Trusted Types** (`require-trusted-types-for 'script'`). |
|
|
370
|
+
| **Cross-origin leakage** | First-party `secureHeaders()` sets `cross-origin-opener-policy` + `cross-origin-resource-policy` to `same-origin`; scaffolded apps enable it. |
|
|
371
|
+
| **CSRF** | First-party `csrf()` ships two strategies: **double-submit cookie** (default) and **Fetch-Metadata** (`Sec-Fetch-Site`-based, tokenless); both with timing-safe verification. |
|
|
372
|
+
| **Information disclosure (5xx)** | Production mode strips `detail` from 5xx problem+json automatically. |
|
|
373
|
+
| **Credential timing attacks** | First-party `timingSafeEqual()` helper for tokens & signatures. |
|
|
374
|
+
| **Brute-force / scraping** | First-party `rateLimit()` with token-bucket + `Retry-After`; Node/Bun/Deno scaffolded apps enable it. |
|
|
375
|
+
| **Method confusion** | Real **405** with `Allow` header, not a misleading 404. |
|
|
376
|
+
| **CORS misconfig** | First-party `cors()` requires an explicit allowlist and throws for `*` with credentials. |
|
|
377
|
+
| **Request correlation** | First-party `requestId()` uses cryptographic ids; scaffolded apps enable it. |
|
|
378
|
+
| **Supply chain (portable)** | pnpm scaffolds keep `ignore-scripts=true`, `minimum-release-age=1440`, verified store, reproducible lockfile, and `pnpm verify:lockfile` source verification; every app also installs a zero-runtime-dependency `@daloyjs/core` published with CycloneDX + SPDX SBOM and npm provenance you can verify on install — regardless of where you host your repo. |
|
|
377
379
|
|
|
378
380
|
**Portable vs. GitHub-only.** The runtime protections and the published `@daloyjs/core` SBOM/provenance travel with every app you scaffold, no matter which CI host you use — GitLab, Bitbucket, Azure DevOps, Jenkins, on-prem, or laptop. The strongest install-time bundle is available when you choose pnpm, because `minimum-release-age`, `blockExoticSubdeps`, and the workspace gates are pnpm features. The **`@daloyjs/core` release pipeline itself** is separately hardened on GitHub Actions — no `pull_request_target`, no Actions cache, top-level `permissions: {}`, `step-security/harden-runner`, a protected `release.yml`, npm trusted publishing with `--provenance`, CodeQL + Opengrep dual SAST, OpenSSF Scorecard, zizmor, Dependabot, and CODEOWNERS — and `create-daloy --with-ci` ships the app-safe parts as an **optional GitHub Actions bundle** for teams on GitHub. See [SECURITY.md](SECURITY.md) and the [supply-chain security docs](https://daloyjs.dev/docs/security/supply-chain).
|
|
379
381
|
|
|
@@ -383,7 +385,7 @@ deployment.
|
|
|
383
385
|
|
|
384
386
|
DaloyJS is a **resource server** (and a toolkit for building a relying party),
|
|
385
387
|
**not** an identity provider. Like Hono, Express, Fastify, or ASP.NET Core, it
|
|
386
|
-
|
|
388
|
+
_verifies_ and _enforces_ tokens on each request — it does **not** ship a login
|
|
387
389
|
UI, a user database, or an OAuth2 authorization server. It is **not** an
|
|
388
390
|
"IdentityServer": it cannot, on its own, do what Duende IdentityServer,
|
|
389
391
|
Keycloak, or Auth0 do (run login pages, manage clients/consent, mint tokens).
|
|
@@ -425,7 +427,7 @@ miss 4,763,878 ops/sec
|
|
|
425
427
|
For deployments where every millisecond of startup matters (Lambda, Vercel, Cloudflare Workers, Fastly Compute), import `App` from the deep entry point instead of the barrel:
|
|
426
428
|
|
|
427
429
|
```ts
|
|
428
|
-
import { App } from "@daloyjs/core/app";
|
|
430
|
+
import { App } from "@daloyjs/core/app"; // ~13 ms faster cold start than "@daloyjs/core"
|
|
429
431
|
import { serve } from "@daloyjs/core/node";
|
|
430
432
|
```
|
|
431
433
|
|
|
@@ -507,14 +509,14 @@ The core only ever sees `Request → Response`. Adapters live at the edge.
|
|
|
507
509
|
|
|
508
510
|
## Status
|
|
509
511
|
|
|
510
|
-
DaloyJS is now in the **`1.0.0` beta** (`1.0.0-beta.
|
|
512
|
+
DaloyJS is now in the **`1.0.0` beta** (`1.0.0-beta.5`). The public API is feature-complete and stable for the 1.0 line; from `1.0.0` onward, breaking changes follow SemVer and deprecations get at least one minor cycle. Small adjustments are still possible before the `1.0.0` GA if beta feedback surfaces something. The framework is already in use for production trials.
|
|
511
513
|
|
|
512
514
|
**Release quality bar.** Every release ships with **≥90% line + function coverage and ≥90% branch coverage**, strict TypeScript, OpenSSF Scorecard, CodeQL + Opengrep dual SAST, zizmor workflow linting, and npm provenance. Coverage was relaxed from a former 100% gate so complex security work isn't blocked chasing throwaway tests for unreachable defensive branches or tsx source-map phantoms; see [AGENTS.md](AGENTS.md) for the policy.
|
|
513
515
|
|
|
514
516
|
### Routing, validation, and docs
|
|
515
517
|
|
|
516
518
|
- Contract-first routing with Standard Schema validation (Zod 4, Valibot, ArkType, TypeBox) and OpenAPI 3.1 generated from a single source of truth.
|
|
517
|
-
- Live OpenAPI 3.1 spec served as both JSON (`GET /openapi.json`) and YAML (`GET /openapi.yaml`) when `docs: true`, with a choice of Scalar (default), Swagger UI, or Redoc via `docs.ui`, plus Scalar theming/custom CSS/auth defaults via `docs.scalar`, Swagger UI options via `docs.swagger` (including persisted Authorize credentials),
|
|
519
|
+
- Live OpenAPI 3.1 spec served as both JSON (`GET /openapi.json`) and YAML (`GET /openapi.yaml`) when `docs: true`, with a choice of Scalar (default), Swagger UI, or Redoc via `docs.ui`, plus Scalar theming/custom CSS/auth defaults via `docs.scalar`, Swagger UI options via `docs.swagger` (including persisted Authorize credentials), Redoc options via `docs.redoc`, and a provider-neutral `docs.auth` launcher for local login routes or third-party OAuth2/OIDC providers.
|
|
518
520
|
- Zero-config OpenAPI `info` autofill from `package.json` (Node / Bun) or `deno.json` / `deno.jsonc` (Deno); explicit `openapi.info` values always win.
|
|
519
521
|
- RFC 7231 + RFC 5789 HTTP-method allowlist enforced inside `app.route()` (WebDAV, `TRACE`, `CONNECT` rejected at the framework boundary).
|
|
520
522
|
- AI-friendly route metadata via optional `meta: { examples, extensions, summary, description, tags }`; examples are validated against your schemas at build time, surfaced as OpenAPI `examples` + `x-daloy-*` extensions, and dumped as `routes.json` / `routes.yaml` via `daloy inspect --ai`.
|
|
@@ -608,6 +610,7 @@ The framework refuses to start (or to construct) when configuration is unsafe:
|
|
|
608
610
|
- an Origin policy (`allowedOrigins: "same-origin"` / `string[]` / predicate) or `acknowledgeCrossOriginUpgrade: true`.
|
|
609
611
|
|
|
610
612
|
This closes the Cross-Site WebSocket Hijacking (CSWSH) class of bug — Storybook's [CVE-2026-27148](https://www.aikido.dev/blog/storybooks-websockets-attack) is the representative case: cookie auth alone does not stop a malicious site from opening an authenticated WS handshake from a victim's browser. The Origin check runs **before** `beforeUpgrade` in both adapters.
|
|
613
|
+
|
|
611
614
|
- Contract-first **AsyncAPI 3.0** generation for `app.ws()` surfaces via `@daloyjs/core/asyncapi` (`generateAsyncAPI()` / `asyncapiToYAML()`) and `daloy inspect --asyncapi`. Each route becomes a channel (address + path params) with a `receive` operation for inbound client messages and an optional `send` operation for outbound messages, described via an optional handler `meta` block (`summary` / `description` / `tags` / `send` / `receive` / `operationId`). Set `asyncapi: true` (mirroring `docs: true`) to **auto-mount an interactive AsyncAPI UI** at `/asyncapi` plus `/asyncapi.json` + `/asyncapi.yaml` — the WebSocket counterpart to the Scalar / Swagger / Redoc OpenAPI viewers, served from a CDN with the same SRI + strict-CSP hardening.
|
|
612
615
|
|
|
613
616
|
### Lifecycle and ops
|
|
@@ -663,7 +666,7 @@ DaloyJS is **public and MIT-licensed, but contributions-closed**. Pull requests
|
|
|
663
666
|
from accounts that are not invited maintainers or explicit repository
|
|
664
667
|
collaborators are closed automatically. Bug reports, feature requests, and
|
|
665
668
|
security disclosures are very welcome; see [CONTRIBUTING.md](./CONTRIBUTING.md)
|
|
666
|
-
and [SECURITY.md](./SECURITY.md) for the channels that
|
|
669
|
+
and [SECURITY.md](./SECURITY.md) for the channels that _are_ open.
|
|
667
670
|
|
|
668
671
|
## License
|
|
669
672
|
|
package/dist/app.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { WebSocketRegistry, type WebSocketHandler } from "./websocket.js";
|
|
|
2
2
|
import { type Logger } from "./logger.js";
|
|
3
3
|
import type { HttpMethod, Hooks, PathString, RequestSchemas, ResponsesMap, RouteDefinition } from "./types.js";
|
|
4
4
|
import { type OpenAPIInfo, type OpenAPIOptions } from "./openapi.js";
|
|
5
|
-
import { type DocsAssetOptions, type DocsContentSecurityPolicyOptions, type RedocConfiguration, type ScalarJsonValue, type ScalarReferenceConfiguration, type SwaggerUiConfiguration } from "./docs.js";
|
|
5
|
+
import { type DocsAssetOptions, type DocsAuthLauncherOptions, type DocsContentSecurityPolicyOptions, type RedocConfiguration, type ScalarJsonValue, type ScalarReferenceConfiguration, type SwaggerUiConfiguration } from "./docs.js";
|
|
6
6
|
import { type AsyncAPIServer } from "./asyncapi.js";
|
|
7
7
|
import { type SecureHeadersOptions } from "./middleware.js";
|
|
8
8
|
import { type LoadSheddingOptions } from "./load-shedding.js";
|
|
@@ -130,8 +130,8 @@ export interface AppOptions {
|
|
|
130
130
|
/**
|
|
131
131
|
* Master switch for the secure-by-default surface (auto-applied
|
|
132
132
|
* {@link secureHeaders}, cross-origin guard for state-changing requests
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
* when no {@link cors} hook allows the request origin). Defaults to `true`
|
|
134
|
+
* in `@daloyjs/core@0.16.0` and later. Per-feature opt-outs
|
|
135
135
|
* (`secureHeaders: false`, `corsCrossOriginGuard: false`) remain available
|
|
136
136
|
* when this is left on. Pass `false` to restore the pre-0.16 behavior
|
|
137
137
|
* wholesale.
|
|
@@ -168,13 +168,13 @@ export interface AppOptions {
|
|
|
168
168
|
secureHeaders?: SecureHeadersOptions | false;
|
|
169
169
|
/**
|
|
170
170
|
* Reject state-changing requests (`POST`, `PUT`, `PATCH`, `DELETE`) that
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
171
|
+
* carry a cross-origin `Origin` header when no {@link cors} hook in the
|
|
172
|
+
* matched route's hook chain allows that origin. Active when
|
|
173
|
+
* {@link AppOptions.secureDefaults} is not `false`. Returns
|
|
174
|
+
* `403 application/problem+json` so the rejection is loud at the network
|
|
175
|
+
* boundary instead of silently allowing a CSRF / SSRF surface. Set to
|
|
176
|
+
* `false` if you intentionally serve a cross-origin API without `cors()`
|
|
177
|
+
* (rare; almost always a misconfiguration).
|
|
178
178
|
*
|
|
179
179
|
* @since 0.16.0
|
|
180
180
|
*/
|
|
@@ -312,8 +312,8 @@ export interface AppOptions {
|
|
|
312
312
|
* is a "secure by default" choice: production deployments should opt in
|
|
313
313
|
* explicitly so internal APIs do not accidentally publish a browsable
|
|
314
314
|
* schema.
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
* - object — full configuration (custom paths, UI choice, title, per-UI
|
|
316
|
+
* config, CSP overrides). The `enabled` field on the object can override the
|
|
317
317
|
* auto/prod rule.
|
|
318
318
|
*
|
|
319
319
|
* The default is `false` so adding a new `App({ ... })` to an existing app
|
|
@@ -402,6 +402,19 @@ export interface DocsRouteOptions {
|
|
|
402
402
|
* @since 0.39.0
|
|
403
403
|
*/
|
|
404
404
|
redoc?: RedocConfiguration;
|
|
405
|
+
/**
|
|
406
|
+
* Optional authorization launcher rendered into the docs page. Use it to
|
|
407
|
+
* make Scalar, Swagger UI, and Redoc expose a consistent button that opens
|
|
408
|
+
* a local login form or a third-party identity provider such as Entra ID,
|
|
409
|
+
* Auth0, Better Auth, Clerk, Okta, Keycloak, or any OAuth2/OIDC provider.
|
|
410
|
+
*
|
|
411
|
+
* The button only starts the login/provider flow; API calls are still
|
|
412
|
+
* authorized by the OpenAPI security scheme and the credentials entered or
|
|
413
|
+
* stored by the selected docs UI.
|
|
414
|
+
*
|
|
415
|
+
* @since 0.43.0
|
|
416
|
+
*/
|
|
417
|
+
auth?: DocsAuthLauncherOptions;
|
|
405
418
|
/** Page `<title>`. Defaults to the resolved OpenAPI `info.title`. */
|
|
406
419
|
title?: string;
|
|
407
420
|
/**
|
|
@@ -848,10 +861,10 @@ export declare class App<Routes extends readonly RouteDefinition<any, any, any,
|
|
|
848
861
|
private inflight;
|
|
849
862
|
private draining;
|
|
850
863
|
/**
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
864
|
+
* CORS origin allowlist predicates from the currently active group-level
|
|
865
|
+
* hooks. Used for unmatched routes; matched routes use the snapshot stored
|
|
866
|
+
* on their compiled route so later `app.use(cors(...))` calls do not
|
|
867
|
+
* retroactively loosen earlier routes.
|
|
855
868
|
*/
|
|
856
869
|
private corsOriginAllows;
|
|
857
870
|
/**
|
|
@@ -877,14 +890,22 @@ export declare class App<Routes extends readonly RouteDefinition<any, any, any,
|
|
|
877
890
|
*/
|
|
878
891
|
private responseBodySchemaAuditDone;
|
|
879
892
|
/**
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
893
|
+
* Cached merge of `options.hooks` only. Used on the cold 404/405 path
|
|
894
|
+
* and as the baseline for cross-origin guard decisions when no route
|
|
895
|
+
* matches.
|
|
883
896
|
*/
|
|
884
897
|
private _globalHooksCache;
|
|
885
898
|
private _globalCorsAllowsCache;
|
|
886
899
|
private get globalHooks();
|
|
887
900
|
private get globalCorsAllows();
|
|
901
|
+
/**
|
|
902
|
+
* Cached merge of `options.hooks` plus every `app.use()` group hook, used on
|
|
903
|
+
* the cold dispatch path (404, 405, and OPTIONS preflight) so perimeter
|
|
904
|
+
* `beforeHandle` guards registered via `app.use()` still cover requests that
|
|
905
|
+
* match no route.
|
|
906
|
+
*/
|
|
907
|
+
private _coldPathHooksCache;
|
|
908
|
+
private get coldPathHooks();
|
|
888
909
|
constructor(options?: AppOptions);
|
|
889
910
|
/**
|
|
890
911
|
* Validate {@link AppOptions.disconnectStatusCode}.
|
|
@@ -1238,8 +1259,8 @@ export declare class App<Routes extends readonly RouteDefinition<any, any, any,
|
|
|
1238
1259
|
* when omitted). Returns `204 No Content` so browsers stop retrying.
|
|
1239
1260
|
*
|
|
1240
1261
|
* Combine with `secureHeaders({ reportingEndpoints, reportTo })` to wire
|
|
1241
|
-
|
|
1242
|
-
|
|
1262
|
+
* the browser to this endpoint. The route is registered as publicly
|
|
1263
|
+
* reachable; that is required for the browser
|
|
1243
1264
|
* Reporting API to send to it.
|
|
1244
1265
|
*
|
|
1245
1266
|
*/
|