@tetsujs/openapi 0.4.0 → 0.4.2
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 +82 -3
- package/dist/src/annotations.d.ts +93 -10
- package/dist/src/annotations.d.ts.map +1 -1
- package/dist/src/controller.d.ts +26 -9
- package/dist/src/controller.d.ts.map +1 -1
- package/dist/src/document.d.ts +7 -0
- package/dist/src/document.d.ts.map +1 -1
- package/dist/src/emit.d.ts +3 -1
- package/dist/src/emit.d.ts.map +1 -1
- package/dist/src/envelopes.d.ts +74 -0
- package/dist/src/envelopes.d.ts.map +1 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +360 -122
- package/dist/src/index.js.map +10 -9
- package/dist/src/json-schema.d.ts +91 -0
- package/dist/src/json-schema.d.ts.map +1 -0
- package/dist/src/operation.d.ts +10 -1
- package/dist/src/operation.d.ts.map +1 -1
- package/dist/src/page.d.ts +20 -0
- package/dist/src/page.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/annotations.ts +162 -21
- package/src/controller.ts +61 -22
- package/src/document.ts +9 -0
- package/src/emit.ts +3 -1
- package/src/envelopes.ts +242 -0
- package/src/index.ts +20 -6
- package/src/json-schema.ts +108 -0
- package/src/operation.ts +381 -152
- package/src/page.ts +65 -6
package/README.md
CHANGED
|
@@ -30,6 +30,38 @@ reported before the first request.
|
|
|
30
30
|
prefix, guard it with hooks, or leave it out in production. Its own two
|
|
31
31
|
routes are left out of the document.
|
|
32
32
|
|
|
33
|
+
### The page runs someone else's code on your origin
|
|
34
|
+
|
|
35
|
+
The page loads its renderer — Scalar, Swagger UI or Redoc — from
|
|
36
|
+
jsDelivr and runs it on the application's origin, with that origin's
|
|
37
|
+
cookies. If a session cookie lives there, a renderer that is not what it
|
|
38
|
+
should be acts as the signed-in user. The defaults are pinned to an exact
|
|
39
|
+
version with a Subresource Integrity hash, so a file the CDN changes is
|
|
40
|
+
refused by the browser; that does not make the renderer yours, and what it
|
|
41
|
+
loads in turn is not covered.
|
|
42
|
+
|
|
43
|
+
Where the origin carries a session, serve the document alone:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
docs({ info, ui: false });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`/openapi.json` is served and there is no page. For a page anyway, host
|
|
50
|
+
the renderer yourself or pin your own copy, with its hash:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
docs({
|
|
54
|
+
info,
|
|
55
|
+
assets: {
|
|
56
|
+
script: "https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.72.1/dist/browser/standalone.js",
|
|
57
|
+
integrity: { script: "sha384-…" },
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`curl -s <url> | openssl dgst -sha384 -binary | openssl base64 -A` prints
|
|
63
|
+
the hash, to be prefixed with `sha384-`.
|
|
64
|
+
|
|
33
65
|
## Options
|
|
34
66
|
|
|
35
67
|
| Option | Default | |
|
|
@@ -38,9 +70,9 @@ routes are left out of the document.
|
|
|
38
70
|
| `servers` | — | where the API is reachable |
|
|
39
71
|
| `path` | `/openapi.json` | where the document is served |
|
|
40
72
|
| `uiPath` | `/docs` | where the page is served |
|
|
41
|
-
| `ui` | `"scalar"` | `"scalar"`, `"swagger-ui"
|
|
73
|
+
| `ui` | `"scalar"` | `"scalar"`, `"swagger-ui"`, `"redoc"`, or `false` for no page |
|
|
42
74
|
| `title` | the document's title | the page's title |
|
|
43
|
-
| `assets` | the renderer
|
|
75
|
+
| `assets` | the renderer on jsDelivr, pinned | your own renderer URLs, with `integrity` hashes |
|
|
44
76
|
| `documentSelf` | `false` | include `/openapi.json` and `/docs` in the document |
|
|
45
77
|
| `onWarning` | `console.warn` | receives what could not be described |
|
|
46
78
|
|
|
@@ -106,6 +138,19 @@ The `error` code is a constant in each schema, so a generated client can
|
|
|
106
138
|
tell failures apart by it. A status the route declares itself is kept, and
|
|
107
139
|
the framework's failures for the same status are listed next to it.
|
|
108
140
|
|
|
141
|
+
Every envelope — the framework's, a hook's, or one the route declares
|
|
142
|
+
itself — is one definition in `components` per status and code, named
|
|
143
|
+
after the code (`ITEM_NOT_FOUND` is `ItemNotFound`), so a generated client
|
|
144
|
+
gets one type per failure. A schema is recognized as an envelope when its
|
|
145
|
+
`error` is required and a single string. When the route and a hook both
|
|
146
|
+
describe one code, the route's definition is kept; if the other one has
|
|
147
|
+
different fields, the generator warns. A union the route declares joins
|
|
148
|
+
the other failures of its status as one flat `anyOf`.
|
|
149
|
+
|
|
150
|
+
When every alternative of a status is an envelope, the union carries a
|
|
151
|
+
`discriminator` on `error`, with the mapping from each code to its
|
|
152
|
+
definition, and a generated client narrows on the code.
|
|
153
|
+
|
|
109
154
|
## Documenting hooks
|
|
110
155
|
|
|
111
156
|
A hook that answers by itself — an auth check, a limiter — can say so, and
|
|
@@ -127,14 +172,48 @@ export const auth = secured(
|
|
|
127
172
|
);
|
|
128
173
|
|
|
129
174
|
export const guard = documented(hook.beforeParse(check), {
|
|
130
|
-
responses: [
|
|
175
|
+
responses: [
|
|
176
|
+
{
|
|
177
|
+
status: 429,
|
|
178
|
+
description: "Rate limit exceeded",
|
|
179
|
+
error: "RATE_LIMITED",
|
|
180
|
+
fields: { retryAfter: { type: "integer", minimum: 0 } },
|
|
181
|
+
headers: { "retry-after": { schema: { type: "integer", minimum: 0 } } },
|
|
182
|
+
},
|
|
183
|
+
],
|
|
131
184
|
});
|
|
132
185
|
```
|
|
133
186
|
|
|
187
|
+
A response with an `error` code is the framework's envelope, defined once
|
|
188
|
+
in `components` and named after the code. `fields` adds what the hook puts
|
|
189
|
+
next to `status`, `message` and `error`, each always present; `headers`,
|
|
190
|
+
what it sets on the response. Both are JSON Schema written by hand, typed
|
|
191
|
+
keyword by keyword (`JsonSchema`), so a misspelled keyword does not
|
|
192
|
+
compile. A hook whose body is not the envelope passes a `schema` instead.
|
|
193
|
+
|
|
134
194
|
Hooks from `@tetsujs/rate-limit` are already documented this way. A scheme
|
|
135
195
|
is identified by its `name`: the same one mounted twice is one
|
|
136
196
|
requirement, and two different schemes under one name are reported.
|
|
137
197
|
|
|
198
|
+
Every hook of a route runs, so every scheme its hooks carry is required
|
|
199
|
+
together: a route behind a CSRF check and a captcha is documented as
|
|
200
|
+
needing both, one entry of `security` — in OpenAPI, separate entries mean
|
|
201
|
+
any one of them will do. Two hooks of one scheme require the scopes of
|
|
202
|
+
both.
|
|
203
|
+
|
|
204
|
+
"Either" lives inside one hook: a hook that accepts a session cookie or a
|
|
205
|
+
bearer token says so with `anyOf`, and the document lists every
|
|
206
|
+
combination a client may bring:
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
export const caller = secured(hook.beforeParse(sessionOrToken), {
|
|
210
|
+
anyOf: [cookieSession, bearerToken],
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// with a CSRF check on the same route:
|
|
214
|
+
// security: [{ session: [], csrf: [] }, { bearer: [], csrf: [] }]
|
|
215
|
+
```
|
|
216
|
+
|
|
138
217
|
## Using the document directly
|
|
139
218
|
|
|
140
219
|
When the document itself is the output — written to a file in CI, fed to a
|
|
@@ -16,15 +16,16 @@
|
|
|
16
16
|
* @module
|
|
17
17
|
*/
|
|
18
18
|
import type { AnyHook, AnySchema } from "@tetsujs/core";
|
|
19
|
+
import type { JsonSchema } from "./json-schema.ts";
|
|
19
20
|
/**
|
|
20
21
|
* The definition of a scheme, as OpenAPI spells it.
|
|
21
22
|
*
|
|
22
|
-
* Typed as loosely as the spec is wide — `http`, `apiKey`, `oauth2
|
|
23
|
-
* `openIdConnect` carry different fields, and narrowing
|
|
24
|
-
* be a second, poorer copy of the specification.
|
|
23
|
+
* Typed as loosely as the spec is wide — `http`, `apiKey`, `oauth2`,
|
|
24
|
+
* `openIdConnect` and `mutualTLS` carry different fields, and narrowing
|
|
25
|
+
* them here would be a second, poorer copy of the specification.
|
|
25
26
|
*/
|
|
26
27
|
export interface SecurityScheme {
|
|
27
|
-
readonly type: "http" | "apiKey" | "oauth2" | "openIdConnect";
|
|
28
|
+
readonly type: "http" | "apiKey" | "oauth2" | "openIdConnect" | "mutualTLS";
|
|
28
29
|
readonly [key: string]: unknown;
|
|
29
30
|
}
|
|
30
31
|
/** What a hook demands of a request, and what it answers when refused. */
|
|
@@ -70,11 +71,65 @@ export interface DocumentedResponse {
|
|
|
70
71
|
readonly error?: string;
|
|
71
72
|
/** An example of the envelope's `message`, for the same reason. */
|
|
72
73
|
readonly message?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Fields the hook adds to the envelope, as JSON Schema by name — the
|
|
76
|
+
* `retryAfter` of `{ ...errorBody(429, "RATE_LIMITED"), retryAfter }`.
|
|
77
|
+
*
|
|
78
|
+
* Each is documented as always present. The envelope's own `status`,
|
|
79
|
+
* `message` and `error` are not redefined by a field of the same name:
|
|
80
|
+
* `error` is what a client discriminates on, and it stays the code the
|
|
81
|
+
* hook declared. Ignored when the response has a `schema`, which says
|
|
82
|
+
* everything about the body itself.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* documented(limiter, {
|
|
87
|
+
* responses: [
|
|
88
|
+
* {
|
|
89
|
+
* status: 429,
|
|
90
|
+
* description: "Too many requests",
|
|
91
|
+
* error: "RATE_LIMITED",
|
|
92
|
+
* fields: { retryAfter: { type: "integer", minimum: 0 } },
|
|
93
|
+
* },
|
|
94
|
+
* ],
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
readonly fields?: Readonly<Record<string, JsonSchema>>;
|
|
99
|
+
/**
|
|
100
|
+
* Headers the hook sets on this response, by name — the `retry-after`
|
|
101
|
+
* of a refusal.
|
|
102
|
+
*
|
|
103
|
+
* Documented as possible rather than required: a status several sources
|
|
104
|
+
* answer with is one response in the document, and a header one of them
|
|
105
|
+
* sets is not on the others'.
|
|
106
|
+
*/
|
|
107
|
+
readonly headers?: Readonly<Record<string, DocumentedHeader>>;
|
|
108
|
+
}
|
|
109
|
+
/** A header a hook's response carries. */
|
|
110
|
+
export interface DocumentedHeader {
|
|
111
|
+
readonly description?: string;
|
|
112
|
+
readonly schema: JsonSchema;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Requirements of which a hook accepts any one: a session cookie *or* a
|
|
116
|
+
* bearer token, checked by one hook.
|
|
117
|
+
*
|
|
118
|
+
* "Either" lives inside a hook, never between hooks — every hook of a
|
|
119
|
+
* route runs, so the schemes of two hooks are both required. A hook that
|
|
120
|
+
* takes either of two credentials says so here, and the document lists
|
|
121
|
+
* the combinations a client may bring.
|
|
122
|
+
*/
|
|
123
|
+
export interface SecurityAlternatives {
|
|
124
|
+
readonly anyOf: readonly SecurityRequirement[];
|
|
73
125
|
}
|
|
74
126
|
/** Everything a hook tells the generator about itself. */
|
|
75
127
|
export interface HookDocs {
|
|
76
|
-
/**
|
|
77
|
-
|
|
128
|
+
/**
|
|
129
|
+
* What the hook demands of a request: one requirement, or alternatives
|
|
130
|
+
* of which any one will do.
|
|
131
|
+
*/
|
|
132
|
+
readonly security?: SecurityRequirement | SecurityAlternatives;
|
|
78
133
|
/** What the hook can answer with. */
|
|
79
134
|
readonly responses?: readonly DocumentedResponse[];
|
|
80
135
|
}
|
|
@@ -100,6 +155,10 @@ export declare function documented<H extends AnyHook>(hook: H, docs: HookDocs):
|
|
|
100
155
|
* Annotates a hook with the security it enforces — {@link documented} for
|
|
101
156
|
* the case that comes up most.
|
|
102
157
|
*
|
|
158
|
+
* One requirement, or `{ anyOf: [...] }` for a hook that accepts any one
|
|
159
|
+
* of several: the schemes of different hooks are all required, the
|
|
160
|
+
* alternatives of one hook are not.
|
|
161
|
+
*
|
|
103
162
|
* @example
|
|
104
163
|
* ```ts
|
|
105
164
|
* export const auth = secured(
|
|
@@ -114,15 +173,37 @@ export declare function documented<H extends AnyHook>(hook: H, docs: HookDocs):
|
|
|
114
173
|
* },
|
|
115
174
|
* );
|
|
116
175
|
* ```
|
|
176
|
+
*
|
|
177
|
+
* @example A hook that accepts a session cookie or a bearer token
|
|
178
|
+
* ```ts
|
|
179
|
+
* export const caller = secured(
|
|
180
|
+
* hook.beforeParse((ctx) => {
|
|
181
|
+
* const user = sessions.fromCookie(ctx) ?? tokens.fromHeader(ctx);
|
|
182
|
+
* if (!user) throw new HttpError(401);
|
|
183
|
+
* return { user };
|
|
184
|
+
* }),
|
|
185
|
+
* { anyOf: [cookieSession, bearerToken] },
|
|
186
|
+
* );
|
|
187
|
+
* ```
|
|
117
188
|
*/
|
|
118
|
-
export declare function secured<H extends AnyHook>(hook: H, requirement: SecurityRequirement): H;
|
|
189
|
+
export declare function secured<H extends AnyHook>(hook: H, requirement: SecurityRequirement | SecurityAlternatives): H;
|
|
119
190
|
/** Reads everything a hook was annotated with. */
|
|
120
191
|
export declare function docsOf(hook: AnyHook): HookDocs | undefined;
|
|
121
|
-
/** Reads the security
|
|
122
|
-
export declare function securityOf(hook: AnyHook): SecurityRequirement | undefined;
|
|
192
|
+
/** Reads the security a hook was annotated with, if it was. */
|
|
193
|
+
export declare function securityOf(hook: AnyHook): SecurityRequirement | SecurityAlternatives | undefined;
|
|
123
194
|
/** What the hooks of one route contribute, in execution order. */
|
|
124
195
|
export interface HookContributions {
|
|
196
|
+
/**
|
|
197
|
+
* Every scheme the hooks mention, once per name, with the scopes of all
|
|
198
|
+
* of them: what the document registers, and what a refusal answers with.
|
|
199
|
+
*/
|
|
125
200
|
readonly security: readonly SecurityRequirement[];
|
|
201
|
+
/**
|
|
202
|
+
* What a request must satisfy, one condition per hook: every condition
|
|
203
|
+
* is required, and any one requirement of a condition satisfies it. A
|
|
204
|
+
* hook with one requirement is a condition of one.
|
|
205
|
+
*/
|
|
206
|
+
readonly conditions: readonly (readonly SecurityRequirement[])[];
|
|
126
207
|
readonly responses: readonly DocumentedResponse[];
|
|
127
208
|
}
|
|
128
209
|
/**
|
|
@@ -130,7 +211,9 @@ export interface HookContributions {
|
|
|
130
211
|
*
|
|
131
212
|
* A scheme is registered once per name and a response once per status and
|
|
132
213
|
* description: the same guard on the application and on a group is one
|
|
133
|
-
* requirement, not two.
|
|
214
|
+
* requirement, not two. Two hooks of one scheme asking for different
|
|
215
|
+
* scopes both run, so the requirement asks for the scopes of both — each
|
|
216
|
+
* once, in the order they were first asked for.
|
|
134
217
|
*
|
|
135
218
|
* Deduplicating by name means two hooks claiming one name with different
|
|
136
219
|
* schemes lose one of them, and that is not a duplicate being collapsed —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/annotations.ts"],"names":[],"mappings":"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"}
|
package/dist/src/controller.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ import type { OpenApiDocument } from "./document.ts";
|
|
|
18
18
|
import type { GeneratorWarning } from "./index.ts";
|
|
19
19
|
import type { DocsAssets, DocsUi } from "./page.ts";
|
|
20
20
|
/** What the documentation controller serves, and from where. */
|
|
21
|
-
export interface DocsOptions<Path extends string, UiPath extends string> {
|
|
21
|
+
export interface DocsOptions<Path extends string, UiPath extends string, Ui extends DocsUi | false = DocsUi | false> {
|
|
22
22
|
/** Title, version and the rest of the document's `info` block. */
|
|
23
23
|
readonly info: OpenApiDocument["info"];
|
|
24
24
|
/** Servers the API is reachable at. */
|
|
@@ -27,8 +27,16 @@ export interface DocsOptions<Path extends string, UiPath extends string> {
|
|
|
27
27
|
readonly path?: Path & ValidatePath<Path>;
|
|
28
28
|
/** Where the page is served. Defaults to `/docs`. */
|
|
29
29
|
readonly uiPath?: UiPath & ValidatePath<UiPath>;
|
|
30
|
-
/**
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Which renderer the page bootstraps. Defaults to `"scalar"`.
|
|
32
|
+
*
|
|
33
|
+
* `false` serves the document without a page — what production wants
|
|
34
|
+
* on an origin that carries a session. The page runs its renderer on the
|
|
35
|
+
* application's origin, so a renderer that is not what it should be acts
|
|
36
|
+
* in the signed-in user's name there; the document alone runs nothing.
|
|
37
|
+
* `uiPath`, `title` and `assets` are then unused.
|
|
38
|
+
*/
|
|
39
|
+
readonly ui?: Ui;
|
|
32
40
|
/** Browser title of the page. Defaults to the document's own title. */
|
|
33
41
|
readonly title?: string;
|
|
34
42
|
/** Overrides the renderer's CDN URLs, for a pinned or self-hosted copy. */
|
|
@@ -56,15 +64,24 @@ export interface DocsOptions<Path extends string, UiPath extends string> {
|
|
|
56
64
|
* Instantiated through the factory, never directly — the routes carry the
|
|
57
65
|
* configured paths in their types, which only the factory can infer.
|
|
58
66
|
*/
|
|
59
|
-
export declare class DocsController<Path extends string, UiPath extends string> {
|
|
67
|
+
export declare class DocsController<Path extends string, UiPath extends string, Page extends boolean = true> {
|
|
60
68
|
private readonly options;
|
|
61
69
|
/** The document itself, as `application/json`. */
|
|
62
70
|
readonly json: RouteDef<Path, SchemaConfig, never, undefined, "GET">;
|
|
63
|
-
/** The page that renders it
|
|
64
|
-
readonly ui: RouteDef<UiPath, SchemaConfig, never, undefined, "GET"
|
|
71
|
+
/** The page that renders it — none with `ui: false`. */
|
|
72
|
+
readonly ui: Page extends true ? RouteDef<UiPath, SchemaConfig, never, undefined, "GET"> : undefined;
|
|
65
73
|
private document;
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
private page;
|
|
75
|
+
constructor(options: DocsOptions<Path, UiPath>, documentPath: string, uiPath: string);
|
|
76
|
+
/**
|
|
77
|
+
* Generates the document of the application this was mounted in, and
|
|
78
|
+
* the page that renders it.
|
|
79
|
+
*
|
|
80
|
+
* The page is built here rather than with the routes because only the
|
|
81
|
+
* application knows where the document ended up: a group this controller
|
|
82
|
+
* is mounted under prefixes its path, and a page pointing at the path as
|
|
83
|
+
* configured would fetch a `404`.
|
|
84
|
+
*/
|
|
68
85
|
[onMount](app: App): void;
|
|
69
86
|
}
|
|
70
87
|
/**
|
|
@@ -87,5 +104,5 @@ export declare class DocsController<Path extends string, UiPath extends string>
|
|
|
87
104
|
* The page loads its renderer from a CDN; see {@link docsPage} for the
|
|
88
105
|
* trade and for how to point it at a self-hosted copy.
|
|
89
106
|
*/
|
|
90
|
-
export declare function docs<const Path extends string = "/openapi.json", const UiPath extends string = "/docs">(options: DocsOptions<Path, UiPath>): DocsController<Path, UiPath>;
|
|
107
|
+
export declare function docs<const Path extends string = "/openapi.json", const UiPath extends string = "/docs", const Ui extends DocsUi | false = "scalar">(options: DocsOptions<Path, UiPath, Ui>): DocsController<Path, UiPath, Ui extends false ? false : true>;
|
|
91
108
|
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAS,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGpD,gEAAgE;AAChE,MAAM,WAAW,WAAW,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAS,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGpD,gEAAgE;AAChE,MAAM,WAAW,WAAW,CAC1B,IAAI,SAAS,MAAM,EACnB,MAAM,SAAS,MAAM,EACrB,EAAE,SAAS,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK;IAE1C,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAEvC,uCAAuC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IAE9C,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAE1C,qDAAqD;IACrD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAEhD;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IAEjB,uEAAuE;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAE7B;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC1D;AAED;;;;;;GAMG;AACH,qBAAa,cAAc,CACzB,IAAI,SAAS,MAAM,EACnB,MAAM,SAAS,MAAM,EACrB,IAAI,SAAS,OAAO,GAAG,IAAI;IAezB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAb1B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAErE,wDAAwD;IACxD,QAAQ,CAAC,EAAE,EAAE,IAAI,SAAS,IAAI,GAC1B,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,GACvD,SAAS,CAAC;IAEd,OAAO,CAAC,QAAQ,CAA8B;IAE9C,OAAO,CAAC,IAAI,CAAqB;IAEjC,YACmB,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,EACnD,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EAkCf;IAED;;;;;;;;OAQG;IACH,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CA0BxB;CACF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,IAAI,CAClB,KAAK,CAAC,IAAI,SAAS,MAAM,GAAG,eAAe,EAC3C,KAAK,CAAC,MAAM,SAAS,MAAM,GAAG,OAAO,EACrC,KAAK,CAAC,EAAE,SAAS,MAAM,GAAG,KAAK,GAAG,QAAQ,EAE1C,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,GACrC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,CAM/D"}
|
package/dist/src/document.d.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @module
|
|
16
16
|
*/
|
|
17
|
+
import type { JsonSchema } from "./json-schema.ts";
|
|
17
18
|
/** Metadata every OpenAPI document must carry. */
|
|
18
19
|
export interface DocumentInfo {
|
|
19
20
|
readonly title: string;
|
|
@@ -38,9 +39,15 @@ export interface ParameterObject {
|
|
|
38
39
|
export type ContentMap = Record<string, {
|
|
39
40
|
readonly schema?: Record<string, unknown>;
|
|
40
41
|
}>;
|
|
42
|
+
/** A header a response carries. */
|
|
43
|
+
export interface HeaderObject {
|
|
44
|
+
readonly description?: string;
|
|
45
|
+
readonly schema: JsonSchema;
|
|
46
|
+
}
|
|
41
47
|
/** One response of an operation. */
|
|
42
48
|
export interface ResponseObject {
|
|
43
49
|
readonly description: string;
|
|
50
|
+
readonly headers?: Record<string, HeaderObject>;
|
|
44
51
|
readonly content?: ContentMap;
|
|
45
52
|
}
|
|
46
53
|
/** One endpoint: a method on a path. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/document.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,MAAM,CAC7B,MAAM,EACN;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAC9C,CAAC;AAEF,oCAAoC;AACpC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;CAC/B;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACjD,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;KAC9B,CAAC;IACF,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACpD;AAED,qDAAqD;AACrD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAE7D,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAE/C;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE;QACpB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC5C,CAAC;IAEF,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC"}
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/document.ts"],"names":[],"mappings":"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"}
|
package/dist/src/emit.d.ts
CHANGED
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
* A JSON Schema as the generator reads it: any keyword, with the
|
|
9
|
+
* A JSON Schema as the generator reads it: any keyword, with the ones it
|
|
10
10
|
* looks into named, so reading them does not depend on the reader's
|
|
11
11
|
* `noPropertyAccessFromIndexSignature`.
|
|
12
12
|
*/
|
|
13
13
|
export interface JsonSchemaObject {
|
|
14
14
|
properties?: unknown;
|
|
15
15
|
required?: unknown;
|
|
16
|
+
anyOf?: unknown;
|
|
17
|
+
oneOf?: unknown;
|
|
16
18
|
[keyword: string]: unknown;
|
|
17
19
|
}
|
|
18
20
|
/** Which shape of a schema to describe: what arrives, or what leaves. */
|
package/dist/src/emit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/emit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAED,yEAAyE;AACzE,KAAK,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAC/B,SAAS,GAAE,SAAoB,GAC9B,gBAAgB,GAAG,SAAS,CAkB9B"}
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/emit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAED,yEAAyE;AACzE,KAAK,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAC/B,SAAS,GAAE,SAAoB,GAC9B,gBAAgB,GAAG,SAAS,CAkB9B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error envelopes, one definition per status and code.
|
|
3
|
+
*
|
|
4
|
+
* An envelope reaches a document from four directions: a route's response
|
|
5
|
+
* map, a hook's annotation, a guard's security requirement, and the
|
|
6
|
+
* framework's own failures. Each used to be described where it arrived —
|
|
7
|
+
* a route's inline, the rest by reference — so one `UNAUTHORIZED` could be
|
|
8
|
+
* listed twice under one status, once as a `$ref` and once as the same
|
|
9
|
+
* shape without a name, and a generated client got a named type next to an
|
|
10
|
+
* anonymous twin.
|
|
11
|
+
*
|
|
12
|
+
* Here every envelope, whoever declared it, becomes a reference to the
|
|
13
|
+
* one definition of its status and code. That is also what makes a status
|
|
14
|
+
* discriminable: a client can branch on `error` only if every code under
|
|
15
|
+
* the status has exactly one shape.
|
|
16
|
+
*
|
|
17
|
+
* The route's definition wins. It is the author's own contract — usually
|
|
18
|
+
* the stricter one, a validator's `additionalProperties: false` — where a
|
|
19
|
+
* hook's is the framework's generic envelope. The routes are therefore
|
|
20
|
+
* read first, before any operation is built, so the winner does not depend
|
|
21
|
+
* on which route happens to come first in the table.
|
|
22
|
+
*
|
|
23
|
+
* Internal to the package.
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
import type { SchemaComponents, SchemaRef } from "./components.ts";
|
|
28
|
+
import type { JsonSchemaObject } from "./emit.ts";
|
|
29
|
+
/** The definitions of every envelope of one document. */
|
|
30
|
+
export interface Envelopes {
|
|
31
|
+
/**
|
|
32
|
+
* Records a route's definition, before anything is referenced. The first
|
|
33
|
+
* route to declare a status and code defines it.
|
|
34
|
+
*/
|
|
35
|
+
declare(status: number, code: string, schema: JsonSchemaObject): void;
|
|
36
|
+
/**
|
|
37
|
+
* The reference to the definition of a status and code.
|
|
38
|
+
*
|
|
39
|
+
* `schema` is how the caller describes it. When a definition already
|
|
40
|
+
* exists, that is what is referenced; if the caller's differs from it
|
|
41
|
+
* in fields, `warn` hears about it — once per document, not once per
|
|
42
|
+
* operation the hook runs on.
|
|
43
|
+
*/
|
|
44
|
+
ref(status: number, code: string, schema: JsonSchemaObject, warn: (message: string) => void): SchemaRef;
|
|
45
|
+
/**
|
|
46
|
+
* The code a reference stands for, when it is one this handed out — what
|
|
47
|
+
* a discriminator maps back from.
|
|
48
|
+
*/
|
|
49
|
+
codeOf(ref: string): string | undefined;
|
|
50
|
+
}
|
|
51
|
+
export declare function envelopes(components: SchemaComponents): Envelopes;
|
|
52
|
+
/**
|
|
53
|
+
* The error code of a schema that is an envelope: an object whose `error`
|
|
54
|
+
* is required and holds one string — a `const`, or an `enum` of one value.
|
|
55
|
+
*
|
|
56
|
+
* Read off what the validator emitted, not off a declaration: the route
|
|
57
|
+
* has no other way to say which of its responses is an envelope, and the
|
|
58
|
+
* shape is what a client would branch on anyway.
|
|
59
|
+
*/
|
|
60
|
+
export declare function envelopeCode(schema: JsonSchemaObject): string | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* The alternatives a schema stands for, as a list the status's own union
|
|
63
|
+
* can take in.
|
|
64
|
+
*
|
|
65
|
+
* `anyOf` nested in `anyOf` says nothing its branches do not say side by
|
|
66
|
+
* side, so a schema that is only an `anyOf` is replaced by its branches.
|
|
67
|
+
* A `oneOf` is different — "exactly one" of two overlapping shapes refuses
|
|
68
|
+
* what both accept — and is taken apart only when its branches cannot
|
|
69
|
+
* overlap: envelopes with a different code each. A schema with anything
|
|
70
|
+
* beside its union, a `title` or a `$defs`, is left whole: those keywords
|
|
71
|
+
* belong to the union, and would be lost with it.
|
|
72
|
+
*/
|
|
73
|
+
export declare function branchesOf(schema: JsonSchemaObject): JsonSchemaObject[];
|
|
74
|
+
//# sourceMappingURL=envelopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelopes.d.ts","sourceRoot":"","sources":["../../src/envelopes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAEtE;;;;;;;OAOG;IACH,GAAG,CACD,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAC9B,SAAS,CAAC;IAEb;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACzC;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,gBAAgB,GAAG,SAAS,CAoEjE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CA0BzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAwBvE"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import type { App } from "@tetsujs/core";
|
|
22
22
|
import type { OpenApiDocument } from "./document.ts";
|
|
23
|
-
export type { DocumentedResponse, HookContributions, HookDocs, SecurityRequirement, SecurityScheme, } from "./annotations.ts";
|
|
23
|
+
export type { DocumentedHeader, DocumentedResponse, HookContributions, HookDocs, SecurityAlternatives, SecurityRequirement, SecurityScheme, } from "./annotations.ts";
|
|
24
24
|
export { documented, secured } from "./annotations.ts";
|
|
25
25
|
export type { DocsOptions } from "./controller.ts";
|
|
26
26
|
export { DocsController, docs } from "./controller.ts";
|
|
27
|
-
export type { ContentMap, DocumentInfo, DocumentServer, OpenApiDocument, OperationObject, ParameterObject, PathItemObject, ResponseObject, } from "./document.ts";
|
|
27
|
+
export type { ContentMap, DocumentInfo, DocumentServer, HeaderObject, OpenApiDocument, OperationObject, ParameterObject, PathItemObject, ResponseObject, } from "./document.ts";
|
|
28
|
+
export type { JsonSchema, JsonSchemaKeywords, JsonSchemaType, } from "./json-schema.ts";
|
|
28
29
|
export type { DocsAssets, DocsPageOptions, DocsUi } from "./page.ts";
|
|
29
30
|
export { docsPage } from "./page.ts";
|
|
30
31
|
/**
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,eAAe,CAAC;AAKrE,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAEvC,uCAAuC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,cAAc,GAAG,eAAe,CA2F1E"}
|