@tetsujs/openapi 0.6.1 → 0.6.3
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 +8 -1
- package/dist/index-f49v8ege.js +28 -0
- package/dist/index-f49v8ege.js.map +10 -0
- package/dist/src/annotations.d.ts +97 -15
- package/dist/src/annotations.d.ts.map +1 -1
- package/dist/src/envelopes.d.ts +10 -8
- package/dist/src/envelopes.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +151 -47
- package/dist/src/index.js.map +6 -6
- package/dist/src/media.d.ts +30 -0
- package/dist/src/media.d.ts.map +1 -0
- package/dist/src/operation.d.ts +5 -2
- package/dist/src/operation.d.ts.map +1 -1
- package/dist/src/testing.d.ts.map +1 -1
- package/dist/src/testing.js +23 -7
- package/dist/src/testing.js.map +3 -3
- package/package.json +3 -3
- package/src/annotations.ts +154 -25
- package/src/envelopes.ts +10 -8
- package/src/index.ts +17 -6
- package/src/media.ts +57 -0
- package/src/operation.ts +249 -71
- package/src/testing.ts +48 -9
package/dist/src/index.js.map
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/annotations.ts", "../src/components.ts", "../src/envelopes.ts", "../src/errors.ts", "../src/operation.ts", "../src/emit.ts", "../src/parameters.ts", "../src/refs.ts", "../src/controller.ts", "../src/page.ts", "../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * What hooks contribute to the documentation.\n *\n * What a route is protected by, or answers with when a guard refuses, is\n * not in its config: a hook is a function in a slot, and the route that\n * mounts it says nothing about tokens or rate limits. The contribution is\n * therefore annotated onto the hook — from this package, not from\n * `hook.*` — so the core keeps knowing nothing about OpenAPI and the\n * factories stay free of documentation options.\n *\n * A hook annotated once is documented everywhere it runs: application and\n * group chains are merged into every route's chains at startup, so a guard\n * mounted on a zone documents the zone's operations without repeating\n * itself.\n *\n * @module\n */\n\nimport type { AnyHook, AnySchema } from \"@tetsujs/core\";\nimport type { JsonSchema } from \"./json-schema.ts\";\n\n/**\n * The definition of a scheme, as OpenAPI spells it.\n *\n * Typed as loosely as the spec is wide — `http`, `apiKey`, `oauth2`,\n * `openIdConnect` and `mutualTLS` carry different fields, and narrowing\n * them here would be a second, poorer copy of the specification.\n */\nexport interface SecurityScheme {\n readonly type: \"http\" | \"apiKey\" | \"oauth2\" | \"openIdConnect\" | \"mutualTLS\";\n readonly [key: string]: unknown;\n}\n\n/** What a hook demands of a request, and what it answers when refused. */\nexport interface SecurityRequirement {\n /** The name the scheme is registered under in `components`. */\n readonly name: string;\n\n /** The scheme itself, registered once per name. */\n readonly scheme: SecurityScheme;\n\n /** OAuth2 scopes; empty for every other type. */\n readonly scopes?: readonly string[];\n\n /** The status an unauthenticated request gets. Defaults to `401`. */\n readonly status?: number;\n\n /** How the refusal is described in the document. */\n readonly description?: string;\n\n /**\n * The `error` code the refusal carries, when the guard answers with the\n * framework's envelope — `\"UNAUTHORIZED\"`, `\"SESSION_EXPIRED\"`.\n *\n * Documented as a `const` for the same reason as on a\n * {@link DocumentedResponse}: only the guard knows its own code.\n */\n readonly error?: string;\n\n /** An example of the refusal's `message`, for the same reason. */\n readonly message?: string;\n}\n\n/**\n * One response a hook can produce, which the route's own schema knows\n * nothing about — a rate limiter's `429`, a guard's `401`.\n */\nexport interface DocumentedResponse {\n readonly status: number;\n readonly description: string;\n\n /** The body, when the hook answers with one. */\n readonly schema?: AnySchema;\n\n /**\n * The `error` code of the failure envelope, when the hook answers with\n * the framework's shape — `\"RATE_LIMITED\"`, `\"SESSION_EXPIRED\"`.\n *\n * Documented as a `const`, so a client can discriminate on it. Only the\n * hook knows its own code; without one the document says the field is a\n * string and no more.\n */\n readonly error?: string;\n\n /** An example of the envelope's `message`, for the same reason. */\n readonly message?: string;\n\n /**\n * Fields the hook adds to the envelope, as JSON Schema by name — the\n * `retryAfter` of `{ ...errorBody(429, \"RATE_LIMITED\"), retryAfter }`.\n *\n * Each is documented as always present. The envelope's own `status`,\n * `message` and `error` are not redefined by a field of the same name:\n * `error` is what a client discriminates on, and it stays the code the\n * hook declared. Ignored when the response has a `schema`, which says\n * everything about the body itself.\n *\n * @example\n * ```ts\n * documented(limiter, {\n * responses: [\n * {\n * status: 429,\n * description: \"Too many requests\",\n * error: \"RATE_LIMITED\",\n * fields: { retryAfter: { type: \"integer\", minimum: 0 } },\n * },\n * ],\n * });\n * ```\n */\n readonly fields?: Readonly<Record<string, JsonSchema>>;\n\n /**\n * Headers the hook sets on this response, by name — the `retry-after`\n * of a refusal.\n *\n * Documented as possible rather than required: a status several sources\n * answer with is one response in the document, and a header one of them\n * sets is not on the others'.\n */\n readonly headers?: Readonly<Record<string, DocumentedHeader>>;\n}\n\n/** A header a hook's response carries. */\nexport interface DocumentedHeader {\n readonly description?: string;\n readonly schema: JsonSchema;\n}\n\n/**\n * Requirements of which a hook accepts any one: a session cookie *or* a\n * bearer token, checked by one hook.\n *\n * \"Either\" lives inside a hook, never between hooks — every hook of a\n * route runs, so the schemes of two hooks are both required. A hook that\n * takes either of two credentials says so here, and the document lists\n * the combinations a client may bring.\n */\nexport interface SecurityAlternatives {\n readonly anyOf: readonly SecurityRequirement[];\n}\n\n/** Everything a hook tells the generator about itself. */\nexport interface HookDocs {\n /**\n * What the hook demands of a request: one requirement, or alternatives\n * of which any one will do.\n */\n readonly security?: SecurityRequirement | SecurityAlternatives;\n\n /** What the hook can answer with. */\n readonly responses?: readonly DocumentedResponse[];\n}\n\nconst docsKey = \"~tetsu/hook-docs\";\n\n/**\n * Annotates a hook with what it contributes to the documentation.\n *\n * Returns a copy: what the caller exports is what carries the annotation,\n * and a hook used elsewhere is not changed behind its author's back. The\n * type is preserved exactly, so an annotated hook goes into a stack like\n * any other.\n *\n * @example\n * ```ts\n * export const limiter = documented(hook.beforeParse(check), {\n * responses: [\n * { status: 429, description: \"Rate limit exceeded\", schema: TooMany },\n * ],\n * });\n * ```\n */\nexport function documented<H extends AnyHook>(hook: H, docs: HookDocs): H {\n const annotated = { ...hook };\n\n Object.defineProperty(annotated, docsKey, {\n enumerable: false,\n value: { ...docsOf(hook), ...docs },\n });\n\n return annotated as H;\n}\n\n/**\n * Annotates a hook with the security it enforces — {@link documented} for\n * the case that comes up most.\n *\n * One requirement, or `{ anyOf: [...] }` for a hook that accepts any one\n * of several: the schemes of different hooks are all required, the\n * alternatives of one hook are not.\n *\n * @example\n * ```ts\n * export const auth = secured(\n * hook.beforeParse((ctx) => {\n * const user = verify(ctx.req.headers.get(\"authorization\"));\n * if (!user) throw new HttpError(401);\n * return { user };\n * }),\n * {\n * name: \"bearerAuth\",\n * scheme: { type: \"http\", scheme: \"bearer\", bearerFormat: \"JWT\" },\n * },\n * );\n * ```\n *\n * @example A hook that accepts a session cookie or a bearer token\n * ```ts\n * export const caller = secured(\n * hook.beforeParse((ctx) => {\n * const user = sessions.fromCookie(ctx) ?? tokens.fromHeader(ctx);\n * if (!user) throw new HttpError(401);\n * return { user };\n * }),\n * { anyOf: [cookieSession, bearerToken] },\n * );\n * ```\n */\nexport function secured<H extends AnyHook>(\n hook: H,\n requirement: SecurityRequirement | SecurityAlternatives,\n): H {\n return documented(hook, { security: requirement });\n}\n\n/** Reads everything a hook was annotated with. */\nexport function docsOf(hook: AnyHook): HookDocs | undefined {\n return (hook as unknown as Record<string, HookDocs | undefined>)[docsKey];\n}\n\n/** Reads the security a hook was annotated with, if it was. */\nexport function securityOf(\n hook: AnyHook,\n): SecurityRequirement | SecurityAlternatives | undefined {\n return docsOf(hook)?.security;\n}\n\n/** What the hooks of one route contribute, in execution order. */\nexport interface HookContributions {\n /**\n * Every scheme the hooks mention, once per name, with the scopes of all\n * of them: what the document registers, and what a refusal answers with.\n */\n readonly security: readonly SecurityRequirement[];\n\n /**\n * What a request must satisfy, one condition per hook: every condition\n * is required, and any one requirement of a condition satisfies it. A\n * hook with one requirement is a condition of one.\n */\n readonly conditions: readonly (readonly SecurityRequirement[])[];\n\n readonly responses: readonly DocumentedResponse[];\n}\n\n/**\n * Collects the contributions of a route's chains.\n *\n * A scheme is registered once per name and a response once per status and\n * description: the same guard on the application and on a group is one\n * requirement, not two. Two hooks of one scheme asking for different\n * scopes both run, so the requirement asks for the scopes of both — each\n * once, in the order they were first asked for.\n *\n * Deduplicating by name means two hooks claiming one name with different\n * schemes lose one of them, and that is not a duplicate being collapsed —\n * it is a requirement the route really has going undescribed. Passing\n * `warn` is how the caller hears about it; the generator does.\n */\nexport function contributionsOf(\n chains: Record<string, readonly AnyHook[]>,\n warn?: (message: string) => void,\n): HookContributions {\n const security = new Map<string, SecurityRequirement>();\n const conditions = new Map<string, readonly SecurityRequirement[]>();\n const responses = new Map<string, DocumentedResponse>();\n\n for (const slot of Object.values(chains)) {\n for (const hook of slot) {\n const docs = docsOf(hook);\n\n if (!docs) {\n continue;\n }\n\n if (docs.security) {\n const alternatives = alternativesOf(docs.security);\n\n conditions.set(conditionKey(alternatives), alternatives);\n\n for (const requirement of alternatives) {\n const claimed = security.get(requirement.name);\n\n if (!claimed) {\n security.set(requirement.name, requirement);\n } else if (\n JSON.stringify(claimed.scheme) ===\n JSON.stringify(requirement.scheme)\n ) {\n security.set(requirement.name, {\n ...claimed,\n scopes: joinScopes(claimed.scopes, requirement.scopes),\n });\n } else {\n warn?.(\n `two hooks claim the security scheme \"${requirement.name}\" with different definitions; one of them is not described`,\n );\n }\n }\n }\n\n for (const response of docs.responses ?? []) {\n const key = `${response.status} ${response.description}`;\n\n if (!responses.has(key)) {\n responses.set(key, response);\n }\n }\n }\n }\n\n return {\n security: [...security.values()],\n conditions: [...conditions.values()],\n responses: [...responses.values()],\n };\n}\n\n/** A hook's security as the alternatives it accepts; one is one. */\nfunction alternativesOf(\n security: SecurityRequirement | SecurityAlternatives,\n): readonly SecurityRequirement[] {\n return \"anyOf\" in security ? security.anyOf : [security];\n}\n\n/**\n * What makes two conditions the same one: the same guard mounted on the\n * application and on a group is one condition, and counting it twice would\n * multiply its alternatives with themselves.\n */\nfunction conditionKey(alternatives: readonly SecurityRequirement[]): string {\n return JSON.stringify(\n alternatives.map((requirement) => [\n requirement.name,\n [...(requirement.scopes ?? [])].sort(),\n ]),\n );\n}\n\n/** The scopes of two requirements of one scheme, each once, in order. */\nfunction joinScopes(\n first: readonly string[] | undefined,\n second: readonly string[] | undefined,\n): readonly string[] {\n const joined = [...(first ?? [])];\n\n for (const scope of second ?? []) {\n if (!joined.includes(scope)) {\n joined.push(scope);\n }\n }\n\n return joined;\n}\n",
|
|
5
|
+
"/**\n * What hooks, and the handlers packages hand out, contribute to the\n * documentation.\n *\n * What a route is protected by, or answers with when a guard refuses, is\n * not in its config: a hook is a function in a slot, and the route that\n * mounts it says nothing about tokens or rate limits. The contribution is\n * therefore annotated onto the hook — from this package, not from\n * `hook.*` — so the core keeps knowing nothing about OpenAPI and the\n * factories stay free of documentation options. A package's handler is\n * annotated the same way, for the routes that mount it.\n *\n * A hook annotated once is documented everywhere it runs: application and\n * group chains are merged into every route's chains at startup, so a guard\n * mounted on a zone documents the zone's operations without repeating\n * itself.\n *\n * @module\n */\n\nimport type { AnyHook, AnySchema } from \"@tetsujs/core\";\nimport type { JsonSchema } from \"./json-schema.ts\";\nimport { isMediaType } from \"./media.ts\";\n\n/**\n * The definition of a scheme, as OpenAPI spells it.\n *\n * Typed as loosely as the spec is wide — `http`, `apiKey`, `oauth2`,\n * `openIdConnect` and `mutualTLS` carry different fields, and narrowing\n * them here would be a second, poorer copy of the specification.\n */\nexport interface SecurityScheme {\n readonly type: \"http\" | \"apiKey\" | \"oauth2\" | \"openIdConnect\" | \"mutualTLS\";\n readonly [key: string]: unknown;\n}\n\n/** What a hook demands of a request, and what it answers when refused. */\nexport interface SecurityRequirement {\n /** The name the scheme is registered under in `components`. */\n readonly name: string;\n\n /** The scheme itself, registered once per name. */\n readonly scheme: SecurityScheme;\n\n /** OAuth2 scopes; empty for every other type. */\n readonly scopes?: readonly string[];\n\n /** The status an unauthenticated request gets. Defaults to `401`. */\n readonly status?: number;\n\n /** How the refusal is described in the document. */\n readonly description?: string;\n\n /**\n * The `error` code the refusal carries, when the guard answers with the\n * framework's envelope — `\"UNAUTHORIZED\"`, `\"SESSION_EXPIRED\"`.\n *\n * Documented as a `const` for the same reason as on a\n * {@link DocumentedResponse}: only the guard knows its own code.\n */\n readonly error?: string;\n\n /** An example of the refusal's `message`, for the same reason. */\n readonly message?: string;\n}\n\n/**\n * One response a hook can produce, which the route's own schema knows\n * nothing about — a rate limiter's `429`, a guard's `401` — or one a\n * package's handler answers with, for the routes that mount it: a file,\n * a `304`.\n */\nexport interface DocumentedResponse {\n readonly status: number;\n readonly description: string;\n\n /**\n * The body, when it is described: JSON, or the content under\n * `contentType` when there is one.\n *\n * Without `schema` or `contentType`, an error status — `400` and above —\n * answers with the framework's envelope, which `error`, `message` and\n * `fields` describe, and any other status carries no body: a `304`, a\n * redirect.\n */\n readonly schema?: AnySchema;\n\n /**\n * The media type of the body when it is not JSON — `\"text/html\"`, or a\n * range such as `\"image/*\"` or the range of every type for a file whose\n * type is not known in advance. Without a `schema`, the body is\n * described by its type alone.\n *\n * Two responses of one status with different types are both in the\n * document, each under its own: the site's `404.html` next to the\n * envelope an API client gets.\n */\n readonly contentType?: string;\n\n /**\n * The `error` code of the failure envelope, when the hook answers with\n * the framework's shape — `\"RATE_LIMITED\"`, `\"SESSION_EXPIRED\"`.\n *\n * Documented as a `const`, so a client can discriminate on it. Only the\n * hook knows its own code; without one the document says the field is a\n * string and no more.\n */\n readonly error?: string;\n\n /** An example of the envelope's `message`, for the same reason. */\n readonly message?: string;\n\n /**\n * Fields the hook adds to the envelope, as JSON Schema by name — the\n * `retryAfter` of `{ ...errorBody(429, \"RATE_LIMITED\"), retryAfter }`.\n *\n * Each is documented as always present. The envelope's own `status`,\n * `message` and `error` are not redefined by a field of the same name:\n * `error` is what a client discriminates on, and it stays the code the\n * hook declared. Ignored when the response has a `schema`, which says\n * everything about the body itself.\n *\n * @example\n * ```ts\n * documented(limiter, {\n * responses: [\n * {\n * status: 429,\n * description: \"Too many requests\",\n * error: \"RATE_LIMITED\",\n * fields: { retryAfter: { type: \"integer\", minimum: 0 } },\n * },\n * ],\n * });\n * ```\n */\n readonly fields?: Readonly<Record<string, JsonSchema>>;\n\n /**\n * Headers the hook sets on this response, by name — the `retry-after`\n * of a refusal.\n *\n * Documented as possible rather than required: a status several sources\n * answer with is one response in the document, and a header one of them\n * sets is not on the others'.\n */\n readonly headers?: Readonly<Record<string, DocumentedHeader>>;\n}\n\n/** A header a hook's response carries. */\nexport interface DocumentedHeader {\n readonly description?: string;\n readonly schema: JsonSchema;\n}\n\n/**\n * Requirements of which a hook accepts any one: a session cookie *or* a\n * bearer token, checked by one hook.\n *\n * \"Either\" lives inside a hook, never between hooks — every hook of a\n * route runs, so the schemes of two hooks are both required. A hook that\n * takes either of two credentials says so here, and the document lists\n * the combinations a client may bring.\n */\nexport interface SecurityAlternatives {\n readonly anyOf: readonly SecurityRequirement[];\n}\n\n/** Everything a hook tells the generator about itself. */\nexport interface HookDocs {\n /**\n * What the hook demands of a request: one requirement, or alternatives\n * of which any one will do.\n */\n readonly security?: SecurityRequirement | SecurityAlternatives;\n\n /** What the hook can answer with. */\n readonly responses?: readonly DocumentedResponse[];\n}\n\n/**\n * Everything a handler tells the generator about the route it answers\n * for.\n *\n * A handler a package hands out — a directory of files, say — knows what\n * it answers with better than the route it is mounted on, whose author\n * wrote one line: annotated once, it describes every route that mounts it.\n */\nexport interface HandlerDocs {\n /**\n * Keeps the route out of the document unless the route says\n * `docs: { hidden: false }`.\n *\n * For a handler whose routes are rarely anyone's API — the files of a\n * site — and which a generated client could not call anyway. The route's\n * own word wins either way: `docs: { hidden: true }` hides it whatever\n * the handler says.\n */\n readonly hidden?: boolean;\n\n /**\n * What the handler answers with, as the route's own responses: a status\n * the route's response map declares too is described by both, and a\n * route that says nothing gets no placeholder `200` in their place.\n */\n readonly responses?: readonly DocumentedResponse[];\n}\n\n/** Any handler a route can take; the context is the route's to type. */\ntype AnyHandler = (ctx: never) => unknown;\n\nconst docsKey = \"~tetsu/hook-docs\";\nconst handlerDocsKey = \"~tetsu/handler-docs\";\n\n/**\n * Annotates a hook, or a handler, with what it contributes to the\n * documentation.\n *\n * Returns a copy: what the caller exports is what carries the annotation,\n * and a hook or a handler used elsewhere is not changed behind its\n * author's back. A handler's copy calls the handler it was made from. The\n * type is preserved exactly, so an annotated hook goes into a stack, and an\n * annotated handler onto a route, like any other.\n *\n * Annotating a handler is for one whose type is already settled — a\n * package's, typed by its own context. An arrow written inside\n * `documented()` on a route does not get the route's context, which\n * `route()` would have given it, and does not compile; its statuses belong\n * in the route's response map.\n *\n * One signature, for a hook and a handler alike, and one shape of what is\n * said about either. An overload for each would keep `hidden` off a hook\n * and `security` off a handler in the types, but TypeScript before 7\n * reports a call no overload matches on the whole call, and a misspelled\n * keyword deep in a response would no longer be pointed at. Those two are\n * refused here instead, when `documented()` is called — as a module loads,\n * before anything is served.\n *\n * @example A hook\n * ```ts\n * export const limiter = documented(hook.beforeParse(check), {\n * responses: [\n * { status: 429, description: \"Rate limit exceeded\", schema: TooMany },\n * ],\n * });\n * ```\n *\n * @example A package's handler, out of the document until a route asks\n * ```ts\n * return documented(serveFile, {\n * hidden: true,\n * responses: [\n * { status: 200, description: \"The file\", contentType: \"image/*\" },\n * { status: 304, description: \"Not modified\" },\n * ],\n * });\n * ```\n */\nexport function documented<T extends AnyHook | AnyHandler>(\n target: T,\n docs: HookDocs & HandlerDocs,\n): T {\n const handled = typeof target === \"function\";\n\n if (handled && docs.security !== undefined) {\n throw new Error(\n \"documented() was given security for a handler — security is stated on the hook that enforces it, with secured()\",\n );\n }\n\n if (!handled && docs.hidden !== undefined) {\n throw new Error(\n \"documented() was given hidden for a hook — a route is hidden by its own docs, or by its handler's annotation, not by a hook it mounts\",\n );\n }\n\n for (const response of docs.responses ?? []) {\n if (\n response.contentType !== undefined &&\n !isMediaType(response.contentType)\n ) {\n throw new Error(\n `The ${response.status} response given to documented() has the content type ${JSON.stringify(response.contentType)}, which is not a type such as text/html or a range such as image/* — the type alone, without parameters: the charset belongs on the response`,\n );\n }\n }\n\n if (handled) {\n const handler = target as AnyHandler;\n const copy: AnyHandler = (ctx) => handler(ctx);\n\n Object.defineProperty(copy, handlerDocsKey, {\n enumerable: false,\n value: { ...handlerDocsOf(handler), ...docs },\n });\n\n return copy as T;\n }\n\n const hook = target as AnyHook;\n const annotated = { ...hook };\n\n Object.defineProperty(annotated, docsKey, {\n enumerable: false,\n value: { ...docsOf(hook), ...docs },\n });\n\n return annotated as T;\n}\n\n/**\n * Annotates a hook with the security it enforces — {@link documented} for\n * the case that comes up most.\n *\n * One requirement, or `{ anyOf: [...] }` for a hook that accepts any one\n * of several: the schemes of different hooks are all required, the\n * alternatives of one hook are not.\n *\n * @example\n * ```ts\n * export const auth = secured(\n * hook.beforeParse((ctx) => {\n * const user = verify(ctx.req.headers.get(\"authorization\"));\n * if (!user) throw new HttpError(401);\n * return { user };\n * }),\n * {\n * name: \"bearerAuth\",\n * scheme: { type: \"http\", scheme: \"bearer\", bearerFormat: \"JWT\" },\n * },\n * );\n * ```\n *\n * @example A hook that accepts a session cookie or a bearer token\n * ```ts\n * export const caller = secured(\n * hook.beforeParse((ctx) => {\n * const user = sessions.fromCookie(ctx) ?? tokens.fromHeader(ctx);\n * if (!user) throw new HttpError(401);\n * return { user };\n * }),\n * { anyOf: [cookieSession, bearerToken] },\n * );\n * ```\n */\nexport function secured<H extends AnyHook>(\n hook: H,\n requirement: SecurityRequirement | SecurityAlternatives,\n): H {\n return documented(hook, { security: requirement });\n}\n\n/** Reads everything a hook was annotated with. */\nexport function docsOf(hook: AnyHook): HookDocs | undefined {\n return (hook as unknown as Record<string, HookDocs | undefined>)[docsKey];\n}\n\n/** Reads everything a handler was annotated with. */\nexport function handlerDocsOf(handler: unknown): HandlerDocs | undefined {\n return typeof handler === \"function\"\n ? (handler as unknown as Record<string, HandlerDocs | undefined>)[\n handlerDocsKey\n ]\n : undefined;\n}\n\n/** Reads the security a hook was annotated with, if it was. */\nexport function securityOf(\n hook: AnyHook,\n): SecurityRequirement | SecurityAlternatives | undefined {\n return docsOf(hook)?.security;\n}\n\n/** What the hooks of one route contribute, in execution order. */\nexport interface HookContributions {\n /**\n * Every scheme the hooks mention, once per name, with the scopes of all\n * of them: what the document registers, and what a refusal answers with.\n */\n readonly security: readonly SecurityRequirement[];\n\n /**\n * What a request must satisfy, one condition per hook: every condition\n * is required, and any one requirement of a condition satisfies it. A\n * hook with one requirement is a condition of one.\n */\n readonly conditions: readonly (readonly SecurityRequirement[])[];\n\n readonly responses: readonly DocumentedResponse[];\n}\n\n/**\n * Collects the contributions of a route's chains.\n *\n * A scheme is registered once per name: two hooks of one scheme asking for\n * different scopes both run, so the requirement asks for the scopes of\n * both — each once, in the order they were first asked for. Responses are\n * kept as the hooks give them. Two guards may answer one status with one\n * description and different codes, and both are what the route sends;\n * answers that say the same are folded when the document is written.\n *\n * Deduplicating by name means two hooks claiming one name with different\n * schemes lose one of them, and that is not a duplicate being collapsed —\n * it is a requirement the route really has going undescribed. Passing\n * `warn` is how the caller hears about it; the generator does.\n */\nexport function contributionsOf(\n chains: Record<string, readonly AnyHook[]>,\n warn?: (message: string) => void,\n): HookContributions {\n const security = new Map<string, SecurityRequirement>();\n const conditions = new Map<string, readonly SecurityRequirement[]>();\n const responses: DocumentedResponse[] = [];\n\n for (const slot of Object.values(chains)) {\n for (const hook of slot) {\n const docs = docsOf(hook);\n\n if (!docs) {\n continue;\n }\n\n if (docs.security) {\n const alternatives = alternativesOf(docs.security);\n\n conditions.set(conditionKey(alternatives), alternatives);\n\n for (const requirement of alternatives) {\n const claimed = security.get(requirement.name);\n\n if (!claimed) {\n security.set(requirement.name, requirement);\n } else if (\n JSON.stringify(claimed.scheme) ===\n JSON.stringify(requirement.scheme)\n ) {\n security.set(requirement.name, {\n ...claimed,\n scopes: joinScopes(claimed.scopes, requirement.scopes),\n });\n } else {\n warn?.(\n `two hooks claim the security scheme \"${requirement.name}\" with different definitions; one of them is not described`,\n );\n }\n }\n }\n\n responses.push(...(docs.responses ?? []));\n }\n }\n\n return {\n security: [...security.values()],\n conditions: [...conditions.values()],\n responses,\n };\n}\n\n/** A hook's security as the alternatives it accepts; one is one. */\nfunction alternativesOf(\n security: SecurityRequirement | SecurityAlternatives,\n): readonly SecurityRequirement[] {\n return \"anyOf\" in security ? security.anyOf : [security];\n}\n\n/**\n * What makes two conditions the same one: the same guard mounted on the\n * application and on a group is one condition, and counting it twice would\n * multiply its alternatives with themselves.\n */\nfunction conditionKey(alternatives: readonly SecurityRequirement[]): string {\n return JSON.stringify(\n alternatives.map((requirement) => [\n requirement.name,\n [...(requirement.scopes ?? [])].sort(),\n ]),\n );\n}\n\n/** The scopes of two requirements of one scheme, each once, in order. */\nfunction joinScopes(\n first: readonly string[] | undefined,\n second: readonly string[] | undefined,\n): readonly string[] {\n const joined = [...(first ?? [])];\n\n for (const scope of second ?? []) {\n if (!joined.includes(scope)) {\n joined.push(scope);\n }\n }\n\n return joined;\n}\n",
|
|
6
6
|
"/**\n * The document's `components/schemas` section.\n *\n * The failures the framework fills in repeat across every operation — a\n * `500` on all of them, a `413` on every route with a body — and inlining\n * the same envelope each time makes a document that is mostly boilerplate.\n * They are defined once here and referenced with `$ref`, which is also how\n * a client generator ends up with one `MalformedJson` type instead of one\n * per endpoint.\n *\n * Only the framework's own shapes go here. A schema that came from a\n * validator is still inlined: it is the author's, it has no name the\n * generator could give it, and `$ref` would invent one.\n *\n * @module\n */\n\n/** A reference to a definition in `components/schemas`. */\nexport interface SchemaRef {\n readonly $ref: string;\n}\n\n/** The definitions collected while generating a document. */\nexport interface SchemaComponents {\n /**\n * Registers a schema and returns the reference to it.\n *\n * Identical schemas share one definition, whatever name each caller\n * asked for; different schemas that want the same name get a numbered\n * one, so a document is never silently wrong about what a `$ref` points\n * at.\n */\n ref(preferred: string, schema: Record<string, unknown>): SchemaRef;\n\n /** What was registered, in registration order. */\n readonly schemas: Record<string, unknown>;\n}\n\nexport function schemaComponents(): SchemaComponents {\n const schemas: Record<string, unknown> = {};\n const registered = new Map<string, string>();\n\n return {\n schemas,\n\n ref(preferred: string, schema: Record<string, unknown>): SchemaRef {\n const fingerprint = JSON.stringify(schema);\n const already = registered.get(fingerprint);\n\n if (already) {\n return { $ref: `#/components/schemas/${already}` };\n }\n\n let name = preferred;\n\n for (let attempt = 2; name in schemas; attempt += 1) {\n name = `${preferred}${attempt}`;\n }\n\n schemas[name] = schema;\n registered.set(fingerprint, name);\n\n return { $ref: `#/components/schemas/${name}` };\n },\n };\n}\n\n/**\n * The name a failure is defined under: its `error` code in PascalCase —\n * `MALFORMED_JSON` becomes `MalformedJson` — so the definition and the code\n * a client branches on read as the same thing.\n *\n * A failure whose code only the hook knows, and which the hook did not\n * declare, is named after its status instead.\n */\nexport function failureName(status: number, error?: string): string {\n const name = (error ?? \"\")\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n\n // A code with nothing ASCII in it sanitizes to nothing — a code in\n // Cyrillic or Japanese, or one that is all punctuation. That is the same\n // situation as no code at all, and gets the same name: the alternative\n // was a component keyed `\"\"`, which the specification does not allow, and\n // a second such code keyed `\"2\"` by the collision numbering below it.\n return name || `Failure${status}`;\n}\n",
|
|
7
|
-
"/**\n * Error envelopes, one definition per status and code.\n *\n * An envelope reaches a document from
|
|
7
|
+
"/**\n * Error envelopes, one definition per status and code.\n *\n * An envelope reaches a document from five directions: a route's response\n * map, its handler's annotation, a hook's annotation, a guard's security\n * requirement, and the framework's own failures. Each used to be described\n * where it arrived —\n * a route's inline, the rest by reference — so one `UNAUTHORIZED` could be\n * listed twice under one status, once as a `$ref` and once as the same\n * shape without a name, and a generated client got a named type next to an\n * anonymous twin.\n *\n * Here every envelope, whoever declared it, becomes a reference to the\n * one definition of its status and code. That is also what makes a status\n * discriminable: a client can branch on `error` only if every code under\n * the status has exactly one shape.\n *\n * The route's definition wins, its handler's annotation counting as the\n * route's own. It is the author's own contract — usually the stricter one,\n * a validator's `additionalProperties: false` — where a hook's is the\n * framework's generic envelope. The routes are therefore read first,\n * before any operation is built, so the winner does not depend on which\n * route happens to come first in the table.\n *\n * What an envelope looks like — how one is described, where its code is,\n * what a client discriminates on — is the document's error format, which\n * the registry carries for everything that builds or reads one.\n *\n * Internal to the package.\n *\n * @module\n */\n\nimport type { SchemaComponents, SchemaRef } from \"./components.ts\";\nimport { failureName } from \"./components.ts\";\nimport type { JsonSchemaObject } from \"./emit.ts\";\nimport type { ResolvedFormat } from \"./errors.ts\";\n\n/** The definitions of every envelope of one document. */\nexport interface Envelopes {\n /** The document's error format. */\n readonly format: ResolvedFormat;\n\n /**\n * Records a route's definition, before anything is referenced. The first\n * route to declare a status and code defines it.\n */\n declare(status: number, code: string, schema: JsonSchemaObject): void;\n\n /**\n * The reference to the definition of a status and code.\n *\n * `schema` is how the caller describes it. When a definition already\n * exists, that is what is referenced; if the caller's differs from it\n * in fields, `warn` hears about it — once per document, not once per\n * operation the hook runs on.\n */\n ref(\n status: number,\n code: string,\n schema: JsonSchemaObject,\n warn: (message: string) => void,\n ): SchemaRef;\n\n /**\n * The code a reference stands for, when it is one this handed out — what\n * a discriminator maps back from.\n */\n codeOf(ref: string): string | undefined;\n}\n\nexport function envelopes(\n components: SchemaComponents,\n format: ResolvedFormat,\n): Envelopes {\n const declared = new Map<string, JsonSchemaObject>();\n const defined = new Map<string, JsonSchemaObject>();\n const refs = new Map<string, SchemaRef>();\n const codes = new Map<string, string>();\n const names = new Map<string, string>();\n const reported = new Set<string>();\n\n return {\n format,\n\n declare(status, code, schema) {\n const key = keyOf(status, code);\n\n if (!declared.has(key)) {\n declared.set(key, schema);\n }\n },\n\n ref(status, code, schema, warn) {\n const key = keyOf(status, code);\n const definition = declared.get(key) ?? defined.get(key) ?? schema;\n\n defined.set(key, definition);\n\n const difference = differenceOf(definition, schema);\n\n if (difference && !reported.has(`${key} ${difference}`)) {\n reported.add(`${key} ${difference}`);\n warn(\n `the ${status} \"${code}\" is described by one definition in the document, and a definition that differs from it in ${difference} is not described`,\n );\n }\n\n const existing = refs.get(key);\n\n if (existing) {\n return existing;\n }\n\n const created = components.ref(nameOf(status, code), definition);\n\n refs.set(key, created);\n codes.set(created.$ref, code);\n\n return created;\n },\n\n codeOf(ref) {\n return codes.get(ref);\n },\n };\n\n /**\n * The name a status and code are defined under: the code's, unless the\n * same code under another status has it already, in which case the\n * status tells the two apart — `Invalid` and `Invalid409`.\n */\n function nameOf(status: number, code: string): string {\n const name = failureName(status, code);\n const holder = names.get(name);\n\n if (holder === undefined || holder === keyOf(status, code)) {\n names.set(name, keyOf(status, code));\n\n return name;\n }\n\n return `${name}${status}`;\n }\n}\n\n/**\n * The alternatives a schema stands for, as a list the status's own union\n * can take in.\n *\n * `anyOf` nested in `anyOf` says nothing its branches do not say side by\n * side, so a schema that is only an `anyOf` is replaced by its branches.\n * A `oneOf` is different — \"exactly one\" of two overlapping shapes refuses\n * what both accept — and is taken apart only when its branches cannot\n * overlap: envelopes with a different code each. A schema with anything\n * beside its union, a `title` or a `$defs`, is left whole: those keywords\n * belong to the union, and would be lost with it.\n */\nexport function branchesOf(\n schema: JsonSchemaObject,\n code: (schema: JsonSchemaObject) => string | undefined,\n): JsonSchemaObject[] {\n const keys = Object.keys(schema);\n\n if (keys.length !== 1) {\n return [schema];\n }\n\n const within = (branch: JsonSchemaObject) => branchesOf(branch, code);\n\n if (Array.isArray(schema.anyOf)) {\n return (schema.anyOf as JsonSchemaObject[]).flatMap(within);\n }\n\n if (Array.isArray(schema.oneOf)) {\n const branches = (schema.oneOf as JsonSchemaObject[]).flatMap(within);\n const codes = branches.map(code);\n\n if (\n codes.every((code) => code !== undefined) &&\n new Set(codes).size === codes.length\n ) {\n return branches;\n }\n }\n\n return [schema];\n}\n\nfunction keyOf(status: number, code: string): string {\n return `${status} ${code}`;\n}\n\n/**\n * How two definitions of one envelope differ in what a client reads: the\n * fields one has and the other does not, or which of them are required —\n * at any depth, by path, so a format that nests its fields\n * (`error.retryAfter`) is compared as closely as a flat one. Wording — a\n * `message` example, `number` against `integer` for the status — is not a\n * difference a client would notice, and is not one.\n */\nfunction differenceOf(\n kept: JsonSchemaObject,\n other: JsonSchemaObject,\n): string | undefined {\n const keptShape = shapeOf(kept);\n const otherShape = shapeOf(other);\n\n const changed = [\n ...otherShape.fields.filter((path) => !keptShape.fields.includes(path)),\n ...keptShape.fields.filter((path) => !otherShape.fields.includes(path)),\n ];\n\n if (changed.length > 0) {\n return `fields: ${changed.join(\", \")}`;\n }\n\n return JSON.stringify(keptShape.required) ===\n JSON.stringify(otherShape.required)\n ? undefined\n : \"which fields are required\";\n}\n\n/** How deep {@link shapeOf} looks; an envelope is a few levels at most. */\nconst shapeDepth = 8;\n\n/**\n * The paths of an object schema's fields, and of the required ones among\n * them, following `properties` down. Sorted, so two shapes compare as\n * strings.\n */\nfunction shapeOf(schema: JsonSchemaObject): {\n fields: string[];\n required: string[];\n} {\n const fields: string[] = [];\n const required: string[] = [];\n\n const walk = (node: JsonSchemaObject, prefix: string, depth: number) => {\n const properties = node.properties;\n\n if (\n depth > shapeDepth ||\n properties === null ||\n typeof properties !== \"object\"\n ) {\n return;\n }\n\n const requiredHere = Array.isArray(node.required) ? node.required : [];\n\n for (const [name, child] of Object.entries(properties)) {\n const path = `${prefix}${name}`;\n\n fields.push(path);\n\n if (requiredHere.includes(name)) {\n required.push(path);\n }\n\n if (child !== null && typeof child === \"object\") {\n walk(child as JsonSchemaObject, `${path}.`, depth + 1);\n }\n }\n };\n\n walk(schema, \"\", 0);\n\n return { fields: fields.sort(), required: required.sort() };\n}\n",
|
|
8
8
|
"/**\n * The shape the document gives an error.\n *\n * Every failure an application answers with reaches its `onError` hooks,\n * so one hook sets the format of all of them. The document is generated\n * from the routes, not from that hook, and cannot see what it does: an\n * application with a format of its own says so here too, and the framework's\n * failures, the hooks' refusals and the routes' own envelopes are described\n * in it. Keeping the two in step is the application's to do — the core knows\n * nothing about documents, and a function cannot be read for the shape it\n * returns.\n *\n * Without it the format is the framework's envelope,\n * `{ status, message, error }`.\n *\n * @module\n */\n\nimport type { JsonSchemaObject } from \"./emit.ts\";\nimport type { JsonSchema, JsonSchemaKeywords } from \"./json-schema.ts\";\n\n/**\n * One failure the document describes, as the generator knows it.\n *\n * This is everything known about a failure before it is answered: its\n * status, its code when the framework or the hook knows it, an example of\n * its message, and what else it carries — the `issues` of a validation\n * failure, the `retryAfter` of a rate limit. Where each goes in the body\n * is the format's to decide.\n */\nexport interface DocumentedFailure {\n readonly status: number;\n\n /** The code a client branches on, when it is known. */\n readonly error?: string;\n\n /** An example of the message; wording, never a contract. */\n readonly message?: string;\n\n /** What the failure carries besides, as JSON Schema by name. */\n readonly fields: Readonly<Record<string, JsonSchema>>;\n}\n\n/** How the application's errors look, for the document to describe them. */\nexport interface ErrorFormat {\n /** The body of one failure. */\n readonly schema: (failure: DocumentedFailure) => JsonSchemaKeywords;\n\n /**\n * The top-level field that holds the code, for a client to discriminate\n * on — `\"code\"` in `{ code, message }`. A status whose alternatives are\n * all envelopes then carries a `discriminator` on it.\n *\n * None unless named: OpenAPI discriminates on a top-level field only, and\n * a format that nests its code — `{ error: { code } }` — has none to\n * name.\n */\n readonly discriminator?: string;\n\n /**\n * The code of a schema a route or a hook declared, when it is an\n * envelope in this format — how the document knows a route's own `404`\n * is the same failure as a hook's, and gives both one definition.\n *\n * Read off the JSON Schema the validator emitted. By default, the\n * `const` of the discriminator's field, when there is one; a nested\n * format says where its code is.\n */\n readonly code?: (schema: JsonSchemaKeywords) => string | undefined;\n}\n\n/** What the generator works with: every part of a format, filled in. */\nexport interface ResolvedFormat {\n describe(failure: DocumentedFailure): JsonSchemaObject;\n code(schema: JsonSchemaObject): string | undefined;\n readonly discriminator: string | undefined;\n}\n\n/**\n * A format as the generator uses it. Absent, the framework's envelope,\n * discriminated on `error`.\n */\nexport function resolveFormat(format: ErrorFormat | undefined): ResolvedFormat {\n if (format === undefined) {\n return {\n describe: envelope,\n code: codeIn(\"error\"),\n discriminator: \"error\",\n };\n }\n\n const discriminator = format.discriminator;\n const read = format.code;\n\n return {\n describe: (failure) => format.schema(failure) as JsonSchemaObject,\n code: read\n ? (schema) => read(schema as JsonSchemaKeywords)\n : discriminator === undefined\n ? () => undefined\n : codeIn(discriminator),\n discriminator,\n };\n}\n\n/**\n * The body of one failure in the framework's envelope, as JSON Schema.\n *\n * The status is a `const`, and so is the code whenever it is known: a\n * generated client can then discriminate on `error` instead of receiving\n * \"an object with three strings\", and a reader of the document sees\n * `\"BODY_TOO_LARGE\"` rather than `string`.\n *\n * The message is documented by example, never as a `const` — it is wording\n * meant for a human, the one field a client must not match on, and the one\n * this project reserves the right to reword.\n *\n * Fields a failure carries besides come after the three, and never in\n * their place.\n */\nfunction envelope(failure: DocumentedFailure): JsonSchemaObject {\n const own = {\n status: { type: \"integer\", const: failure.status },\n message: failure.message\n ? { type: \"string\", examples: [failure.message] }\n : { type: \"string\" },\n error: failure.error\n ? { type: \"string\", const: failure.error }\n : { type: \"string\" },\n };\n\n const added = Object.keys(failure.fields).filter(\n (name) => !Object.hasOwn(own, name),\n );\n\n return {\n type: \"object\",\n required: [\"status\", \"message\", \"error\", ...added],\n properties: { ...failure.fields, ...own },\n };\n}\n\n/**\n * Reads the code of an envelope from one top-level field: required, and\n * holding one string — a `const`, or an `enum` of one value.\n */\nfunction codeIn(\n field: string,\n): (schema: JsonSchemaObject) => string | undefined {\n return (schema) => {\n const required = Array.isArray(schema.required) ? schema.required : [];\n\n if (!required.includes(field)) {\n return undefined;\n }\n\n const value = (\n schema.properties as\n | Record<string, { const?: unknown; enum?: unknown } | undefined>\n | undefined\n )?.[field];\n\n if (typeof value?.const === \"string\") {\n return value.const;\n }\n\n if (\n Array.isArray(value?.enum) &&\n value.enum.length === 1 &&\n typeof value.enum[0] === \"string\"\n ) {\n return value.enum[0];\n }\n\n return undefined;\n };\n}\n",
|
|
9
|
-
"/**\n * One route table entry, described as an OpenAPI operation.\n *\n * Bodies and responses live here; parameters are in `parameters.ts`. The\n * error responses a route can produce without the author writing anything\n * — a rejected schema, an unparsable body, a body over the limit — are\n * derived from what the route declares and from the options the\n * application actually runs with.\n *\n * @module\n */\n\nimport type {\n AnySchema,\n AppOptions,\n BodyType,\n ResponseEntry,\n RouteTableEntry,\n} from \"@tetsujs/core\";\nimport { errorBody } from \"@tetsujs/core\";\nimport type {\n DocumentedResponse,\n HookContributions,\n SecurityRequirement,\n} from \"./annotations.ts\";\nimport { contributionsOf } from \"./annotations.ts\";\nimport type { SchemaComponents } from \"./components.ts\";\nimport { failureName } from \"./components.ts\";\nimport type {\n ContentMap,\n HeaderObject,\n OperationObject,\n ResponseObject,\n} from \"./document.ts\";\nimport type { JsonSchemaObject } from \"./emit.ts\";\nimport { emitted } from \"./emit.ts\";\nimport type { Envelopes } from \"./envelopes.ts\";\nimport { branchesOf } from \"./envelopes.ts\";\nimport type { JsonSchema } from \"./json-schema.ts\";\nimport { partParameters, pathParameters } from \"./parameters.ts\";\n\n/** Describes one route. */\nexport function operationOf(\n entry: RouteTableEntry,\n options: AppOptions,\n components: SchemaComponents,\n envelopes: Envelopes,\n ids: OperationIds,\n warn: (message: string) => void,\n): OperationObject {\n const schema = entry.def.schema;\n\n const parameters = [\n ...pathParameters(entry.path, schema?.params, warn),\n ...partParameters(schema?.query, \"query\", warn),\n ...partParameters(schema?.headers, \"header\", warn),\n ...partParameters(schema?.cookies, \"cookie\", warn),\n ];\n\n const body = requestBody(entry, warn);\n const contributed = contributionsOf(entry.hooks, warn);\n\n return {\n operationId: ids.take(entry),\n ...(entry.def.docs?.summary === undefined\n ? {}\n : { summary: entry.def.docs.summary }),\n ...(entry.def.docs?.description === undefined\n ? {}\n : { description: entry.def.docs.description }),\n ...(entry.def.docs?.tags === undefined\n ? {}\n : { tags: entry.def.docs.tags }),\n ...(entry.def.docs?.deprecated === undefined\n ? {}\n : { deprecated: entry.def.docs.deprecated }),\n ...(parameters.length > 0 ? { parameters } : {}),\n ...(body ? { requestBody: body } : {}),\n ...(contributed.security.length > 0\n ? { security: securityOf(contributed.conditions) }\n : {}),\n responses: responses(\n entry,\n options,\n contributed,\n components,\n envelopes,\n warn,\n ),\n };\n}\n\n/**\n * Records the envelopes a route declares, so that its definitions are the\n * ones the document keeps — whichever operation refers to them first.\n *\n * Runs before any operation is built. A schema that cannot describe itself\n * is skipped without a word: building the operation says so, once.\n */\nexport function declareEnvelopes(\n entry: RouteTableEntry,\n envelopes: Envelopes,\n): void {\n for (const [status, { body }] of declaredResponses(entry)) {\n const described = body === null ? undefined : emitted(body, \"\", () => {});\n\n const code = envelopes.format.code;\n\n for (const branch of described ? branchesOf(described, code) : []) {\n const found = code(branch);\n\n if (found !== undefined) {\n envelopes.declare(Number(status), found, branch);\n }\n }\n }\n}\n\n/** One status of a route's response map, whichever form it was written in. */\ninterface Declared {\n readonly body: AnySchema | null;\n readonly headers?: AnySchema;\n readonly cookies?: AnySchema;\n}\n\n/** The route's response map as pairs; a single schema is its `200`. */\nfunction declaredResponses(\n entry: RouteTableEntry,\n): [status: string, declared: Declared][] {\n const response = entry.def.schema?.response;\n\n if (!response) {\n return [];\n }\n\n if (\"~standard\" in response) {\n return [[\"200\", { body: response as AnySchema }]];\n }\n\n return Object.entries(response).map(([status, value]) => [\n status,\n asDeclared(value as AnySchema | ResponseEntry | null),\n ]);\n}\n\nfunction asDeclared(value: AnySchema | ResponseEntry | null): Declared {\n if (value === null || \"~standard\" in value) {\n return { body: value as AnySchema | null };\n }\n\n return {\n body: value.body ?? null,\n ...(value.headers === undefined ? {} : { headers: value.headers }),\n ...(value.cookies === undefined ? {} : { cookies: value.cookies }),\n };\n}\n\n/**\n * The headers a declared status says it leaves with: one per property of\n * its `headers` schema, required as the schema says, and its cookies as\n * the one header that sets them.\n *\n * A property's `description` is the header's: it is what a renderer\n * shows in the header's row.\n */\nfunction declaredHeaders(\n declared: Declared,\n warn: (message: string) => void,\n): Record<string, HeaderObject> | undefined {\n const headers: Record<string, HeaderObject> = {};\n\n const [properties, required] = shapeOf(\n declared.headers,\n \"a response's headers\",\n warn,\n );\n\n for (const [name, property] of Object.entries(properties)) {\n const { description, ...schema } = property;\n\n headers[name] = {\n ...(typeof description === \"string\" ? { description } : {}),\n ...(required.has(name) ? { required: true } : {}),\n schema: schema as JsonSchema,\n };\n }\n\n const cookies = setCookie(declared.cookies, warn);\n\n if (cookies) {\n headers[\"set-cookie\"] = cookies;\n }\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\n/**\n * The cookies a status sets, as the header that sets them. OpenAPI has no\n * object for a cookie a response sets — only a `set-cookie` header — so the\n * cookies are listed in its description, by name, each with its own\n * description; the header is required when any of them is.\n */\nfunction setCookie(\n schema: AnySchema | undefined,\n warn: (message: string) => void,\n): HeaderObject | undefined {\n const [properties, required] = shapeOf(schema, \"a response's cookies\", warn);\n\n const names = Object.keys(properties);\n\n if (names.length === 0) {\n return undefined;\n }\n\n const lines = names.map((name) => {\n const description = properties[name]?.[\"description\"];\n\n return typeof description === \"string\"\n ? `- \\`${name}\\`: ${description}`\n : `- \\`${name}\\``;\n });\n\n return {\n description: [\"Sets these cookies:\", \"\", ...lines].join(\"\\n\"),\n ...(required.size > 0 ? { required: true } : {}),\n schema: { type: \"string\" },\n };\n}\n\n/**\n * The properties of an object schema, and which of them it requires.\n *\n * Read as the schema's input: a response's headers and cookies are checked\n * against it and sent as the handler set them, not as the schema returns\n * them — unlike a body, whose checked value is what gets serialized. A\n * field with a default is one the handler may leave out, and the response\n * then leaves without it.\n */\nfunction shapeOf(\n schema: AnySchema | undefined,\n subject: string,\n warn: (message: string) => void,\n): [Record<string, Record<string, unknown>>, Set<string>] {\n const described = schema\n ? emitted(schema, subject, warn, \"input\")\n : undefined;\n\n const properties = (described?.properties ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n const required = new Set(\n Array.isArray(described?.required) ? (described.required as string[]) : [],\n );\n\n return [properties, required];\n}\n\n/**\n * A described body as the alternatives the document lists: every envelope\n * in it a reference to the one definition of its status and code, and a\n * union taken apart into its branches, so that it joins the other answers\n * of its status rather than nesting inside them.\n */\nfunction branchesFor(\n schema: JsonSchemaObject,\n status: number,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): Record<string, unknown>[] {\n return branchesOf(schema, envelopes.format.code).map((branch) => {\n const code = envelopes.format.code(branch);\n\n return code === undefined\n ? branch\n : (envelopes.ref(status, code, branch, warn) as unknown as Record<\n string,\n unknown\n >);\n });\n}\n\n/**\n * The security a route asks for, as OpenAPI spells it.\n *\n * OpenAPI reads the entries of an operation's `security` as alternatives —\n * any one of them authorizes a request — and the schemes inside one entry\n * as all required. A route's conditions are the other way round: every\n * hook runs, so every condition is required, and a condition is satisfied\n * by any one of its alternatives. The entries are therefore the\n * combinations — one alternative from each condition, taken together:\n * a hook accepting a cookie *or* a token, next to a CSRF check, is\n * `[{ cookie, csrf }, { token, csrf }]`. With no alternatives anywhere\n * that is a single entry holding every scheme, which is the usual case.\n *\n * Two alternatives of one scheme in a combination ask for the scopes of\n * both; a combination that comes out twice is listed once.\n */\nfunction securityOf(\n conditions: readonly (readonly SecurityRequirement[])[],\n): Record<string, readonly string[]>[] {\n let combinations: Record<string, readonly string[]>[] = [{}];\n\n for (const alternatives of conditions) {\n combinations = combinations.flatMap((combination) =>\n alternatives.map((requirement) => ({\n ...combination,\n [requirement.name]: joined(\n combination[requirement.name],\n requirement.scopes,\n ),\n })),\n );\n }\n\n const seen = new Set<string>();\n\n return combinations.filter((combination) => {\n const key = JSON.stringify(\n Object.entries(combination)\n .map(([name, scopes]) => [name, [...scopes].sort()])\n .sort(),\n );\n\n if (seen.has(key)) {\n return false;\n }\n\n seen.add(key);\n\n return true;\n });\n}\n\n/** The scopes of a scheme already in a combination, and another's. */\nfunction joined(\n present: readonly string[] | undefined,\n added: readonly string[] | undefined,\n): readonly string[] {\n const scopes = [...(present ?? [])];\n\n for (const scope of added ?? []) {\n if (!scopes.includes(scope)) {\n scopes.push(scope);\n }\n }\n\n return scopes;\n}\n\n/**\n * Hands out the `operationId` of every route in one document.\n *\n * An `operationId` is a contract: a generated client names its methods\n * after them, so an id that moves breaks code nobody reviewing the change\n * sees. The id is therefore always stated or derived from names the\n * author wrote — never from where a route happened to land:\n *\n * | | |\n * | --- | --- |\n * | `docs.operationId` on the route | taken as written |\n * | a route of a named controller | the name and the field — `authRequestCode` |\n * | a route of an unnamed object | the field — `requestCode` |\n * | a route mounted standalone | its method and path — `postAuthCode` |\n *\n * Two routes arriving at one id is an error, not something to route\n * around. Falling back to the method and path, or numbering the second\n * one, would hand one of them an id that changes when a path is edited or\n * a route is added — silently, in someone else's SDK. The error names\n * both routes and the two ways out: a controller name of its own, or an\n * id stated on the route. The core already refuses two controllers of\n * one name; what reaches this is two stated ids, or a stated id meeting a\n * derived one.\n */\nexport interface OperationIds {\n /** The id for this route, unique within the document being built. */\n take(entry: RouteTableEntry): string;\n}\n\nexport function operationIds(): OperationIds {\n const taken = new Map<string, RouteTableEntry>();\n\n return {\n take(entry: RouteTableEntry): string {\n const id = idOf(entry);\n const holder = taken.get(id);\n\n if (holder !== undefined) {\n throw new Error(\n `operationId \"${id}\" is taken by both ${describe(holder)} and ${describe(entry)} — a generated client would get one method for two operations. Give one of them docs.operationId, or its controller a name of its own.`,\n );\n }\n\n taken.set(id, entry);\n\n return id;\n },\n };\n}\n\n/** The id a route asks for, before anything checks it is free. */\nfunction idOf(entry: RouteTableEntry): string {\n const stated = entry.def.docs?.operationId;\n\n if (stated !== undefined) {\n return stated;\n }\n\n if (entry.name === undefined) {\n return derivedId(entry);\n }\n\n if (entry.controller === undefined) {\n return entry.name;\n }\n\n const controller = entry.controller.replace(/Controller$/, \"\");\n\n return `${lowerFirst(controller)}${capitalize(entry.name)}`;\n}\n\n/** How the error above names a route: the one line that finds it. */\nfunction describe(entry: RouteTableEntry): string {\n return `${entry.method} ${entry.path}`;\n}\n\n/**\n * What a route mounted standalone is named by: it has no field and no\n * controller, and its method and path are what it has.\n */\nfunction derivedId(entry: RouteTableEntry): string {\n return `${entry.method.toLowerCase()}${entry.path\n .split(/[/:*]/)\n .filter(Boolean)\n .map(capitalize)\n .join(\"\")}`;\n}\n\n/**\n * Describes the request body, when the route reads one.\n *\n * The media type follows the declaration, not a guess: `\"form\"` accepts\n * both multipart and urlencoded at runtime, so both are listed — unless\n * the schema declares a binary field, which only multipart can carry.\n */\nfunction requestBody(\n entry: RouteTableEntry,\n warn: (message: string) => void,\n): { required: boolean; content: ContentMap } | undefined {\n const declared = entry.def.schema?.body;\n\n /**\n * A body is read when the core reads one: a schema, a declared shape, or\n * `rawBody` — which parses JSON as any body does, next to keeping its\n * bytes. Without a schema the document says what the body is, not what\n * is in it.\n */\n const bodyType =\n entry.def.bodyType ?? (declared || entry.def.rawBody ? \"json\" : undefined);\n\n if (!bodyType) {\n return undefined;\n }\n\n const described = declared\n ? emitted(declared, \"the body\", warn, \"input\")\n : undefined;\n\n const schema = described ? { schema: described } : {};\n\n // Whether a body must be sent is a question about the wire, not about\n // the schema: `json` and `form` parse it before anything is validated,\n // and an empty one fails that parse with a `400` — so the client has to\n // send something whether or not a shape was declared. `text` has no such\n // step, because an absent body reads as `\"\"` just like an empty one; if\n // that string is unacceptable, the schema is where it says so. Neither\n // has `stream`: an absent body is handed over as an empty stream.\n const required = bodyType !== \"text\" && bodyType !== \"stream\";\n\n if (bodyType === \"stream\") {\n /**\n * Bytes with no shape to describe: the route takes the body unread, so\n * the document says what it is rather than what is in it. A `stream`\n * route cannot carry a body schema at all — the compiler refuses the\n * pair — so there is never a `schema` to attach here.\n */\n return { required, content: { \"application/octet-stream\": {} } };\n }\n\n if (bodyType === \"text\") {\n return { required, content: { \"text/plain\": schema } };\n }\n\n if (bodyType === \"json\") {\n return { required, content: { \"application/json\": schema } };\n }\n\n const content: ContentMap = { \"multipart/form-data\": schema };\n\n if (!described || !carriesBinary(described)) {\n content[\"application/x-www-form-urlencoded\"] = schema;\n }\n\n return { required, content };\n}\n\n/**\n * Whether any part of an emitted schema describes binary content.\n *\n * Walked with a stack rather than by recursion, and remembering what it has\n * already seen: the shape comes from an adapter, so its depth is the\n * author's to choose and nothing says it is a tree. Recursion would answer\n * a deep one by overflowing the stack, and a self-referential one by never\n * returning — both while `createApp` is still assembling the application.\n */\nfunction carriesBinary(root: unknown): boolean {\n const pending: unknown[] = [root];\n const seen = new Set<unknown>();\n\n while (pending.length > 0) {\n const node = pending.pop();\n\n if (node === null || typeof node !== \"object\" || seen.has(node)) {\n continue;\n }\n\n seen.add(node);\n\n if ((node as { contentEncoding?: unknown }).contentEncoding === \"binary\") {\n return true;\n }\n\n for (const value of Object.values(node)) {\n pending.push(value);\n }\n }\n\n return false;\n}\n\n/**\n * Describes what the route answers with.\n *\n * The declared responses come first; the framework's own failures fill in\n * around them, and never over them — an author who documented `422`\n * himself has said something more specific than this could.\n */\nfunction responses(\n entry: RouteTableEntry,\n options: AppOptions,\n contributed: HookContributions,\n components: SchemaComponents,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): Record<string, ResponseObject> {\n const answers = new Map<string, Answer[]>();\n\n const add = (status: string, answer: Answer): void => {\n answers.set(status, [...(answers.get(status) ?? []), answer]);\n };\n\n const declared = declaredResponses(entry);\n\n for (const [status, { body, ...rest }] of declared) {\n const described =\n body === null ? undefined : emitted(body, \"a response\", warn);\n\n const headers = declaredHeaders({ body, ...rest }, warn);\n\n add(status, {\n placeholder: describeStatus(status),\n said: described ? wordsOf(described, envelopes) : [],\n schemas: described\n ? branchesFor(unionOnly(described), Number(status), envelopes, warn)\n : [],\n ...(headers === undefined ? {} : { headers }),\n });\n }\n\n /**\n * A route that declares nothing answers with something: a `200`, as far\n * as the document can tell. One that declares only a `303`, or only its\n * failures, has said what it answers with, and a success it never sends\n * would be a response a generated client waits for in vain.\n */\n if (declared.length === 0) {\n add(\"200\", { placeholder: \"Successful response\", said: [], schemas: [] });\n }\n\n for (const [status, answer] of failures(\n entry,\n options,\n contributed,\n components,\n envelopes,\n warn,\n )) {\n add(String(status), answer);\n }\n\n const described: Record<string, ResponseObject> = {};\n\n for (const [status, list] of answers) {\n described[status] = merge(list, envelopes);\n }\n\n return described;\n}\n\n/**\n * Everything the route can answer with that its own schema does not say:\n * what its hooks declare, and what the framework itself answers.\n */\nfunction failures(\n entry: RouteTableEntry,\n options: AppOptions,\n contributed: HookContributions,\n components: SchemaComponents,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): [status: number, answer: Answer][] {\n const schema = entry.def.schema;\n const found: [number, Answer][] = [];\n\n /**\n * Refers to the definition of one failure: the one of its status and\n * code, or — for a failure whose code only the hook knows and did not\n * declare — one of its own, named after the status.\n */\n const envelopeRef = (\n status: number,\n error?: string,\n message?: string,\n fields?: DocumentedResponse[\"fields\"],\n ): Record<string, unknown> => {\n const described = envelopes.format.describe({\n status,\n ...(error === undefined ? {} : { error }),\n ...(message === undefined ? {} : { message }),\n fields: fields ?? {},\n });\n\n const ref =\n error === undefined\n ? components.ref(failureName(status), described)\n : envelopes.ref(status, error, described, warn);\n\n return ref as unknown as Record<string, unknown>;\n };\n\n if (\n schema?.params ||\n schema?.query ||\n schema?.headers ||\n schema?.cookies ||\n schema?.body\n ) {\n found.push([\n options.validationStatus,\n {\n said: [\n {\n code: \"VALIDATION_FAILED\",\n text: \"Request failed schema validation\",\n },\n ],\n schemas: [\n envelopes.ref(\n options.validationStatus,\n \"VALIDATION_FAILED\",\n envelopes.format.describe({\n status: options.validationStatus,\n error: \"VALIDATION_FAILED\",\n message: \"Validation failed\",\n fields: { issues },\n }),\n warn,\n ) as unknown as Record<string, unknown>,\n ],\n },\n ]);\n }\n\n for (const requirement of contributed.security) {\n const status = requirement.status ?? 401;\n\n found.push([\n status,\n {\n said: [\n said(\n requirement.error,\n requirement.description ??\n `Request did not satisfy ${requirement.name}`,\n ),\n ],\n schemas: [envelopeRef(status, requirement.error, requirement.message)],\n },\n ]);\n }\n\n for (const response of contributed.responses) {\n const described = response.schema\n ? emitted(response.schema, \"a hook's response\", warn)\n : undefined;\n\n found.push([\n response.status,\n {\n said: [said(response.error, response.description)],\n schemas: described\n ? branchesFor(described, response.status, envelopes, warn)\n : [\n envelopeRef(\n response.status,\n response.error,\n response.message,\n response.fields,\n ),\n ],\n ...(response.headers ? { headers: response.headers } : {}),\n },\n ]);\n }\n\n if (schema?.body || entry.def.bodyType || entry.def.rawBody) {\n const unparsable = parseFailure(entry.def.bodyType);\n\n if (unparsable) {\n found.push([\n 400,\n {\n said: [\n said(\n unparsable.error,\n \"Body could not be parsed in the declared shape\",\n ),\n ],\n schemas: [envelopeRef(400, unparsable.error, unparsable.message)],\n },\n ]);\n }\n\n found.push([\n 413,\n {\n said: [\n said(\"BODY_TOO_LARGE\", \"Body exceeded the configured size limit\"),\n ],\n schemas: [\n envelopeRef(\n 413,\n \"BODY_TOO_LARGE\",\n \"Body exceeds the configured limit\",\n ),\n ],\n },\n ]);\n }\n\n found.push([\n 500,\n {\n said: [\n said(\n \"INTERNAL_SERVER_ERROR\",\n \"The request failed and nothing mapped the failure\",\n ),\n ],\n schemas: [\n envelopeRef(500, \"INTERNAL_SERVER_ERROR\", \"Internal Server Error\"),\n ],\n },\n ]);\n\n return found;\n}\n\n/**\n * One way a route can answer with a status: what the route declared, what\n * a hook declared, or what the framework answers by itself.\n *\n * `schemas` are the alternatives of the body, each envelope already a\n * reference to its definition; empty when the answer has no body to\n * describe.\n *\n * `said` is what the answer says about itself, with the code each part is\n * about when it is known: a hook's description, the framework's, what a\n * route's schema says. A route whose schema says nothing has only its\n * `placeholder` — the reason phrase — which stands for the status when\n * nothing else describes it.\n */\ninterface Answer {\n readonly said: readonly Said[];\n readonly placeholder?: string;\n readonly schemas: readonly Record<string, unknown>[];\n readonly headers?: Readonly<Record<string, HeaderObject>>;\n}\n\n/** One description, and the code it describes when that is known. */\ninterface Said {\n readonly code?: string;\n readonly text: string;\n}\n\nfunction said(code: string | undefined, text: string): Said {\n return code === undefined ? { text } : { code, text };\n}\n\n/**\n * What a route's schema says about the status it is declared for: its own\n * `description`, or — for a union that has none — each branch's, with the\n * branch's code. A schema that says nothing says nothing here either.\n */\nfunction wordsOf(schema: JsonSchemaObject, envelopes: Envelopes): Said[] {\n if (typeof schema.description === \"string\") {\n return [said(envelopes.format.code(schema), schema.description)];\n }\n\n return branchesOf(unionOnly(schema), envelopes.format.code).flatMap(\n (branch) =>\n typeof branch.description === \"string\"\n ? [said(envelopes.format.code(branch), branch.description)]\n : [],\n );\n}\n\n/**\n * A union without the `description` it carried as a whole — which says\n * what the status is, and is used as the status's description — so its\n * branches can join the status's own alternatives. Anything but a union\n * is kept as it is, its description included, for its definition.\n */\nfunction unionOnly(schema: JsonSchemaObject): JsonSchemaObject {\n if (\n typeof schema.description !== \"string\" ||\n (!Array.isArray(schema.anyOf) && !Array.isArray(schema.oneOf))\n ) {\n return schema;\n }\n\n const { description: _, ...union } = schema;\n\n return union;\n}\n\n/**\n * Folds everything that answers with one status into one response.\n *\n * Three things can meet on a status: what the route declared, and any\n * number of failures the framework fills in — a rejected schema and an\n * unparsable body collide on `400` as soon as an application configures\n * `validation: { status: 400 }`, and a route that answers `404` itself\n * shares that status with nothing while sharing `400` with the parser.\n *\n * All of them are true at once, so the document says so with an `anyOf`\n * rather than picking a winner. The route's own body comes first: it is\n * the answer the endpoint is about, and the failures are what can happen\n * to it. Identical bodies are folded together — a `$ref` repeated is one\n * alternative, not two.\n *\n * Headers are gathered the same way, the first description of a name\n * standing for all of them; descriptions as {@link wording} words them.\n */\nfunction merge(list: readonly Answer[], envelopes: Envelopes): ResponseObject {\n const schemas = distinct(list.flatMap((answer) => answer.schemas));\n const headers: Record<string, HeaderObject> = {};\n\n for (const answer of list) {\n for (const [name, header] of Object.entries(answer.headers ?? {})) {\n headers[name] ??= header;\n }\n }\n\n return {\n description: wording(list),\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n ...(schemas.length > 0\n ? {\n content: {\n \"application/json\": { schema: unionOf(schemas, envelopes) },\n },\n }\n : {}),\n };\n}\n\n/**\n * The description of a status, from everything that answers with it.\n *\n * One thing said is the description. Several are a list, each item led\n * by the code it is about, so a reader sees which description goes with\n * which code — descriptions are CommonMark, and every renderer draws the\n * list. The same code said the same way twice, by the route and a hook,\n * is one item. With nothing said at all, the route's placeholder stands.\n */\nfunction wording(list: readonly Answer[]): string {\n const seen = new Set<string>();\n const items: Said[] = [];\n\n for (const answer of list) {\n for (const item of answer.said) {\n const key = `${item.code ?? \"\"}\\n${item.text}`;\n\n if (!seen.has(key)) {\n seen.add(key);\n items.push(item);\n }\n }\n }\n\n const [only] = items;\n\n if (items.length === 1 && only) {\n return only.text;\n }\n\n if (items.length > 1) {\n return items\n .map((item) =>\n item.code === undefined\n ? `- ${item.text}`\n : `- \\`${item.code}\\`: ${item.text}`,\n )\n .join(\"\\n\");\n }\n\n return list.find((answer) => answer.placeholder)?.placeholder ?? \"\";\n}\n\n/**\n * The alternatives of a body as one schema.\n *\n * When every alternative is an envelope, each with its own code, the union\n * says so with a `discriminator` on `error`: a generated client then\n * builds a tagged union and narrows on the code, instead of trying the\n * shapes in turn. The mapping is spelled out, because without it OpenAPI\n * matches the value against the component's name — `Unauthorized`, where\n * the body says `UNAUTHORIZED`. The field is the error format's; a format\n * that names none — its code nested below the top — has no discriminator.\n */\nfunction unionOf(\n schemas: readonly Record<string, unknown>[],\n envelopes: Envelopes,\n): Record<string, unknown> {\n const [only] = schemas;\n\n if (schemas.length === 1 && only) {\n return only;\n }\n\n const propertyName = envelopes.format.discriminator;\n\n if (propertyName === undefined) {\n return { anyOf: schemas };\n }\n\n const mapping: Record<string, string> = {};\n\n for (const schema of schemas) {\n const ref = (schema as { $ref?: unknown }).$ref;\n const code = typeof ref === \"string\" ? envelopes.codeOf(ref) : undefined;\n\n if (typeof ref !== \"string\" || code === undefined) {\n return { anyOf: schemas };\n }\n\n mapping[code] = ref;\n }\n\n return {\n anyOf: schemas,\n discriminator: { propertyName, mapping },\n };\n}\n\nfunction distinct(\n schemas: readonly Record<string, unknown>[],\n): Record<string, unknown>[] {\n const seen = new Set<string>();\n\n return schemas.filter((schema) => {\n const fingerprint = JSON.stringify(schema);\n\n if (seen.has(fingerprint)) {\n return false;\n }\n\n seen.add(fingerprint);\n\n return true;\n });\n}\n\nfunction describeStatus(status: string): string {\n if (status === \"204\") {\n return \"No content\";\n }\n\n return status.startsWith(\"2\")\n ? \"Successful response\"\n : errorBody(Number(status)).message;\n}\n\n/**\n * What a validation failure carries besides the code and the message: every\n * issue, with where it is. Handed to the error format as a field, for the\n * format to place.\n */\nconst issues: JsonSchema = {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"message\", \"path\"],\n properties: {\n message: { type: \"string\" },\n path: { type: \"array\", items: { type: [\"string\", \"number\"] } },\n },\n },\n};\n\n/**\n * How a body of this type fails to parse — or nothing, for a text or a\n * stream body: one is whatever bytes arrived, the other is handed over\n * unread, and neither can be malformed.\n */\nfunction parseFailure(\n bodyType: BodyType | undefined,\n): { error: string; message: string } | undefined {\n if (bodyType === \"text\" || bodyType === \"stream\") {\n return undefined;\n }\n\n return bodyType === \"form\"\n ? { error: \"MALFORMED_FORM\", message: \"Body is not a valid form\" }\n : { error: \"MALFORMED_JSON\", message: \"Body is not valid JSON\" };\n}\n\nfunction capitalize(value: string): string {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n\nfunction lowerFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n",
|
|
9
|
+
"/**\n * One route table entry, described as an OpenAPI operation.\n *\n * Bodies and responses live here; parameters are in `parameters.ts`. The\n * error responses a route can produce without the author writing anything\n * — a rejected schema, an unparsable body, a body over the limit — are\n * derived from what the route declares and from the options the\n * application actually runs with.\n *\n * @module\n */\n\nimport type {\n AnySchema,\n AppOptions,\n BodyType,\n ResponseEntry,\n RouteTableEntry,\n} from \"@tetsujs/core\";\nimport { errorBody } from \"@tetsujs/core\";\nimport type {\n DocumentedResponse,\n HookContributions,\n SecurityRequirement,\n} from \"./annotations.ts\";\nimport { contributionsOf, handlerDocsOf } from \"./annotations.ts\";\nimport type { SchemaComponents } from \"./components.ts\";\nimport { failureName } from \"./components.ts\";\nimport type {\n ContentMap,\n HeaderObject,\n OperationObject,\n ResponseObject,\n} from \"./document.ts\";\nimport type { JsonSchemaObject } from \"./emit.ts\";\nimport { emitted } from \"./emit.ts\";\nimport type { Envelopes } from \"./envelopes.ts\";\nimport { branchesOf } from \"./envelopes.ts\";\nimport type { JsonSchema } from \"./json-schema.ts\";\nimport { isJson } from \"./media.ts\";\nimport { partParameters, pathParameters } from \"./parameters.ts\";\n\n/** Describes one route. */\nexport function operationOf(\n entry: RouteTableEntry,\n options: AppOptions,\n components: SchemaComponents,\n envelopes: Envelopes,\n ids: OperationIds,\n warn: (message: string) => void,\n): OperationObject {\n const schema = entry.def.schema;\n\n const parameters = [\n ...pathParameters(entry.path, schema?.params, warn),\n ...partParameters(schema?.query, \"query\", warn),\n ...partParameters(schema?.headers, \"header\", warn),\n ...partParameters(schema?.cookies, \"cookie\", warn),\n ];\n\n const body = requestBody(entry, warn);\n const contributed = contributionsOf(entry.hooks, warn);\n\n return {\n operationId: ids.take(entry),\n ...(entry.def.docs?.summary === undefined\n ? {}\n : { summary: entry.def.docs.summary }),\n ...(entry.def.docs?.description === undefined\n ? {}\n : { description: entry.def.docs.description }),\n ...(entry.def.docs?.tags === undefined\n ? {}\n : { tags: entry.def.docs.tags }),\n ...(entry.def.docs?.deprecated === undefined\n ? {}\n : { deprecated: entry.def.docs.deprecated }),\n ...(parameters.length > 0 ? { parameters } : {}),\n ...(body ? { requestBody: body } : {}),\n ...(contributed.security.length > 0\n ? { security: securityOf(contributed.conditions) }\n : {}),\n responses: responses(\n entry,\n options,\n contributed,\n components,\n envelopes,\n warn,\n ),\n };\n}\n\n/**\n * Records the envelopes a route declares, so that its definitions are the\n * ones the document keeps — whichever operation refers to them first. What\n * its handler was annotated with is the route's own too, and declares the\n * same way.\n *\n * Runs before any operation is built. A schema that cannot describe itself\n * is skipped without a word: building the operation says so, once. A body\n * of another type than JSON is no envelope.\n */\nexport function declareEnvelopes(\n entry: RouteTableEntry,\n envelopes: Envelopes,\n): void {\n const own: [status: number, body: AnySchema][] = [];\n\n for (const [status, { body, contentType }] of declaredResponses(entry)) {\n if (body !== null && (contentType === undefined || isJson(contentType))) {\n own.push([Number(status), body]);\n }\n }\n\n for (const response of handlerDocsOf(entry.def.handler)?.responses ?? []) {\n const { contentType, schema, status } = response;\n\n if (schema && (contentType === undefined || isJson(contentType))) {\n own.push([status, schema]);\n }\n }\n\n const code = envelopes.format.code;\n\n for (const [status, body] of own) {\n const described = emitted(body, \"\", () => {});\n\n for (const branch of described ? branchesOf(described, code) : []) {\n const found = code(branch);\n\n if (found !== undefined) {\n envelopes.declare(status, found, branch);\n }\n }\n }\n}\n\n/** One status of a route's response map, whichever form it was written in. */\ninterface Declared {\n readonly body: AnySchema | null;\n readonly headers?: AnySchema;\n readonly cookies?: AnySchema;\n readonly contentType?: string;\n}\n\n/** The route's response map as pairs; a single schema is its `200`. */\nfunction declaredResponses(\n entry: RouteTableEntry,\n): [status: string, declared: Declared][] {\n const response = entry.def.schema?.response;\n\n if (!response) {\n return [];\n }\n\n if (\"~standard\" in response) {\n return [[\"200\", { body: response as AnySchema }]];\n }\n\n return Object.entries(response).map(([status, value]) => [\n status,\n asDeclared(value as AnySchema | ResponseEntry | null),\n ]);\n}\n\nfunction asDeclared(value: AnySchema | ResponseEntry | null): Declared {\n if (value === null || \"~standard\" in value) {\n return { body: value as AnySchema | null };\n }\n\n return {\n body: value.body ?? null,\n ...(value.headers === undefined ? {} : { headers: value.headers }),\n ...(value.cookies === undefined ? {} : { cookies: value.cookies }),\n ...(value.contentType === undefined\n ? {}\n : { contentType: value.contentType }),\n };\n}\n\n/**\n * The headers a declared status says it leaves with: one per property of\n * its `headers` schema, required as the schema says, and its cookies as\n * the one header that sets them.\n *\n * A property's `description` is the header's: it is what a renderer\n * shows in the header's row.\n */\nfunction declaredHeaders(\n declared: Declared,\n warn: (message: string) => void,\n): Record<string, HeaderObject> | undefined {\n const headers: Record<string, HeaderObject> = {};\n\n const [properties, required] = shapeOf(\n declared.headers,\n \"a response's headers\",\n warn,\n );\n\n for (const [name, property] of Object.entries(properties)) {\n const { description, ...schema } = property;\n\n headers[name] = {\n ...(typeof description === \"string\" ? { description } : {}),\n ...(required.has(name) ? { required: true } : {}),\n schema: schema as JsonSchema,\n };\n }\n\n const cookies = setCookie(declared.cookies, warn);\n\n if (cookies) {\n headers[\"set-cookie\"] = cookies;\n }\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\n/**\n * The cookies a status sets, as the header that sets them. OpenAPI has no\n * object for a cookie a response sets — only a `set-cookie` header — so the\n * cookies are listed in its description, by name, each with its own\n * description; the header is required when any of them is.\n */\nfunction setCookie(\n schema: AnySchema | undefined,\n warn: (message: string) => void,\n): HeaderObject | undefined {\n const [properties, required] = shapeOf(schema, \"a response's cookies\", warn);\n\n const names = Object.keys(properties);\n\n if (names.length === 0) {\n return undefined;\n }\n\n const lines = names.map((name) => {\n const description = properties[name]?.[\"description\"];\n\n return typeof description === \"string\"\n ? `- \\`${name}\\`: ${description}`\n : `- \\`${name}\\``;\n });\n\n return {\n description: [\"Sets these cookies:\", \"\", ...lines].join(\"\\n\"),\n ...(required.size > 0 ? { required: true } : {}),\n schema: { type: \"string\" },\n };\n}\n\n/**\n * The properties of an object schema, and which of them it requires.\n *\n * Read as the schema's input: a response's headers and cookies are checked\n * against it and sent as the handler set them, not as the schema returns\n * them — unlike a body, whose checked value is what gets serialized. A\n * field with a default is one the handler may leave out, and the response\n * then leaves without it.\n */\nfunction shapeOf(\n schema: AnySchema | undefined,\n subject: string,\n warn: (message: string) => void,\n): [Record<string, Record<string, unknown>>, Set<string>] {\n const described = schema\n ? emitted(schema, subject, warn, \"input\")\n : undefined;\n\n const properties = (described?.properties ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n const required = new Set(\n Array.isArray(described?.required) ? (described.required as string[]) : [],\n );\n\n return [properties, required];\n}\n\n/**\n * A described body as the alternatives the document lists: every envelope\n * in it a reference to the one definition of its status and code, and a\n * union taken apart into its branches, so that it joins the other answers\n * of its status rather than nesting inside them.\n */\nfunction branchesFor(\n schema: JsonSchemaObject,\n status: number,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): Record<string, unknown>[] {\n return branchesOf(schema, envelopes.format.code).map((branch) => {\n const code = envelopes.format.code(branch);\n\n return code === undefined\n ? branch\n : (envelopes.ref(status, code, branch, warn) as unknown as Record<\n string,\n unknown\n >);\n });\n}\n\n/**\n * The security a route asks for, as OpenAPI spells it.\n *\n * OpenAPI reads the entries of an operation's `security` as alternatives —\n * any one of them authorizes a request — and the schemes inside one entry\n * as all required. A route's conditions are the other way round: every\n * hook runs, so every condition is required, and a condition is satisfied\n * by any one of its alternatives. The entries are therefore the\n * combinations — one alternative from each condition, taken together:\n * a hook accepting a cookie *or* a token, next to a CSRF check, is\n * `[{ cookie, csrf }, { token, csrf }]`. With no alternatives anywhere\n * that is a single entry holding every scheme, which is the usual case.\n *\n * Two alternatives of one scheme in a combination ask for the scopes of\n * both; a combination that comes out twice is listed once.\n */\nfunction securityOf(\n conditions: readonly (readonly SecurityRequirement[])[],\n): Record<string, readonly string[]>[] {\n let combinations: Record<string, readonly string[]>[] = [{}];\n\n for (const alternatives of conditions) {\n combinations = combinations.flatMap((combination) =>\n alternatives.map((requirement) => ({\n ...combination,\n [requirement.name]: joined(\n combination[requirement.name],\n requirement.scopes,\n ),\n })),\n );\n }\n\n const seen = new Set<string>();\n\n return combinations.filter((combination) => {\n const key = JSON.stringify(\n Object.entries(combination)\n .map(([name, scopes]) => [name, [...scopes].sort()])\n .sort(),\n );\n\n if (seen.has(key)) {\n return false;\n }\n\n seen.add(key);\n\n return true;\n });\n}\n\n/** The scopes of a scheme already in a combination, and another's. */\nfunction joined(\n present: readonly string[] | undefined,\n added: readonly string[] | undefined,\n): readonly string[] {\n const scopes = [...(present ?? [])];\n\n for (const scope of added ?? []) {\n if (!scopes.includes(scope)) {\n scopes.push(scope);\n }\n }\n\n return scopes;\n}\n\n/**\n * Hands out the `operationId` of every route in one document.\n *\n * An `operationId` is a contract: a generated client names its methods\n * after them, so an id that moves breaks code nobody reviewing the change\n * sees. The id is therefore always stated or derived from names the\n * author wrote — never from where a route happened to land:\n *\n * | | |\n * | --- | --- |\n * | `docs.operationId` on the route | taken as written |\n * | a route of a named controller | the name and the field — `authRequestCode` |\n * | a route of an unnamed object | the field — `requestCode` |\n * | a route mounted standalone | its method and path — `postAuthCode` |\n *\n * Two routes arriving at one id is an error, not something to route\n * around. Falling back to the method and path, or numbering the second\n * one, would hand one of them an id that changes when a path is edited or\n * a route is added — silently, in someone else's SDK. The error names\n * both routes and the two ways out: a controller name of its own, or an\n * id stated on the route. The core already refuses two controllers of\n * one name; what reaches this is two stated ids, or a stated id meeting a\n * derived one.\n */\nexport interface OperationIds {\n /** The id for this route, unique within the document being built. */\n take(entry: RouteTableEntry): string;\n}\n\nexport function operationIds(): OperationIds {\n const taken = new Map<string, RouteTableEntry>();\n\n return {\n take(entry: RouteTableEntry): string {\n const id = idOf(entry);\n const holder = taken.get(id);\n\n if (holder !== undefined) {\n throw new Error(\n `operationId \"${id}\" is taken by both ${describe(holder)} and ${describe(entry)} — a generated client would get one method for two operations. Give one of them docs.operationId, or its controller a name of its own.`,\n );\n }\n\n taken.set(id, entry);\n\n return id;\n },\n };\n}\n\n/** The id a route asks for, before anything checks it is free. */\nfunction idOf(entry: RouteTableEntry): string {\n const stated = entry.def.docs?.operationId;\n\n if (stated !== undefined) {\n return stated;\n }\n\n if (entry.name === undefined) {\n return derivedId(entry);\n }\n\n if (entry.controller === undefined) {\n return entry.name;\n }\n\n const controller = entry.controller.replace(/Controller$/, \"\");\n\n return `${lowerFirst(controller)}${capitalize(entry.name)}`;\n}\n\n/** How the error above names a route: the one line that finds it. */\nfunction describe(entry: RouteTableEntry): string {\n return `${entry.method} ${entry.path}`;\n}\n\n/**\n * What a route mounted standalone is named by: it has no field and no\n * controller, and its method and path are what it has.\n */\nfunction derivedId(entry: RouteTableEntry): string {\n return `${entry.method.toLowerCase()}${entry.path\n .split(/[/:*]/)\n .filter(Boolean)\n .map(capitalize)\n .join(\"\")}`;\n}\n\n/**\n * Describes the request body, when the route reads one.\n *\n * The media type follows the declaration, not a guess: `\"form\"` accepts\n * both multipart and urlencoded at runtime, so both are listed — unless\n * the schema declares a binary field, which only multipart can carry.\n */\nfunction requestBody(\n entry: RouteTableEntry,\n warn: (message: string) => void,\n): { required: boolean; content: ContentMap } | undefined {\n const declared = entry.def.schema?.body;\n\n /**\n * A body is read when the core reads one: a schema, a declared shape, or\n * `rawBody` — which parses JSON as any body does, next to keeping its\n * bytes. Without a schema the document says what the body is, not what\n * is in it.\n */\n const bodyType =\n entry.def.bodyType ?? (declared || entry.def.rawBody ? \"json\" : undefined);\n\n if (!bodyType) {\n return undefined;\n }\n\n const described = declared\n ? emitted(declared, \"the body\", warn, \"input\")\n : undefined;\n\n const schema = described ? { schema: described } : {};\n\n // Whether a body must be sent is a question about the wire, not about\n // the schema: `json` and `form` parse it before anything is validated,\n // and an empty one fails that parse with a `400` — so the client has to\n // send something whether or not a shape was declared. `text` has no such\n // step, because an absent body reads as `\"\"` just like an empty one; if\n // that string is unacceptable, the schema is where it says so. Neither\n // has `stream`: an absent body is handed over as an empty stream.\n const required = bodyType !== \"text\" && bodyType !== \"stream\";\n\n if (bodyType === \"stream\") {\n /**\n * Bytes with no shape to describe: the route takes the body unread, so\n * the document says what it is rather than what is in it. A `stream`\n * route cannot carry a body schema at all — the compiler refuses the\n * pair — so there is never a `schema` to attach here.\n */\n return { required, content: { \"application/octet-stream\": {} } };\n }\n\n if (bodyType === \"text\") {\n return { required, content: { \"text/plain\": schema } };\n }\n\n if (bodyType === \"json\") {\n return { required, content: { \"application/json\": schema } };\n }\n\n const content: ContentMap = { \"multipart/form-data\": schema };\n\n if (!described || !carriesBinary(described)) {\n content[\"application/x-www-form-urlencoded\"] = schema;\n }\n\n return { required, content };\n}\n\n/**\n * Whether any part of an emitted schema describes binary content.\n *\n * Walked with a stack rather than by recursion, and remembering what it has\n * already seen: the shape comes from an adapter, so its depth is the\n * author's to choose and nothing says it is a tree. Recursion would answer\n * a deep one by overflowing the stack, and a self-referential one by never\n * returning — both while `createApp` is still assembling the application.\n */\nfunction carriesBinary(root: unknown): boolean {\n const pending: unknown[] = [root];\n const seen = new Set<unknown>();\n\n while (pending.length > 0) {\n const node = pending.pop();\n\n if (node === null || typeof node !== \"object\" || seen.has(node)) {\n continue;\n }\n\n seen.add(node);\n\n if ((node as { contentEncoding?: unknown }).contentEncoding === \"binary\") {\n return true;\n }\n\n for (const value of Object.values(node)) {\n pending.push(value);\n }\n }\n\n return false;\n}\n\n/**\n * Describes what the route answers with.\n *\n * The declared responses come first; the framework's own failures fill in\n * around them, and never over them — an author who documented `422`\n * himself has said something more specific than this could.\n */\nfunction responses(\n entry: RouteTableEntry,\n options: AppOptions,\n contributed: HookContributions,\n components: SchemaComponents,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): Record<string, ResponseObject> {\n const answers = new Map<string, Answer[]>();\n\n const add = (status: string, answer: Answer): void => {\n answers.set(status, [...(answers.get(status) ?? []), answer]);\n };\n\n const declared = declaredResponses(entry);\n\n for (const [status, { body, contentType, ...rest }] of declared) {\n const described =\n body === null ? undefined : emitted(body, \"a response\", warn);\n\n const headers = declaredHeaders({ body, ...rest }, warn);\n const own = contentType !== undefined && !isJson(contentType);\n\n add(status, {\n placeholder: describeStatus(status),\n said: described ? wordsOf(described, envelopes) : [],\n schemas:\n described && !own\n ? branchesFor(unionOnly(described), Number(status), envelopes, warn)\n : [],\n ...(own ? { media: [mediaOf(contentType, described)] } : {}),\n ...(headers === undefined ? {} : { headers }),\n });\n }\n\n const handled = handlerDocsOf(entry.def.handler)?.responses ?? [];\n const envelopeRef = envelopeRefs(components, envelopes, warn);\n\n for (const response of handled) {\n add(\n String(response.status),\n documentedAnswer(\n response,\n \"a handler's response\",\n envelopeRef,\n envelopes,\n warn,\n ),\n );\n }\n\n /**\n * A route that declares nothing answers with something: a `200`, as far\n * as the document can tell. One that declares only a `303`, or only its\n * failures, has said what it answers with, and a success it never sends\n * would be a response a generated client waits for in vain. So has a\n * route whose handler describes what it answers with.\n */\n if (declared.length === 0 && handled.length === 0) {\n add(\"200\", { placeholder: \"Successful response\", said: [], schemas: [] });\n }\n\n for (const [status, answer] of failures(\n entry,\n options,\n contributed,\n components,\n envelopes,\n warn,\n )) {\n add(String(status), answer);\n }\n\n const described: Record<string, ResponseObject> = {};\n\n for (const [status, list] of answers) {\n described[status] = merge(list, envelopes);\n }\n\n return described;\n}\n\n/**\n * Everything the route can answer with that its own schema does not say:\n * what its hooks declare, and what the framework itself answers.\n */\nfunction failures(\n entry: RouteTableEntry,\n options: AppOptions,\n contributed: HookContributions,\n components: SchemaComponents,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): [status: number, answer: Answer][] {\n const schema = entry.def.schema;\n const found: [number, Answer][] = [];\n const envelopeRef = envelopeRefs(components, envelopes, warn);\n\n if (\n schema?.params ||\n schema?.query ||\n schema?.headers ||\n schema?.cookies ||\n schema?.body\n ) {\n found.push([\n options.validationStatus,\n {\n said: [\n {\n code: \"VALIDATION_FAILED\",\n text: \"Request failed schema validation\",\n },\n ],\n schemas: [\n envelopes.ref(\n options.validationStatus,\n \"VALIDATION_FAILED\",\n envelopes.format.describe({\n status: options.validationStatus,\n error: \"VALIDATION_FAILED\",\n message: \"Validation failed\",\n fields: { issues },\n }),\n warn,\n ) as unknown as Record<string, unknown>,\n ],\n },\n ]);\n }\n\n for (const requirement of contributed.security) {\n const status = requirement.status ?? 401;\n\n found.push([\n status,\n {\n said: [\n said(\n requirement.error,\n requirement.description ??\n `Request did not satisfy ${requirement.name}`,\n ),\n ],\n schemas:\n status >= 400\n ? [envelopeRef(status, requirement.error, requirement.message)]\n : [],\n },\n ]);\n }\n\n for (const response of contributed.responses) {\n found.push([\n response.status,\n documentedAnswer(\n response,\n \"a hook's response\",\n envelopeRef,\n envelopes,\n warn,\n ),\n ]);\n }\n\n if (schema?.body || entry.def.bodyType || entry.def.rawBody) {\n const unparsable = parseFailure(entry.def.bodyType);\n\n if (unparsable) {\n found.push([\n 400,\n {\n said: [\n said(\n unparsable.error,\n \"Body could not be parsed in the declared shape\",\n ),\n ],\n schemas: [envelopeRef(400, unparsable.error, unparsable.message)],\n },\n ]);\n }\n\n found.push([\n 413,\n {\n said: [\n said(\"BODY_TOO_LARGE\", \"Body exceeded the configured size limit\"),\n ],\n schemas: [\n envelopeRef(\n 413,\n \"BODY_TOO_LARGE\",\n \"Body exceeds the configured limit\",\n ),\n ],\n },\n ]);\n }\n\n found.push([\n 500,\n {\n said: [\n said(\n \"INTERNAL_SERVER_ERROR\",\n \"The request failed and nothing mapped the failure\",\n ),\n ],\n schemas: [\n envelopeRef(500, \"INTERNAL_SERVER_ERROR\", \"Internal Server Error\"),\n ],\n },\n ]);\n\n return found;\n}\n\n/**\n * Refers to the definition of one failure: the one of its status and code,\n * or — for a failure whose code only its hook knows and did not declare —\n * one of its own, named after the status.\n */\ntype EnvelopeRef = (\n status: number,\n error?: string,\n message?: string,\n fields?: DocumentedResponse[\"fields\"],\n) => Record<string, unknown>;\n\nfunction envelopeRefs(\n components: SchemaComponents,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): EnvelopeRef {\n return (status, error, message, fields) => {\n const described = envelopes.format.describe({\n status,\n ...(error === undefined ? {} : { error }),\n ...(message === undefined ? {} : { message }),\n fields: fields ?? {},\n });\n\n const ref =\n error === undefined\n ? components.ref(failureName(status), described)\n : envelopes.ref(status, error, described, warn);\n\n return ref as unknown as Record<string, unknown>;\n };\n}\n\n/**\n * What a hook or a handler said it answers with, as an answer of its\n * status.\n *\n * A body of a type of its own is described under that type. A schema\n * without one is JSON. Neither is the framework's envelope for an error\n * status — a hook refuses by throwing, and what it throws leaves in the\n * envelope — and no body at all for any other: a handler's `304`, a hook's\n * redirect.\n */\nfunction documentedAnswer(\n response: DocumentedResponse,\n subject: string,\n envelopeRef: EnvelopeRef,\n envelopes: Envelopes,\n warn: (message: string) => void,\n): Answer {\n const described = response.schema\n ? emitted(response.schema, subject, warn)\n : undefined;\n\n const answer = {\n said: [said(response.error, response.description)],\n ...(response.headers ? { headers: response.headers } : {}),\n };\n\n if (response.contentType !== undefined && !isJson(response.contentType)) {\n return {\n ...answer,\n schemas: [],\n media: [mediaOf(response.contentType, described)],\n };\n }\n\n if (described) {\n return {\n ...answer,\n schemas: branchesFor(described, response.status, envelopes, warn),\n };\n }\n\n return {\n ...answer,\n schemas:\n response.status >= 400\n ? [\n envelopeRef(\n response.status,\n response.error,\n response.message,\n response.fields,\n ),\n ]\n : [],\n };\n}\n\n/** A body of a type other than JSON, and its schema when there is one. */\ninterface Media {\n readonly type: string;\n readonly schema?: Record<string, unknown>;\n}\n\nfunction mediaOf(type: string, schema: JsonSchemaObject | undefined): Media {\n return schema === undefined\n ? { type }\n : { type, schema: schema as Record<string, unknown> };\n}\n\n/**\n * One way a route can answer with a status: what the route declared, what\n * a hook declared, or what the framework answers by itself.\n *\n * `schemas` are the alternatives of the body, each envelope already a\n * reference to its definition; empty when the answer has no body to\n * describe. `media` are bodies of other types than JSON, each described\n * under its own.\n *\n * `said` is what the answer says about itself, with the code each part is\n * about when it is known: a hook's description, the framework's, what a\n * route's schema says. A route whose schema says nothing has only its\n * `placeholder` — the reason phrase — which stands for the status when\n * nothing else describes it.\n */\ninterface Answer {\n readonly said: readonly Said[];\n readonly placeholder?: string;\n readonly schemas: readonly Record<string, unknown>[];\n readonly media?: readonly Media[];\n readonly headers?: Readonly<Record<string, HeaderObject>>;\n}\n\n/** One description, and the code it describes when that is known. */\ninterface Said {\n readonly code?: string;\n readonly text: string;\n}\n\nfunction said(code: string | undefined, text: string): Said {\n return code === undefined ? { text } : { code, text };\n}\n\n/**\n * What a route's schema says about the status it is declared for: its own\n * `description`, or — for a union that has none — each branch's, with the\n * branch's code. A schema that says nothing says nothing here either.\n */\nfunction wordsOf(schema: JsonSchemaObject, envelopes: Envelopes): Said[] {\n if (typeof schema.description === \"string\") {\n return [said(envelopes.format.code(schema), schema.description)];\n }\n\n return branchesOf(unionOnly(schema), envelopes.format.code).flatMap(\n (branch) =>\n typeof branch.description === \"string\"\n ? [said(envelopes.format.code(branch), branch.description)]\n : [],\n );\n}\n\n/**\n * A union without the `description` it carried as a whole — which says\n * what the status is, and is used as the status's description — so its\n * branches can join the status's own alternatives. Anything but a union\n * is kept as it is, its description included, for its definition.\n */\nfunction unionOnly(schema: JsonSchemaObject): JsonSchemaObject {\n if (\n typeof schema.description !== \"string\" ||\n (!Array.isArray(schema.anyOf) && !Array.isArray(schema.oneOf))\n ) {\n return schema;\n }\n\n const { description: _, ...union } = schema;\n\n return union;\n}\n\n/**\n * Folds everything that answers with one status into one response.\n *\n * Three things can meet on a status: what the route declared, and any\n * number of failures the framework fills in — a rejected schema and an\n * unparsable body collide on `400` as soon as an application configures\n * `validation: { status: 400 }`, and a route that answers `404` itself\n * shares that status with nothing while sharing `400` with the parser.\n *\n * All of them are true at once, so the document says so with an `anyOf`\n * rather than picking a winner. The route's own body comes first: it is\n * the answer the endpoint is about, and the failures are what can happen\n * to it. Identical bodies are folded together — a `$ref` repeated is one\n * alternative, not two.\n *\n * Headers are gathered the same way, the first description of a name\n * standing for all of them; descriptions as {@link wording} words them.\n *\n * A body of another type is not an alternative of the JSON one but a\n * second content of the same status, under its own media type: the\n * envelope an API client gets for a `404` sits next to the page a\n * browser does. JSON comes first; the others in the order they were said,\n * each type once in lower case, as media types compare. A type one answer\n * left undescribed takes any body, and is described by its type alone.\n */\nfunction merge(list: readonly Answer[], envelopes: Envelopes): ResponseObject {\n const schemas = distinct(list.flatMap((answer) => answer.schemas));\n const headers: Record<string, HeaderObject> = {};\n const media = new Map<string, Record<string, unknown>[]>();\n const unconstrained = new Set<string>();\n\n for (const answer of list) {\n for (const [name, header] of Object.entries(answer.headers ?? {})) {\n headers[name] ??= header;\n }\n\n for (const { type, schema } of answer.media ?? []) {\n const key = type.toLowerCase();\n const alternatives = media.get(key) ?? [];\n\n media.set(key, schema ? [...alternatives, schema] : alternatives);\n\n if (!schema) {\n unconstrained.add(key);\n }\n }\n }\n\n const content: ContentMap = {};\n\n if (schemas.length > 0) {\n content[\"application/json\"] = { schema: unionOf(schemas, envelopes) };\n }\n\n for (const [type, alternatives] of media) {\n const [only, ...others] = distinct(alternatives);\n\n content[type] =\n only === undefined || unconstrained.has(type)\n ? {}\n : { schema: others.length === 0 ? only : { anyOf: [only, ...others] } };\n }\n\n return {\n description: wording(list),\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n ...(Object.keys(content).length > 0 ? { content } : {}),\n };\n}\n\n/**\n * The description of a status, from everything that answers with it.\n *\n * One thing said is the description. Several are a list, each item led\n * by the code it is about, so a reader sees which description goes with\n * which code — descriptions are CommonMark, and every renderer draws the\n * list. The same code said the same way twice, by the route and a hook,\n * is one item, and so are words with no code that a coded item already\n * says — the page of a 404 described as its envelope is. With nothing said\n * at all, the route's placeholder stands.\n */\nfunction wording(list: readonly Answer[]): string {\n const seen = new Set<string>();\n const items: Said[] = [];\n\n for (const answer of list) {\n for (const item of answer.said) {\n const key = `${item.code ?? \"\"}\\n${item.text}`;\n\n if (!seen.has(key)) {\n seen.add(key);\n items.push(item);\n }\n }\n }\n\n const coded = new Set(\n items.flatMap((item) => (item.code === undefined ? [] : [item.text])),\n );\n const said = items.filter(\n (item) => item.code !== undefined || !coded.has(item.text),\n );\n\n const [only] = said;\n\n if (said.length === 1 && only) {\n return only.text;\n }\n\n if (said.length > 1) {\n return said\n .map((item) =>\n item.code === undefined\n ? `- ${item.text}`\n : `- \\`${item.code}\\`: ${item.text}`,\n )\n .join(\"\\n\");\n }\n\n return list.find((answer) => answer.placeholder)?.placeholder ?? \"\";\n}\n\n/**\n * The alternatives of a body as one schema.\n *\n * When every alternative is an envelope, each with its own code, the union\n * says so with a `discriminator` on `error`: a generated client then\n * builds a tagged union and narrows on the code, instead of trying the\n * shapes in turn. The mapping is spelled out, because without it OpenAPI\n * matches the value against the component's name — `Unauthorized`, where\n * the body says `UNAUTHORIZED`. The field is the error format's; a format\n * that names none — its code nested below the top — has no discriminator.\n */\nfunction unionOf(\n schemas: readonly Record<string, unknown>[],\n envelopes: Envelopes,\n): Record<string, unknown> {\n const [only] = schemas;\n\n if (schemas.length === 1 && only) {\n return only;\n }\n\n const propertyName = envelopes.format.discriminator;\n\n if (propertyName === undefined) {\n return { anyOf: schemas };\n }\n\n const mapping: Record<string, string> = {};\n\n for (const schema of schemas) {\n const ref = (schema as { $ref?: unknown }).$ref;\n const code = typeof ref === \"string\" ? envelopes.codeOf(ref) : undefined;\n\n if (typeof ref !== \"string\" || code === undefined) {\n return { anyOf: schemas };\n }\n\n mapping[code] = ref;\n }\n\n return {\n anyOf: schemas,\n discriminator: { propertyName, mapping },\n };\n}\n\nfunction distinct(\n schemas: readonly Record<string, unknown>[],\n): Record<string, unknown>[] {\n const seen = new Set<string>();\n\n return schemas.filter((schema) => {\n const fingerprint = JSON.stringify(schema);\n\n if (seen.has(fingerprint)) {\n return false;\n }\n\n seen.add(fingerprint);\n\n return true;\n });\n}\n\n/**\n * The description of a status nothing else describes. `default` and a range\n * such as `4XX`, OpenAPI's own keys, are no number: a reason phrase of one\n * read as `HTTP NaN`.\n */\nfunction describeStatus(status: string): string {\n if (status === \"204\") {\n return \"No content\";\n }\n\n if (status === \"default\") {\n return \"Any other response\";\n }\n\n const range = ranges[status.toUpperCase()];\n\n if (range !== undefined) {\n return range;\n }\n\n return status.startsWith(\"2\")\n ? \"Successful response\"\n : errorBody(Number(status)).message;\n}\n\n/** What a range of statuses is, by its key. */\nconst ranges: Readonly<Record<string, string>> = {\n \"1XX\": \"Informational response\",\n \"2XX\": \"Successful response\",\n \"3XX\": \"Redirection\",\n \"4XX\": \"Client error\",\n \"5XX\": \"Server error\",\n};\n\n/**\n * What a validation failure carries besides the code and the message: every\n * issue, with where it is. Handed to the error format as a field, for the\n * format to place.\n */\nconst issues: JsonSchema = {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"message\", \"path\"],\n properties: {\n message: { type: \"string\" },\n path: { type: \"array\", items: { type: [\"string\", \"number\"] } },\n },\n },\n};\n\n/**\n * How a body of this type fails to parse — or nothing, for a text or a\n * stream body: one is whatever bytes arrived, the other is handed over\n * unread, and neither can be malformed.\n */\nfunction parseFailure(\n bodyType: BodyType | undefined,\n): { error: string; message: string } | undefined {\n if (bodyType === \"text\" || bodyType === \"stream\") {\n return undefined;\n }\n\n return bodyType === \"form\"\n ? { error: \"MALFORMED_FORM\", message: \"Body is not a valid form\" }\n : { error: \"MALFORMED_JSON\", message: \"Body is not valid JSON\" };\n}\n\nfunction capitalize(value: string): string {\n return value.charAt(0).toUpperCase() + value.slice(1);\n}\n\nfunction lowerFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n",
|
|
10
10
|
"/**\n * Asking a schema to describe itself, without letting it stop the document.\n *\n * Internal to the package.\n *\n * @module\n */\n\nimport { toJsonSchema } from \"@tetsujs/core\";\n\n/**\n * The JSON Schema dialect a schema is asked for.\n *\n * OpenAPI 3.1 takes JSON Schema 2020-12 as it is, and `draft-2020-12` is a\n * target the Standard JSON Schema specification names — so every library\n * that implements it answers. This used to be `openapi-3.1`, which only\n * Zod accepts: ArkType and Valibot refused it, and their bodies went into\n * the document without a shape and with a warning each.\n */\nconst target = { target: \"draft-2020-12\" } as const;\n\n/**\n * A JSON Schema as the generator reads it: any keyword, with the ones it\n * looks into named, so reading them does not depend on the reader's\n * `noPropertyAccessFromIndexSignature`.\n */\nexport interface JsonSchemaObject {\n properties?: unknown;\n required?: unknown;\n anyOf?: unknown;\n oneOf?: unknown;\n description?: unknown;\n [keyword: string]: unknown;\n}\n\n/** Which shape of a schema to describe: what arrives, or what leaves. */\ntype Direction = \"input\" | \"output\";\n\n/**\n * The JSON Schema of a declaration, or `undefined` and a warning saying why.\n *\n * A schema can fail to describe itself in two ways, and the generator owes\n * the same answer to both: an adapter without JSON Schema support returns\n * nothing, and an adapter that has it can still throw — a converter meeting\n * a shape it cannot express, a structure too deep to walk, a `$ref` that\n * leads back to where it started.\n *\n * Only the first was handled, and the difference between them is not the\n * document: it is whether the application starts at all. `docs()` builds\n * the document from `onMount`, which `createApp` calls while it is still\n * assembling itself, so an escaping error is not a gap in a description —\n * it is a server that never listens, over a route that would have worked.\n *\n * `subject` names the declaration for the message, as the reader of a\n * warning would name it: `\"the body\"`, `\"a response\"`.\n */\nexport function emitted(\n schema: unknown,\n subject: string,\n warn: (message: string) => void,\n direction: Direction = \"output\",\n): JsonSchemaObject | undefined {\n let described: JsonSchemaObject | undefined;\n\n try {\n described = toJsonSchema(schema, target, direction);\n } catch (error) {\n warn(`${subject} schema failed to emit JSON Schema: ${reason(error)}`);\n\n return undefined;\n }\n\n if (!described) {\n warn(`${subject} schema does not emit JSON Schema`);\n\n return undefined;\n }\n\n return withoutDialect(described);\n}\n\n/**\n * A schema as the document embeds it: without its own `$schema`.\n *\n * Asked for draft 2020-12, Zod and ArkType name the dialect at the root of\n * every schema they emit. The document declares it once for all of them,\n * and the same line on every body and response is noise.\n */\nfunction withoutDialect(schema: JsonSchemaObject): JsonSchemaObject {\n if (!(\"$schema\" in schema)) {\n return schema;\n }\n\n const { $schema: _, ...rest } = schema;\n\n return rest;\n}\n\nfunction reason(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n",
|
|
11
11
|
"/**\n * Path templates and request parameters.\n *\n * The framework's path syntax is Bun's — `:param` and a trailing `*` —\n * while OpenAPI templates variables as `{param}`. The conversion happens\n * here, together with the parameter objects the template then requires:\n * OpenAPI demands that every variable in a path be declared.\n *\n * @module\n */\n\nimport type { AnySchema } from \"@tetsujs/core\";\nimport type { ParameterObject } from \"./document.ts\";\nimport { emitted } from \"./emit.ts\";\n\n/** The name a wildcard segment is documented under. */\nexport const wildcardName = \"wildcard\";\n\n/**\n * Rewrites a route path as an OpenAPI path template.\n *\n * A wildcard becomes an ordinary variable: OpenAPI has no syntax for\n * \"everything below here\", so the closest honest template is a named\n * segment, documented as such.\n */\nexport function toTemplate(path: string): string {\n return path\n .split(\"/\")\n .map((segment) => {\n if (segment.startsWith(\":\")) {\n return `{${segment.slice(1)}}`;\n }\n\n return segment === \"*\" ? `{${wildcardName}}` : segment;\n })\n .join(\"/\");\n}\n\n/** The variables a path template declares, in order. */\nexport function templateNames(path: string): string[] {\n const names: string[] = [];\n\n for (const segment of path.split(\"/\")) {\n if (segment.startsWith(\":\")) {\n names.push(segment.slice(1));\n } else if (segment === \"*\") {\n names.push(wildcardName);\n }\n }\n\n return names;\n}\n\n/**\n * Describes the path parameters of a route.\n *\n * A `params` schema describes the whole object, so each variable takes the\n * property of the same name; without one — or without a property for a\n * given variable — the value is what the router captured: a string.\n */\nexport function pathParameters(\n path: string,\n schema: AnySchema | undefined,\n warn: (message: string) => void,\n): ParameterObject[] {\n const properties = objectProperties(schema, \"params\", warn);\n\n return templateNames(path).map((name) => ({\n name,\n in: \"path\" as const,\n required: true,\n ...(name === wildcardName\n ? {\n description:\n \"Matches the rest of the path, including further segments.\",\n }\n : {}),\n schema: properties[name] ?? { type: \"string\" },\n }));\n}\n\n/**\n * Describes the query, header or cookie parameters of a route.\n *\n * All three are objects at the schema level and lists of parameters in a\n * document, so each declared property becomes one parameter, required when\n * the schema says so.\n *\n * A session cookie is the exception the specification makes itself: a\n * credential belongs in `securitySchemes` as `apiKey in: cookie`, not\n * among the parameters. Nothing here can tell one cookie from the other —\n * that is what an annotation on the hook reading it is for, the same way\n * `secured()` marks an authenticating hook.\n */\nexport function partParameters(\n schema: AnySchema | undefined,\n where: \"query\" | \"header\" | \"cookie\",\n warn: (message: string) => void,\n): ParameterObject[] {\n if (!schema) {\n return [];\n }\n\n const described = emitted(schema, `the ${where}`, warn, \"input\");\n\n if (!described) {\n return [];\n }\n\n const properties = (described.properties ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n const required = new Set(\n Array.isArray(described.required) ? (described.required as string[]) : [],\n );\n\n return Object.entries(properties).map(([name, property]) => ({\n name,\n in: where,\n required: required.has(name),\n schema: property,\n }));\n}\n\nfunction objectProperties(\n schema: AnySchema | undefined,\n where: string,\n warn: (message: string) => void,\n): Record<string, Record<string, unknown>> {\n if (!schema) {\n return {};\n }\n\n const described = emitted(schema, `the ${where}`, warn, \"input\");\n\n if (!described) {\n return {};\n }\n\n return (described.properties ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n}\n",
|
|
12
12
|
"/**\n * Finding the references in a document that lead nowhere.\n *\n * A validator's JSON Schema is embedded in the document as it is, and the\n * references inside it were written for a schema that stood alone. `#` is\n * the root of the schema, `#/$defs/Node` a definition next to it — but\n * embedded, both resolve against the root of the document instead, which\n * is no schema and has no `$defs`. Zod's recursive and named schemas,\n * ArkType's scopes and Valibot's `lazy` all emit such references, and the\n * document they end up in is invalid without anything saying so.\n *\n * Moving the definitions into `components/schemas` and rewriting the\n * references to them would make those schemas describable. Until then the\n * generator says which references broke, which is what it owes a reader:\n * a document that is silently wrong is worse than one that says so.\n *\n * Internal to the package.\n *\n * @module\n */\n\n/**\n * Keywords whose values are data, not schemas: a `$ref` inside an example\n * or a `const` is a string someone meant to send, not a reference.\n */\nconst data = new Set([\"const\", \"default\", \"enum\", \"example\", \"examples\"]);\n\n/**\n * The local references under `node` that resolve to nothing, each once, in\n * the order they are met.\n *\n * A reference resolves against the closest enclosing schema with an `$id`,\n * as JSON Schema has it — the document, when there is none. A reference\n * that is not local, such as TypeBox's `Node` under `$id: \"Node\"`, and one\n * to an anchor rather than a pointer are left alone: neither is what the\n * libraries this is about emit, and resolving them takes more than a walk.\n *\n * The walk keeps its own stack and visits each object once per base: a\n * schema may be deeper than the call stack, or contain itself, and neither\n * is a reason for the document not to be generated.\n */\nexport function unresolvedRefs(node: unknown, document: object): string[] {\n const unresolved = new Set<string>();\n const visited = new Map<object, Set<object>>();\n const pending: [value: unknown, base: object][] = [[node, document]];\n\n for (let next = pending.pop(); next; next = pending.pop()) {\n const [value, base] = next;\n\n if (typeof value !== \"object\" || value === null) {\n continue;\n }\n\n const bases = visited.get(value) ?? new Set<object>();\n\n if (bases.has(base)) {\n continue;\n }\n\n visited.set(value, bases.add(base));\n\n const schema = value as Record<string, unknown>;\n const resource =\n !Array.isArray(value) && typeof schema[\"$id\"] === \"string\"\n ? schema\n : base;\n const ref = Array.isArray(value) ? undefined : schema[\"$ref\"];\n\n if (\n typeof ref === \"string\" &&\n ref.startsWith(\"#\") &&\n !resolves(ref.slice(1), resource, document)\n ) {\n unresolved.add(ref);\n }\n\n const children = Object.entries(schema).filter(\n ([keyword]) => Array.isArray(value) || !data.has(keyword),\n );\n\n for (let index = children.length - 1; index >= 0; index -= 1) {\n pending.push([children[index]?.[1], resource]);\n }\n }\n\n return [...unresolved];\n}\n\n/**\n * Whether a fragment names a schema within `base`.\n *\n * The empty fragment is `base` itself — a schema when it is a resource,\n * and nothing a schema can refer to when it is the document. A pointer is\n * followed token by token, decoded as a URI fragment and then as JSON\n * Pointer; anything else is an anchor, and is taken on trust.\n */\nfunction resolves(fragment: string, base: object, document: object): boolean {\n if (fragment === \"\") {\n return base !== document;\n }\n\n if (!fragment.startsWith(\"/\")) {\n return true;\n }\n\n let target: unknown = base;\n\n for (const token of fragment.slice(1).split(\"/\")) {\n if (typeof target !== \"object\" || target === null) {\n return false;\n }\n\n const key = decoded(token);\n\n if (key === undefined || !Object.hasOwn(target, key)) {\n return false;\n }\n\n target = (target as Record<string, unknown>)[key];\n }\n\n return (\n (typeof target === \"object\" && target !== null) ||\n typeof target === \"boolean\"\n );\n}\n\nfunction decoded(token: string): string | undefined {\n try {\n return decodeURIComponent(token)\n .replaceAll(\"~1\", \"/\")\n .replaceAll(\"~0\", \"~\");\n } catch {\n return undefined;\n }\n}\n",
|
|
13
13
|
"/**\n * The documentation endpoints as a mountable controller.\n *\n * `openapi()` returns data and mounts nothing, which is the right default\n * for a generator but a chore in the ordinary case: every application ends\n * up writing the same controller, holding the same application, to serve\n * the same two routes. {@link docs} is that controller, written once.\n *\n * It is a controller like any other — mounted in `routes`, groupable,\n * hookable — that receives the application through `onMount` and generates\n * the document from it at startup.\n *\n * @module\n */\n\nimport type { App, RouteDef, SchemaConfig, ValidatePath } from \"@tetsujs/core\";\nimport { onMount, route } from \"@tetsujs/core\";\nimport type { OpenApiDocument } from \"./document.ts\";\nimport type { ErrorFormat } from \"./errors.ts\";\nimport type { GeneratorWarning } from \"./index.ts\";\nimport { openapi } from \"./index.ts\";\nimport type { DocsAssets, DocsUi } from \"./page.ts\";\nimport { docsPage } from \"./page.ts\";\n\n/** What the documentation controller serves, and from where. */\nexport interface DocsOptions<\n Path extends string,\n UiPath extends string,\n Ui extends DocsUi | false = DocsUi | false,\n> {\n /** Title, version and the rest of the document's `info` block. */\n readonly info: OpenApiDocument[\"info\"];\n\n /** Servers the API is reachable at. */\n readonly servers?: OpenApiDocument[\"servers\"];\n\n /**\n * How the application's errors look, when not like the framework's\n * envelope — see `errors` on {@link openapi}.\n */\n readonly errors?: ErrorFormat;\n\n /**\n * What each tag is — see `tags` on {@link openapi}. The controller's own\n * tag, `docs`, is described for you when its routes are in the document\n * (`documentSelf`) and you did not describe it.\n */\n readonly tags?: Readonly<Record<string, string>>;\n\n /** Where the document is served. Defaults to `/openapi.json`. */\n readonly path?: Path & ValidatePath<Path>;\n\n /** Where the page is served. Defaults to `/docs`. */\n readonly uiPath?: UiPath & ValidatePath<UiPath>;\n\n /**\n * Which renderer the page bootstraps. Defaults to `\"scalar\"`.\n *\n * `false` serves the document without a page — what production wants\n * on an origin that carries a session. The page runs its renderer on the\n * application's origin, so a renderer that is not what it should be acts\n * in the signed-in user's name there; the document alone runs nothing.\n * `uiPath`, `title` and `assets` are then unused.\n */\n readonly ui?: Ui;\n\n /** Browser title of the page. Defaults to the document's own title. */\n readonly title?: string;\n\n /** Overrides the renderer's CDN URLs, for a pinned or self-hosted copy. */\n readonly assets?: DocsAssets;\n\n /**\n * Documents the two endpoints this controller serves.\n *\n * Off by default: a reader who is looking at the document has already\n * found the document, and an operation for \"the page you are reading\"\n * is one a generated client would happily produce a method for.\n */\n readonly documentSelf?: boolean;\n\n /**\n * What to do with what the generator could not describe.\n *\n * Defaults to one `console.warn` per warning, at startup — a document\n * that silently omits a body is worse than a noisy one.\n */\n readonly onWarning?: (warning: GeneratorWarning) => void;\n}\n\n/**\n * The controller {@link docs} returns: two routes and the `onMount` that\n * fills them.\n *\n * Instantiated through the factory, never directly — the routes carry the\n * configured paths in their types, which only the factory can infer.\n */\nexport class DocsController<\n Path extends string,\n UiPath extends string,\n Page extends boolean = true,\n> {\n /** The document itself, as `application/json`. */\n readonly json: RouteDef<Path, SchemaConfig, never, undefined, \"GET\">;\n\n /** The page that renders it — none with `ui: false`. */\n readonly ui: Page extends true\n ? RouteDef<UiPath, SchemaConfig, never, undefined, \"GET\">\n : undefined;\n\n private document: OpenApiDocument | undefined;\n\n private page: string | undefined;\n\n constructor(\n private readonly options: DocsOptions<Path, UiPath>,\n documentPath: string,\n uiPath: string,\n ) {\n const hidden = !options.documentSelf;\n\n const json = route({\n method: \"GET\",\n path: \"/openapi.json\",\n docs: { summary: \"This document\", tags: [\"docs\"], hidden },\n handler: () => this.document,\n });\n\n const ui = route({\n method: \"GET\",\n path: \"/docs\",\n docs: { summary: \"Rendered documentation\", tags: [\"docs\"], hidden },\n handler: () =>\n new Response(this.page, {\n headers: { \"content-type\": \"text/html; charset=utf-8\" },\n }),\n });\n\n /**\n * The configured paths, put back on the routes.\n *\n * `route()` validates its path at the type level, and that check\n * cannot be satisfied by a type variable — `ValidatePath<Path>` stays\n * unresolved while `Path` is generic. The routes are therefore built\n * with the default literals and re-typed here, which is also where the\n * configured path lands at runtime.\n */\n this.json = { ...json, path: documentPath } as unknown as this[\"json\"];\n this.ui = (\n options.ui === false ? undefined : { ...ui, path: uiPath }\n ) as this[\"ui\"];\n }\n\n /**\n * The tags to describe: the application's, and this controller's own when\n * its routes are in the document — without it, a described set of tags\n * would report `docs` as a tag nobody described.\n */\n private tagsOf(\n tags: Readonly<Record<string, string>>,\n ): Readonly<Record<string, string>> {\n if (!this.options.documentSelf || Object.hasOwn(tags, \"docs\")) {\n return tags;\n }\n\n return { ...tags, docs: \"This documentation\" };\n }\n\n /**\n * Generates the document of the application this was mounted in, and\n * the page that renders it.\n *\n * The page is built here rather than with the routes because only the\n * application knows where the document ended up: a group this controller\n * is mounted under prefixes its path, and a page pointing at the path as\n * configured would fetch a `404`.\n */\n [onMount](app: App): void {\n const generated = openapi(app, {\n info: this.options.info,\n ...(this.options.servers ? { servers: this.options.servers } : {}),\n ...(this.options.errors ? { errors: this.options.errors } : {}),\n ...(this.options.tags ? { tags: this.tagsOf(this.options.tags) } : {}),\n });\n\n this.document = generated.document;\n\n const ui = this.options.ui ?? \"scalar\";\n const json: unknown = this.json;\n const served = app.entries.find((entry) => entry.def === json);\n\n if (ui !== false && served) {\n this.page = docsPage({\n ui,\n documentUrl: served.path,\n title: this.options.title ?? this.options.info.title,\n ...(this.options.assets ? { assets: this.options.assets } : {}),\n });\n }\n\n const report = this.options.onWarning ?? warn;\n\n for (const warning of generated.warnings) {\n report(warning);\n }\n }\n}\n\n/**\n * The documentation of an application, as a controller to mount.\n *\n * @example\n * ```ts\n * createApp({\n * routes: [\n * group(\"/api\", { children: [usersController({ users })] }),\n * docs({ info: { title: \"Users API\", version: \"1.0.0\" } }),\n * ],\n * });\n * ```\n *\n * The document is generated once, at startup, from the application the\n * controller was mounted in. Its own two routes stay out of it — pass\n * `documentSelf` to put them in.\n *\n * The page loads its renderer from a CDN; see {@link docsPage} for the\n * trade and for how to point it at a self-hosted copy.\n */\nexport function docs<\n const Path extends string = \"/openapi.json\",\n const UiPath extends string = \"/docs\",\n const Ui extends DocsUi | false = \"scalar\",\n>(\n options: DocsOptions<Path, UiPath, Ui>,\n): DocsController<Path, UiPath, Ui extends false ? false : true> {\n return new DocsController(\n options,\n options.path ?? \"/openapi.json\",\n options.uiPath ?? \"/docs\",\n ) as DocsController<Path, UiPath, Ui extends false ? false : true>;\n}\n\nfunction warn(warning: GeneratorWarning): void {\n console.warn(\n warning.route === \"\"\n ? `[openapi] ${warning.message}`\n : `[openapi] ${warning.route}: ${warning.message}`,\n );\n}\n",
|
|
14
14
|
"/**\n * The HTML page that renders a document.\n *\n * Returns a string and mounts nothing: which path serves the page, and\n * whether one is served at all, is the application's decision like every\n * other route.\n *\n * The renderers themselves are loaded from a CDN. Vendoring Scalar or\n * Swagger UI would put megabytes of somebody else's bundle into a\n * dependency-free repository, so the trade is stated instead of hidden:\n * the documentation page — and only it — needs the network, and the URL is\n * a parameter, so a self-hosted copy is one option away. Nothing is\n * fetched unless this function is called.\n *\n * What the CDN serves runs on the application's origin, with its cookies.\n * The default renderers are therefore pinned to an exact version and\n * carry the hash of that file: a CDN, or a package release, that serves\n * something else is refused by the browser rather than run. A page on an\n * origin with a session is still somebody else's application in the\n * user's session — which is why `docs()` can serve the document alone.\n *\n * @module\n */\n\n/** The renderers this package knows how to bootstrap. */\nexport type DocsUi = \"scalar\" | \"swagger-ui\" | \"redoc\";\n\n/** Where a renderer is loaded from. */\nexport interface DocsAssets {\n readonly script: string;\n readonly style?: string;\n\n /**\n * Subresource Integrity hashes of the two files, for a copy that is not\n * on the application's own origin: the browser runs the file only if it\n * hashes to this. Absent, the files are loaded as they are.\n *\n * One line computes one:\n * `curl -s <url> | openssl dgst -sha384 -binary | openssl base64 -A`,\n * prefixed with `sha384-`.\n */\n readonly integrity?: {\n readonly script?: string;\n readonly style?: string;\n };\n}\n\n/** What the page needs to know. */\nexport interface DocsPageOptions {\n /** Which renderer to bootstrap. */\n readonly ui: DocsUi;\n\n /** Where the document is served — the page fetches it from there. */\n readonly documentUrl: string;\n\n /** Browser title; defaults to `\"API documentation\"`. */\n readonly title?: string;\n\n /** Overrides the CDN URLs, for a pinned version or a self-hosted copy. */\n readonly assets?: DocsAssets;\n}\n\n/**\n * The renderers by default: an exact version, the file by its full path,\n * and the hash of that file.\n *\n * The full path because a bare package URL is not a file — jsDelivr\n * answers it with a build of its own, whose bytes differ from the file's.\n * Moving to a newer version means a new hash, computed as\n * {@link DocsAssets.integrity} describes.\n */\nconst defaults: Record<DocsUi, DocsAssets> = {\n scalar: {\n script:\n \"https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.72.1/dist/browser/standalone.js\",\n integrity: {\n script:\n \"sha384-U11tb2XnKvmwt8RlTvnwUnYgrN+ur4Xyh9htLhjajWNR/Oyl5AX5DEz00qRmlrmK\",\n },\n },\n \"swagger-ui\": {\n script:\n \"https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.33.0/swagger-ui-bundle.js\",\n style: \"https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.33.0/swagger-ui.css\",\n integrity: {\n script:\n \"sha384-YDALVcy8kj8yltLBVi1vBiBAUqdxvus673gM8XKwiy6aDUJFXivF/KCufekjYbVf\",\n style:\n \"sha384-Ov4/wv3j2bmct8cDc5X4ngJZohVPzEmc6uDPH8WeljUxO5vtoykvMEfbu9Vh6RaW\",\n },\n },\n redoc: {\n script:\n \"https://cdn.jsdelivr.net/npm/redoc@2.5.4/bundles/redoc.standalone.js\",\n integrity: {\n script:\n \"sha384-w447zOpYfw/1Tv/5AK9NfHTlQIqE3RVR6KY62jCyy9zNDgO64cMwGGP1Fj0zJVf5\",\n },\n },\n};\n\n/**\n * Builds the documentation page.\n *\n * Called by `docs()` for the page it serves; call it directly to serve one\n * from somewhere else.\n *\n * @example\n * ```ts\n * const page = docsPage({ ui: \"scalar\", documentUrl: \"/openapi.json\" });\n *\n * const ui = route({\n * method: \"GET\",\n * path: \"/docs\",\n * handler: () =>\n * new Response(page, { headers: { \"content-type\": \"text/html\" } }),\n * });\n * ```\n */\nexport function docsPage(options: DocsPageOptions): string {\n const assets = options.assets ?? defaults[options.ui];\n const title = escapeHtml(options.title ?? \"API documentation\");\n const url = escapeHtml(options.documentUrl);\n\n return [\n \"<!doctype html>\",\n '<html lang=\"en\">',\n \"<head>\",\n '<meta charset=\"utf-8\" />',\n '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n `<title>${title}</title>`,\n assets.style\n ? `<link rel=\"stylesheet\" href=\"${escapeHtml(assets.style)}\"${verified(assets.integrity?.style)} />`\n : \"\",\n \"</head>\",\n \"<body>\",\n body(options.ui, url),\n `<script src=\"${escapeHtml(assets.script)}\"${verified(assets.integrity?.script)}></script>`,\n bootstrap(options.ui),\n \"</body>\",\n \"</html>\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction body(ui: DocsUi, url: string): string {\n if (ui === \"scalar\") {\n return `<script id=\"api-reference\" data-url=\"${url}\"></script>`;\n }\n\n if (ui === \"redoc\") {\n return `<redoc spec-url=\"${url}\"></redoc>`;\n }\n\n return `<div id=\"swagger-ui\" data-url=\"${url}\"></div>`;\n}\n\n/**\n * The call that starts Swagger UI, which alone of the three is started by\n * a script. It reads the document's address from the element's\n * attribute, where the other two carry it: a value escaped for HTML is\n * decoded there and not inside a script, where `&` stayed `&` and the\n * renderer fetched a URL nobody served. So the script holds no value of\n * the application's, and needs no escaping of its own.\n */\nfunction bootstrap(ui: DocsUi): string {\n if (ui !== \"swagger-ui\") {\n return \"\";\n }\n\n return [\n \"<script>\",\n 'const root = document.getElementById(\"swagger-ui\");',\n 'SwaggerUIBundle({ url: root.dataset.url, dom_id: \"#swagger-ui\" });',\n \"</script>\",\n ].join(\"\\n\");\n}\n\n/**\n * The attributes that make the browser check a file against its hash.\n *\n * `crossorigin` comes with it: a file from another origin is checked only\n * when fetched with CORS, and without the attribute the browser refuses\n * it outright rather than skip the check.\n */\nfunction verified(integrity: string | undefined): string {\n return integrity\n ? ` integrity=\"${escapeHtml(integrity)}\" crossorigin=\"anonymous\"`\n : \"\";\n}\n\n/**\n * Escapes the values that reach the markup.\n *\n * The document URL and the title come from the application, but they are\n * still values interpolated into HTML — a quote in either would break out\n * of the attribute it sits in.\n */\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n}\n",
|
|
15
|
-
"/**\n * OpenAPI generation for the framework.\n *\n * Reads a compiled application — `app.entries` and the options it actually\n * runs with — and returns an OpenAPI 3.1 document. Nothing is registered,\n * served or mutated: the document is data, and serving it is a route the\n * application declares like any other.\n *\n * Serving it is a route the application declares — or `docs()`, the\n * controller that declares those routes for you.\n *\n * @example\n * ```ts\n * const { document, warnings } = openapi(app, {\n * info: { title: \"Users API\", version: \"1.0.0\" },\n * });\n * ```\n *\n * @module\n */\n\nimport type { App } from \"@tetsujs/core\";\nimport { contributionsOf } from \"./annotations.ts\";\nimport { schemaComponents } from \"./components.ts\";\nimport type { OpenApiDocument, PathItemObject, TagObject } from \"./document.ts\";\nimport { envelopes as envelopeDefinitions } from \"./envelopes.ts\";\nimport type { ErrorFormat } from \"./errors.ts\";\nimport { resolveFormat } from \"./errors.ts\";\nimport { declareEnvelopes, operationIds, operationOf } from \"./operation.ts\";\nimport { toTemplate } from \"./parameters.ts\";\nimport { unresolvedRefs } from \"./refs.ts\";\n\nexport type {\n DocumentedHeader,\n DocumentedResponse,\n HookContributions,\n HookDocs,\n SecurityAlternatives,\n SecurityRequirement,\n SecurityScheme,\n} from \"./annotations.ts\";\nexport { documented, secured } from \"./annotations.ts\";\nexport type { DocsOptions } from \"./controller.ts\";\nexport { DocsController, docs } from \"./controller.ts\";\nexport type {\n ContentMap,\n DocumentInfo,\n DocumentServer,\n HeaderObject,\n OpenApiDocument,\n OperationObject,\n ParameterObject,\n PathItemObject,\n ResponseObject,\n TagObject,\n} from \"./document.ts\";\nexport type { DocumentedFailure, ErrorFormat } from \"./errors.ts\";\nexport type {\n JsonSchema,\n JsonSchemaKeywords,\n JsonSchemaType,\n} from \"./json-schema.ts\";\nexport type { DocsAssets, DocsPageOptions, DocsUi } from \"./page.ts\";\nexport { docsPage } from \"./page.ts\";\n\n/**\n * What the generator cannot read off the application.\n */\nexport interface OpenApiOptions {\n /** Title, version and the rest of the document's `info` block. */\n readonly info: OpenApiDocument[\"info\"];\n\n /** Servers the API is reachable at. */\n readonly servers?: OpenApiDocument[\"servers\"];\n\n /**\n * How the application's errors look, when not like the framework's\n * envelope — for an application whose `onError` hook answers in a format\n * of its own. The framework's failures, the hooks' refusals and the\n * routes' own envelopes are then described in it.\n *\n * @example `{ code, message }`, discriminated on `code`\n * ```ts\n * openapi(app, {\n * info,\n * errors: {\n * schema: ({ error, message, fields }) => ({\n * type: \"object\",\n * required: [\"code\", \"message\", ...Object.keys(fields)],\n * properties: {\n * code: error ? { type: \"string\", const: error } : { type: \"string\" },\n * message: { type: \"string\", ...(message ? { examples: [message] } : {}) },\n * ...fields,\n * },\n * }),\n * discriminator: \"code\",\n * },\n * });\n * ```\n */\n readonly errors?: ErrorFormat;\n\n /**\n * What each tag is, by name — the sections a renderer's sidebar shows,\n * in the order given here.\n *\n * A tag the routes use and this leaves out is listed after these, in the\n * order the routes first use it, without a description; so is reported,\n * as a likely misspelling — `sign_in` for `sign-in` makes a section of its\n * own. So is a tag described here that no operation uses. Without\n * `tags`, the document lists none and nothing is reported.\n *\n * @example\n * ```ts\n * openapi(app, {\n * info,\n * tags: {\n * \"sign-in\": \"Signing in with a code sent by email, and signing out\",\n * me: \"The signed-in user\",\n * },\n * });\n * ```\n */\n readonly tags?: Readonly<Record<string, string>>;\n}\n\n/**\n * What the generator could not describe faithfully.\n *\n * Each entry names a route and what was missing — almost always a schema\n * from a validator that emits no JSON Schema. Documentation that silently\n * omits a body is worse than documentation that says it does not know, so\n * these are returned rather than swallowed.\n */\nexport interface GeneratorWarning {\n /**\n * The route the warning is about, as `GET /path` — empty for a warning\n * about the document as a whole, such as a described tag nothing uses.\n */\n readonly route: string;\n readonly message: string;\n}\n\n/** A generated document together with what could not be described. */\nexport interface GeneratorResult {\n readonly document: OpenApiDocument;\n readonly warnings: readonly GeneratorWarning[];\n}\n\n/**\n * Generates the OpenAPI document of an application.\n *\n * Socket endpoints are skipped: a handshake is a `GET` in the table, but\n * OpenAPI has no way to describe what happens after it, and documenting\n * the upgrade as an ordinary operation would describe a request that\n * clients must not make. AsyncAPI is that format, and a separate document.\n *\n * So are routes marked `docs: { hidden: true }`, and everything they would\n * have contributed with them: a security scheme only a hidden route\n * requires has nothing left to describe.\n *\n * Every route of the table becomes an operation under its path template,\n * with the parameters, body and responses its schemas describe. What the\n * framework itself can answer — a validation failure, an unparsable body,\n * a body over the limit — is filled in from the options the application\n * runs with, so the document states the status actually configured.\n */\nexport function openapi(app: App, options: OpenApiOptions): GeneratorResult {\n const paths: Record<string, PathItemObject> = {};\n const warnings: GeneratorWarning[] = [];\n const schemes: Record<string, unknown> = {};\n const components = schemaComponents();\n const envelopes = envelopeDefinitions(\n components,\n resolveFormat(options.errors),\n );\n const ids = operationIds();\n const described = app.entries.filter(\n (entry) => !entry.ws && !entry.def.docs?.hidden,\n );\n\n for (const entry of described) {\n declareEnvelopes(entry, envelopes);\n }\n\n // Which route already occupies each slot of the document. Two routes the\n // router keeps apart can still meet here, because a template says less\n // than a path does: `/files/*` and `/files/:wildcard` both become\n // `/files/{wildcard}`, and a literal `/users/{id}` — which Bun matches as\n // the string it is — is spelled the same as `/users/:id`. The second one\n // then replaces the first, and the document quietly loses an endpoint\n // that works. It still loses it; it no longer does so without saying.\n const occupied = new Map<string, string>();\n\n // Every tag the operations use, with the first route using it: the\n // order undescribed tags are listed in, and where each is reported.\n const used = new Map<string, string>();\n\n for (const entry of described) {\n const template = toTemplate(entry.path);\n const route = `${entry.method} ${entry.path}`;\n\n const operation = operationOf(\n entry,\n app.options,\n components,\n envelopes,\n ids,\n (message) => {\n warnings.push({ route, message });\n },\n );\n\n // First definition wins, as it does among the hooks of one route: a\n // name is the identity of a scheme, and the operations that reference\n // it say only the name. A second, different scheme under that name\n // cannot be described without renaming it out from under everything\n // already pointing at it, so it is refused rather than silently\n // swapped in — which used to make every earlier operation describe an\n // authentication its route does not perform.\n for (const requirement of contributionsOf(entry.hooks).security) {\n const defined = schemes[requirement.name];\n\n if (defined === undefined) {\n schemes[requirement.name] = requirement.scheme;\n\n continue;\n }\n\n if (JSON.stringify(defined) !== JSON.stringify(requirement.scheme)) {\n warnings.push({\n route,\n message: `the security scheme \"${requirement.name}\" is already defined differently; this definition is ignored`,\n });\n }\n }\n\n const slot = `${entry.method.toLowerCase()} ${template}`;\n const taken = occupied.get(slot);\n\n if (taken) {\n warnings.push({\n route,\n message: `${template} is already described by ${taken}, whose operation this replaces`,\n });\n }\n\n occupied.set(slot, route);\n\n for (const tag of operation.tags ?? []) {\n if (!used.has(tag)) {\n used.set(tag, route);\n }\n }\n\n paths[template] = {\n ...paths[template],\n [entry.method.toLowerCase()]: operation,\n };\n }\n\n const tags = options.tags ? tagsOf(options.tags, used, warnings) : undefined;\n const document: OpenApiDocument = {\n openapi: \"3.1.0\",\n info: options.info,\n ...(options.servers ? { servers: options.servers } : {}),\n ...(tags ? { tags } : {}),\n paths,\n ...componentsOf(schemes, components.schemas),\n };\n\n refsOf(document, occupied, warnings);\n\n return { document, warnings };\n}\n\n/**\n * Reports each reference in the document that resolves to nothing: in an\n * operation, at the route it describes; in a definition of\n * `components/schemas`, for the document, naming the definition.\n *\n * Checked on the finished document, since a reference may point at what\n * the document defines anywhere — a failure envelope registered by a\n * later route included.\n */\nfunction refsOf(\n document: OpenApiDocument,\n routes: ReadonlyMap<string, string>,\n warnings: GeneratorWarning[],\n): void {\n const unresolved = (ref: string) =>\n `refers to \"${ref}\", which is no schema in the document: references are embedded as they are, and resolve against the document's root`;\n\n for (const [template, item] of Object.entries(document.paths)) {\n for (const [method, operation] of Object.entries(item)) {\n const route = routes.get(`${method} ${template}`) ?? \"\";\n\n for (const ref of unresolvedRefs(operation, document)) {\n warnings.push({ route, message: `a schema ${unresolved(ref)}` });\n }\n }\n }\n\n const schemas = document.components?.schemas ?? {};\n\n for (const [name, schema] of Object.entries(schemas)) {\n for (const ref of unresolvedRefs(schema, document)) {\n warnings.push({\n route: \"\",\n message: `components/schemas/${name} ${unresolved(ref)}`,\n });\n }\n }\n}\n\n/**\n * The document's tags: the described ones in the order given, then those\n * the operations use and the description leaves out, in the order they are\n * first used — so the order of the sections is the application's, not\n * whatever a renderer does with a tag it was not told about.\n *\n * Both kinds of mismatch are reported, since either is usually one tag\n * spelled two ways: a tag used and not described, at the first route\n * using it, and a tag described and not used, for the document.\n */\nfunction tagsOf(\n described: Readonly<Record<string, string>>,\n used: ReadonlyMap<string, string>,\n warnings: GeneratorWarning[],\n): TagObject[] {\n const tags: TagObject[] = Object.entries(described).map(\n ([name, description]) => ({ name, description }),\n );\n\n for (const [name, route] of used) {\n if (Object.hasOwn(described, name)) {\n continue;\n }\n\n tags.push({ name });\n warnings.push({\n route,\n message: `the tag \"${name}\" is not in tags; it is listed after them, without a description`,\n });\n }\n\n for (const name of Object.keys(described)) {\n if (!used.has(name)) {\n warnings.push({\n route: \"\",\n message: `the tag \"${name}\" is described in tags, but no operation uses it`,\n });\n }\n }\n\n return tags;\n}\n\n/**\n * The `components` block, present only when something goes in it: the\n * security schemes the guards registered, and the failure envelopes the\n * operations refer to.\n */\nfunction componentsOf(\n securitySchemes: Record<string, unknown>,\n schemas: Record<string, unknown>,\n): { components?: Record<string, unknown> } {\n const components = {\n ...(Object.keys(securitySchemes).length > 0 ? { securitySchemes } : {}),\n ...(Object.keys(schemas).length > 0 ? { schemas } : {}),\n };\n\n return Object.keys(components).length > 0 ? { components } : {};\n}\n"
|
|
15
|
+
"/**\n * OpenAPI generation for the framework.\n *\n * Reads a compiled application — `app.entries` and the options it actually\n * runs with — and returns an OpenAPI 3.1 document. Nothing is registered,\n * served or mutated: the document is data, and serving it is a route the\n * application declares like any other.\n *\n * Serving it is a route the application declares — or `docs()`, the\n * controller that declares those routes for you.\n *\n * @example\n * ```ts\n * const { document, warnings } = openapi(app, {\n * info: { title: \"Users API\", version: \"1.0.0\" },\n * });\n * ```\n *\n * @module\n */\n\nimport type { App, RouteTableEntry } from \"@tetsujs/core\";\nimport { contributionsOf, handlerDocsOf } from \"./annotations.ts\";\nimport { schemaComponents } from \"./components.ts\";\nimport type { OpenApiDocument, PathItemObject, TagObject } from \"./document.ts\";\nimport { envelopes as envelopeDefinitions } from \"./envelopes.ts\";\nimport type { ErrorFormat } from \"./errors.ts\";\nimport { resolveFormat } from \"./errors.ts\";\nimport { declareEnvelopes, operationIds, operationOf } from \"./operation.ts\";\nimport { toTemplate } from \"./parameters.ts\";\nimport { unresolvedRefs } from \"./refs.ts\";\n\nexport type {\n DocumentedHeader,\n DocumentedResponse,\n HandlerDocs,\n HookContributions,\n HookDocs,\n SecurityAlternatives,\n SecurityRequirement,\n SecurityScheme,\n} from \"./annotations.ts\";\nexport { documented, secured } from \"./annotations.ts\";\nexport type { DocsOptions } from \"./controller.ts\";\nexport { DocsController, docs } from \"./controller.ts\";\nexport type {\n ContentMap,\n DocumentInfo,\n DocumentServer,\n HeaderObject,\n OpenApiDocument,\n OperationObject,\n ParameterObject,\n PathItemObject,\n ResponseObject,\n TagObject,\n} from \"./document.ts\";\nexport type { DocumentedFailure, ErrorFormat } from \"./errors.ts\";\nexport type {\n JsonSchema,\n JsonSchemaKeywords,\n JsonSchemaType,\n} from \"./json-schema.ts\";\nexport type { DocsAssets, DocsPageOptions, DocsUi } from \"./page.ts\";\nexport { docsPage } from \"./page.ts\";\n\n/**\n * What the generator cannot read off the application.\n */\nexport interface OpenApiOptions {\n /** Title, version and the rest of the document's `info` block. */\n readonly info: OpenApiDocument[\"info\"];\n\n /** Servers the API is reachable at. */\n readonly servers?: OpenApiDocument[\"servers\"];\n\n /**\n * How the application's errors look, when not like the framework's\n * envelope — for an application whose `onError` hook answers in a format\n * of its own. The framework's failures, the hooks' refusals and the\n * routes' own envelopes are then described in it.\n *\n * @example `{ code, message }`, discriminated on `code`\n * ```ts\n * openapi(app, {\n * info,\n * errors: {\n * schema: ({ error, message, fields }) => ({\n * type: \"object\",\n * required: [\"code\", \"message\", ...Object.keys(fields)],\n * properties: {\n * code: error ? { type: \"string\", const: error } : { type: \"string\" },\n * message: { type: \"string\", ...(message ? { examples: [message] } : {}) },\n * ...fields,\n * },\n * }),\n * discriminator: \"code\",\n * },\n * });\n * ```\n */\n readonly errors?: ErrorFormat;\n\n /**\n * What each tag is, by name — the sections a renderer's sidebar shows,\n * in the order given here.\n *\n * A tag the routes use and this leaves out is listed after these, in the\n * order the routes first use it, without a description; so is reported,\n * as a likely misspelling — `sign_in` for `sign-in` makes a section of its\n * own. So is a tag described here that no operation uses. Without\n * `tags`, the document lists none and nothing is reported.\n *\n * @example\n * ```ts\n * openapi(app, {\n * info,\n * tags: {\n * \"sign-in\": \"Signing in with a code sent by email, and signing out\",\n * me: \"The signed-in user\",\n * },\n * });\n * ```\n */\n readonly tags?: Readonly<Record<string, string>>;\n}\n\n/**\n * What the generator could not describe faithfully.\n *\n * Each entry names a route and what was missing — almost always a schema\n * from a validator that emits no JSON Schema. Documentation that silently\n * omits a body is worse than documentation that says it does not know, so\n * these are returned rather than swallowed.\n */\nexport interface GeneratorWarning {\n /**\n * The route the warning is about, as `GET /path` — empty for a warning\n * about the document as a whole, such as a described tag nothing uses.\n */\n readonly route: string;\n readonly message: string;\n}\n\n/** A generated document together with what could not be described. */\nexport interface GeneratorResult {\n readonly document: OpenApiDocument;\n readonly warnings: readonly GeneratorWarning[];\n}\n\n/**\n * Generates the OpenAPI document of an application.\n *\n * Socket endpoints are skipped: a handshake is a `GET` in the table, but\n * OpenAPI has no way to describe what happens after it, and documenting\n * the upgrade as an ordinary operation would describe a request that\n * clients must not make. AsyncAPI is that format, and a separate document.\n *\n * So are routes marked `docs: { hidden: true }`, and everything they would\n * have contributed with them: a security scheme only a hidden route\n * requires has nothing left to describe. A route that says nothing either\n * way is hidden when its handler was annotated so — see {@link documented}\n * — and `docs: { hidden: false }` shows it all the same.\n *\n * Every route of the table becomes an operation under its path template,\n * with the parameters, body and responses its schemas describe. What the\n * framework itself can answer — a validation failure, an unparsable body,\n * a body over the limit — is filled in from the options the application\n * runs with, so the document states the status actually configured.\n */\nexport function openapi(app: App, options: OpenApiOptions): GeneratorResult {\n const paths: Record<string, PathItemObject> = {};\n const warnings: GeneratorWarning[] = [];\n const schemes: Record<string, unknown> = {};\n const components = schemaComponents();\n const envelopes = envelopeDefinitions(\n components,\n resolveFormat(options.errors),\n );\n const ids = operationIds();\n const described = app.entries.filter((entry) => !entry.ws && !hidden(entry));\n\n for (const entry of described) {\n declareEnvelopes(entry, envelopes);\n }\n\n // Which route already occupies each slot of the document. Two routes the\n // router keeps apart can still meet here, because a template says less\n // than a path does: `/files/*` and `/files/:wildcard` both become\n // `/files/{wildcard}`, and a literal `/users/{id}` — which Bun matches as\n // the string it is — is spelled the same as `/users/:id`. The second one\n // then replaces the first, and the document quietly loses an endpoint\n // that works. It still loses it; it no longer does so without saying.\n const occupied = new Map<string, string>();\n\n // Every tag the operations use, with the first route using it: the\n // order undescribed tags are listed in, and where each is reported.\n const used = new Map<string, string>();\n\n for (const entry of described) {\n const template = toTemplate(entry.path);\n const route = `${entry.method} ${entry.path}`;\n\n const operation = operationOf(\n entry,\n app.options,\n components,\n envelopes,\n ids,\n (message) => {\n warnings.push({ route, message });\n },\n );\n\n // First definition wins, as it does among the hooks of one route: a\n // name is the identity of a scheme, and the operations that reference\n // it say only the name. A second, different scheme under that name\n // cannot be described without renaming it out from under everything\n // already pointing at it, so it is refused rather than silently\n // swapped in — which used to make every earlier operation describe an\n // authentication its route does not perform.\n for (const requirement of contributionsOf(entry.hooks).security) {\n const defined = schemes[requirement.name];\n\n if (defined === undefined) {\n schemes[requirement.name] = requirement.scheme;\n\n continue;\n }\n\n if (JSON.stringify(defined) !== JSON.stringify(requirement.scheme)) {\n warnings.push({\n route,\n message: `the security scheme \"${requirement.name}\" is already defined differently; this definition is ignored`,\n });\n }\n }\n\n const slot = `${entry.method.toLowerCase()} ${template}`;\n const taken = occupied.get(slot);\n\n if (taken) {\n warnings.push({\n route,\n message: `${template} is already described by ${taken}, whose operation this replaces`,\n });\n }\n\n occupied.set(slot, route);\n\n for (const tag of operation.tags ?? []) {\n if (!used.has(tag)) {\n used.set(tag, route);\n }\n }\n\n paths[template] = {\n ...paths[template],\n [entry.method.toLowerCase()]: operation,\n };\n }\n\n const tags = options.tags ? tagsOf(options.tags, used, warnings) : undefined;\n const document: OpenApiDocument = {\n openapi: \"3.1.0\",\n info: options.info,\n ...(options.servers ? { servers: options.servers } : {}),\n ...(tags ? { tags } : {}),\n paths,\n ...componentsOf(schemes, components.schemas),\n };\n\n refsOf(document, occupied, warnings);\n\n return { document, warnings };\n}\n\n/**\n * Whether a route stays out of the document: by its own word when it said\n * one, `true` or `false`, and by its handler's when it said nothing.\n */\nfunction hidden(entry: RouteTableEntry): boolean {\n return (\n entry.def.docs?.hidden ?? handlerDocsOf(entry.def.handler)?.hidden ?? false\n );\n}\n\n/**\n * Reports each reference in the document that resolves to nothing: in an\n * operation, at the route it describes; in a definition of\n * `components/schemas`, for the document, naming the definition.\n *\n * Checked on the finished document, since a reference may point at what\n * the document defines anywhere — a failure envelope registered by a\n * later route included.\n */\nfunction refsOf(\n document: OpenApiDocument,\n routes: ReadonlyMap<string, string>,\n warnings: GeneratorWarning[],\n): void {\n const unresolved = (ref: string) =>\n `refers to \"${ref}\", which is no schema in the document: references are embedded as they are, and resolve against the document's root`;\n\n for (const [template, item] of Object.entries(document.paths)) {\n for (const [method, operation] of Object.entries(item)) {\n const route = routes.get(`${method} ${template}`) ?? \"\";\n\n for (const ref of unresolvedRefs(operation, document)) {\n warnings.push({ route, message: `a schema ${unresolved(ref)}` });\n }\n }\n }\n\n const schemas = document.components?.schemas ?? {};\n\n for (const [name, schema] of Object.entries(schemas)) {\n for (const ref of unresolvedRefs(schema, document)) {\n warnings.push({\n route: \"\",\n message: `components/schemas/${name} ${unresolved(ref)}`,\n });\n }\n }\n}\n\n/**\n * The document's tags: the described ones in the order given, then those\n * the operations use and the description leaves out, in the order they are\n * first used — so the order of the sections is the application's, not\n * whatever a renderer does with a tag it was not told about.\n *\n * Both kinds of mismatch are reported, since either is usually one tag\n * spelled two ways: a tag used and not described, at the first route\n * using it, and a tag described and not used, for the document.\n */\nfunction tagsOf(\n described: Readonly<Record<string, string>>,\n used: ReadonlyMap<string, string>,\n warnings: GeneratorWarning[],\n): TagObject[] {\n const tags: TagObject[] = Object.entries(described).map(\n ([name, description]) => ({ name, description }),\n );\n\n for (const [name, route] of used) {\n if (Object.hasOwn(described, name)) {\n continue;\n }\n\n tags.push({ name });\n warnings.push({\n route,\n message: `the tag \"${name}\" is not in tags; it is listed after them, without a description`,\n });\n }\n\n for (const name of Object.keys(described)) {\n if (!used.has(name)) {\n warnings.push({\n route: \"\",\n message: `the tag \"${name}\" is described in tags, but no operation uses it`,\n });\n }\n }\n\n return tags;\n}\n\n/**\n * The `components` block, present only when something goes in it: the\n * security schemes the guards registered, and the failure envelopes the\n * operations refer to.\n */\nfunction componentsOf(\n securitySchemes: Record<string, unknown>,\n schemas: Record<string, unknown>,\n): { components?: Record<string, unknown> } {\n const components = {\n ...(Object.keys(securitySchemes).length > 0 ? { securitySchemes } : {}),\n ...(Object.keys(schemas).length > 0 ? { schemas } : {}),\n };\n\n return Object.keys(components).length > 0 ? { components } : {};\n}\n"
|
|
16
16
|
],
|
|
17
|
-
"mappings": "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",
|
|
18
|
-
"debugId": "
|
|
17
|
+
"mappings": "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",
|
|
18
|
+
"debugId": "94105F31CF41593E64756E2164756E21",
|
|
19
19
|
"names": []
|
|
20
20
|
}
|