express-zod-api 28.1.1 → 28.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +38 -15
- package/dist/index.d.ts +335 -37
- package/dist/index.js +5 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
## Version 28
|
|
4
4
|
|
|
5
|
+
### v28.3.0
|
|
6
|
+
|
|
7
|
+
- `EndpointsFactory::addContext()` now passes the previously accumulated context to its callback:
|
|
8
|
+
- The argument function receives the current context as the first argument;
|
|
9
|
+
- Improved the declaration file for most of the essential entities.
|
|
10
|
+
|
|
11
|
+
### v28.2.0
|
|
12
|
+
|
|
13
|
+
- Added `createCacheMiddleware()` function for solving most of the caching problems:
|
|
14
|
+
- The function accepts an optional default policy to apply `Cache-Control` header to every response;
|
|
15
|
+
- It returns a Middleware providing several properties and caching helpers to context:
|
|
16
|
+
- `cacheControl` — the parsed request's `Cache-Control` header into a typed object;
|
|
17
|
+
- `ifNoneMatch` — the parsed `If-None-Match` request header into an array of ETags or `"*"`;
|
|
18
|
+
- `ifModifiedSince` — the parsed `If-Modified-Since` request header into a `Date`;
|
|
19
|
+
- `addCachePolicy()` — extends the default policy into the `Cache-Control` response header;
|
|
20
|
+
- `setETag()` — sets the `ETag` response header;
|
|
21
|
+
- `setLastModified()` — sets the `Last-Modified` response header;
|
|
22
|
+
- `setVary()` — sets the `Vary` response header;
|
|
23
|
+
- `setExpires()` — sets the `Expires` response header;
|
|
24
|
+
- `clearSiteData()` — sets the `Clear-Site-Data` header with `cache` directive;
|
|
25
|
+
- `notModified()` — sends an HTTP 304 response and ends the stream;
|
|
26
|
+
- Adjusted the Endpoint execution to skip output validation in case `response.writableEnded` (`notModified` called);
|
|
27
|
+
- Added two shorthand methods to `EndpointsFactory` class: `useCache()` and `useCookies()`.
|
|
28
|
+
|
|
5
29
|
### v28.1.1
|
|
6
30
|
|
|
7
31
|
- Depicting Endpoints built on `new EventStreamFactory({})` (having empty argument) will throw a `ResultHandlerError`:
|
package/README.md
CHANGED
|
@@ -36,16 +36,17 @@ Start your API server with I/O schema validation and custom middlewares in minut
|
|
|
36
36
|
1. [Customizing input sources](#customizing-input-sources)
|
|
37
37
|
2. [Headers as an input source](#headers-as-an-input-source)
|
|
38
38
|
3. [Cookies](#cookies)
|
|
39
|
-
4. [
|
|
40
|
-
5. [
|
|
41
|
-
6. [
|
|
42
|
-
7. [
|
|
43
|
-
8. [
|
|
44
|
-
9. [
|
|
45
|
-
10. [
|
|
46
|
-
11. [
|
|
47
|
-
12. [
|
|
48
|
-
13. [Testing
|
|
39
|
+
4. [Caching](#caching)
|
|
40
|
+
5. [Response customization](#response-customization)
|
|
41
|
+
6. [Empty response](#empty-response)
|
|
42
|
+
7. [Non-JSON response](#non-json-response) including file downloads
|
|
43
|
+
8. [Error handling](#error-handling)
|
|
44
|
+
9. [Production mode](#production-mode)
|
|
45
|
+
10. [HTML Forms (URL encoded)](#html-forms-url-encoded)
|
|
46
|
+
11. [File uploads](#file-uploads)
|
|
47
|
+
12. [Connect to your own express app](#connect-to-your-own-express-app)
|
|
48
|
+
13. [Testing endpoints](#testing-endpoints)
|
|
49
|
+
14. [Testing middlewares](#testing-middlewares)
|
|
49
50
|
6. [Integration and Documentation](#integration-and-documentation)
|
|
50
51
|
1. [Zod Plugin](#zod-plugin)
|
|
51
52
|
2. [End-to-End Type Safety](#end-to-end-type-safety)
|
|
@@ -394,7 +395,7 @@ connection, consider shorthand method `addContext`. For static values consider r
|
|
|
394
395
|
import { readFile } from "node:fs/promises";
|
|
395
396
|
import { defaultEndpointsFactory } from "express-zod-api";
|
|
396
397
|
|
|
397
|
-
const endpointsFactory = defaultEndpointsFactory.addContext(async () => {
|
|
398
|
+
const endpointsFactory = defaultEndpointsFactory.addContext(async (ctx) => {
|
|
398
399
|
// caution: new connection on every request:
|
|
399
400
|
const db = mongoose.connect("mongodb://connection.string");
|
|
400
401
|
const privateKey = await readFile("private-key.pem", "utf-8");
|
|
@@ -842,9 +843,7 @@ as well as `getCookie()` — alternative to the cookies as an input source:
|
|
|
842
843
|
import { createCookieMiddleware, Middleware } from "express-zod-api";
|
|
843
844
|
|
|
844
845
|
const cookieDrivenFactory = factory
|
|
845
|
-
.
|
|
846
|
-
createCookieMiddleware({ httpOnly: true, sameSite: "lax", path: "/" }), // recommended base options
|
|
847
|
-
)
|
|
846
|
+
.useCookies({ httpOnly: true, sameSite: "lax", path: "/" }) // shorthand, recommended base options
|
|
848
847
|
.addMiddleware(
|
|
849
848
|
new Middleware({
|
|
850
849
|
security: { type: "cookie", name: "session" }, // improves Documentation
|
|
@@ -862,6 +861,30 @@ const sessionSettingEndpoint = cookieDrivenFactory.buildVoid({
|
|
|
862
861
|
});
|
|
863
862
|
```
|
|
864
863
|
|
|
864
|
+
## Caching
|
|
865
|
+
|
|
866
|
+
Consider the `createCacheMiddleware()` that provides helpers for HTTP caching following the MDN HTTP Caching guide.
|
|
867
|
+
It covers all standard `Cache-Control` directives, conditional request handling, and the "Not Modified" (304) flow:
|
|
868
|
+
|
|
869
|
+
```ts
|
|
870
|
+
import { createCacheMiddleware } from "express-zod-api";
|
|
871
|
+
|
|
872
|
+
const avatarEndpoint = factory
|
|
873
|
+
.useCache({ maxAge: 3600, scope: "public" }) // shorthand, the policy applies to every response
|
|
874
|
+
.build({
|
|
875
|
+
output: z.object({ avatar: z.string() }),
|
|
876
|
+
handler: async ({
|
|
877
|
+
ctx: { ifNoneMatch, setETag, notModified, addCachePolicy },
|
|
878
|
+
}) => {
|
|
879
|
+
const etag = `"avatar-v2"`;
|
|
880
|
+
if (ifNoneMatch?.includes(etag)) return notModified() as never; // skips validation, sends 304
|
|
881
|
+
setETag(etag);
|
|
882
|
+
addCachePolicy({ staleWhileRevalidate: 86400 }); // extends the default policy
|
|
883
|
+
return { avatar: "https://example.com/avatar.png" };
|
|
884
|
+
},
|
|
885
|
+
});
|
|
886
|
+
```
|
|
887
|
+
|
|
865
888
|
## Response customization
|
|
866
889
|
|
|
867
890
|
`ResultHandler` is responsible for transmitting consistent responses containing the endpoint output or an error.
|
|
@@ -960,7 +983,7 @@ it normalizes errors into consistent HTTP responses with sensible status codes.
|
|
|
960
983
|
- `OutputValidationError`: handler violates `output` schema, the default status code is `500`;
|
|
961
984
|
- `HttpError`: can be thrown in handlers with help of `createHttpError()`, its `.statusCode` is used for response;
|
|
962
985
|
- For other errors the default status code is `500`;
|
|
963
|
-
- Routing, parsing and upload issues:
|
|
986
|
+
- Routing, parsing, and upload issues:
|
|
964
987
|
- Handled by `ResultHandler` configured as `errorHandler` (the defaults is `defaultResultHandler`);
|
|
965
988
|
- Parsing errors: passed through as-is (typically `HttpError` with `4XX` code used for response by default);
|
|
966
989
|
- Routing errors: `404` or `405`, based on `hintAllowedMethods` configuration;
|
package/dist/index.d.ts
CHANGED
|
@@ -31,14 +31,22 @@ type Method = (typeof methods)[number];
|
|
|
31
31
|
* @example Method | "head"
|
|
32
32
|
* */
|
|
33
33
|
type ClientMethod = (typeof clientMethods)[number];
|
|
34
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* @desc A container for describing an API response: its schema, status code(s) and MIME type(s).
|
|
36
|
+
* @see ResultHandler
|
|
37
|
+
* */
|
|
35
38
|
interface ApiResponse<S extends z.ZodType> {
|
|
39
|
+
/** @desc The Zod schema describing the response body. */
|
|
36
40
|
schema: S;
|
|
37
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* @desc The status code(s) for this response.
|
|
43
|
+
* @default 200 for a positive response, 400 for a negative one
|
|
44
|
+
* */
|
|
38
45
|
statusCode?: number | [number, ...number[]];
|
|
39
46
|
/**
|
|
40
|
-
* @
|
|
47
|
+
* @desc The MIME type(s) of the response.
|
|
41
48
|
* @default "application/json"
|
|
49
|
+
* @example null — no content, typical for 204 and 302
|
|
42
50
|
* */
|
|
43
51
|
mimeType?: string | [string, ...string[]] | null;
|
|
44
52
|
}
|
|
@@ -228,10 +236,10 @@ type Security<K extends string = string, S extends string = string> =
|
|
|
228
236
|
| OpenIdSecurity
|
|
229
237
|
| OAuth2Security<S>;
|
|
230
238
|
type Handler$2<IN, CTX, RET> = (params: {
|
|
231
|
-
/** @desc The inputs from the enabled input sources validated against the input schema of the Middleware */
|
|
239
|
+
/** @desc The inputs from the enabled input sources validated against the input schema of the Middleware. */
|
|
232
240
|
input: IN;
|
|
233
241
|
/**
|
|
234
|
-
* @desc The returns of the previously executed Middlewares (typed when chaining Middlewares)
|
|
242
|
+
* @desc The returns of the previously executed Middlewares (typed when chaining Middlewares).
|
|
235
243
|
* @link https://github.com/RobinTail/express-zod-api/discussions/1250
|
|
236
244
|
* */
|
|
237
245
|
ctx: CTX;
|
|
@@ -239,7 +247,7 @@ type Handler$2<IN, CTX, RET> = (params: {
|
|
|
239
247
|
request: Request;
|
|
240
248
|
/** @link https://expressjs.com/en/5x/api.html#res */
|
|
241
249
|
response: Response;
|
|
242
|
-
/** @desc The instance of the configured logger */
|
|
250
|
+
/** @desc The instance of the configured logger. */
|
|
243
251
|
logger: ActualLogger;
|
|
244
252
|
}) => Promise<RET>;
|
|
245
253
|
declare abstract class AbstractMiddleware {
|
|
@@ -251,6 +259,11 @@ declare abstract class AbstractMiddleware {
|
|
|
251
259
|
logger: ActualLogger;
|
|
252
260
|
}): Promise<FlatObject>;
|
|
253
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* @desc A Middleware that validates its input schema, executes its handler, and returns context properties available to
|
|
264
|
+
* next middlewares and the Endpoint handler. Can also declare security schemas for Documentation.
|
|
265
|
+
* @see EndpointsFactory#addMiddleware
|
|
266
|
+
* */
|
|
254
267
|
declare class Middleware<
|
|
255
268
|
CTX extends FlatObject,
|
|
256
269
|
RET extends FlatObject,
|
|
@@ -268,9 +281,12 @@ declare class Middleware<
|
|
|
268
281
|
* @see defaultInputSources
|
|
269
282
|
* */
|
|
270
283
|
input?: IN;
|
|
271
|
-
/**
|
|
284
|
+
/**
|
|
285
|
+
* @desc Declaration of the security schemas implemented within the handler (used by Documentation).
|
|
286
|
+
* @see Documentation
|
|
287
|
+
* */
|
|
272
288
|
security?: LogicalContainer<Security<Extract<keyof z.input<IN>, string>, SCO>>;
|
|
273
|
-
/** @desc The handler returning a context available to Endpoints */
|
|
289
|
+
/** @desc The handler returning a context available to Endpoints. */
|
|
274
290
|
handler: Handler$2<z.output<IN>, CTX, RET>;
|
|
275
291
|
});
|
|
276
292
|
/** @throws InputValidationError */
|
|
@@ -285,6 +301,11 @@ declare class Middleware<
|
|
|
285
301
|
logger: ActualLogger;
|
|
286
302
|
}): Promise<RET>;
|
|
287
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* @desc A wrapper around native Express middlewares that converts them into the framework's Middleware instances.
|
|
306
|
+
* Optionally, a `provider` can extend the context, and a `transformer` can convert caught errors.
|
|
307
|
+
* @see EndpointsFactory#addExpressMiddleware
|
|
308
|
+
* */
|
|
288
309
|
declare class ExpressMiddleware<R extends Request, S extends Response, RET extends FlatObject> extends Middleware<
|
|
289
310
|
FlatObject,
|
|
290
311
|
RET,
|
|
@@ -296,7 +317,9 @@ declare class ExpressMiddleware<R extends Request, S extends Response, RET exten
|
|
|
296
317
|
provider,
|
|
297
318
|
transformer,
|
|
298
319
|
}?: {
|
|
320
|
+
/** @desc Extracts context properties from request and response after the native middleware execution. */
|
|
299
321
|
provider?: (request: R, response: S) => RET | Promise<RET>;
|
|
322
|
+
/** @desc Transforms errors caught from the native middleware before they propagate further. */
|
|
300
323
|
transformer?: (err: Error) => Error;
|
|
301
324
|
},
|
|
302
325
|
);
|
|
@@ -320,19 +343,29 @@ type Handler$1<RES = unknown> = (
|
|
|
320
343
|
params: DiscriminatedResult & {
|
|
321
344
|
/** null in case of failure to parse or to find the matching endpoint (error: not found) */
|
|
322
345
|
input: FlatObject | null;
|
|
323
|
-
/** can be empty: check presence of the required property using "in" operator */
|
|
346
|
+
/** can be empty: check the presence of the required property using the "in" operator */
|
|
324
347
|
ctx: FlatObject;
|
|
325
348
|
request: Request;
|
|
326
349
|
response: Response<RES>;
|
|
327
350
|
logger: ActualLogger;
|
|
328
351
|
},
|
|
329
352
|
) => void | Promise<void>;
|
|
353
|
+
/**
|
|
354
|
+
* @desc Result definition for ResultHandler: a plain schema (for JSON and default status codes) or custom ApiResponse.
|
|
355
|
+
* @see ApiResponse
|
|
356
|
+
* */
|
|
330
357
|
type Result<S extends z.ZodType = z.ZodType> = S | ApiResponse<S> | ApiResponse<S>[];
|
|
358
|
+
/** @desc A function that lazily produces a Result definition. */
|
|
331
359
|
type LazyResult<R extends Result, A extends unknown[] = []> = (...args: A) => R;
|
|
332
360
|
declare abstract class AbstractResultHandler {
|
|
333
361
|
protected constructor(handler: Handler$1);
|
|
334
362
|
execute(...params: Parameters<Handler$1>): void | Promise<void>;
|
|
335
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* @desc The entity responsible to respond consistently. Accepts positive and negative Result definitions.
|
|
366
|
+
* The positive definition can be a lazy function receiving the output schema of an Endpoint.
|
|
367
|
+
* @see Result
|
|
368
|
+
* */
|
|
336
369
|
declare class ResultHandler<POS extends Result, NEG extends Result> extends AbstractResultHandler {
|
|
337
370
|
constructor(params: {
|
|
338
371
|
/** @desc A description of the API response in case of success (schema, status code, MIME type) */
|
|
@@ -343,6 +376,12 @@ declare class ResultHandler<POS extends Result, NEG extends Result> extends Abst
|
|
|
343
376
|
handler: Handler$1<z.output<ResultSchema<POS> | ResultSchema<NEG>>>;
|
|
344
377
|
});
|
|
345
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* @desc The default ResultHandler wrapping Endpoint output in `{ status: "success", data: output }`
|
|
381
|
+
* and errors in `{ status: "error", error: { message } }`. Responds with JSON Content-Type.
|
|
382
|
+
* Respects the status of errors from createHttpError(), others become InternalServerError (500).
|
|
383
|
+
* @see ensureHttpError
|
|
384
|
+
* */
|
|
346
385
|
declare const defaultResultHandler: ResultHandler<
|
|
347
386
|
z.ZodObject<
|
|
348
387
|
{
|
|
@@ -366,7 +405,7 @@ declare const defaultResultHandler: ResultHandler<
|
|
|
366
405
|
>;
|
|
367
406
|
/**
|
|
368
407
|
* @deprecated Resist the urge of using it: this handler is designed only to simplify the migration of legacy APIs.
|
|
369
|
-
* @desc Responding with array is a bad practice keeping your endpoints from evolving without breaking changes.
|
|
408
|
+
* @desc Responding with an array is a bad practice keeping your endpoints from evolving without breaking changes.
|
|
370
409
|
* @desc This handler expects your endpoint to have the property 'items' in the output object schema
|
|
371
410
|
* */
|
|
372
411
|
declare const arrayResultHandler: ResultHandler<
|
|
@@ -646,6 +685,196 @@ interface AppConfig extends CommonConfig {
|
|
|
646
685
|
}
|
|
647
686
|
declare function createConfig(config: ServerConfig): ServerConfig;
|
|
648
687
|
declare function createConfig(config: AppConfig): AppConfig;
|
|
688
|
+
/**
|
|
689
|
+
* @desc Directives shared by both request and response Cache-Control headers.
|
|
690
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#cache_directives
|
|
691
|
+
*/
|
|
692
|
+
interface CommonDirectives {
|
|
693
|
+
/**
|
|
694
|
+
* @desc Response: the response remains fresh for N seconds after it was generated.
|
|
695
|
+
* @desc Request: the client will accept a stored response that was generated at most N seconds ago.
|
|
696
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#max-age
|
|
697
|
+
*/
|
|
698
|
+
maxAge?: number;
|
|
699
|
+
/**
|
|
700
|
+
* @desc Forces revalidation with the server before reuse.
|
|
701
|
+
* @desc In a response this tells caches to revalidate; in a request it asks caches to revalidate.
|
|
702
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#no-cache
|
|
703
|
+
*/
|
|
704
|
+
noCache?: boolean;
|
|
705
|
+
/**
|
|
706
|
+
* @desc Prevents storing the response in any cache. In a response this instructs caches not to store.
|
|
707
|
+
* @desc In a request it asks caches not to store the request or its response.
|
|
708
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#no-store
|
|
709
|
+
*/
|
|
710
|
+
noStore?: boolean;
|
|
711
|
+
/**
|
|
712
|
+
* @desc Prevents intermediaries from transforming the response body (e.g. converting images).
|
|
713
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#no-transform
|
|
714
|
+
*/
|
|
715
|
+
noTransform?: boolean;
|
|
716
|
+
/**
|
|
717
|
+
* @desc Allows a stale cached response to be reused for N seconds when the origin server returns an error.
|
|
718
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#stale-if-error
|
|
719
|
+
*/
|
|
720
|
+
staleIfError?: number;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* @desc Directives that clients send in requests to express their caching preferences.
|
|
724
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#request_directives
|
|
725
|
+
*/
|
|
726
|
+
interface CacheControl extends CommonDirectives {
|
|
727
|
+
/**
|
|
728
|
+
* @desc The client will accept a stored response that is stale for up to N seconds beyond its freshness lifetime.
|
|
729
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#max-stale
|
|
730
|
+
*/
|
|
731
|
+
maxStale?: number;
|
|
732
|
+
/**
|
|
733
|
+
* @desc The client requires a stored response that will remain fresh for at least N more seconds.
|
|
734
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#min-fresh
|
|
735
|
+
*/
|
|
736
|
+
minFresh?: number;
|
|
737
|
+
/**
|
|
738
|
+
* @desc The client wants a response only from the cache. Throw createHttpError(504) in this case.
|
|
739
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#only-if-cached
|
|
740
|
+
*/
|
|
741
|
+
onlyIfCached?: boolean;
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* @desc Directives that servers send in responses to control how caches store and reuse the response.
|
|
745
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#response_directives
|
|
746
|
+
*/
|
|
747
|
+
interface CachePolicy extends CommonDirectives {
|
|
748
|
+
/**
|
|
749
|
+
* @desc Restricts which caches may store the response.
|
|
750
|
+
* @example "public" — any cache (browser, proxy, CDN); for static assets, responses without user-specific data.
|
|
751
|
+
* @example "private" — browser only; for user-specific and personalized content.
|
|
752
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#response_directives
|
|
753
|
+
*/
|
|
754
|
+
scope?: "public" | "private";
|
|
755
|
+
/**
|
|
756
|
+
* @desc Overrides max-age for shared caches (proxies, CDNs). Ignored by private (browser) caches.
|
|
757
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#s-maxage
|
|
758
|
+
*/
|
|
759
|
+
sMaxAge?: number;
|
|
760
|
+
/**
|
|
761
|
+
* @desc Forces all caches to revalidate stale responses with the origin server before reusing them.
|
|
762
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#must-revalidate
|
|
763
|
+
*/
|
|
764
|
+
mustRevalidate?: boolean;
|
|
765
|
+
/**
|
|
766
|
+
* @desc Forces proxies and CDNs to revalidate stale responses with the origin server before reusing them.
|
|
767
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#proxy-revalidate
|
|
768
|
+
*/
|
|
769
|
+
proxyRevalidate?: boolean;
|
|
770
|
+
/**
|
|
771
|
+
* @desc A cache must understand the caching requirements for the response's status code before storing it.
|
|
772
|
+
* @desc Pair with no-store as a fallback for caches that don't support it.
|
|
773
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#must-understand
|
|
774
|
+
*/
|
|
775
|
+
mustUnderstand?: boolean;
|
|
776
|
+
/**
|
|
777
|
+
* @desc Indicates that the response body will never change while fresh.
|
|
778
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#immutable
|
|
779
|
+
*/
|
|
780
|
+
immutable?: boolean;
|
|
781
|
+
/**
|
|
782
|
+
* @desc Allows a stale response to be served in the background while the cache revalidates it, for up to N seconds.
|
|
783
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#stale-while-revalidate
|
|
784
|
+
*/
|
|
785
|
+
staleWhileRevalidate?: number;
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* @desc Creates a Middleware providing caching helpers.
|
|
789
|
+
* @param defaultPolicy — Optional default Cache-Control policy applied to all responses.
|
|
790
|
+
* @example createCacheMiddleware({ noCache: true, scope: "private" })
|
|
791
|
+
*/
|
|
792
|
+
declare const createCacheMiddleware: (defaultPolicy?: CachePolicy) => Middleware<
|
|
793
|
+
FlatObject,
|
|
794
|
+
{
|
|
795
|
+
/**
|
|
796
|
+
* @desc Provides the parsed If-None-Match request header into an array of ETags. Can also be '*' wildcard.
|
|
797
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/If-None-Match
|
|
798
|
+
*/
|
|
799
|
+
readonly ifNoneMatch: string[] | "*" | undefined;
|
|
800
|
+
/**
|
|
801
|
+
* @desc Provides the parsed If-Modified-Since request header having the timestamp of the client's cached copy.
|
|
802
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/If-Modified-Since
|
|
803
|
+
*/
|
|
804
|
+
readonly ifModifiedSince: Date | undefined;
|
|
805
|
+
/**
|
|
806
|
+
* @desc Provides the parsed Cache-Control request header to reveal the client's caching intent.
|
|
807
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control
|
|
808
|
+
*/
|
|
809
|
+
readonly cacheControl: CacheControl | undefined;
|
|
810
|
+
/**
|
|
811
|
+
* @desc Augments the Cache-Control response header, merging with the defaultPolicy if provided.
|
|
812
|
+
* @desc Pass `undefined` for a directive to unset the default value.
|
|
813
|
+
* @see defaultPolicy
|
|
814
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching
|
|
815
|
+
*/
|
|
816
|
+
addCachePolicy: (policy: CachePolicy) => void;
|
|
817
|
+
/**
|
|
818
|
+
* @desc Sets the ETag response header with a unique identifier for this version of the resource.
|
|
819
|
+
* @see ifNoneMatch
|
|
820
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag
|
|
821
|
+
*/
|
|
822
|
+
setETag: (value: string) => void;
|
|
823
|
+
/**
|
|
824
|
+
* @desc Sets the Last-Modified response header to the timestamp when the resource was last changed.
|
|
825
|
+
* @see ifModifiedSince
|
|
826
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Last-Modified
|
|
827
|
+
*/
|
|
828
|
+
setLastModified: (date: Date) => void;
|
|
829
|
+
/**
|
|
830
|
+
* @desc Sets the Vary response header to the list of request headers that influence the response.
|
|
831
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Vary
|
|
832
|
+
*/
|
|
833
|
+
setVary: (...headers: string[]) => void;
|
|
834
|
+
/**
|
|
835
|
+
* @desc Sets the Expires response header with an explicit expiration date. Consider addCachePolicy({ maxAge }).
|
|
836
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Expires
|
|
837
|
+
*/
|
|
838
|
+
setExpires: (date: Date) => void;
|
|
839
|
+
/**
|
|
840
|
+
* @desc Sets the Clear-Site-Data response header with the "cache" directive to remove all cached responses.
|
|
841
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Clear-Site-Data
|
|
842
|
+
*/
|
|
843
|
+
clearSiteData: () => void;
|
|
844
|
+
/**
|
|
845
|
+
* @desc Sends an HTTP 304 Not Modified empty response and ends the response stream.
|
|
846
|
+
* @example return ctx.notModified() as never; // to satisfy the handler's return type
|
|
847
|
+
* @see ifNoneMatch
|
|
848
|
+
* @see ifModifiedSince
|
|
849
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/304
|
|
850
|
+
*/
|
|
851
|
+
notModified: () => void;
|
|
852
|
+
},
|
|
853
|
+
string,
|
|
854
|
+
undefined
|
|
855
|
+
>;
|
|
856
|
+
/**
|
|
857
|
+
* @desc Creates a Middleware providing cookie-setting convenience methods.
|
|
858
|
+
* @param baseOptions — Default options applied to every setCookie / clearCookie call.
|
|
859
|
+
* @example createCookieMiddleware({ httpOnly: true, secure: true, path: "/" })
|
|
860
|
+
*/
|
|
861
|
+
declare const createCookieMiddleware: (baseOptions?: CookieOptions) => Middleware<
|
|
862
|
+
FlatObject,
|
|
863
|
+
{
|
|
864
|
+
/**
|
|
865
|
+
* @desc Reads a cookie value. Checks signedCookies first, then falls back to cookies.
|
|
866
|
+
* @requires cookie-parser
|
|
867
|
+
* @see ServerConfig.cookies
|
|
868
|
+
* */
|
|
869
|
+
getCookie: (name: string) => z.core.util.JSONType | undefined;
|
|
870
|
+
/** @desc Sets a cookie on the response. Express converts non-string values to JSON. */
|
|
871
|
+
setCookie: (name: string, value: string | z.core.util.JSONType, overrides?: CookieOptions) => void;
|
|
872
|
+
/** @desc Clears a cookie on the response. */
|
|
873
|
+
clearCookie: (name: string, overrides?: Omit<CookieOptions, "expires" | "maxAge">) => void;
|
|
874
|
+
},
|
|
875
|
+
string,
|
|
876
|
+
undefined
|
|
877
|
+
>;
|
|
649
878
|
interface BuildProps<
|
|
650
879
|
IN extends IOSchema,
|
|
651
880
|
OUT extends IOSchema | z.ZodVoid,
|
|
@@ -687,6 +916,12 @@ interface BuildProps<
|
|
|
687
916
|
/** @desc Marks the operation deprecated in the generated Documentation */
|
|
688
917
|
deprecated?: boolean;
|
|
689
918
|
}
|
|
919
|
+
/**
|
|
920
|
+
* @desc Creates a factory for building Endpoints. It can be extended by adding Middlewares that enrich the context
|
|
921
|
+
* available to the Endpoint handler. It requires a ResultHandler to respond consistently.
|
|
922
|
+
* @see Middleware
|
|
923
|
+
* @see ResultHandler
|
|
924
|
+
* */
|
|
690
925
|
declare class EndpointsFactory<
|
|
691
926
|
IN extends IOSchema | undefined = undefined,
|
|
692
927
|
CTX extends FlatObject = EmptyObject,
|
|
@@ -695,10 +930,69 @@ declare class EndpointsFactory<
|
|
|
695
930
|
protected resultHandler: AbstractResultHandler;
|
|
696
931
|
protected schema: IN;
|
|
697
932
|
protected middlewares: AbstractMiddleware[];
|
|
933
|
+
/**
|
|
934
|
+
* @param resultHandler An instance of ResultHandler for handling both Endpoint outputs and all possible errors.
|
|
935
|
+
* @see ResultHandler
|
|
936
|
+
* */
|
|
698
937
|
constructor(resultHandler: AbstractResultHandler);
|
|
938
|
+
/**
|
|
939
|
+
* @desc Attaches a Middleware to the factory, extending the context available to Endpoints built on it.
|
|
940
|
+
* Accepts either a Middleware instance or a plain object compatible with the Middleware constructor.
|
|
941
|
+
* @see Middleware
|
|
942
|
+
* */
|
|
699
943
|
addMiddleware<RET extends FlatObject, ASCO extends string, AIN extends IOSchema | undefined = undefined>(
|
|
700
944
|
subject: Middleware<CTX, RET, ASCO, AIN> | ConstructorParameters<typeof Middleware<CTX, RET, ASCO, AIN>>[0],
|
|
701
945
|
): EndpointsFactory<Extension<IN, AIN>, (CTX extends Record<string, never> ? RET : CTX) & RET, SCO & ASCO>;
|
|
946
|
+
/** @desc Shorthand for .addMiddleware(createCookieMiddleware()) */
|
|
947
|
+
useCookies(...args: Parameters<typeof createCookieMiddleware>): EndpointsFactory<
|
|
948
|
+
Extension<IN, undefined>,
|
|
949
|
+
(CTX extends Record<string, never>
|
|
950
|
+
? {
|
|
951
|
+
getCookie: (name: string) => z.core.util.JSONType | undefined;
|
|
952
|
+
setCookie: (name: string, value: string | z.core.util.JSONType, overrides?: _$express.CookieOptions) => void;
|
|
953
|
+
clearCookie: (name: string, overrides?: Omit<_$express.CookieOptions, "expires" | "maxAge">) => void;
|
|
954
|
+
}
|
|
955
|
+
: CTX) & {
|
|
956
|
+
getCookie: (name: string) => z.core.util.JSONType | undefined;
|
|
957
|
+
setCookie: (name: string, value: string | z.core.util.JSONType, overrides?: _$express.CookieOptions) => void;
|
|
958
|
+
clearCookie: (name: string, overrides?: Omit<_$express.CookieOptions, "expires" | "maxAge">) => void;
|
|
959
|
+
},
|
|
960
|
+
SCO
|
|
961
|
+
>;
|
|
962
|
+
/** @desc Shorthand for .addMiddleware(createCacheMiddleware()) */
|
|
963
|
+
useCache(...args: Parameters<typeof createCacheMiddleware>): EndpointsFactory<
|
|
964
|
+
Extension<IN, undefined>,
|
|
965
|
+
(CTX extends Record<string, never>
|
|
966
|
+
? {
|
|
967
|
+
readonly ifNoneMatch: string[] | "*" | undefined;
|
|
968
|
+
readonly ifModifiedSince: Date | undefined;
|
|
969
|
+
readonly cacheControl: CacheControl | undefined;
|
|
970
|
+
addCachePolicy: (policy: CachePolicy) => void;
|
|
971
|
+
setETag: (value: string) => void;
|
|
972
|
+
setLastModified: (date: Date) => void;
|
|
973
|
+
setVary: (...headers: string[]) => void;
|
|
974
|
+
setExpires: (date: Date) => void;
|
|
975
|
+
clearSiteData: () => void;
|
|
976
|
+
notModified: () => void;
|
|
977
|
+
}
|
|
978
|
+
: CTX) & {
|
|
979
|
+
readonly ifNoneMatch: string[] | "*" | undefined;
|
|
980
|
+
readonly ifModifiedSince: Date | undefined;
|
|
981
|
+
readonly cacheControl: CacheControl | undefined;
|
|
982
|
+
addCachePolicy: (policy: CachePolicy) => void;
|
|
983
|
+
setETag: (value: string) => void;
|
|
984
|
+
setLastModified: (date: Date) => void;
|
|
985
|
+
setVary: (...headers: string[]) => void;
|
|
986
|
+
setExpires: (date: Date) => void;
|
|
987
|
+
clearSiteData: () => void;
|
|
988
|
+
notModified: () => void;
|
|
989
|
+
},
|
|
990
|
+
SCO
|
|
991
|
+
>;
|
|
992
|
+
/**
|
|
993
|
+
* @desc Shorthand for addExpressMiddleware(). Use it for wrapping native Express middlewares.
|
|
994
|
+
* @see addExpressMiddleware
|
|
995
|
+
* */
|
|
702
996
|
use: <R extends Request, S extends Response, AOUT extends FlatObject = Record<string, never>>(
|
|
703
997
|
nativeMw: (request: R, response: S, next: _$express.NextFunction) => any,
|
|
704
998
|
params_1?:
|
|
@@ -708,12 +1002,28 @@ declare class EndpointsFactory<
|
|
|
708
1002
|
}
|
|
709
1003
|
| undefined,
|
|
710
1004
|
) => EndpointsFactory<Extension<IN, undefined>, (CTX extends Record<string, never> ? AOUT : CTX) & AOUT, SCO>;
|
|
1005
|
+
/**
|
|
1006
|
+
* @desc Wraps a native Express middleware and attaches it to the factory as a Middleware. Optionally, a `provider`
|
|
1007
|
+
* can extract context properties from the request and response, and a `transformer` can convert errors.
|
|
1008
|
+
* @see ExpressMiddleware
|
|
1009
|
+
* */
|
|
711
1010
|
addExpressMiddleware<R extends Request, S extends Response, AOUT extends FlatObject = EmptyObject>(
|
|
712
1011
|
...params: ConstructorParameters<typeof ExpressMiddleware<R, S, AOUT>>
|
|
713
1012
|
): EndpointsFactory<Extension<IN, undefined>, (CTX extends Record<string, never> ? AOUT : CTX) & AOUT, SCO>;
|
|
1013
|
+
/**
|
|
1014
|
+
* @desc Extends the context available to Endpoints built on this factory by resolving additional properties
|
|
1015
|
+
* from an asynchronous callback. The callback receives the current accumulated context, allowing further
|
|
1016
|
+
* context values to depend on previously provided ones. This is a shorthand for addMiddleware() with no schema.
|
|
1017
|
+
* @see addMiddleware
|
|
1018
|
+
* */
|
|
714
1019
|
addContext<RET extends FlatObject>(
|
|
715
|
-
|
|
1020
|
+
provider: (current: CTX) => Promise<RET>,
|
|
716
1021
|
): EndpointsFactory<Extension<IN, undefined>, (CTX extends Record<string, never> ? RET : CTX) & RET, SCO>;
|
|
1022
|
+
/**
|
|
1023
|
+
* @desc Builds an Endpoint using the accumulated Middlewares, the ResultHandler, and the given configuration.
|
|
1024
|
+
* The output is validated against the output schema; the handler receives the validated input and context.
|
|
1025
|
+
* @see Endpoint
|
|
1026
|
+
* */
|
|
717
1027
|
build<BOUT extends IOSchema, BIN extends IOSchema = EmptySchema>({
|
|
718
1028
|
input,
|
|
719
1029
|
output: outputSchema,
|
|
@@ -723,7 +1033,10 @@ declare class EndpointsFactory<
|
|
|
723
1033
|
method,
|
|
724
1034
|
...rest
|
|
725
1035
|
}: BuildProps<BIN, BOUT, IN, CTX, SCO>): Endpoint<FinalInputSchema<IN, BIN>, BOUT, CTX>;
|
|
726
|
-
/**
|
|
1036
|
+
/**
|
|
1037
|
+
* @desc shorthand for build() having output schema assigned with an empty object
|
|
1038
|
+
* @see build
|
|
1039
|
+
* */
|
|
727
1040
|
buildVoid<BIN extends IOSchema = EmptySchema>({
|
|
728
1041
|
handler,
|
|
729
1042
|
...rest
|
|
@@ -733,35 +1046,17 @@ declare class EndpointsFactory<
|
|
|
733
1046
|
CTX
|
|
734
1047
|
>;
|
|
735
1048
|
}
|
|
1049
|
+
/**
|
|
1050
|
+
* @desc The factory based on the default ResultHandler: suitable for JSON responses.
|
|
1051
|
+
* @see defaultResultHandler
|
|
1052
|
+
* */
|
|
736
1053
|
declare const defaultEndpointsFactory: EndpointsFactory<undefined, Record<string, never>, string>;
|
|
737
1054
|
/**
|
|
738
1055
|
* @deprecated Resist the urge of using it: this factory is designed only to simplify the migration of legacy APIs.
|
|
739
|
-
* @desc Responding with array is a bad practice keeping your endpoints from evolving without breaking changes.
|
|
1056
|
+
* @desc Responding with an array is a bad practice keeping your endpoints from evolving without breaking changes.
|
|
740
1057
|
* @desc The result handler of this factory expects your endpoint to have the property 'items' in the output schema
|
|
741
1058
|
*/
|
|
742
1059
|
declare const arrayEndpointsFactory: EndpointsFactory<undefined, Record<string, never>, string>;
|
|
743
|
-
/**
|
|
744
|
-
* @desc Creates a Middleware providing cookie-setting convenience methods.
|
|
745
|
-
* @param baseOptions — Default options applied to every setCookie / clearCookie call.
|
|
746
|
-
* @example createCookieMiddleware({ httpOnly: true, secure: true, path: "/" })
|
|
747
|
-
*/
|
|
748
|
-
declare const createCookieMiddleware: (baseOptions?: CookieOptions) => Middleware<
|
|
749
|
-
FlatObject,
|
|
750
|
-
{
|
|
751
|
-
/**
|
|
752
|
-
* @desc Reads a cookie value. Checks signedCookies first, then falls back to cookies.
|
|
753
|
-
* @requires cookie-parser
|
|
754
|
-
* @see ServerConfig.cookies
|
|
755
|
-
* */
|
|
756
|
-
getCookie: (name: string) => z.core.util.JSONType | undefined;
|
|
757
|
-
/** @desc Sets a cookie on the response. Express converts non-string values to JSON. */
|
|
758
|
-
setCookie: (name: string, value: string | z.core.util.JSONType, overrides?: CookieOptions) => void;
|
|
759
|
-
/** @desc Clears a cookie on the response. */
|
|
760
|
-
clearCookie: (name: string, overrides?: Omit<CookieOptions, "expires" | "maxAge">) => void;
|
|
761
|
-
},
|
|
762
|
-
string,
|
|
763
|
-
undefined
|
|
764
|
-
>;
|
|
765
1060
|
declare const attachRouting: (
|
|
766
1061
|
config: AppConfig,
|
|
767
1062
|
routing: Routing,
|
|
@@ -958,7 +1253,7 @@ declare const testEndpoint: <LOG extends FlatObject, REQ extends RequestOptions>
|
|
|
958
1253
|
responseMock: _$node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
|
|
959
1254
|
loggerMock: AbstractLogger &
|
|
960
1255
|
LOG & {
|
|
961
|
-
_getLogs: () => Record<"
|
|
1256
|
+
_getLogs: () => Record<"error" | "debug" | "info" | "warn", unknown[]>;
|
|
962
1257
|
};
|
|
963
1258
|
}>;
|
|
964
1259
|
declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOptions>({
|
|
@@ -977,7 +1272,7 @@ declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOption
|
|
|
977
1272
|
responseMock: _$node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
|
|
978
1273
|
loggerMock: AbstractLogger &
|
|
979
1274
|
LOG & {
|
|
980
|
-
_getLogs: () => Record<"
|
|
1275
|
+
_getLogs: () => Record<"error" | "debug" | "info" | "warn", unknown[]>;
|
|
981
1276
|
};
|
|
982
1277
|
output: FlatObject;
|
|
983
1278
|
}>;
|
|
@@ -1244,6 +1539,8 @@ export {
|
|
|
1244
1539
|
type BasicSecurity,
|
|
1245
1540
|
type BearerSecurity,
|
|
1246
1541
|
BuiltinLogger,
|
|
1542
|
+
type CacheControl,
|
|
1543
|
+
type CachePolicy,
|
|
1247
1544
|
type CommonConfig,
|
|
1248
1545
|
type CookieSecurity,
|
|
1249
1546
|
type Depicter,
|
|
@@ -1274,6 +1571,7 @@ export {
|
|
|
1274
1571
|
arrayEndpointsFactory,
|
|
1275
1572
|
arrayResultHandler,
|
|
1276
1573
|
attachRouting,
|
|
1574
|
+
createCacheMiddleware,
|
|
1277
1575
|
createConfig,
|
|
1278
1576
|
createCookieMiddleware,
|
|
1279
1577
|
createServer,
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{globalRegistry as e,z as t}from"zod";import*as n from"ramda";import r,{isHttpError as i}from"http-errors";import{isPromise as a}from"node:util/types";import o,{blue as s,cyanBright as c,gray as l,green as u,hex as d,italic as f,red as p,whiteBright as m}from"ansis";import{inspect as h}from"node:util";import{performance as g}from"node:perf_hooks";import _ from"express";import ee from"node:http";import te from"node:https";import{setInterval as ne}from"node:timers/promises";import{OpenApiBuilder as re,isReferenceObject as ie,isSchemaObject as v}from"openapi3-ts/oas31";import{createRequest as ae,createResponse as oe}from"node-mocks-http";function se(e){return e}const y={json:`application/json`,upload:`multipart/form-data`,raw:`application/octet-stream`,sse:`text/event-stream`,form:`application/x-www-form-urlencoded`},ce=[`get`,`post`,`put`,`delete`,`patch`],le=[...ce,`head`],b=e=>ce.includes(e),ue=t.object({}),de=/:([A-Za-z0-9_]+)/g,fe=e=>e.match(de)?.map(e=>e.slice(1))||[],pe=e=>{let t=(e.header(`content-type`)||``).toLowerCase().startsWith(y.upload);return`files`in e&&t},me={get:[`query`,`params`],post:[`body`,`params`,`files`],put:[`body`,`params`],patch:[`body`,`params`],delete:[`query`,`params`]},he=[`body`,`query`,`params`],ge=e=>e.method.toLowerCase(),_e=(e,t={})=>{if(e===`options`)return[];let n=e===`head`?`get`:b(e)?e:void 0;return(n?t[n]||me[n]:void 0)||he},ve=(e,t={})=>_e(ge(e),t).filter(t=>t===`files`?pe(e):!0).reduce((t,n)=>Object.assign(t,e[n]),{}),x=e=>e instanceof Error?e:e instanceof t.ZodError?new t.ZodRealError(e.issues):Error(String(e)),S=e=>e instanceof t.ZodError?e.issues.map(({path:e,message:n})=>`${e.length?`${t.core.toDotPath(e)}: `:``}${n}`).join(`; `):e.message,C=(e,t)=>E(e)&&`_zod`in e&&(t?n.path([`_zod`,`def`,`type`],e)===t:!0),w=(e,t,r)=>e.length&&t.length?n.xprod(e,t).map(r):e.concat(t),ye=e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),T=(...e)=>{let t=n.chain(e=>e.split(/[^A-Z0-9]/gi),e);return n.chain(e=>e.replaceAll(/[A-Z]+/g,e=>`/${e}`).split(`/`),t).map(ye).join(``)},be=n.tryCatch((e,n)=>typeof t.parse(e,n),n.always(void 0)),E=e=>typeof e==`object`&&!!e,xe=n.memoizeWith(()=>`static`,()=>process.env.NODE_ENV===`production`),Se=(e,t)=>!!t&&e!==`head`,D=`x-brand`,O=t=>{let{[D]:n}=e.get(t)||{};if(typeof n==`symbol`||typeof n==`string`||typeof n==`number`)return n},k=t=>{let{examples:n}=e.get(t)||{};return Array.isArray(n)?n:[]},A=Symbol(`Buffer`),Ce=()=>t.custom(e=>Buffer.isBuffer(e),{error:`Expected Buffer`}).meta({[D]:A}),j=Symbol(`DateIn`),we=({examples:e,...n}={})=>t.union([t.iso.date(),t.iso.datetime(),t.iso.datetime({local:!0})]).meta({examples:e}).transform(e=>new Date(e)).pipe(t.date()).meta({...n,[D]:j}),M=Symbol(`DateOut`),Te=(e={})=>t.date().transform(e=>e.toISOString()).meta({...e,[D]:M});var N=class extends Error{name=`RoutingError`;cause;constructor(e,t,n){super(e),this.cause={method:t,path:n}}},P=class extends Error{name=`DocumentationError`;cause;constructor(e,{method:t,path:n,isResponse:r}){super(e),this.cause=`${r?`Response`:`Input`} schema of an Endpoint assigned to ${t.toUpperCase()} method of ${n} path.`}},Ee=class extends Error{name=`IOSchemaError`},De=class extends Ee{cause;name=`DeepCheckError`;constructor(e){super(`Found`,{cause:e}),this.cause=e}},Oe=class extends Ee{cause;name=`OutputValidationError`;constructor(e){let n=new t.ZodError(e.issues.map(({path:e,...t})=>({...t,path:[`output`,...e]})));super(S(n),{cause:e}),this.cause=e}},F=class extends Ee{cause;name=`InputValidationError`;constructor(e){super(S(e),{cause:e}),this.cause=e}},I=class extends Error{cause;handled;name=`ResultHandlerError`;constructor(e,t){super(S(e),{cause:e}),this.cause=e,this.handled=t}},ke=class extends Error{name=`MissingPeerError`;constructor(e){super(`Missing peer dependency: ${e}. Please install it to use the feature.`)}};const Ae=Symbol(`Form`),je=e=>(e instanceof t.ZodObject?e:t.object(e)).meta({[D]:Ae}),L=Symbol(`Upload`),Me=e=>E(e)&&`name`in e&&`encoding`in e&&`mimetype`in e&&`data`in e&&`tempFilePath`in e&&`truncated`in e&&`size`in e&&`md5`in e&&`mv`in e,Ne=()=>t.custom(e=>Me(e)&&typeof e.name==`string`&&typeof e.encoding==`string`&&typeof e.mimetype==`string`&&Buffer.isBuffer(e.data)&&typeof e.tempFilePath==`string`&&typeof e.truncated==`boolean`&&typeof e.size==`number`&&typeof e.md5==`string`&&typeof e.mv==`function`,{error:({input:e})=>({message:`Expected file upload, received ${typeof e}`})}).meta({[D]:L}),R=Symbol(`Raw`),Pe=t.object({raw:Ce()}),Fe=e=>Pe.extend(e).meta({[D]:R});function Ie(e){return e?Fe(e):Pe.meta({[D]:R})}const Le=(e,{io:r,condition:i})=>n.tryCatch(()=>void t.toJSONSchema(e,{io:r,unrepresentable:`any`,override:({zodSchema:e})=>{if(i(e))throw new De(e)}}),e=>e.cause)(),Re=(e,{io:r})=>{let i=[t.toJSONSchema(e,{io:r,unrepresentable:`any`})];for(let e=0;e<i.length;e++){let t=i[e];if(n.is(Object,t)){if(t.$ref===`#`)return!0;i.push(...n.values(t))}n.is(Array,t)&&i.push(...n.values(t))}return!1},ze=e=>Le(e,{condition:e=>{let t=O(e);return typeof t==`symbol`&&[L,R,Ae].includes(t)},io:`input`}),Be=[`nan`,`symbol`,`map`,`set`,`bigint`,`void`,`promise`,`never`,`function`],Ve=(e,t)=>Le(e,{io:t,condition:e=>{let n=O(e),{type:r}=e._zod.def;return!!(Be.includes(r)||n===A||t===`input`&&(r===`date`||n===M)||t===`output`&&(n===j||n===R||n===L))}}),He=(e,{variant:n,args:r,...i})=>{if(typeof e==`function`&&(e=e(...r)),e instanceof t.ZodType)return[{schema:e,...i}];if(Array.isArray(e)&&!e.length)throw new I(Error(`At least one ${n} response schema required.`));return(Array.isArray(e)?e:[e]).map(({schema:e,statusCode:t,mimeType:n})=>({schema:e,statusCodes:typeof t==`number`?[t]:t||i.statusCodes,mimeTypes:typeof n==`string`?[n]:n===void 0?i.mimeTypes:n}))},Ue=(e,t,{url:n},r)=>!e.expose&&t.error(`Server side error`,{error:e,url:n,payload:r}),z=e=>i(e)?e:r(e instanceof F?400:500,S(e),{cause:e.cause||e}),B=e=>xe()&&!e.expose?r(e.statusCode).message:e.message,We=e=>Object.entries(e._zod.def.shape).reduce((e,[t,r])=>w(e,k(r).map(n.objOf(t)),([e,t])=>({...e,...t})),[]),Ge=({error:e,logger:t,response:n})=>{t.error(`Result handler failure`,e);let a=B(r(500,`An error occurred while serving the result: ${e.message}.`+(e.handled?`\nOriginal error: ${e.handled.message}.`:``),{expose:i(e.cause)?e.cause.expose:!1}));n.status(500).type(`text/plain`).end(a)};var Ke=class{},V=class extends Ke{#e;#t;#n;constructor({input:e,security:t,handler:n}){super(),this.#e=e,this.#t=t,this.#n=n}get security(){return this.#t}get schema(){return this.#e}async execute({input:e,...n}){try{let t=await(this.#e||ue).parseAsync(e);return this.#n({...n,input:t})}catch(e){throw e instanceof t.ZodError?new F(e):e}}},qe=class extends V{constructor(e,{provider:t=()=>({}),transformer:n=e=>e}={}){super({handler:async({request:r,response:i})=>{let{promise:o,resolve:s,reject:c}=Promise.withResolvers(),l=e=>{if(e&&e instanceof Error)return c(n(e));s(t(r,i))},u=e(r,i,l);return a(u)&&u.catch(l),o}})}},Je=class{nest(e){return{...e,"":this}}},Ye=class r extends Je{#e;#t=n.once(()=>{if(k(this.#e.outputSchema).length||!C(this.#e.outputSchema,`object`))return;let t=We(this.#e.outputSchema);if(!t.length)return;let n=this.#e.outputSchema.meta();e.remove(this.#e.outputSchema).add(this.#e.outputSchema,{...n,examples:t})});constructor(e){super(),this.#e=e}#n(e){return new r({...this.#e,...e})}deprecated(){return this.#n({deprecated:!0})}get isDeprecated(){return this.#e.deprecated||!1}get description(){return this.#e.description}get summary(){return this.#e.summary}get methods(){return Object.freeze(this.#e.methods)}get inputSchema(){return this.#e.inputSchema}get outputSchema(){return this.#e.outputSchema}get requestType(){let e=ze(this.#e.inputSchema);if(e){let t=O(e);if(t===L)return`upload`;if(t===R)return`raw`;if(t===Ae)return`form`}return`json`}getResponses(e){return e===`positive`&&this.#t(),Object.freeze(e===`negative`?this.#e.resultHandler.getNegativeResponse():this.#e.resultHandler.getPositiveResponse(this.#e.outputSchema))}get security(){let e=n.pluck(`security`,this.#e.middlewares||[]);return n.reject(n.isNil,e)}get scopes(){return Object.freeze(this.#e.scopes||[])}get tags(){return Object.freeze(this.#e.tags||[])}getOperationId(e){return this.#e.getOperationId?.(e)}async#r(e){try{return await this.#e.outputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new Oe(e):e}}async#i({method:e,logger:t,ctx:n,response:r,...i}){for(let a of this.#e.middlewares||[])if(!(e===`options`&&!(a instanceof qe))&&(Object.assign(n,await a.execute({...i,ctx:n,response:r,logger:t})),r.writableEnded)){t.warn(`A middleware has closed the stream. Accumulated context:`,n);break}}async#a({input:e,...n}){let r;try{r=await this.#e.inputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new F(e):e}return this.#e.handler({...n,input:r})}async#o(e){try{await this.#e.resultHandler.execute(e)}catch(t){Ge({...e,error:new I(x(t),e.error||void 0)})}}async execute({request:e,response:t,logger:n,config:r}){let i=ge(e),a={},o,s=ve(e,r.inputSources);try{if(await this.#i({method:i,input:s,request:e,response:t,logger:n,ctx:a}),t.writableEnded)return;if(i===`options`)return void t.status(200).end();o={output:await this.#r(await this.#a({input:s,logger:n,ctx:a})),error:null}}catch(e){o={output:null,error:x(e)}}await this.#o({...o,input:s,request:e,response:t,logger:n,ctx:a})}};const Xe=(e,t)=>e&&t?e.and(t):e||t,Ze=(e,t)=>e?e.and(t):t,H={positive:200,negative:400},Qe=Object.keys(H);var $e=class{#e;constructor(e){this.#e=e}execute(...e){return this.#e(...e)}},U=class extends $e{#e;#t;constructor(e){super(e.handler),this.#e=e.positive,this.#t=e.negative}getPositiveResponse(e){return He(this.#e,{variant:`positive`,args:[e],statusCodes:[H.positive],mimeTypes:[y.json]})}getNegativeResponse(){return He(this.#t,{variant:`negative`,args:[],statusCodes:[H.negative],mimeTypes:[y.json]})}};const et=t.object({status:t.literal(`error`),error:t.object({message:t.string()})});e.add(et,{examples:[{status:`error`,error:{message:`Sample error message`}}]});const W=new U({positive:n=>{let r=t.object({status:t.literal(`success`),data:n}),i=k(n);return i.length&&e.add(r,{examples:i.map(e=>({status:`success`,data:e}))}),r},negative:et,handler:({error:e,input:t,output:n,request:r,response:i,logger:a})=>{if(e){let n=z(e);Ue(n,a,r,t),i.status(n.statusCode).set(n.headers).json({status:`error`,error:{message:B(n)}});return}i.status(H.positive).json({status:`success`,data:n})}}),tt=t.string();e.add(tt,{examples:[`Sample error message`]});const nt=new U({positive:n=>{let r=n instanceof t.ZodObject&&`items`in n.shape&&n.shape.items instanceof t.ZodArray?n.shape.items:t.array(t.any());if(k(r).length)return r;let i=k(n).filter(e=>E(e)&&`items`in e&&Array.isArray(e.items)).map(e=>e.items);if(i?.length){let t=r.meta();e.remove(r).add(r,{...t,examples:i})}return r},negative:{schema:tt,mimeType:`text/plain`},handler:({response:e,output:t,error:n,logger:r,request:i,input:a})=>{if(n){let t=z(n);Ue(t,r,i,a),e.status(t.statusCode).type(`text/plain`).send(B(t));return}if(`items`in t&&Array.isArray(t.items)){e.status(H.positive).json(t.items);return}throw Error(`Property 'items' is missing in the endpoint output`)}});var G=class e{resultHandler;schema=void 0;middlewares=[];constructor(e){this.resultHandler=e}#e(t){let n=new e(this.resultHandler);return n.middlewares=this.middlewares.concat(t),n.schema=Xe(this.schema,t.schema),n}addMiddleware(e){return this.#e(e instanceof V?e:new V(e))}use=this.addExpressMiddleware;addExpressMiddleware(...e){return this.#e(new qe(...e))}addContext(e){return this.#e(new V({handler:e}))}build({input:e=ue,output:t,operationId:n,scope:r,tag:i,method:a,...o}){let{middlewares:s,resultHandler:c}=this,l=typeof a==`string`?[a]:a,u=typeof n==`function`?n:e=>n&&`${n}${e===`head`?`__HEAD`:``}`,d=typeof r==`string`?[r]:r||[],f=typeof i==`string`?[i]:i||[];return new Ye({...o,middlewares:s,outputSchema:t,resultHandler:c,scopes:d,tags:f,methods:l,getOperationId:u,inputSchema:Ze(this.schema,e)})}buildVoid({handler:e,...t}){return this.build({...t,output:ue,handler:async t=>(await e(t),{})})}};const rt=new G(W),it=new G(nt),at={debug:s,info:u,warn:d(`#FFA500`),error:p,ctx:c},K={debug:10,info:20,warn:30,error:40},ot=e=>E(e)&&Object.keys(K).some(t=>t in e),st=e=>e in K,ct=(e,t)=>K[e]<K[t],q=n.memoizeWith((e,t)=>`${e}${t}`,(e,t=0)=>Intl.NumberFormat(void 0,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t,style:`unit`,unitDisplay:`long`,unit:e})),lt=e=>e<1e-6?q(`nanosecond`,3).format(e/1e-6):e<.001?q(`nanosecond`).format(e/1e-6):e<1?q(`microsecond`).format(e/.001):e<1e3?q(`millisecond`).format(e):e<6e4?q(`second`,2).format(e/1e3):q(`minute`,2).format(e/6e4);var ut=class e{config;constructor({color:e=o.isSupported(),level:t=xe()?`warn`:`debug`,depth:n=2,ctx:r={}}={}){this.config={color:e,level:t,depth:n,ctx:r}}format(e){let{depth:t,color:n,level:r}=this.config;return h(e,{depth:t,colors:n,breakLength:r===`debug`?80:1/0,compact:r===`debug`?3:!0})}print(e,t,n){let{level:r,ctx:{requestId:i,...a},color:o}=this.config;if(r===`silent`||ct(e,r))return;let s=[new Date().toISOString()];i&&s.push(o?at.ctx(i):i),s.push(o?`${at[e](e)}:`:`${e}:`,t),n!==void 0&&s.push(this.format(n)),Object.keys(a).length>0&&s.push(this.format(a)),console.log(s.join(` `))}debug(e,t){this.print(`debug`,e,t)}info(e,t){this.print(`info`,e,t)}warn(e,t){this.print(`warn`,e,t)}error(e,t){this.print(`error`,e,t)}child(t){return new e({...this.config,ctx:t})}get ctx(){return this.config.ctx}profile(e){let t=g.now();return()=>{let n=g.now()-t,{message:r,severity:i=`debug`,formatter:a=lt}=typeof e==`object`?e:{message:e};this.print(typeof i==`function`?i(n):i,r,a(n))}}};const dt=e=>new V({handler:async({request:t,response:n})=>({getCookie:e=>t.signedCookies?.[e]??t.cookies?.[e],setCookie:(t,r,i)=>{n.cookie(t,r,{...e,...i})},clearCookie:(t,r)=>{n.clearCookie(t,{...e,...r})}})});var ft=class{#e;constructor(...e){this.#e=e}apply(e,t){return t(e,_.static(...this.#e))}};const J=async(e,t=`default`)=>{try{return(await import(e))[t]}catch{}throw new ke(e)},pt=e=>e.type===`object`,mt=n.mergeDeepWith((e,t)=>{if(Array.isArray(e)&&Array.isArray(t))return n.concat(e,t);if(e===t)return t;throw Error(`Can not flatten properties`,{cause:{a:e,b:t}})}),ht=new Set([`type`,`properties`,`required`,`examples`,`description`,`additionalProperties`]),gt=e=>{for(let t of Object.keys(e))if(!ht.has(t))return!1;return!0},_t=n.pair(!0),vt=(e,t,r)=>!(`allOf`in e)||!e.allOf?[]:e.allOf.map(e=>{if(t===`throw`&&!(e.type===`object`&>(e)))throw Error(`Can not merge`);return n.pair(r,e)}),yt=e=>{let t=[];return e.anyOf&&t.push(...n.map(_t,e.anyOf)),e.oneOf&&t.push(...n.map(_t,e.oneOf)),t},bt=(e,t,n,r)=>{if(!E(e.propertyNames))return;let i=[];typeof e.propertyNames.const==`string`&&i.push(e.propertyNames.const),e.propertyNames.enum&&i.push(...e.propertyNames.enum.filter(e=>typeof e==`string`));let a={...Object(e.additionalProperties)};for(let e of i)t.properties[e]??=a;r||n.push(...i)},xt=(e,t,r)=>{t.examples?.length&&(r?e.examples=n.concat(e.examples||[],t.examples):e.examples=w(e.examples?.filter(E)||[],t.examples.filter(E),([e,t])=>n.mergeDeepRight(e,t)))},Y=(e,t=`coerce`)=>{let r=[n.pair(!1,e)],i={type:`object`,properties:{}},a=[];for(let[e,o]of r)o.description&&(i.description??=o.description),r.push(...vt(o,t,e)),r.push(...yt(o)),xt(i,o,e),pt(o)&&(r.push([e,{examples:St(o)}]),o.properties&&(i.properties=(t===`throw`?mt:n.mergeDeepRight)(i.properties,o.properties),!e&&o.required&&a.push(...o.required)),bt(o,i,a,e));return a.length&&(i.required=[...new Set(a)]),i},St=e=>Object.entries(e.properties||{}).reduce((e,[t,r])=>{let{examples:i=[]}=E(r)?r:{};return w(e,i.map(n.objOf(t)),([e,t])=>({...e,...t}))},[]);var Ct=class{logger;#e=new WeakMap;constructor(e){this.logger=e}#t(e,n,r){if(!e.isSchemaChecked){for(let e of[`input`,`output`]){let i=[t.toJSONSchema(n[`${e}Schema`],{unrepresentable:`any`})];for(let t of i){t.type&&t.type!==`object`&&this.logger.warn(`Endpoint ${e} schema is not object-based`,r);for(let e of[`allOf`,`oneOf`,`anyOf`])t[e]&&i.push(...t[e])}}if(n.requestType===`json`){let e=Ve(n.inputSchema,`input`);e&&this.logger.warn(`The final input schema of the endpoint contains an unsupported JSON payload type.`,{...r,reason:e})}for(let e of Qe)for(let{mimeTypes:t,schema:i}of n.getResponses(e)){if(!t?.includes(y.json))continue;let n=Ve(i,`output`);n&&this.logger.warn(`The final ${e} response schema of the endpoint contains an unsupported JSON payload type.`,{...r,reason:n})}e.isSchemaChecked=!0}}#n(e,n,r,i){if(e.paths.has(r))return;let a=fe(r);if(a.length!==0){e.flat??=Y(t.toJSONSchema(n.inputSchema,{unrepresentable:`any`,io:`input`}));for(let t of a)t in e.flat.properties||this.logger.warn(`The input schema of the endpoint is most likely missing the parameter of the path it's assigned to.`,{...i,path:r,param:t});e.paths.add(r)}}check=(e,t,n)=>{let r=this.#e.get(n);r||(r={isSchemaChecked:!1,paths:new Set},this.#e.set(n,r)),this.#t(r,n,{method:e,path:t}),this.#n(r,n,t,{method:e})}};const wt=e=>(t,...n)=>{e(t,...n),t===`get`&&e(`head`,...n)},Tt=e=>{let[t,n]=e.trim().split(/ (.+)/,2);return n&&b(t)?[n,t]:[e]},Et=e=>e.trim().split(`/`).filter(Boolean).join(`/`),Dt=({recognizeMethodDependentRoutes:e=!0},t,n)=>Object.entries(t).map(([t,r])=>{let[i,a]=e&&b(t)&&r instanceof Je?[`/`,t]:Tt(t);return[[n||``].concat(Et(i)||[]).join(`/`),r,a]}),Ot=(e,t)=>{throw new N(`Route with explicit method can only be assigned with Endpoint`,e,t)},kt=(e,t,n)=>{if(!(!n||n.includes(e)))throw new N(`Method ${e} is not supported by the assigned Endpoint.`,e,t)},At=(e,t,n)=>{let r=`${e} ${t}`;if(n.has(r))throw new N(`Route has a duplicate`,e,t);n.add(r)},jt=({routing:e,config:t,onEndpoint:n,onStatic:r})=>{let i=Dt(t,e),a=new Set;for(let e=0;e<i.length;e++){let[o,s,c]=i[e];if(s instanceof Je)if(c)At(c,o,a),kt(c,o,s.methods),n(c,o,s);else{let{methods:e=[`get`]}=s;for(let t of e)At(t,o,a),n(t,o,s)}else c&&Ot(c,o),s instanceof ft?r&&s.apply(o,r):i.splice(e+1,0,...Dt(t,s,o))}},Mt=e=>e.sort((e,t)=>b(t)-+b(e)||e.localeCompare(t)).join(`, `).toUpperCase(),Nt=e=>({method:t},n,i)=>{let a=Mt(e);n.set({Allow:a}),i(r(405,`${t} is not allowed`,{headers:{Allow:a}}))},Pt=e=>({"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":Mt(e),"Access-Control-Allow-Headers":`content-type`}),Ft=({app:e,getLogger:t,config:r,routing:i,parsers:a})=>{let o=xe()?void 0:new Ct(t()),s=new Map;return jt({routing:i,config:r,onEndpoint:(e,t,i)=>{o?.check(e,t,i);let c=a?.[i.requestType]||[],l=n.pair(c,i);s.has(t)||s.set(t,new Map(r.cors?[[`options`,l]]:[])),s.get(t)?.set(e,l)},onStatic:e.use.bind(e)}),s},It=({app:e,config:t,getLogger:n,...r})=>{let i=Ft({app:e,getLogger:n,config:t,...r}),a=new Map;for(let[r,o]of i){let i=Array.from(o.keys());i.includes(`get`)&&i.push(`head`);for(let[a,[s,c]]of o){let o=[];t.cors&&o.push(async(e,r,a)=>{let o=n(e),s=Pt(i),l=typeof t.cors==`function`?await t.cors({request:e,endpoint:c,logger:o,defaultHeaders:s}):s;r.set(l),a()}),o.push(...s,async(e,r)=>{let i=n(e);return c.execute({request:e,response:r,logger:i,config:t})}),e[a](r,...o)}t.hintAllowedMethods!==!1&&a.set(r,Nt(i))}for(let[t,n]of a)e.all(t,n)},Lt=e=>`_httpMessage`in e&&typeof e._httpMessage==`object`&&e._httpMessage!==null&&`headersSent`in e._httpMessage&&typeof e._httpMessage.headersSent==`boolean`&&`setHeader`in e._httpMessage&&typeof e._httpMessage.setHeader==`function`,Rt=e=>`server`in e&&typeof e.server==`object`&&e.server!==null&&`close`in e.server&&typeof e.server.close==`function`,zt=e=>`encrypted`in e&&typeof e.encrypted==`boolean`&&e.encrypted,Bt=({},e)=>void(!e.headersSent&&e.setHeader(`connection`,`close`)),Vt=e=>{let{promise:t,resolve:n,reject:r}=Promise.withResolvers();return e.close(e=>e?r(e):n()),t},Ht=(e,{timeout:t=1e3,logger:n}={})=>{let r,i=new Set,a=e=>void i.delete(e.destroy()),o=e=>void(Lt(e)?!e._httpMessage.headersSent&&e._httpMessage.setHeader(`connection`,`close`):a(e)),s=e=>void(r?e.destroy():i.add(e.once(`close`,()=>void i.delete(e))));for(let t of e)for(let e of[`connection`,`secureConnection`])t.on(e,s);let c=async()=>{for(let t of e)t.on(`request`,Bt);n?.info(`Graceful shutdown`,{sockets:i.size,timeout:t});for(let e of i)(zt(e)||Rt(e))&&o(e);for await(let e of ne(10,Date.now()))if(i.size===0||Date.now()-e>=t)break;for(let e of i)a(e);return Promise.allSettled(e.map(Vt))};return{sockets:i,shutdown:()=>r??=c()}},Ut=Symbol.for(`express-zod-api`),Wt=({errorHandler:e,getLogger:t})=>async(n,r,i,a)=>n?e.execute({error:x(n),request:r,response:i,input:null,output:null,ctx:{},logger:t(r)}):a(),Gt=({errorHandler:e,getLogger:t})=>async(n,i)=>{let a=r(404,`Can not ${n.method} ${n.path}`),o=t(n);try{await e.execute({request:n,response:i,logger:o,error:a,input:null,output:null,ctx:{}})}catch(e){Ge({response:i,logger:o,error:new I(x(e),a)})}},Kt=e=>(t,{},n)=>{if(Object.values(t?.files||[]).flat().find(({truncated:e})=>e))return n(e);n()},qt=async({config:e})=>{let t=await J(`cookie-parser`),{secret:n,...r}={...typeof e.cookies==`object`&&e.cookies};return t(n,Object.keys(r).length?r:void 0)},Jt=e=>({log:e.debug.bind(e)}),Yt=async({getLogger:e,config:t})=>{let n=await J(`express-fileupload`),{limitError:r,beforeUpload:i,...a}={...typeof t.upload==`object`&&t.upload},o=[];return o.push(async(t,r,o)=>{let s=e(t);return await i?.({request:t,logger:s}),n({debug:!0,...a,abortOnLimit:!1,parseNested:!0,logger:Jt(s)})(t,r,o)}),r&&o.push(Kt(r)),o},Xt=(e,{},t)=>{Buffer.isBuffer(e.body)&&(e.body={raw:e.body}),t()},Zt=({logger:e,config:{childLoggerProvider:t,accessLogger:n=({method:e,path:t},n)=>n.debug(`${e}: ${t}`)}})=>async(r,i,a)=>{let o=await t?.({request:r,parent:e})||e;n?.(r,o),r.res&&(r.res.locals[Ut]={logger:o}),a()},Qt=e=>t=>t?.res?.locals[Ut]?.logger||e,$t=e=>process.on(`deprecation`,({message:t,namespace:n,name:r,stack:i})=>e.warn(`${r} (${n}): ${t}`,i.split(`
|
|
2
|
-
`).slice(1))),
|
|
1
|
+
import{globalRegistry as e,z as t}from"zod";import*as n from"ramda";import r,{isHttpError as i}from"http-errors";import{isPromise as a}from"node:util/types";import o,{blue as s,cyanBright as c,gray as l,green as u,hex as d,italic as f,red as p,whiteBright as m}from"ansis";import{inspect as h}from"node:util";import{performance as g}from"node:perf_hooks";import _ from"express";import ee from"node:http";import te from"node:https";import{setInterval as ne}from"node:timers/promises";import{OpenApiBuilder as re,isReferenceObject as ie,isSchemaObject as v}from"openapi3-ts/oas31";import{createRequest as ae,createResponse as oe}from"node-mocks-http";function se(e){return e}const y={json:`application/json`,upload:`multipart/form-data`,raw:`application/octet-stream`,sse:`text/event-stream`,form:`application/x-www-form-urlencoded`},ce=[`get`,`post`,`put`,`delete`,`patch`],le=[...ce,`head`],b=e=>ce.includes(e),ue=t.object({}),de=/:([A-Za-z0-9_]+)/g,fe=e=>e.match(de)?.map(e=>e.slice(1))||[],pe=e=>{let t=(e.header(`content-type`)||``).toLowerCase().startsWith(y.upload);return`files`in e&&t},me={get:[`query`,`params`],post:[`body`,`params`,`files`],put:[`body`,`params`],patch:[`body`,`params`],delete:[`query`,`params`]},he=[`body`,`query`,`params`],ge=e=>e.method.toLowerCase(),_e=(e,t={})=>{if(e===`options`)return[];let n=e===`head`?`get`:b(e)?e:void 0;return(n?t[n]||me[n]:void 0)||he},ve=(e,t={})=>_e(ge(e),t).filter(t=>t===`files`?pe(e):!0).reduce((t,n)=>Object.assign(t,e[n]),{}),x=e=>e instanceof Error?e:e instanceof t.ZodError?new t.ZodRealError(e.issues):Error(String(e)),S=e=>e instanceof t.ZodError?e.issues.map(({path:e,message:n})=>`${e.length?`${t.core.toDotPath(e)}: `:``}${n}`).join(`; `):e.message,C=(e,t)=>E(e)&&`_zod`in e&&(t?n.path([`_zod`,`def`,`type`],e)===t:!0),w=(e,t,r)=>e.length&&t.length?n.xprod(e,t).map(r):e.concat(t),ye=e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),T=(...e)=>{let t=n.chain(e=>e.split(/[^A-Z0-9]/gi),e);return n.chain(e=>e.replaceAll(/[A-Z]+/g,e=>`/${e}`).split(`/`),t).map(ye).join(``)},be=n.tryCatch((e,n)=>typeof t.parse(e,n),n.always(void 0)),E=e=>typeof e==`object`&&!!e,xe=n.memoizeWith(()=>`static`,()=>process.env.NODE_ENV===`production`),Se=(e,t)=>!!t&&e!==`head`,D=`x-brand`,O=t=>{let{[D]:n}=e.get(t)||{};if(typeof n==`symbol`||typeof n==`string`||typeof n==`number`)return n},k=t=>{let{examples:n}=e.get(t)||{};return Array.isArray(n)?n:[]},A=Symbol(`Buffer`),Ce=()=>t.custom(e=>Buffer.isBuffer(e),{error:`Expected Buffer`}).meta({[D]:A}),j=Symbol(`DateIn`),we=({examples:e,...n}={})=>t.union([t.iso.date(),t.iso.datetime(),t.iso.datetime({local:!0})]).meta({examples:e}).transform(e=>new Date(e)).pipe(t.date()).meta({...n,[D]:j}),M=Symbol(`DateOut`),Te=(e={})=>t.date().transform(e=>e.toISOString()).meta({...e,[D]:M});var N=class extends Error{name=`RoutingError`;cause;constructor(e,t,n){super(e),this.cause={method:t,path:n}}},P=class extends Error{name=`DocumentationError`;cause;constructor(e,{method:t,path:n,isResponse:r}){super(e),this.cause=`${r?`Response`:`Input`} schema of an Endpoint assigned to ${t.toUpperCase()} method of ${n} path.`}},Ee=class extends Error{name=`IOSchemaError`},De=class extends Ee{cause;name=`DeepCheckError`;constructor(e){super(`Found`,{cause:e}),this.cause=e}},Oe=class extends Ee{cause;name=`OutputValidationError`;constructor(e){let n=new t.ZodError(e.issues.map(({path:e,...t})=>({...t,path:[`output`,...e]})));super(S(n),{cause:e}),this.cause=e}},F=class extends Ee{cause;name=`InputValidationError`;constructor(e){super(S(e),{cause:e}),this.cause=e}},I=class extends Error{cause;handled;name=`ResultHandlerError`;constructor(e,t){super(S(e),{cause:e}),this.cause=e,this.handled=t}},ke=class extends Error{name=`MissingPeerError`;constructor(e){super(`Missing peer dependency: ${e}. Please install it to use the feature.`)}};const Ae=Symbol(`Form`),je=e=>(e instanceof t.ZodObject?e:t.object(e)).meta({[D]:Ae}),L=Symbol(`Upload`),Me=e=>E(e)&&`name`in e&&`encoding`in e&&`mimetype`in e&&`data`in e&&`tempFilePath`in e&&`truncated`in e&&`size`in e&&`md5`in e&&`mv`in e,Ne=()=>t.custom(e=>Me(e)&&typeof e.name==`string`&&typeof e.encoding==`string`&&typeof e.mimetype==`string`&&Buffer.isBuffer(e.data)&&typeof e.tempFilePath==`string`&&typeof e.truncated==`boolean`&&typeof e.size==`number`&&typeof e.md5==`string`&&typeof e.mv==`function`,{error:({input:e})=>({message:`Expected file upload, received ${typeof e}`})}).meta({[D]:L}),R=Symbol(`Raw`),Pe=t.object({raw:Ce()}),Fe=e=>Pe.extend(e).meta({[D]:R});function Ie(e){return e?Fe(e):Pe.meta({[D]:R})}const Le=(e,{io:r,condition:i})=>n.tryCatch(()=>void t.toJSONSchema(e,{io:r,unrepresentable:`any`,override:({zodSchema:e})=>{if(i(e))throw new De(e)}}),e=>e.cause)(),Re=(e,{io:r})=>{let i=[t.toJSONSchema(e,{io:r,unrepresentable:`any`})];for(let e=0;e<i.length;e++){let t=i[e];if(n.is(Object,t)){if(t.$ref===`#`)return!0;i.push(...n.values(t))}n.is(Array,t)&&i.push(...n.values(t))}return!1},ze=e=>Le(e,{condition:e=>{let t=O(e);return typeof t==`symbol`&&[L,R,Ae].includes(t)},io:`input`}),Be=[`nan`,`symbol`,`map`,`set`,`bigint`,`void`,`promise`,`never`,`function`],Ve=(e,t)=>Le(e,{io:t,condition:e=>{let n=O(e),{type:r}=e._zod.def;return!!(Be.includes(r)||n===A||t===`input`&&(r===`date`||n===M)||t===`output`&&(n===j||n===R||n===L))}}),He=(e,{variant:n,args:r,...i})=>{if(typeof e==`function`&&(e=e(...r)),e instanceof t.ZodType)return[{schema:e,...i}];if(Array.isArray(e)&&!e.length)throw new I(Error(`At least one ${n} response schema required.`));return(Array.isArray(e)?e:[e]).map(({schema:e,statusCode:t,mimeType:n})=>({schema:e,statusCodes:typeof t==`number`?[t]:t||i.statusCodes,mimeTypes:typeof n==`string`?[n]:n===void 0?i.mimeTypes:n}))},Ue=(e,t,{url:n},r)=>!e.expose&&t.error(`Server side error`,{error:e,url:n,payload:r}),z=e=>i(e)?e:r(e instanceof F?400:500,S(e),{cause:e.cause||e}),B=e=>xe()&&!e.expose?r(e.statusCode).message:e.message,We=e=>Object.entries(e._zod.def.shape).reduce((e,[t,r])=>w(e,k(r).map(n.objOf(t)),([e,t])=>({...e,...t})),[]),Ge=({error:e,logger:t,response:n})=>{t.error(`Result handler failure`,e);let a=B(r(500,`An error occurred while serving the result: ${e.message}.`+(e.handled?`\nOriginal error: ${e.handled.message}.`:``),{expose:i(e.cause)?e.cause.expose:!1}));n.status(500).type(`text/plain`).end(a)};var Ke=class{},V=class extends Ke{#e;#t;#n;constructor({input:e,security:t,handler:n}){super(),this.#e=e,this.#t=t,this.#n=n}get security(){return this.#t}get schema(){return this.#e}async execute({input:e,...n}){try{let t=await(this.#e||ue).parseAsync(e);return this.#n({...n,input:t})}catch(e){throw e instanceof t.ZodError?new F(e):e}}},qe=class extends V{constructor(e,{provider:t=()=>({}),transformer:n=e=>e}={}){super({handler:async({request:r,response:i})=>{let{promise:o,resolve:s,reject:c}=Promise.withResolvers(),l=e=>{if(e&&e instanceof Error)return c(n(e));s(t(r,i))},u=e(r,i,l);return a(u)&&u.catch(l),o}})}},Je=class{nest(e){return{...e,"":this}}},Ye=class r extends Je{#e;#t=n.once(()=>{if(k(this.#e.outputSchema).length||!C(this.#e.outputSchema,`object`))return;let t=We(this.#e.outputSchema);if(!t.length)return;let n=this.#e.outputSchema.meta();e.remove(this.#e.outputSchema).add(this.#e.outputSchema,{...n,examples:t})});constructor(e){super(),this.#e=e}#n(e){return new r({...this.#e,...e})}deprecated(){return this.#n({deprecated:!0})}get isDeprecated(){return this.#e.deprecated||!1}get description(){return this.#e.description}get summary(){return this.#e.summary}get methods(){return Object.freeze(this.#e.methods)}get inputSchema(){return this.#e.inputSchema}get outputSchema(){return this.#e.outputSchema}get requestType(){let e=ze(this.#e.inputSchema);if(e){let t=O(e);if(t===L)return`upload`;if(t===R)return`raw`;if(t===Ae)return`form`}return`json`}getResponses(e){return e===`positive`&&this.#t(),Object.freeze(e===`negative`?this.#e.resultHandler.getNegativeResponse():this.#e.resultHandler.getPositiveResponse(this.#e.outputSchema))}get security(){let e=n.pluck(`security`,this.#e.middlewares||[]);return n.reject(n.isNil,e)}get scopes(){return Object.freeze(this.#e.scopes||[])}get tags(){return Object.freeze(this.#e.tags||[])}getOperationId(e){return this.#e.getOperationId?.(e)}async#r(e){try{return await this.#e.outputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new Oe(e):e}}async#i({method:e,logger:t,ctx:n,response:r,...i}){for(let a of this.#e.middlewares||[])if(!(e===`options`&&!(a instanceof qe))&&(Object.assign(n,await a.execute({...i,ctx:n,response:r,logger:t})),r.writableEnded)){t.warn(`A middleware has closed the stream. Accumulated context:`,n);break}}async#a({input:e,...n}){let r;try{r=await this.#e.inputSchema.parseAsync(e)}catch(e){throw e instanceof t.ZodError?new F(e):e}return this.#e.handler({...n,input:r})}async#o(e){try{await this.#e.resultHandler.execute(e)}catch(t){Ge({...e,error:new I(x(t),e.error||void 0)})}}async execute({request:e,response:t,logger:n,config:r}){let i=ge(e),a={},o,s=ve(e,r.inputSources);try{if(await this.#i({method:i,input:s,request:e,response:t,logger:n,ctx:a}),t.writableEnded)return;if(i===`options`)return void t.status(200).end();let r=await this.#a({input:s,logger:n,ctx:a});if(t.writableEnded)return;o={output:await this.#r(r),error:null}}catch(e){o={output:null,error:x(e)}}await this.#o({...o,input:s,request:e,response:t,logger:n,ctx:a})}};const Xe=(e,t)=>e&&t?e.and(t):e||t,Ze=(e,t)=>e?e.and(t):t,H={positive:200,negative:400},Qe=Object.keys(H);var $e=class{#e;constructor(e){this.#e=e}execute(...e){return this.#e(...e)}},U=class extends $e{#e;#t;constructor(e){super(e.handler),this.#e=e.positive,this.#t=e.negative}getPositiveResponse(e){return He(this.#e,{variant:`positive`,args:[e],statusCodes:[H.positive],mimeTypes:[y.json]})}getNegativeResponse(){return He(this.#t,{variant:`negative`,args:[],statusCodes:[H.negative],mimeTypes:[y.json]})}};const et=t.object({status:t.literal(`error`),error:t.object({message:t.string()})});e.add(et,{examples:[{status:`error`,error:{message:`Sample error message`}}]});const W=new U({positive:n=>{let r=t.object({status:t.literal(`success`),data:n}),i=k(n);return i.length&&e.add(r,{examples:i.map(e=>({status:`success`,data:e}))}),r},negative:et,handler:({error:e,input:t,output:n,request:r,response:i,logger:a})=>{if(e){let n=z(e);Ue(n,a,r,t),i.status(n.statusCode).set(n.headers).json({status:`error`,error:{message:B(n)}});return}i.status(H.positive).json({status:`success`,data:n})}}),tt=t.string();e.add(tt,{examples:[`Sample error message`]});const nt=new U({positive:n=>{let r=n instanceof t.ZodObject&&`items`in n.shape&&n.shape.items instanceof t.ZodArray?n.shape.items:t.array(t.any());if(k(r).length)return r;let i=k(n).filter(e=>E(e)&&`items`in e&&Array.isArray(e.items)).map(e=>e.items);if(i?.length){let t=r.meta();e.remove(r).add(r,{...t,examples:i})}return r},negative:{schema:tt,mimeType:`text/plain`},handler:({response:e,output:t,error:n,logger:r,request:i,input:a})=>{if(n){let t=z(n);Ue(t,r,i,a),e.status(t.statusCode).type(`text/plain`).send(B(t));return}if(`items`in t&&Array.isArray(t.items)){e.status(H.positive).json(t.items);return}throw Error(`Property 'items' is missing in the endpoint output`)}}),rt=e=>{let t=[];return e.scope&&t.push(e.scope),e.noStore&&t.push(`no-store`),e.noCache&&t.push(`no-cache`),e.maxAge!==void 0&&t.push(`max-age=${e.maxAge}`),e.sMaxAge!==void 0&&t.push(`s-maxage=${e.sMaxAge}`),e.mustRevalidate&&t.push(`must-revalidate`),e.proxyRevalidate&&t.push(`proxy-revalidate`),e.mustUnderstand&&t.push(`must-understand`),e.immutable&&t.push(`immutable`),e.noTransform&&t.push(`no-transform`),e.staleWhileRevalidate!==void 0&&t.push(`stale-while-revalidate=${e.staleWhileRevalidate}`),e.staleIfError!==void 0&&t.push(`stale-if-error=${e.staleIfError}`),t.join(`, `)},it={"max-age":`maxAge`,"max-stale":`maxStale`,"min-fresh":`minFresh`,"stale-if-error":`staleIfError`},at={"no-cache":`noCache`,"no-store":`noStore`,"no-transform":`noTransform`,"only-if-cached":`onlyIfCached`},ot=e=>{if(!e)return;let t={};for(let n of e.toLowerCase().split(`,`)){let[e,r]=n.split(`=`),i=it[e.trim()];if(i){let e=parseInt(r?.trim()??``,10);isNaN(e)||(t[i]=e);continue}let a=at[e.trim()];a&&(t[a]=!0)}return t},st=e=>new V({handler:async({request:t,response:n})=>(e&&n.setHeader(`Cache-Control`,rt(e)),{get ifNoneMatch(){let e=t.headers[`if-none-match`];if(!e)return;let n=e.trim();return n===`*`?n:n.split(`,`).map(e=>e.trim().replace(/^(?:W\/)?"/,``).replace(/"$/,``))},get ifModifiedSince(){let e=t.headers[`if-modified-since`];if(!e)return;let n=new Date(e);return isNaN(n.getTime())?void 0:n},get cacheControl(){return ot(t.headers[`cache-control`])},addCachePolicy:t=>{n.setHeader(`Cache-Control`,rt({...e,...t}))},setETag:e=>{n.setHeader(`ETag`,e.startsWith(`"`)?e:`"${e}"`)},setLastModified:e=>{n.setHeader(`Last-Modified`,e.toUTCString())},setVary:(...e)=>{n.setHeader(`Vary`,e.join(`, `))},setExpires:e=>{n.setHeader(`Expires`,e.toUTCString())},clearSiteData:()=>{n.setHeader(`Clear-Site-Data`,`"cache"`)},notModified:()=>{n.status(304).end()}})}),ct=e=>new V({handler:async({request:t,response:n})=>({getCookie:e=>t.signedCookies?.[e]??t.cookies?.[e],setCookie:(t,r,i)=>{n.cookie(t,r,{...e,...i})},clearCookie:(t,r)=>{n.clearCookie(t,{...e,...r})}})});var G=class e{resultHandler;schema=void 0;middlewares=[];constructor(e){this.resultHandler=e}#e(t){let n=new e(this.resultHandler);return n.middlewares=this.middlewares.concat(t),n.schema=Xe(this.schema,t.schema),n}addMiddleware(e){return this.#e(e instanceof V?e:new V(e))}useCookies(...e){return this.#e(ct(...e))}useCache(...e){return this.#e(st(...e))}use=this.addExpressMiddleware;addExpressMiddleware(...e){return this.#e(new qe(...e))}addContext(e){return this.#e(new V({handler:({ctx:t})=>e(t)}))}build({input:e=ue,output:t,operationId:n,scope:r,tag:i,method:a,...o}){let{middlewares:s,resultHandler:c}=this,l=typeof a==`string`?[a]:a,u=typeof n==`function`?n:e=>n&&`${n}${e===`head`?`__HEAD`:``}`,d=typeof r==`string`?[r]:r||[],f=typeof i==`string`?[i]:i||[];return new Ye({...o,middlewares:s,outputSchema:t,resultHandler:c,scopes:d,tags:f,methods:l,getOperationId:u,inputSchema:Ze(this.schema,e)})}buildVoid({handler:e,...t}){return this.build({...t,output:ue,handler:async t=>(await e(t),{})})}};const lt=new G(W),ut=new G(nt),dt={debug:s,info:u,warn:d(`#FFA500`),error:p,ctx:c},K={debug:10,info:20,warn:30,error:40},ft=e=>E(e)&&Object.keys(K).some(t=>t in e),pt=e=>e in K,mt=(e,t)=>K[e]<K[t],q=n.memoizeWith((e,t)=>`${e}${t}`,(e,t=0)=>Intl.NumberFormat(void 0,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t,style:`unit`,unitDisplay:`long`,unit:e})),ht=e=>e<1e-6?q(`nanosecond`,3).format(e/1e-6):e<.001?q(`nanosecond`).format(e/1e-6):e<1?q(`microsecond`).format(e/.001):e<1e3?q(`millisecond`).format(e):e<6e4?q(`second`,2).format(e/1e3):q(`minute`,2).format(e/6e4);var gt=class e{config;constructor({color:e=o.isSupported(),level:t=xe()?`warn`:`debug`,depth:n=2,ctx:r={}}={}){this.config={color:e,level:t,depth:n,ctx:r}}format(e){let{depth:t,color:n,level:r}=this.config;return h(e,{depth:t,colors:n,breakLength:r===`debug`?80:1/0,compact:r===`debug`?3:!0})}print(e,t,n){let{level:r,ctx:{requestId:i,...a},color:o}=this.config;if(r===`silent`||mt(e,r))return;let s=[new Date().toISOString()];i&&s.push(o?dt.ctx(i):i),s.push(o?`${dt[e](e)}:`:`${e}:`,t),n!==void 0&&s.push(this.format(n)),Object.keys(a).length>0&&s.push(this.format(a)),console.log(s.join(` `))}debug(e,t){this.print(`debug`,e,t)}info(e,t){this.print(`info`,e,t)}warn(e,t){this.print(`warn`,e,t)}error(e,t){this.print(`error`,e,t)}child(t){return new e({...this.config,ctx:t})}get ctx(){return this.config.ctx}profile(e){let t=g.now();return()=>{let n=g.now()-t,{message:r,severity:i=`debug`,formatter:a=ht}=typeof e==`object`?e:{message:e};this.print(typeof i==`function`?i(n):i,r,a(n))}}},_t=class{#e;constructor(...e){this.#e=e}apply(e,t){return t(e,_.static(...this.#e))}};const J=async(e,t=`default`)=>{try{return(await import(e))[t]}catch{}throw new ke(e)},vt=e=>e.type===`object`,yt=n.mergeDeepWith((e,t)=>{if(Array.isArray(e)&&Array.isArray(t))return n.concat(e,t);if(e===t)return t;throw Error(`Can not flatten properties`,{cause:{a:e,b:t}})}),bt=new Set([`type`,`properties`,`required`,`examples`,`description`,`additionalProperties`]),xt=e=>{for(let t of Object.keys(e))if(!bt.has(t))return!1;return!0},St=n.pair(!0),Ct=(e,t,r)=>!(`allOf`in e)||!e.allOf?[]:e.allOf.map(e=>{if(t===`throw`&&!(e.type===`object`&&xt(e)))throw Error(`Can not merge`);return n.pair(r,e)}),wt=e=>{let t=[];return e.anyOf&&t.push(...n.map(St,e.anyOf)),e.oneOf&&t.push(...n.map(St,e.oneOf)),t},Tt=(e,t,n,r)=>{if(!E(e.propertyNames))return;let i=[];typeof e.propertyNames.const==`string`&&i.push(e.propertyNames.const),e.propertyNames.enum&&i.push(...e.propertyNames.enum.filter(e=>typeof e==`string`));let a={...Object(e.additionalProperties)};for(let e of i)t.properties[e]??=a;r||n.push(...i)},Et=(e,t,r)=>{t.examples?.length&&(r?e.examples=n.concat(e.examples||[],t.examples):e.examples=w(e.examples?.filter(E)||[],t.examples.filter(E),([e,t])=>n.mergeDeepRight(e,t)))},Y=(e,t=`coerce`)=>{let r=[n.pair(!1,e)],i={type:`object`,properties:{}},a=[];for(let[e,o]of r)o.description&&(i.description??=o.description),r.push(...Ct(o,t,e)),r.push(...wt(o)),Et(i,o,e),vt(o)&&(r.push([e,{examples:Dt(o)}]),o.properties&&(i.properties=(t===`throw`?yt:n.mergeDeepRight)(i.properties,o.properties),!e&&o.required&&a.push(...o.required)),Tt(o,i,a,e));return a.length&&(i.required=[...new Set(a)]),i},Dt=e=>Object.entries(e.properties||{}).reduce((e,[t,r])=>{let{examples:i=[]}=E(r)?r:{};return w(e,i.map(n.objOf(t)),([e,t])=>({...e,...t}))},[]);var Ot=class{logger;#e=new WeakMap;constructor(e){this.logger=e}#t(e,n,r){if(!e.isSchemaChecked){for(let e of[`input`,`output`]){let i=[t.toJSONSchema(n[`${e}Schema`],{unrepresentable:`any`})];for(let t of i){t.type&&t.type!==`object`&&this.logger.warn(`Endpoint ${e} schema is not object-based`,r);for(let e of[`allOf`,`oneOf`,`anyOf`])t[e]&&i.push(...t[e])}}if(n.requestType===`json`){let e=Ve(n.inputSchema,`input`);e&&this.logger.warn(`The final input schema of the endpoint contains an unsupported JSON payload type.`,{...r,reason:e})}for(let e of Qe)for(let{mimeTypes:t,schema:i}of n.getResponses(e)){if(!t?.includes(y.json))continue;let n=Ve(i,`output`);n&&this.logger.warn(`The final ${e} response schema of the endpoint contains an unsupported JSON payload type.`,{...r,reason:n})}e.isSchemaChecked=!0}}#n(e,n,r,i){if(e.paths.has(r))return;let a=fe(r);if(a.length!==0){e.flat??=Y(t.toJSONSchema(n.inputSchema,{unrepresentable:`any`,io:`input`}));for(let t of a)t in e.flat.properties||this.logger.warn(`The input schema of the endpoint is most likely missing the parameter of the path it's assigned to.`,{...i,path:r,param:t});e.paths.add(r)}}check=(e,t,n)=>{let r=this.#e.get(n);r||(r={isSchemaChecked:!1,paths:new Set},this.#e.set(n,r)),this.#t(r,n,{method:e,path:t}),this.#n(r,n,t,{method:e})}};const kt=e=>(t,...n)=>{e(t,...n),t===`get`&&e(`head`,...n)},At=e=>{let[t,n]=e.trim().split(/ (.+)/,2);return n&&b(t)?[n,t]:[e]},jt=e=>e.trim().split(`/`).filter(Boolean).join(`/`),Mt=({recognizeMethodDependentRoutes:e=!0},t,n)=>Object.entries(t).map(([t,r])=>{let[i,a]=e&&b(t)&&r instanceof Je?[`/`,t]:At(t);return[[n||``].concat(jt(i)||[]).join(`/`),r,a]}),Nt=(e,t)=>{throw new N(`Route with explicit method can only be assigned with Endpoint`,e,t)},Pt=(e,t,n)=>{if(!(!n||n.includes(e)))throw new N(`Method ${e} is not supported by the assigned Endpoint.`,e,t)},Ft=(e,t,n)=>{let r=`${e} ${t}`;if(n.has(r))throw new N(`Route has a duplicate`,e,t);n.add(r)},It=({routing:e,config:t,onEndpoint:n,onStatic:r})=>{let i=Mt(t,e),a=new Set;for(let e=0;e<i.length;e++){let[o,s,c]=i[e];if(s instanceof Je)if(c)Ft(c,o,a),Pt(c,o,s.methods),n(c,o,s);else{let{methods:e=[`get`]}=s;for(let t of e)Ft(t,o,a),n(t,o,s)}else c&&Nt(c,o),s instanceof _t?r&&s.apply(o,r):i.splice(e+1,0,...Mt(t,s,o))}},Lt=e=>e.sort((e,t)=>b(t)-+b(e)||e.localeCompare(t)).join(`, `).toUpperCase(),Rt=e=>({method:t},n,i)=>{let a=Lt(e);n.set({Allow:a}),i(r(405,`${t} is not allowed`,{headers:{Allow:a}}))},zt=e=>({"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":Lt(e),"Access-Control-Allow-Headers":`content-type`}),Bt=({app:e,getLogger:t,config:r,routing:i,parsers:a})=>{let o=xe()?void 0:new Ot(t()),s=new Map;return It({routing:i,config:r,onEndpoint:(e,t,i)=>{o?.check(e,t,i);let c=a?.[i.requestType]||[],l=n.pair(c,i);s.has(t)||s.set(t,new Map(r.cors?[[`options`,l]]:[])),s.get(t)?.set(e,l)},onStatic:e.use.bind(e)}),s},Vt=({app:e,config:t,getLogger:n,...r})=>{let i=Bt({app:e,getLogger:n,config:t,...r}),a=new Map;for(let[r,o]of i){let i=Array.from(o.keys());i.includes(`get`)&&i.push(`head`);for(let[a,[s,c]]of o){let o=[];t.cors&&o.push(async(e,r,a)=>{let o=n(e),s=zt(i),l=typeof t.cors==`function`?await t.cors({request:e,endpoint:c,logger:o,defaultHeaders:s}):s;r.set(l),a()}),o.push(...s,async(e,r)=>{let i=n(e);return c.execute({request:e,response:r,logger:i,config:t})}),e[a](r,...o)}t.hintAllowedMethods!==!1&&a.set(r,Rt(i))}for(let[t,n]of a)e.all(t,n)},Ht=e=>`_httpMessage`in e&&typeof e._httpMessage==`object`&&e._httpMessage!==null&&`headersSent`in e._httpMessage&&typeof e._httpMessage.headersSent==`boolean`&&`setHeader`in e._httpMessage&&typeof e._httpMessage.setHeader==`function`,Ut=e=>`server`in e&&typeof e.server==`object`&&e.server!==null&&`close`in e.server&&typeof e.server.close==`function`,Wt=e=>`encrypted`in e&&typeof e.encrypted==`boolean`&&e.encrypted,Gt=({},e)=>void(!e.headersSent&&e.setHeader(`connection`,`close`)),Kt=e=>{let{promise:t,resolve:n,reject:r}=Promise.withResolvers();return e.close(e=>e?r(e):n()),t},qt=(e,{timeout:t=1e3,logger:n}={})=>{let r,i=new Set,a=e=>void i.delete(e.destroy()),o=e=>void(Ht(e)?!e._httpMessage.headersSent&&e._httpMessage.setHeader(`connection`,`close`):a(e)),s=e=>void(r?e.destroy():i.add(e.once(`close`,()=>void i.delete(e))));for(let t of e)for(let e of[`connection`,`secureConnection`])t.on(e,s);let c=async()=>{for(let t of e)t.on(`request`,Gt);n?.info(`Graceful shutdown`,{sockets:i.size,timeout:t});for(let e of i)(Wt(e)||Ut(e))&&o(e);for await(let e of ne(10,Date.now()))if(i.size===0||Date.now()-e>=t)break;for(let e of i)a(e);return Promise.allSettled(e.map(Kt))};return{sockets:i,shutdown:()=>r??=c()}},Jt=Symbol.for(`express-zod-api`),Yt=({errorHandler:e,getLogger:t})=>async(n,r,i,a)=>n?e.execute({error:x(n),request:r,response:i,input:null,output:null,ctx:{},logger:t(r)}):a(),Xt=({errorHandler:e,getLogger:t})=>async(n,i)=>{let a=r(404,`Can not ${n.method} ${n.path}`),o=t(n);try{await e.execute({request:n,response:i,logger:o,error:a,input:null,output:null,ctx:{}})}catch(e){Ge({response:i,logger:o,error:new I(x(e),a)})}},Zt=e=>(t,{},n)=>{if(Object.values(t?.files||[]).flat().find(({truncated:e})=>e))return n(e);n()},Qt=async({config:e})=>{let t=await J(`cookie-parser`),{secret:n,...r}={...typeof e.cookies==`object`&&e.cookies};return t(n,Object.keys(r).length?r:void 0)},$t=e=>({log:e.debug.bind(e)}),en=async({getLogger:e,config:t})=>{let n=await J(`express-fileupload`),{limitError:r,beforeUpload:i,...a}={...typeof t.upload==`object`&&t.upload},o=[];return o.push(async(t,r,o)=>{let s=e(t);return await i?.({request:t,logger:s}),n({debug:!0,...a,abortOnLimit:!1,parseNested:!0,logger:$t(s)})(t,r,o)}),r&&o.push(Zt(r)),o},tn=(e,{},t)=>{Buffer.isBuffer(e.body)&&(e.body={raw:e.body}),t()},nn=({logger:e,config:{childLoggerProvider:t,accessLogger:n=({method:e,path:t},n)=>n.debug(`${e}: ${t}`)}})=>async(r,i,a)=>{let o=await t?.({request:r,parent:e})||e;n?.(r,o),r.res&&(r.res.locals[Jt]={logger:o}),a()},rn=e=>t=>t?.res?.locals[Jt]?.logger||e,an=e=>process.on(`deprecation`,({message:t,namespace:n,name:r,stack:i})=>e.warn(`${r} (${n}): ${t}`,i.split(`
|
|
2
|
+
`).slice(1))),on=({servers:e,logger:t,options:{timeout:n,beforeExit:r,events:i=[`SIGINT`,`SIGTERM`]}})=>{let a=qt(e,{logger:t,timeout:n}),o=async()=>{await a.shutdown(),await r?.(),process.exit()};for(let e of i)process.on(e,o)},sn=e=>{if(e.columns<132)return;let t=f(`Proudly supports transgender community.`.padStart(109)),n=f(`Start your API server with I/O schema validation and custom middlewares in minutes.`.padStart(109)),r=f(`Thank you for choosing Express Zod API for your project.`.padStart(132)),i=f(`for Koko`.padEnd(20)),a=d(`#F5A9B8`),o=d(`#5BCEFA`),s=Array(14).fill(o,1,3).fill(a,3,5).fill(m,5,7).fill(a,7,9).fill(o,9,12).fill(l,12,13),c=`
|
|
3
3
|
8888888888 8888888888P 888 d8888 8888888b. 8888888
|
|
4
4
|
888 d88P 888 d88888 888 Y88b 888
|
|
5
5
|
888 d88P 888 d88P888 888 888 888
|
|
@@ -14,8 +14,8 @@ ${i}888${n}
|
|
|
14
14
|
${r}
|
|
15
15
|
`;e.write(c.split(`
|
|
16
16
|
`).map((e,t)=>s[t]?s[t](e):e).join(`
|
|
17
|
-
`))},nn=e=>{e.startupLogo!==!1&&tn(process.stdout);let t=e.errorHandler||W,n=ot(e.logger)?e.logger:new ut(e.logger);n.debug(`Running`,{build:`v28.1.1`,env:process.env.NODE_ENV||`development`}),$t(n);let r=Zt({logger:n,config:e}),i={getLogger:Qt(n),errorHandler:t},a=Gt(i),o=Wt(i);return{...i,logger:n,notFoundHandler:a,catcher:o,loggingMiddleware:r}},rn=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,loggingMiddleware:a}=nn(e);return It({app:e.app.use(a),routing:t,getLogger:r,config:e}),{notFoundHandler:i,logger:n}},an=async(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,catcher:a,loggingMiddleware:o}=nn(e),s=_().disable(`x-powered-by`).set(`query parser`,e.queryParser??`simple`).use(o);if(e.compression){let t=await J(`compression`);s.use(t(typeof e.compression==`object`?e.compression:void 0))}e.cookies&&s.use(await qt({config:e})),await e.beforeRouting?.({app:s,getLogger:r}),It({app:s,routing:t,getLogger:r,config:e,parsers:{json:[e.jsonParser||_.json()],raw:[e.rawParser||_.raw(),Xt],form:[e.formParser||_.urlencoded()],upload:e.upload?await Yt({config:e,getLogger:r}):[]}}),await e.afterRouting?.({app:s,getLogger:r}),s.use(a,i);let c=[],l=(e,t)=>()=>e.listen(t,()=>n.info(`Listening`,t)),u=[];if(e.http){let t=ee.createServer(s);c.push(t),u.push(l(t,e.http.listen))}if(e.https){let t=te.createServer(e.https.options,s);c.push(t),u.push(l(t,e.https.listen))}return c.length||n.warn(`No servers configured.`),e.gracefulShutdown&&en({logger:n,servers:c,options:e.gracefulShutdown===!0?{}:e.gracefulShutdown}),{app:s,logger:n,servers:u.map(e=>e())}},on=e=>E(e)&&`or`in e,sn=e=>E(e)&&`and`in e,cn=e=>!sn(e)&&!on(e),ln=e=>{let t=n.filter(cn,e),r=n.chain(n.prop(`and`),n.filter(sn,e)),[i,a]=n.partition(cn,r),o=n.concat(t,i),s=n.filter(on,e);return n.map(n.prop(`or`),n.concat(s,a)).reduce((e,t)=>w(e,n.map(e=>cn(e)?[e]:e.and,t),([e,t])=>n.concat(e,t)),n.reject(n.isEmpty,[o]))},un=(e,t)=>sn(e)?n.chain(e=>un(e,t),e.and):on(e)?n.chain(e=>un(e,t),e.or):e.type===t?[e.name]:[],dn=(e,t)=>new Set(n.chain(e=>un(e,t),e));let fn;const pn=()=>fn??=new Set(`a-im.accept.accept-additions.accept-charset.accept-datetime.accept-encoding.accept-features.accept-language.accept-signature.access-control.access-control-request-headers.access-control-request-method.alpn.alt-used.amp-cache-transform.apply-to-redirect-ref.authorization.available-dictionary.c-ext.c-man.c-opt.c-pep.c-pep-info.cache-control.cal-managed-id.caldav-timezones.capsule-protocol.cdn-loop.cert-not-after.cert-not-before.client-cert.client-cert-chain.close.cmcd-object.cmcd-request.cmcd-session.cmcd-status.cmsd-dynamic.cmsd-static.concealed-auth-export.configuration-context.connection.content-digest.content-disposition.content-encoding.content-id.content-language.content-length.content-location.content-md5.content-range.content-script-type.content-type.cookie.cookie2.cta-common-access-token.dasl.date.dav.default-style.delta-base.deprecation.depth.derived-from.destination.detached-jws.dictionary-id.differential-id.digest.dpop.early-data.ediint-features.expect.expect-ct.ext.forwarded.from.getprofile.hobareg.host.http2-settings.if.if-match.if-modified-since.if-none-match.if-range.if-schedule-tag-match.if-unmodified-since.im.include-referred-token-binding-id.incremental.isolation.keep-alive.label.last-event-id.link.link-template.lock-token.man.max-forwards.memento-datetime.meter.method-check.method-check-expires.mime-version.negotiate.odata-entityid.odata-isolation.odata-maxversion.odata-version.opt.ordering-type.origin.origin-agent-cluster.oscore.oslc-core-version.overwrite.pep.pep-info.permissions-policy.pics-label.ping-from.ping-to.position.pragma.prefer.preference-applied.priority.profileobject.protocol.protocol-info.protocol-query.protocol-request.proxy-authorization.proxy-features.proxy-instruction.range.redirect-ref.referer.referer-root.referrer-policy.repeatability-client-id.repeatability-first-sent.repeatability-request-id.repeatability-result.replay-nonce.reporting-endpoints.repr-digest.safe.schedule-reply.schedule-tag.sec-fetch-storage-access.sec-gpc.sec-purpose.sec-token-binding.sec-websocket-extensions.sec-websocket-key.sec-websocket-protocol.sec-websocket-version.security-scheme.signature.signature-input.slug.soapaction.status-uri.sunset.surrogate-capability.tcn.te.timeout.topic.traceparent.tracestate.trailer.transfer-encoding.ttl.upgrade.urgency.uri.user-agent.variant-vary.via.want-content-digest.want-digest.want-repr-digest.warning.x-content-type-options.x-frame-options`.split(`.`)),mn=`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString`,hn={integer:0,number:0,string:``,boolean:!1,object:{},null:null,array:[]},gn=e=>e.replace(de,e=>`{${e.slice(1)}}`),_n=({},e)=>{if(e.isResponse)throw new P(`Please use ez.upload() only for input.`,e);return{type:`string`,format:`binary`}},vn=({jsonSchema:e})=>({...e,externalDocs:{description:`raw binary data`,url:`https://swagger.io/specification/#working-with-binary-data`}}),yn=({zodSchema:e,jsonSchema:t})=>{if(!C(e,`union`)||!(`discriminator`in e._zod.def))return t;let n=e._zod.def.discriminator;return{...t,discriminator:t.discriminator??{propertyName:n}}},bn=n.tryCatch(({jsonSchema:e})=>{if(!e.allOf)throw`no allOf`;return Y(e,`throw`)},(e,{jsonSchema:t})=>t),xn=({jsonSchema:e})=>{if(!e.anyOf||!e.anyOf.length)return e;let t=e.anyOf[0];return Object.assign(t,{type:Dn(t.type)})},X=e=>e,Sn=({jsonSchema:{examples:e,description:t}},n)=>{if(n.isResponse)throw new P(`Please use ez.dateOut() for output.`,n);let r={description:t||`YYYY-MM-DDTHH:mm:ss.sssZ`,type:`string`,format:`date-time`,pattern:`^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?)?Z?$`,externalDocs:{url:mn}};return e?.length&&(r.examples=e),r},Cn=({jsonSchema:{examples:e,description:t}},n)=>{if(!n.isResponse)throw new P(`Please use ez.dateIn() for input.`,n);let r={description:t||`YYYY-MM-DDTHH:mm:ss.sssZ`,type:`string`,format:`date-time`,externalDocs:{url:mn}};return e?.length&&(r.examples=e),r},wn=()=>({type:`string`,format:`bigint`,pattern:`^-?\\d+$`}),Tn=({zodSchema:e,jsonSchema:t})=>e._zod.def.rest===null?{...t,items:{not:{}}}:t,En=e=>{let t=Array.isArray(e.type)?e.type[0]:e.type;return hn?.[t]},Dn=e=>e===`null`?e:typeof e==`string`?[e,`null`]:e&&[...new Set(e).add(`null`)],On=({zodSchema:e,jsonSchema:t},n)=>{let r=e._zod.def[n.isResponse?`out`:`in`],i=e._zod.def[n.isResponse?`in`:`out`];if(!C(r,`transform`))return t;let a=X(Fn(i,{ctx:n}));if(v(a))if(n.isResponse){let e=be(r,En(a));if(e&&[`number`,`string`,`boolean`].includes(e))return{...t,type:e}}else{let{type:e,...t}=a;return{...t,format:`${t.format||e} (preprocessed)`}}return t},kn=({jsonSchema:e})=>{if(e.type!==`object`)return e;let t=e;return!t.properties||!(`raw`in t.properties)||!E(t.properties.raw)?e:t.properties.raw},An=e=>e.length?n.fromPairs(n.zip(n.times(e=>`example${e+1}`,e.length),n.map(n.objOf(`value`),e))):void 0,jn=(e,t)=>t?.has(e)||e.startsWith(`x-`)||pn().has(e),Mn=({path:e,method:t,request:r,inputSources:i,makeRef:a,composition:o,isHeader:s,securityHeaders:c,securityCookies:l,description:u=`${t.toUpperCase()} ${e} Parameter`})=>{let d=Y(r),f=fe(e),p=i.includes(`query`),m=i.includes(`params`),h=i.includes(`headers`),g=i.includes(`cookies`)||i.includes(`signedCookies`),_=n=>{if(m&&f.includes(n))return`path`;if(g&&l?.has(n))return`cookie`;if(h&&(s?.(n,t,e)??jn(n,c)))return`header`;if(p)return`query`};return Object.entries(d.properties).reduce((e,[t,r])=>{if(!E(r))return e;let i=_(t);if(!i)return e;let s=X(r),c=o===`components`?a(r.id||JSON.stringify(r),s,r.id||T(u,t)):s;return e.concat({name:t,in:i,deprecated:r.deprecated,required:d.required?.includes(t)||!1,description:s.description||u,schema:c,examples:An(v(s)&&s.examples?.length?s.examples:n.pluck(t,d.examples?.filter(n.both(E,n.has(t)))||[]))})},[])},Nn={nullable:xn,union:yn,bigint:wn,intersection:bn,tuple:Tn,pipe:On,[j]:Sn,[M]:Cn,[L]:_n,[R]:kn,[A]:vn},Pn=(e,t,r)=>{let i=[e,t],a=e=>/schema\d+$/.test(e)?void 0:e;for(let e=0;e<i.length;e++){let o=i[e];if(n.is(Object,o)){if(ie(o)&&!o.$ref.startsWith(`#/components`)){let e=o.$ref.split(`/`).pop(),n=t[e];n&&(o.$ref=r.makeRef(n.id||n,X(n),n.id||a(e)).$ref);continue}i.push(...n.values(o))}n.is(Array,o)&&i.push(...n.values(o))}return e},Fn=(e,{ctx:n,rules:r=Nn})=>{let{$defs:i={},properties:a={}}=t.toJSONSchema(t.object({subject:e}),{unrepresentable:`any`,io:n.isResponse?`output`:`input`,override:e=>{let t=O(e.zodSchema),i=r[t&&t in r?t:e.zodSchema._zod.def.type];if(i){let t={...i(e,n)};for(let t in e.jsonSchema)delete e.jsonSchema[t];Object.assign(e.jsonSchema,t)}}});return Pn(E(a.subject)?a.subject:{},i,n)},In=(e,t)=>{if(ie(e))return[e,!1];let r=!1,i=n.map(e=>{let[n,i]=In(e,t);return r||=i,n}),a=n.omit(t),o={properties:a,examples:n.map(a),required:n.without(t),allOf:i,oneOf:i,anyOf:i},s=n.evolve(o,e);return[s,r||!!s.required?.length]},Ln=({method:e,path:t,schema:r,mimeTypes:i,variant:a,makeRef:o,composition:s,hasMultipleStatusCodes:c,statusCode:l,brandHandling:u,description:d=`${e.toUpperCase()} ${t} ${ye(a)} response ${c?l:``}`.trim()})=>{if(!Se(e,i))return{description:d};let f=X(Fn(r,{rules:{...u,...Nn},ctx:{isResponse:!0,makeRef:o,path:t,method:e}})),p=[];v(f)&&f.examples&&(p.push(...f.examples),delete f.examples);let m={schema:s===`components`?o(r,f,T(d)):f,examples:An(p)};return{description:d,content:n.fromPairs(n.xprod(i,[m]))}},Rn=({format:e})=>{let t={type:`http`,scheme:`bearer`};return e&&(t.bearerFormat=e),t},zn=({name:e},t)=>{let n={type:`apiKey`,in:`query`,name:e};return t?.includes(`body`)&&(t?.includes(`query`)?(n[`x-in-alternative`]=`body`,n.description=`${e} CAN also be supplied within the request body`):(n[`x-in-actual`]=`body`,n.description=`${e} MUST be supplied within the request body instead of query`)),n},Bn=({name:e})=>({type:`apiKey`,in:`header`,name:e}),Vn=({name:e})=>({type:`apiKey`,in:`cookie`,name:e}),Hn=({url:e})=>({type:`openIdConnect`,openIdConnectUrl:e}),Un=({flows:e={}})=>({type:`oauth2`,flows:n.map(e=>({...e,scopes:e.scopes||{}}),n.reject(n.isNil,e))}),Wn=(e,t=[])=>{let n=e=>e.type===`basic`?{type:`http`,scheme:`basic`}:e.type===`bearer`?Rn(e):e.type===`input`?zn(e,t):e.type===`header`?Bn(e):e.type===`cookie`?Vn(e):e.type===`openid`?Hn(e):Un(e);return e.map(e=>e.map(n))},Gn=(e,t,n)=>e.map(e=>e.reduce((e,r)=>{let i=n(r),a=[`oauth2`,`openIdConnect`].includes(r.type);return Object.assign(e,{[i]:a?t:[]})},{})),Kn=({schema:e,brandHandling:t,makeRef:n,path:r,method:i})=>Fn(e,{rules:{...t,...Nn},ctx:{isResponse:!1,makeRef:n,path:r,method:i}}),qn=({method:e,path:t,schema:r,request:i,mimeType:a,makeRef:o,composition:s,paramNames:c,description:l=`${e.toUpperCase()} ${t} Request body`})=>{let[u,d]=In(X(i),c),f=[];v(u)&&u.examples&&(f.push(...u.examples),delete u.examples);let p={schema:s===`components`?o(r,u,T(l)):u,examples:An(f.length?f:Y(i).examples?.filter(e=>E(e)&&!Array.isArray(e)).map(n.omit(c))||[])},m={description:l,content:{[a]:p}};return(d||a===y.raw)&&(m.required=!0),m},Jn=e=>Object.entries(e).reduce((e,[t,n])=>{if(!n)return e;let r={name:t,description:typeof n==`string`?n:n.description};return typeof n==`object`&&n.url&&(r.externalDocs={url:n.url}),e.concat(r)},[]),Yn=(e,t=50)=>!e||e.length<=t?e:e.slice(0,Math.max(1,t||0)-1)+`…`,Xn=e=>e.length?e.slice():void 0,Zn=({description:e,summary:t=e,trim:n})=>n(t);var Qn=class extends re{#e=new Map;#t=new Map;#n=new Map;#r(e,t,n){let r=this.#n.get(e);if(!r){let t=+!n;do r=`${n??`Schema`}${t?this.#n.size+t:``}`,t++;while(this.rootDoc.components?.schemas?.[r]);this.#n.set(e,r)}return this.addSchema(r,t),{$ref:`#/components/schemas/${r}`}}#i(e,t,n){let r=n||T(t,e),i=this.#t.get(r);if(i===void 0)return this.#t.set(r,1),r;if(n)throw new P(`Duplicated operationId: "${n}"`,{method:t,isResponse:!1,path:e});return i++,this.#t.set(r,i),`${r}${i}`}#a(e){let t=JSON.stringify(e);for(let e in this.rootDoc.components?.securitySchemes||{})if(t===JSON.stringify(this.rootDoc.components?.securitySchemes?.[e]))return e;let n=(this.#e.get(e.type)||0)+1;return this.#e.set(e.type,n),`${e.type.toUpperCase()}_${n}`}constructor({routing:e,config:t,title:r,version:i,serverUrl:a,descriptions:o,brandHandling:s,tags:c,isHeader:l,hasHeadMethod:u=!0,summarizer:d=Zn,composition:f=`inline`}){super(),this.addInfo({title:r,version:i});for(let e of typeof a==`string`?[a]:a)this.addServer({url:e});let p=(e,r,i)=>{let a={path:r,method:e,endpoint:i,composition:f,brandHandling:s,makeRef:this.#r.bind(this)},{description:c,summary:u,scopes:p,inputSchema:m}=i,h=_e(e,t.inputSources),g=this.#i(r,e,i.getOperationId(e)),_=Kn({...a,schema:m}),ee=Mn({...a,inputSources:h,isHeader:l,securityHeaders:dn(i.security,`header`),securityCookies:dn(i.security,`cookie`),request:_,description:o?.requestParameter?.({method:e,path:r,operationId:g})}),te={};for(let t of Qe){let n=i.getResponses(t);for(let{mimeTypes:i,schema:s,statusCodes:c}of n)for(let l of c)te[l]=Ln({...a,variant:t,schema:s,mimeTypes:i,statusCode:l,hasMultipleStatusCodes:n.length>1||c.length>1,description:o?.[`${t}Response`]?.({method:e,path:r,operationId:g,statusCode:l})})}let ne=h.includes(`body`)?qn({...a,request:_,paramNames:n.pluck(`name`,ee),schema:m,mimeType:y[i.requestType],description:o?.requestBody?.({method:e,path:r,operationId:g})}):void 0,re=Gn(Wn(ln(i.security),h),p,e=>{let t=this.#a(e);return this.addSecurityScheme(t,e),t}),ie={operationId:g,summary:d({summary:u,description:c,trim:Yn}),description:c,deprecated:i.isDeprecated||void 0,tags:Xn(i.tags),parameters:Xn(ee),requestBody:ne,security:Xn(re),responses:te};this.addPath(gn(r),{[e]:ie})};jt({routing:e,config:t,onEndpoint:u?wt(p):p}),c&&(this.rootDoc.tags=Jn(c))}};const $n=e=>ae({...e,headers:{"content-type":y.json,...e?.headers}}),er=e=>oe(e),tr=e=>{let t={warn:[],error:[],info:[],debug:[]};return new Proxy(e||{},{get(e,n,r){return n===`_getLogs`?()=>t:st(n)?(...e)=>t[n].push(e):Reflect.get(e,n,r)}})},nr=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=$n(e),a=er({req:i,...t});a.req=t?.req||i,i.res=a;let o=tr(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},rr=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=nr(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},ir=async({middleware:e,ctx:t={},...n})=>{let{requestMock:r,responseMock:i,loggerMock:a,configMock:{inputSources:o,errorHandler:s=W}}=nr(n),c={request:r,response:i,logger:a,input:ve(r,o),ctx:t};try{return{requestMock:r,responseMock:i,loggerMock:a,output:await e.execute(c)}}catch(e){return await s.execute({...c,error:x(e),output:null}),{requestMock:r,responseMock:i,loggerMock:a,output:{}}}};var ar=class e{ts;f;exportModifier;asyncModifier;accessModifiers;#e;static#t=/^[A-Za-z_$][A-Za-z0-9_$]*$/;constructor(e){this.ts=e,this.f=this.ts.factory,this.exportModifier=[this.f.createModifier(this.ts.SyntaxKind.ExportKeyword)],this.asyncModifier=[this.f.createModifier(this.ts.SyntaxKind.AsyncKeyword)],this.accessModifiers={public:[this.f.createModifier(this.ts.SyntaxKind.PublicKeyword)],publicStatic:[this.f.createModifier(this.ts.SyntaxKind.PublicKeyword),this.f.createModifier(this.ts.SyntaxKind.StaticKeyword)],protectedReadonly:[this.f.createModifier(this.ts.SyntaxKind.ProtectedKeyword),this.f.createModifier(this.ts.SyntaxKind.ReadonlyKeyword)]},this.#e=[this.ts.SyntaxKind.AnyKeyword,this.ts.SyntaxKind.BigIntKeyword,this.ts.SyntaxKind.BooleanKeyword,this.ts.SyntaxKind.NeverKeyword,this.ts.SyntaxKind.NumberKeyword,this.ts.SyntaxKind.ObjectKeyword,this.ts.SyntaxKind.StringKeyword,this.ts.SyntaxKind.SymbolKeyword,this.ts.SyntaxKind.UndefinedKeyword,this.ts.SyntaxKind.UnknownKeyword,this.ts.SyntaxKind.VoidKeyword]}addJsDoc=(e,t)=>this.ts.addSyntheticLeadingComment(e,this.ts.SyntaxKind.MultiLineCommentTrivia,`* ${t} `,!0);printNode=(e,t)=>{let n=this.ts.createSourceFile(`print.ts`,``,this.ts.ScriptTarget.Latest,!1,this.ts.ScriptKind.TS);return this.ts.createPrinter(t).printNode(this.ts.EmitHint.Unspecified,e,n)};makeId=e=>this.f.createIdentifier(e);makePropertyIdentifier=t=>typeof t==`string`&&e.#t.test(t)?this.makeId(t):this.literally(t);makeTemplate=(e,...t)=>this.f.createTemplateExpression(this.f.createTemplateHead(e),t.map(([e,n=``],r)=>this.f.createTemplateSpan(typeof e==`string`?this.makeId(e):e,r===t.length-1?this.f.createTemplateTail(n):this.f.createTemplateMiddle(n))));makeParam=(e,{type:t,mod:n,initId:r,optional:i}={})=>this.f.createParameterDeclaration(n,void 0,e,i?this.f.createToken(this.ts.SyntaxKind.QuestionToken):void 0,t?this.ensureTypeNode(t):void 0,r?this.makeId(r):void 0);makeParams=e=>Object.entries(e).map(([e,t])=>this.makeParam(e,typeof t==`string`||typeof t==`number`||typeof t==`object`&&`kind`in t?{type:t}:t));makePublicConstructor=(e,t=[])=>this.f.createConstructorDeclaration(this.accessModifiers.public,e,this.f.createBlock(t));ensureTypeNode=(e,t)=>typeof e==`number`?this.f.createKeywordTypeNode(e):typeof e==`string`||this.ts.isIdentifier(e)?this.f.createTypeReferenceNode(e,t&&n.map(this.ensureTypeNode,t)):e;makeRecordStringAny=()=>this.ensureTypeNode(`Record`,[this.ts.SyntaxKind.StringKeyword,this.ts.SyntaxKind.AnyKeyword]);makeUnion=e=>{let t=new Map;for(let n of e)t.set(this.isPrimitive(n)?n.kind:n,n);return this.f.createUnionTypeNode(Array.from(t.values()))};makeInterfaceProp=(e,t,{isOptional:r,hasUndefined:i=r,isDeprecated:a,comment:o}={})=>{let s=this.ensureTypeNode(t),c=this.f.createPropertySignature(void 0,this.makePropertyIdentifier(e),r?this.f.createToken(this.ts.SyntaxKind.QuestionToken):void 0,i?this.makeUnion([s,this.ensureTypeNode(this.ts.SyntaxKind.UndefinedKeyword)]):s),l=n.reject(n.isNil,[a?`@deprecated`:void 0,o]);return l.length?this.addJsDoc(c,l.join(` `)):c};makeOneLine=e=>this.ts.setEmitFlags(e,this.ts.EmitFlags.SingleLine);makeDeconstruction=(...e)=>this.f.createArrayBindingPattern(e.map(e=>this.f.createBindingElement(void 0,void 0,e)));makeConst=(e,t,{type:n,expose:r}={})=>this.f.createVariableStatement(r&&this.exportModifier,this.f.createVariableDeclarationList([this.f.createVariableDeclaration(e,void 0,n?this.ensureTypeNode(n):void 0,t)],this.ts.NodeFlags.Const));makePublicLiteralType=(e,t)=>this.makeType(e,this.makeUnion(n.map(this.makeLiteralType,t)),{expose:!0});makeType=(e,t,{expose:n,comment:r,params:i}={})=>{let a=this.f.createTypeAliasDeclaration(n?this.exportModifier:void 0,e,i&&this.makeTypeParams(i),t);return r?this.addJsDoc(a,r):a};makePublicProperty=(e,t)=>this.f.createPropertyDeclaration(this.accessModifiers.public,e,void 0,this.ensureTypeNode(t),void 0);makePublicMethod=(e,t,n,{typeParams:r,returns:i,isStatic:a}={})=>this.f.createMethodDeclaration(a?this.accessModifiers.publicStatic:this.accessModifiers.public,void 0,e,void 0,r&&this.makeTypeParams(r),t,i,this.f.createBlock(n));makePublicClass=(e,t,{typeParams:n}={})=>this.f.createClassDeclaration(this.exportModifier,e,n&&this.makeTypeParams(n),void 0,t);makeKeyOf=e=>this.f.createTypeOperatorNode(this.ts.SyntaxKind.KeyOfKeyword,this.ensureTypeNode(e));makePromise=e=>this.ensureTypeNode(Promise.name,[e]);makeInterface=(e,t,{expose:n,comment:r}={})=>{let i=this.f.createInterfaceDeclaration(n?this.exportModifier:void 0,e,void 0,void 0,t);return r?this.addJsDoc(i,r):i};makeTypeParams=e=>(Array.isArray(e)?e.map(e=>n.pair(e,void 0)):Object.entries(e)).map(([e,t])=>{let{type:n,init:r}=typeof t==`object`&&`init`in t?t:{type:t};return this.f.createTypeParameterDeclaration([],e,n?this.ensureTypeNode(n):void 0,r?this.ensureTypeNode(r):void 0)});makeArrowFn=(e,t,{isAsync:r}={})=>this.f.createArrowFunction(r?this.asyncModifier:void 0,void 0,Array.isArray(e)?n.map(this.makeParam,e):this.makeParams(e),void 0,void 0,t);makeTernary=(...e)=>{let[t,n,r]=e.map(e=>typeof e==`string`?this.makeId(e):e);return this.f.createConditionalExpression(t,this.f.createToken(this.ts.SyntaxKind.QuestionToken),n,this.f.createToken(this.ts.SyntaxKind.ColonToken),r)};makeCall=(e,...t)=>(...n)=>this.f.createCallExpression(t.reduce((e,t)=>typeof t==`string`||this.ts.isIdentifier(t)?this.f.createPropertyAccessExpression(e,t):this.f.createElementAccessExpression(e,t),typeof e==`string`?this.makeId(e):e),void 0,n.map(e=>typeof e==`string`?this.makeId(e):e));makeNew=(e,...t)=>this.f.createNewExpression(this.makeId(e),void 0,t);makeExtract=(e,t)=>this.ensureTypeNode(`Extract`,[e,t]);makeAssignment=(e,t)=>this.f.createExpressionStatement(this.f.createBinaryExpression(typeof e==`string`?this.makeId(e):e,this.f.createToken(this.ts.SyntaxKind.EqualsToken),t));makeIndexed=(e,t)=>this.f.createIndexedAccessTypeNode(this.ensureTypeNode(e),this.ensureTypeNode(t));makeMaybeAsync=e=>this.makeUnion([this.ensureTypeNode(e),this.makePromise(e)]);makeFnType=(e,t)=>this.f.createFunctionTypeNode(void 0,this.makeParams(e),this.ensureTypeNode(t));literally=e=>typeof e==`number`?this.f.createNumericLiteral(e):typeof e==`bigint`?this.f.createBigIntLiteral(e.toString()):typeof e==`boolean`?e?this.f.createTrue():this.f.createFalse():e===null?this.f.createNull():this.f.createStringLiteral(e);makeLiteralType=e=>this.f.createLiteralTypeNode(this.literally(e));isPrimitive=e=>this.#e.includes(e.kind)};const Z=e=>e;var or=class{serverUrl;api;paths=new Set;tags=new Map;registry=new Map;constructor(e,t){this.serverUrl=t,this.api=new ar(e)}#e={pathType:`Path`,implementationType:`Implementation`,keyParameter:`key`,pathParameter:`path`,paramsArgument:`params`,ctxArgument:`ctx`,methodParameter:`method`,requestParameter:`request`,eventParameter:`event`,dataParameter:`data`,handlerParameter:`handler`,msgParameter:`msg`,parseRequestFn:`parseRequest`,substituteFn:`substitute`,provideMethod:`provide`,onMethod:`on`,implementationArgument:`implementation`,hasBodyConst:`hasBody`,undefinedValue:`undefined`,responseConst:`response`,restConst:`rest`,searchParamsConst:`searchParams`,defaultImplementationConst:`defaultImplementation`,clientConst:`client`,contentTypeConst:`contentType`,isJsonConst:`isJSON`,sourceProp:`source`,methodType:`Method`,someOfType:`SomeOf`,requestType:`Request`,paginationType:`Pagination`};interfaces={input:`Input`,positive:`PositiveResponse`,negative:`NegativeResponse`,encoded:`EncodedResponse`,response:`Response`};makeMethodType=()=>this.api.makePublicLiteralType(this.#e.methodType,le);makeSomeOfType=()=>this.api.makeType(this.#e.someOfType,this.api.makeIndexed(`T`,this.api.makeKeyOf(`T`)),{params:[`T`]});makeRequestType=()=>this.api.makeType(this.#e.requestType,this.api.makeKeyOf(this.interfaces.input),{expose:!0});someOf=({name:e})=>this.api.ensureTypeNode(this.#e.someOfType,[e]);makePathType=()=>this.api.makePublicLiteralType(this.#e.pathType,Array.from(this.paths));makePublicInterfaces=()=>Object.keys(this.interfaces).map(e=>this.api.makeInterface(this.interfaces[e],Array.from(this.registry).map(([t,{store:n,isDeprecated:r}])=>this.api.makeInterfaceProp(t,n[e],{isDeprecated:r})),{expose:!0}));makeEndpointTags=()=>this.api.makeConst(`endpointTags`,this.api.f.createObjectLiteralExpression(Array.from(this.tags).map(([e,t])=>this.api.f.createPropertyAssignment(this.api.makePropertyIdentifier(e),this.api.f.createArrayLiteralExpression(n.map(this.api.literally,t))))),{expose:!0});makeImplementationType=()=>this.api.makeType(this.#e.implementationType,this.api.makeFnType({[this.#e.methodParameter]:this.#e.methodType,[this.#e.pathParameter]:this.api.ts.SyntaxKind.StringKeyword,[this.#e.paramsArgument]:this.api.makeRecordStringAny(),[this.#e.ctxArgument]:{optional:!0,type:`T`}},this.api.makePromise(this.api.ts.SyntaxKind.AnyKeyword)),{expose:!0,params:{T:{init:this.api.ts.SyntaxKind.UnknownKeyword}}});makeParseRequestFn=()=>this.api.makeConst(this.#e.parseRequestFn,this.api.makeArrowFn({[this.#e.requestParameter]:this.api.ts.SyntaxKind.StringKeyword},this.api.f.createAsExpression(this.api.makeCall(this.#e.requestParameter,Z(`split`))(this.api.f.createRegularExpressionLiteral(`/ (.+)/`),this.api.literally(2)),this.api.f.createTupleTypeNode([this.api.ensureTypeNode(this.#e.methodType),this.api.ensureTypeNode(this.#e.pathType)]))));makeSubstituteFn=()=>this.api.makeConst(this.#e.substituteFn,this.api.makeArrowFn({[this.#e.pathParameter]:this.api.ts.SyntaxKind.StringKeyword,[this.#e.paramsArgument]:this.api.makeRecordStringAny()},this.api.f.createBlock([this.api.makeConst(this.#e.restConst,this.api.f.createObjectLiteralExpression([this.api.f.createSpreadAssignment(this.api.makeId(this.#e.paramsArgument))])),this.api.f.createForInStatement(this.api.f.createVariableDeclarationList([this.api.f.createVariableDeclaration(this.#e.keyParameter)],this.api.ts.NodeFlags.Const),this.api.makeId(this.#e.paramsArgument),this.api.f.createBlock([this.api.makeAssignment(this.#e.pathParameter,this.api.makeCall(this.#e.pathParameter,Z(`replace`))(this.api.makeTemplate(`:`,[this.#e.keyParameter]),this.api.makeArrowFn([],this.api.f.createBlock([this.api.f.createExpressionStatement(this.api.f.createDeleteExpression(this.api.f.createElementAccessExpression(this.api.makeId(this.#e.restConst),this.api.makeId(this.#e.keyParameter)))),this.api.f.createReturnStatement(this.api.f.createElementAccessExpression(this.api.makeId(this.#e.paramsArgument),this.api.makeId(this.#e.keyParameter)))]))))])),this.api.f.createReturnStatement(this.api.f.createAsExpression(this.api.f.createArrayLiteralExpression([this.api.makeId(this.#e.pathParameter),this.api.makeId(this.#e.restConst)]),this.api.ensureTypeNode(`const`)))])));makePaginationType=()=>{let e=Z(`nextCursor`),t=Z(`total`),n=Z(`limit`),r=Z(`offset`),i=this.api.f.createTypeLiteralNode([this.api.makeInterfaceProp(e,this.api.makeUnion([this.api.ensureTypeNode(this.api.ts.SyntaxKind.StringKeyword),this.api.makeLiteralType(null)]))]),a=this.api.f.createTypeLiteralNode([t,n,r].map(e=>this.api.makeInterfaceProp(e,this.api.ts.SyntaxKind.NumberKeyword)));return this.api.makeType(this.#e.paginationType,this.api.makeUnion([i,a]))};#t=()=>{let e=this.api.makeId(this.#e.responseConst),t=Z(`nextCursor`),n=Z(`total`),r=Z(`limit`),i=Z(`offset`),a=this.api.f.createBinaryExpression(this.api.literally(t),this.api.ts.SyntaxKind.InKeyword,e),o=this.api.f.createReturnStatement(this.api.f.createBinaryExpression(this.api.f.createPropertyAccessExpression(e,t),this.api.ts.SyntaxKind.ExclamationEqualsEqualsToken,this.api.literally(null))),s=this.api.f.createBinaryExpression(this.api.f.createPropertyAccessExpression(e,i),this.api.ts.SyntaxKind.PlusToken,this.api.f.createPropertyAccessExpression(e,r)),c=this.api.f.createReturnStatement(this.api.f.createBinaryExpression(s,this.api.ts.SyntaxKind.LessThanToken,this.api.f.createPropertyAccessExpression(e,n)));return this.api.makePublicMethod(`hasMore`,[this.api.makeParam(e,{type:this.#e.paginationType})],[this.api.f.createIfStatement(a,o),c],{returns:this.api.ensureTypeNode(this.api.ts.SyntaxKind.BooleanKeyword),isStatic:!0})};#n=()=>this.api.makePublicMethod(this.#e.provideMethod,this.api.makeParams({[this.#e.requestParameter]:`K`,[this.#e.paramsArgument]:this.api.makeIndexed(this.interfaces.input,`K`),[this.#e.ctxArgument]:{optional:!0,type:`T`}}),[this.api.makeConst(this.api.makeDeconstruction(this.#e.methodParameter,this.#e.pathParameter),this.api.makeCall(this.#e.parseRequestFn)(this.#e.requestParameter)),this.api.f.createReturnStatement(this.api.makeCall(this.api.f.createThis(),this.#e.implementationArgument)(this.#e.methodParameter,this.api.f.createSpreadElement(this.api.makeCall(this.#e.substituteFn)(this.#e.pathParameter,this.#e.paramsArgument)),this.#e.ctxArgument))],{typeParams:{K:this.#e.requestType},returns:this.api.makePromise(this.api.makeIndexed(this.interfaces.response,`K`))});makeClientClass=e=>this.api.makePublicClass(e,[this.api.makePublicConstructor([this.api.makeParam(this.#e.implementationArgument,{type:this.api.ensureTypeNode(this.#e.implementationType,[`T`]),mod:this.api.accessModifiers.protectedReadonly,initId:this.#e.defaultImplementationConst})]),this.#n(),this.#t()],{typeParams:[`T`]});#r=e=>this.api.makeTemplate(`?`,[this.api.makeNew(URLSearchParams.name,this.api.makeId(e))]);#i=()=>this.api.makeNew(URL.name,this.api.makeTemplate(``,[this.#e.pathParameter],[this.#e.searchParamsConst]),this.api.literally(this.serverUrl));makeDefaultImplementation=()=>{let e=this.api.f.createPropertyAssignment(Z(`method`),this.api.makeCall(this.#e.methodParameter,Z(`toUpperCase`))()),t=this.api.f.createPropertyAssignment(Z(`headers`),this.api.makeTernary(this.#e.hasBodyConst,this.api.f.createObjectLiteralExpression([this.api.f.createPropertyAssignment(this.api.literally(`Content-Type`),this.api.literally(y.json))]),this.#e.undefinedValue)),n=this.api.f.createPropertyAssignment(Z(`body`),this.api.makeTernary(this.#e.hasBodyConst,this.api.makeCall(JSON[Symbol.toStringTag],Z(`stringify`))(this.#e.paramsArgument),this.#e.undefinedValue)),r=this.api.makeConst(this.#e.responseConst,this.api.f.createAwaitExpression(this.api.makeCall(fetch.name)(this.#i(),this.api.f.createObjectLiteralExpression([e,t,n])))),i=this.api.makeConst(this.#e.hasBodyConst,this.api.f.createLogicalNot(this.api.makeCall(this.api.f.createArrayLiteralExpression([this.api.literally(`get`),this.api.literally(`head`),this.api.literally(`delete`)]),Z(`includes`))(this.#e.methodParameter))),a=this.api.makeConst(this.#e.searchParamsConst,this.api.makeTernary(this.#e.hasBodyConst,this.api.literally(``),this.#r(this.#e.paramsArgument))),o=this.api.makeConst(this.#e.contentTypeConst,this.api.makeCall(this.#e.responseConst,Z(`headers`),Z(`get`))(this.api.literally(`content-type`))),s=this.api.f.createIfStatement(this.api.f.createPrefixUnaryExpression(this.api.ts.SyntaxKind.ExclamationToken,this.api.makeId(this.#e.contentTypeConst)),this.api.f.createReturnStatement()),c=this.api.makeConst(this.#e.isJsonConst,this.api.makeCall(this.#e.contentTypeConst,Z(`startsWith`))(this.api.literally(y.json))),l=this.api.f.createReturnStatement(this.api.makeCall(this.#e.responseConst,this.api.makeTernary(this.#e.isJsonConst,this.api.literally(Z(`json`)),this.api.literally(Z(`text`))))());return this.api.makeConst(this.#e.defaultImplementationConst,this.api.makeArrowFn([this.#e.methodParameter,this.#e.pathParameter,this.#e.paramsArgument],this.api.f.createBlock([i,a,r,o,s,c,l]),{isAsync:!0}),{type:this.#e.implementationType})};#a=()=>this.api.makePublicConstructor(this.api.makeParams({request:`K`,params:this.api.makeIndexed(this.interfaces.input,`K`)}),[this.api.makeConst(this.api.makeDeconstruction(this.#e.pathParameter,this.#e.restConst),this.api.makeCall(this.#e.substituteFn)(this.api.f.createElementAccessExpression(this.api.makeCall(this.#e.parseRequestFn)(this.#e.requestParameter),this.api.literally(1)),this.#e.paramsArgument)),this.api.makeConst(this.#e.searchParamsConst,this.#r(this.#e.restConst)),this.api.makeAssignment(this.api.f.createPropertyAccessExpression(this.api.f.createThis(),this.#e.sourceProp),this.api.makeNew(`EventSource`,this.#i()))]);#o=e=>this.api.f.createTypeLiteralNode([this.api.makeInterfaceProp(Z(`event`),e)]);#s=()=>this.api.makePublicMethod(this.#e.onMethod,this.api.makeParams({[this.#e.eventParameter]:`E`,[this.#e.handlerParameter]:this.api.makeFnType({[this.#e.dataParameter]:this.api.makeIndexed(this.api.makeExtract(`R`,this.api.makeOneLine(this.#o(`E`))),this.api.makeLiteralType(Z(`data`)))},this.api.makeMaybeAsync(this.api.ts.SyntaxKind.VoidKeyword))}),[this.api.f.createExpressionStatement(this.api.makeCall(this.api.f.createThis(),this.#e.sourceProp,Z(`addEventListener`))(this.#e.eventParameter,this.api.makeArrowFn([this.#e.msgParameter],this.api.makeCall(this.#e.handlerParameter)(this.api.makeCall(JSON[Symbol.toStringTag],Z(`parse`))(this.api.f.createPropertyAccessExpression(this.api.f.createParenthesizedExpression(this.api.f.createAsExpression(this.api.makeId(this.#e.msgParameter),this.api.ensureTypeNode(MessageEvent.name))),Z(`data`))))))),this.api.f.createReturnStatement(this.api.f.createThis())],{typeParams:{E:this.api.makeIndexed(`R`,this.api.makeLiteralType(Z(`event`)))}});makeSubscriptionClass=e=>this.api.makePublicClass(e,[this.api.makePublicProperty(this.#e.sourceProp,`EventSource`),this.#a(),this.#s()],{typeParams:{K:this.api.makeExtract(this.#e.requestType,this.api.f.createTemplateLiteralType(this.api.f.createTemplateHead(`get `),[this.api.f.createTemplateLiteralTypeSpan(this.api.ensureTypeNode(this.api.ts.SyntaxKind.StringKeyword),this.api.f.createTemplateTail(``))])),R:this.api.makeExtract(this.api.makeIndexed(this.interfaces.positive,`K`),this.api.makeOneLine(this.#o(this.api.ts.SyntaxKind.StringKeyword)))}});makeUsageStatements=(e,t)=>[this.api.makeConst(this.#e.clientConst,this.api.makeNew(e)),this.api.makeCall(this.#e.clientConst,this.#e.provideMethod)(this.api.literally(`get /v1/user/retrieve`),this.api.f.createObjectLiteralExpression([this.api.f.createPropertyAssignment(`id`,this.api.literally(`10`))])),this.api.makeCall(this.api.makeNew(t,this.api.literally(`get /v1/events/stream`),this.api.f.createObjectLiteralExpression()),this.#e.onMethod)(this.api.literally(`time`),this.api.makeArrowFn([`time`],this.api.f.createBlock([])))]};const sr=(e,{rules:t,onMissing:n,ctx:r={}})=>{let i=O(e),a=i&&i in t?t[i]:t[e._zod.def.type],o=e=>sr(e,{ctx:r,rules:t,onMissing:n});return a?a(e,{...r,next:o}):n(e,r)},cr={name:n.path([`name`,`text`]),type:n.path([`type`]),optional:n.path([`questionToken`])},lr=({_zod:{def:e}},{api:t})=>{let n=e.values.map(e=>e===void 0?t.ensureTypeNode(t.ts.SyntaxKind.UndefinedKeyword):t.makeLiteralType(e));return n.length===1?n[0]:t.makeUnion(n)},ur=({_zod:{def:e}},{next:t,api:n})=>{let{parts:r}=e,i=0,a=()=>{let e=``;for(;i<r.length;){let t=r[i];if(C(t))break;i++,e+=t??``}return e},o=n.f.createTemplateHead(a()),s=[];for(;i<r.length;){let e=t(r[i++]),o=a(),c=i<r.length?n.f.createTemplateMiddle:n.f.createTemplateTail;s.push(n.f.createTemplateLiteralTypeSpan(e,c(o)))}return s.length?n.f.createTemplateLiteralType(o,s):n.makeLiteralType(o.text)},dr=(n,{isResponse:r,next:i,makeAlias:a,api:o})=>{let s=()=>{let a=Object.entries(n._zod.def.shape).map(([n,a])=>{let{description:s,deprecated:c}=e.get(a)||{},l=(r?a._zod.optout:a._zod.optin)===`optional`,u=l&&!(a instanceof t.core.$ZodExactOptional);return o.makeInterfaceProp(n,i(a),{comment:s,isDeprecated:c,isOptional:l,hasUndefined:u})});return o.f.createTypeLiteralNode(a)};return Re(n,{io:r?`output`:`input`})?a(n,s):s()},fr=({_zod:{def:e}},{next:t,api:n})=>n.f.createArrayTypeNode(t(e.element)),pr=({_zod:{def:e}},{api:t})=>t.makeUnion(n.map(t.makeLiteralType,Object.values(e.entries))),mr=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion(e.options.map(t)),hr=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion([t(e.innerType),n.makeLiteralType(null)]),gr=({_zod:{def:e}},{next:t,api:n})=>n.f.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:n.f.createRestTypeNode(t(e.rest)))),_r=({_zod:{def:e}},{next:t,api:n})=>{let[r,i]=[e.keyType,e.valueType].map(t),a=n.ensureTypeNode(`Record`,[r,i]);return e.mode===`loose`?n.f.createIntersectionTypeNode([a,n.ensureTypeNode(`Record`,[`PropertyKey`,i])]):a},vr=n.tryCatch((e,t)=>{if(!t.every(e.ts.isTypeLiteralNode))throw Error(`Not objects`);let r=n.chain(n.prop(`members`),t),i=n.uniqWith((...e)=>{if(!n.eqBy(cr.name,...e))return!1;if(n.both(n.eqBy(cr.type),n.eqBy(cr.optional))(...e))return!0;throw Error(`Has conflicting prop`)},r);return e.f.createTypeLiteralNode(i)},(e,t,n)=>t.f.createIntersectionTypeNode(n)),yr=({_zod:{def:e}},{next:t,api:n})=>vr(n,[e.left,e.right].map(t)),Q=e=>({},{api:t})=>t.ensureTypeNode(t.ts.SyntaxKind[e]),$=({_zod:{def:e}},{next:t})=>t(e.innerType),br=(e,t)=>e.ensureTypeNode(t?e.ts.SyntaxKind.UnknownKeyword:e.ts.SyntaxKind.AnyKeyword),xr=({_zod:{def:e}},{next:t,isResponse:n,api:r})=>{let i=e[n?`out`:`in`],a=e[n?`in`:`out`];if(!C(i,`transform`))return t(i);let o=t(a),s={[r.ts.SyntaxKind.AnyKeyword]:``,[r.ts.SyntaxKind.BigIntKeyword]:BigInt(0),[r.ts.SyntaxKind.BooleanKeyword]:!1,[r.ts.SyntaxKind.NumberKeyword]:0,[r.ts.SyntaxKind.ObjectKeyword]:{},[r.ts.SyntaxKind.StringKeyword]:``,[r.ts.SyntaxKind.UndefinedKeyword]:void 0}[o.kind],c=be(i,s),l={number:r.ts.SyntaxKind.NumberKeyword,bigint:r.ts.SyntaxKind.BigIntKeyword,boolean:r.ts.SyntaxKind.BooleanKeyword,string:r.ts.SyntaxKind.StringKeyword,undefined:r.ts.SyntaxKind.UndefinedKeyword,object:r.ts.SyntaxKind.ObjectKeyword};return r.ensureTypeNode(c&&l[c]||br(r,n))},Sr=({},{api:e})=>e.makeLiteralType(null),Cr=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),wr=({},{api:e})=>e.ensureTypeNode(`Buffer`),Tr=(e,{next:t})=>t(e._zod.def.shape.raw),Er={string:Q(`StringKeyword`),number:Q(`NumberKeyword`),bigint:Q(`BigIntKeyword`),boolean:Q(`BooleanKeyword`),any:Q(`AnyKeyword`),undefined:Q(`UndefinedKeyword`),[j]:Q(`StringKeyword`),[M]:Q(`StringKeyword`),never:Q(`NeverKeyword`),void:Q(`UndefinedKeyword`),unknown:Q(`UnknownKeyword`),null:Sr,array:fr,tuple:gr,record:_r,object:dr,literal:lr,template_literal:ur,intersection:yr,union:mr,default:$,enum:pr,optional:$,nonoptional:$,nullable:hr,catch:$,pipe:xr,lazy:Cr,readonly:$,[A]:wr,[R]:Tr},Dr=(e,{brandHandling:t,ctx:n})=>sr(e,{rules:{...t,...Er},onMissing:({},{isResponse:e,api:t})=>br(t,e),ctx:n});var Or=class e extends or{#e=[this.makeSomeOfType()];#t=new Map;#n=[];#r(e,t){let n=this.#t.get(e)?.name?.text;if(!n){n=`Type${this.#t.size+1}`;let r=this.api.makeLiteralType(null);this.#t.set(e,this.api.makeType(n,r)),this.#t.set(e,this.api.makeType(n,t()))}return this.api.ensureTypeNode(n)}constructor({typescript:e,routing:r,config:i,brandHandling:a,variant:o=`client`,clientClassName:s=`Client`,subscriptionClassName:c=`Subscription`,serverUrl:l=`https://example.com`,noBodySchema:u=t.undefined(),hasHeadMethod:d=!0}){super(e,l);let f={makeAlias:this.#r.bind(this),api:this.api},p={brandHandling:a,ctx:{...f,isResponse:!1}},m={brandHandling:a,ctx:{...f,isResponse:!0}},h=(e,t,r)=>{let i=T.bind(null,e,t),{isDeprecated:a,inputSchema:o,tags:s}=r,c=`${e} ${t}`,l=this.api.makeType(i(`input`),Dr(o,p),{comment:c});this.#e.push(l);let d=Qe.reduce((t,a)=>{let o=r.getResponses(a),s=n.chain(([t,{schema:n,mimeTypes:r,statusCodes:o}])=>{let s=Se(e,r),l=this.api.makeType(i(a,`variant`,`${t+1}`),Dr(s?n:u,m),{comment:c});return this.#e.push(l),o.map(e=>this.api.makeInterfaceProp(e,l.name))},Array.from(o.entries())),l=this.api.makeInterface(i(a,`response`,`variants`),s,{comment:c});return this.#e.push(l),Object.assign(t,{[a]:l})},{});this.paths.add(t);let f=this.api.makeLiteralType(c),h={input:this.api.ensureTypeNode(l.name),positive:this.someOf(d.positive),negative:this.someOf(d.negative),response:this.api.makeUnion([this.api.makeIndexed(this.interfaces.positive,f),this.api.makeIndexed(this.interfaces.negative,f)]),encoded:this.api.f.createIntersectionTypeNode([this.api.ensureTypeNode(d.positive.name),this.api.ensureTypeNode(d.negative.name)])};this.registry.set(c,{isDeprecated:a,store:h}),this.tags.set(c,s)};jt({routing:r,config:i,onEndpoint:d?wt(h):h}),this.#e.unshift(...this.#t.values()),this.#e.push(this.makePathType(),this.makeMethodType(),...this.makePublicInterfaces(),this.makeRequestType()),o!==`types`&&(this.#e.push(this.makeEndpointTags(),this.makeParseRequestFn(),this.makeSubstituteFn(),this.makeImplementationType(),this.makePaginationType(),this.makeDefaultImplementation(),this.makeClientClass(s),this.makeSubscriptionClass(c)),this.#n.push(...this.makeUsageStatements(s,c)))}static async create(t){return new e({...t,typescript:await J(`typescript`)})}#i(e){return this.#n.length?this.#n.map(t=>typeof t==`string`?t:this.api.printNode(t,e)).join(`
|
|
17
|
+
`))},cn=e=>{e.startupLogo!==!1&&sn(process.stdout);let t=e.errorHandler||W,n=ft(e.logger)?e.logger:new gt(e.logger);n.debug(`Running`,{build:`v28.3.0`,env:process.env.NODE_ENV||`development`}),an(n);let r=nn({logger:n,config:e}),i={getLogger:rn(n),errorHandler:t},a=Xt(i),o=Yt(i);return{...i,logger:n,notFoundHandler:a,catcher:o,loggingMiddleware:r}},ln=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,loggingMiddleware:a}=cn(e);return Vt({app:e.app.use(a),routing:t,getLogger:r,config:e}),{notFoundHandler:i,logger:n}},un=async(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,catcher:a,loggingMiddleware:o}=cn(e),s=_().disable(`x-powered-by`).set(`query parser`,e.queryParser??`simple`).use(o);if(e.compression){let t=await J(`compression`);s.use(t(typeof e.compression==`object`?e.compression:void 0))}e.cookies&&s.use(await Qt({config:e})),await e.beforeRouting?.({app:s,getLogger:r}),Vt({app:s,routing:t,getLogger:r,config:e,parsers:{json:[e.jsonParser||_.json()],raw:[e.rawParser||_.raw(),tn],form:[e.formParser||_.urlencoded()],upload:e.upload?await en({config:e,getLogger:r}):[]}}),await e.afterRouting?.({app:s,getLogger:r}),s.use(a,i);let c=[],l=(e,t)=>()=>e.listen(t,()=>n.info(`Listening`,t)),u=[];if(e.http){let t=ee.createServer(s);c.push(t),u.push(l(t,e.http.listen))}if(e.https){let t=te.createServer(e.https.options,s);c.push(t),u.push(l(t,e.https.listen))}return c.length||n.warn(`No servers configured.`),e.gracefulShutdown&&on({logger:n,servers:c,options:e.gracefulShutdown===!0?{}:e.gracefulShutdown}),{app:s,logger:n,servers:u.map(e=>e())}},dn=e=>E(e)&&`or`in e,fn=e=>E(e)&&`and`in e,pn=e=>!fn(e)&&!dn(e),mn=e=>{let t=n.filter(pn,e),r=n.chain(n.prop(`and`),n.filter(fn,e)),[i,a]=n.partition(pn,r),o=n.concat(t,i),s=n.filter(dn,e);return n.map(n.prop(`or`),n.concat(s,a)).reduce((e,t)=>w(e,n.map(e=>pn(e)?[e]:e.and,t),([e,t])=>n.concat(e,t)),n.reject(n.isEmpty,[o]))},hn=(e,t)=>fn(e)?n.chain(e=>hn(e,t),e.and):dn(e)?n.chain(e=>hn(e,t),e.or):e.type===t?[e.name]:[],gn=(e,t)=>new Set(n.chain(e=>hn(e,t),e));let _n;const vn=()=>_n??=new Set(`a-im.accept.accept-additions.accept-charset.accept-datetime.accept-encoding.accept-features.accept-language.accept-signature.access-control.access-control-request-headers.access-control-request-method.alpn.alt-used.amp-cache-transform.apply-to-redirect-ref.authorization.available-dictionary.c-ext.c-man.c-opt.c-pep.c-pep-info.cache-control.cal-managed-id.caldav-timezones.capsule-protocol.cdn-loop.cert-not-after.cert-not-before.client-cert.client-cert-chain.close.cmcd-object.cmcd-request.cmcd-session.cmcd-status.cmsd-dynamic.cmsd-static.concealed-auth-export.configuration-context.connection.content-digest.content-disposition.content-encoding.content-id.content-language.content-length.content-location.content-md5.content-range.content-script-type.content-type.cookie.cookie2.cta-common-access-token.dasl.date.dav.default-style.delta-base.deprecation.depth.derived-from.destination.detached-jws.dictionary-id.differential-id.digest.dpop.early-data.ediint-features.expect.expect-ct.ext.forwarded.from.getprofile.hobareg.host.http2-settings.if.if-match.if-modified-since.if-none-match.if-range.if-schedule-tag-match.if-unmodified-since.im.include-referred-token-binding-id.incremental.isolation.keep-alive.label.last-event-id.link.link-template.lock-token.man.max-forwards.memento-datetime.meter.method-check.method-check-expires.mime-version.negotiate.odata-entityid.odata-isolation.odata-maxversion.odata-version.opt.ordering-type.origin.origin-agent-cluster.oscore.oslc-core-version.overwrite.pep.pep-info.permissions-policy.pics-label.ping-from.ping-to.position.pragma.prefer.preference-applied.priority.profileobject.protocol.protocol-info.protocol-query.protocol-request.proxy-authorization.proxy-features.proxy-instruction.range.redirect-ref.referer.referer-root.referrer-policy.repeatability-client-id.repeatability-first-sent.repeatability-request-id.repeatability-result.replay-nonce.reporting-endpoints.repr-digest.safe.schedule-reply.schedule-tag.sec-fetch-storage-access.sec-gpc.sec-purpose.sec-token-binding.sec-websocket-extensions.sec-websocket-key.sec-websocket-protocol.sec-websocket-version.security-scheme.signature.signature-input.slug.soapaction.status-uri.sunset.surrogate-capability.tcn.te.timeout.topic.traceparent.tracestate.trailer.transfer-encoding.ttl.upgrade.urgency.uri.user-agent.variant-vary.via.want-content-digest.want-digest.want-repr-digest.warning.x-content-type-options.x-frame-options`.split(`.`)),yn=`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString`,bn={integer:0,number:0,string:``,boolean:!1,object:{},null:null,array:[]},xn=e=>e.replace(de,e=>`{${e.slice(1)}}`),Sn=({},e)=>{if(e.isResponse)throw new P(`Please use ez.upload() only for input.`,e);return{type:`string`,format:`binary`}},Cn=({jsonSchema:e})=>({...e,externalDocs:{description:`raw binary data`,url:`https://swagger.io/specification/#working-with-binary-data`}}),wn=({zodSchema:e,jsonSchema:t})=>{if(!C(e,`union`)||!(`discriminator`in e._zod.def))return t;let n=e._zod.def.discriminator;return{...t,discriminator:t.discriminator??{propertyName:n}}},Tn=n.tryCatch(({jsonSchema:e})=>{if(!e.allOf)throw`no allOf`;return Y(e,`throw`)},(e,{jsonSchema:t})=>t),En=({jsonSchema:e})=>{if(!e.anyOf||!e.anyOf.length)return e;let t=e.anyOf[0];return Object.assign(t,{type:Mn(t.type)})},X=e=>e,Dn=({jsonSchema:{examples:e,description:t}},n)=>{if(n.isResponse)throw new P(`Please use ez.dateOut() for output.`,n);let r={description:t||`YYYY-MM-DDTHH:mm:ss.sssZ`,type:`string`,format:`date-time`,pattern:`^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?)?Z?$`,externalDocs:{url:yn}};return e?.length&&(r.examples=e),r},On=({jsonSchema:{examples:e,description:t}},n)=>{if(!n.isResponse)throw new P(`Please use ez.dateIn() for input.`,n);let r={description:t||`YYYY-MM-DDTHH:mm:ss.sssZ`,type:`string`,format:`date-time`,externalDocs:{url:yn}};return e?.length&&(r.examples=e),r},kn=()=>({type:`string`,format:`bigint`,pattern:`^-?\\d+$`}),An=({zodSchema:e,jsonSchema:t})=>e._zod.def.rest===null?{...t,items:{not:{}}}:t,jn=e=>{let t=Array.isArray(e.type)?e.type[0]:e.type;return bn?.[t]},Mn=e=>e===`null`?e:typeof e==`string`?[e,`null`]:e&&[...new Set(e).add(`null`)],Nn=({zodSchema:e,jsonSchema:t},n)=>{let r=e._zod.def[n.isResponse?`out`:`in`],i=e._zod.def[n.isResponse?`in`:`out`];if(!C(r,`transform`))return t;let a=X(Bn(i,{ctx:n}));if(v(a))if(n.isResponse){let e=be(r,jn(a));if(e&&[`number`,`string`,`boolean`].includes(e))return{...t,type:e}}else{let{type:e,...t}=a;return{...t,format:`${t.format||e} (preprocessed)`}}return t},Pn=({jsonSchema:e})=>{if(e.type!==`object`)return e;let t=e;return!t.properties||!(`raw`in t.properties)||!E(t.properties.raw)?e:t.properties.raw},Fn=e=>e.length?n.fromPairs(n.zip(n.times(e=>`example${e+1}`,e.length),n.map(n.objOf(`value`),e))):void 0,In=(e,t)=>t?.has(e)||e.startsWith(`x-`)||vn().has(e),Ln=({path:e,method:t,request:r,inputSources:i,makeRef:a,composition:o,isHeader:s,securityHeaders:c,securityCookies:l,description:u=`${t.toUpperCase()} ${e} Parameter`})=>{let d=Y(r),f=fe(e),p=i.includes(`query`),m=i.includes(`params`),h=i.includes(`headers`),g=i.includes(`cookies`)||i.includes(`signedCookies`),_=n=>{if(m&&f.includes(n))return`path`;if(g&&l?.has(n))return`cookie`;if(h&&(s?.(n,t,e)??In(n,c)))return`header`;if(p)return`query`};return Object.entries(d.properties).reduce((e,[t,r])=>{if(!E(r))return e;let i=_(t);if(!i)return e;let s=X(r),c=o===`components`?a(r.id||JSON.stringify(r),s,r.id||T(u,t)):s;return e.concat({name:t,in:i,deprecated:r.deprecated,required:d.required?.includes(t)||!1,description:s.description||u,schema:c,examples:Fn(v(s)&&s.examples?.length?s.examples:n.pluck(t,d.examples?.filter(n.both(E,n.has(t)))||[]))})},[])},Rn={nullable:En,union:wn,bigint:kn,intersection:Tn,tuple:An,pipe:Nn,[j]:Dn,[M]:On,[L]:Sn,[R]:Pn,[A]:Cn},zn=(e,t,r)=>{let i=[e,t],a=e=>/schema\d+$/.test(e)?void 0:e;for(let e=0;e<i.length;e++){let o=i[e];if(n.is(Object,o)){if(ie(o)&&!o.$ref.startsWith(`#/components`)){let e=o.$ref.split(`/`).pop(),n=t[e];n&&(o.$ref=r.makeRef(n.id||n,X(n),n.id||a(e)).$ref);continue}i.push(...n.values(o))}n.is(Array,o)&&i.push(...n.values(o))}return e},Bn=(e,{ctx:n,rules:r=Rn})=>{let{$defs:i={},properties:a={}}=t.toJSONSchema(t.object({subject:e}),{unrepresentable:`any`,io:n.isResponse?`output`:`input`,override:e=>{let t=O(e.zodSchema),i=r[t&&t in r?t:e.zodSchema._zod.def.type];if(i){let t={...i(e,n)};for(let t in e.jsonSchema)delete e.jsonSchema[t];Object.assign(e.jsonSchema,t)}}});return zn(E(a.subject)?a.subject:{},i,n)},Vn=(e,t)=>{if(ie(e))return[e,!1];let r=!1,i=n.map(e=>{let[n,i]=Vn(e,t);return r||=i,n}),a=n.omit(t),o={properties:a,examples:n.map(a),required:n.without(t),allOf:i,oneOf:i,anyOf:i},s=n.evolve(o,e);return[s,r||!!s.required?.length]},Hn=({method:e,path:t,schema:r,mimeTypes:i,variant:a,makeRef:o,composition:s,hasMultipleStatusCodes:c,statusCode:l,brandHandling:u,description:d=`${e.toUpperCase()} ${t} ${ye(a)} response ${c?l:``}`.trim()})=>{if(!Se(e,i))return{description:d};let f=X(Bn(r,{rules:{...u,...Rn},ctx:{isResponse:!0,makeRef:o,path:t,method:e}})),p=[];v(f)&&f.examples&&(p.push(...f.examples),delete f.examples);let m={schema:s===`components`?o(r,f,T(d)):f,examples:Fn(p)};return{description:d,content:n.fromPairs(n.xprod(i,[m]))}},Un=({format:e})=>{let t={type:`http`,scheme:`bearer`};return e&&(t.bearerFormat=e),t},Wn=({name:e},t)=>{let n={type:`apiKey`,in:`query`,name:e};return t?.includes(`body`)&&(t?.includes(`query`)?(n[`x-in-alternative`]=`body`,n.description=`${e} CAN also be supplied within the request body`):(n[`x-in-actual`]=`body`,n.description=`${e} MUST be supplied within the request body instead of query`)),n},Gn=({name:e})=>({type:`apiKey`,in:`header`,name:e}),Kn=({name:e})=>({type:`apiKey`,in:`cookie`,name:e}),qn=({url:e})=>({type:`openIdConnect`,openIdConnectUrl:e}),Jn=({flows:e={}})=>({type:`oauth2`,flows:n.map(e=>({...e,scopes:e.scopes||{}}),n.reject(n.isNil,e))}),Yn=(e,t=[])=>{let n=e=>e.type===`basic`?{type:`http`,scheme:`basic`}:e.type===`bearer`?Un(e):e.type===`input`?Wn(e,t):e.type===`header`?Gn(e):e.type===`cookie`?Kn(e):e.type===`openid`?qn(e):Jn(e);return e.map(e=>e.map(n))},Xn=(e,t,n)=>e.map(e=>e.reduce((e,r)=>{let i=n(r),a=[`oauth2`,`openIdConnect`].includes(r.type);return Object.assign(e,{[i]:a?t:[]})},{})),Zn=({schema:e,brandHandling:t,makeRef:n,path:r,method:i})=>Bn(e,{rules:{...t,...Rn},ctx:{isResponse:!1,makeRef:n,path:r,method:i}}),Qn=({method:e,path:t,schema:r,request:i,mimeType:a,makeRef:o,composition:s,paramNames:c,description:l=`${e.toUpperCase()} ${t} Request body`})=>{let[u,d]=Vn(X(i),c),f=[];v(u)&&u.examples&&(f.push(...u.examples),delete u.examples);let p={schema:s===`components`?o(r,u,T(l)):u,examples:Fn(f.length?f:Y(i).examples?.filter(e=>E(e)&&!Array.isArray(e)).map(n.omit(c))||[])},m={description:l,content:{[a]:p}};return(d||a===y.raw)&&(m.required=!0),m},$n=e=>Object.entries(e).reduce((e,[t,n])=>{if(!n)return e;let r={name:t,description:typeof n==`string`?n:n.description};return typeof n==`object`&&n.url&&(r.externalDocs={url:n.url}),e.concat(r)},[]),er=(e,t=50)=>!e||e.length<=t?e:e.slice(0,Math.max(1,t||0)-1)+`…`,tr=e=>e.length?e.slice():void 0,nr=({description:e,summary:t=e,trim:n})=>n(t);var rr=class extends re{#e=new Map;#t=new Map;#n=new Map;#r(e,t,n){let r=this.#n.get(e);if(!r){let t=+!n;do r=`${n??`Schema`}${t?this.#n.size+t:``}`,t++;while(this.rootDoc.components?.schemas?.[r]);this.#n.set(e,r)}return this.addSchema(r,t),{$ref:`#/components/schemas/${r}`}}#i(e,t,n){let r=n||T(t,e),i=this.#t.get(r);if(i===void 0)return this.#t.set(r,1),r;if(n)throw new P(`Duplicated operationId: "${n}"`,{method:t,isResponse:!1,path:e});return i++,this.#t.set(r,i),`${r}${i}`}#a(e){let t=JSON.stringify(e);for(let e in this.rootDoc.components?.securitySchemes||{})if(t===JSON.stringify(this.rootDoc.components?.securitySchemes?.[e]))return e;let n=(this.#e.get(e.type)||0)+1;return this.#e.set(e.type,n),`${e.type.toUpperCase()}_${n}`}constructor({routing:e,config:t,title:r,version:i,serverUrl:a,descriptions:o,brandHandling:s,tags:c,isHeader:l,hasHeadMethod:u=!0,summarizer:d=nr,composition:f=`inline`}){super(),this.addInfo({title:r,version:i});for(let e of typeof a==`string`?[a]:a)this.addServer({url:e});let p=(e,r,i)=>{let a={path:r,method:e,endpoint:i,composition:f,brandHandling:s,makeRef:this.#r.bind(this)},{description:c,summary:u,scopes:p,inputSchema:m}=i,h=_e(e,t.inputSources),g=this.#i(r,e,i.getOperationId(e)),_=Zn({...a,schema:m}),ee=Ln({...a,inputSources:h,isHeader:l,securityHeaders:gn(i.security,`header`),securityCookies:gn(i.security,`cookie`),request:_,description:o?.requestParameter?.({method:e,path:r,operationId:g})}),te={};for(let t of Qe){let n=i.getResponses(t);for(let{mimeTypes:i,schema:s,statusCodes:c}of n)for(let l of c)te[l]=Hn({...a,variant:t,schema:s,mimeTypes:i,statusCode:l,hasMultipleStatusCodes:n.length>1||c.length>1,description:o?.[`${t}Response`]?.({method:e,path:r,operationId:g,statusCode:l})})}let ne=h.includes(`body`)?Qn({...a,request:_,paramNames:n.pluck(`name`,ee),schema:m,mimeType:y[i.requestType],description:o?.requestBody?.({method:e,path:r,operationId:g})}):void 0,re=Xn(Yn(mn(i.security),h),p,e=>{let t=this.#a(e);return this.addSecurityScheme(t,e),t}),ie={operationId:g,summary:d({summary:u,description:c,trim:er}),description:c,deprecated:i.isDeprecated||void 0,tags:tr(i.tags),parameters:tr(ee),requestBody:ne,security:tr(re),responses:te};this.addPath(xn(r),{[e]:ie})};It({routing:e,config:t,onEndpoint:u?kt(p):p}),c&&(this.rootDoc.tags=$n(c))}};const ir=e=>ae({...e,headers:{"content-type":y.json,...e?.headers}}),ar=e=>oe(e),or=e=>{let t={warn:[],error:[],info:[],debug:[]};return new Proxy(e||{},{get(e,n,r){return n===`_getLogs`?()=>t:pt(n)?(...e)=>t[n].push(e):Reflect.get(e,n,r)}})},sr=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=ir(e),a=ar({req:i,...t});a.req=t?.req||i,i.res=a;let o=or(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},cr=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=sr(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},lr=async({middleware:e,ctx:t={},...n})=>{let{requestMock:r,responseMock:i,loggerMock:a,configMock:{inputSources:o,errorHandler:s=W}}=sr(n),c={request:r,response:i,logger:a,input:ve(r,o),ctx:t};try{return{requestMock:r,responseMock:i,loggerMock:a,output:await e.execute(c)}}catch(e){return await s.execute({...c,error:x(e),output:null}),{requestMock:r,responseMock:i,loggerMock:a,output:{}}}};var ur=class e{ts;f;exportModifier;asyncModifier;accessModifiers;#e;static#t=/^[A-Za-z_$][A-Za-z0-9_$]*$/;constructor(e){this.ts=e,this.f=this.ts.factory,this.exportModifier=[this.f.createModifier(this.ts.SyntaxKind.ExportKeyword)],this.asyncModifier=[this.f.createModifier(this.ts.SyntaxKind.AsyncKeyword)],this.accessModifiers={public:[this.f.createModifier(this.ts.SyntaxKind.PublicKeyword)],publicStatic:[this.f.createModifier(this.ts.SyntaxKind.PublicKeyword),this.f.createModifier(this.ts.SyntaxKind.StaticKeyword)],protectedReadonly:[this.f.createModifier(this.ts.SyntaxKind.ProtectedKeyword),this.f.createModifier(this.ts.SyntaxKind.ReadonlyKeyword)]},this.#e=[this.ts.SyntaxKind.AnyKeyword,this.ts.SyntaxKind.BigIntKeyword,this.ts.SyntaxKind.BooleanKeyword,this.ts.SyntaxKind.NeverKeyword,this.ts.SyntaxKind.NumberKeyword,this.ts.SyntaxKind.ObjectKeyword,this.ts.SyntaxKind.StringKeyword,this.ts.SyntaxKind.SymbolKeyword,this.ts.SyntaxKind.UndefinedKeyword,this.ts.SyntaxKind.UnknownKeyword,this.ts.SyntaxKind.VoidKeyword]}addJsDoc=(e,t)=>this.ts.addSyntheticLeadingComment(e,this.ts.SyntaxKind.MultiLineCommentTrivia,`* ${t} `,!0);printNode=(e,t)=>{let n=this.ts.createSourceFile(`print.ts`,``,this.ts.ScriptTarget.Latest,!1,this.ts.ScriptKind.TS);return this.ts.createPrinter(t).printNode(this.ts.EmitHint.Unspecified,e,n)};makeId=e=>this.f.createIdentifier(e);makePropertyIdentifier=t=>typeof t==`string`&&e.#t.test(t)?this.makeId(t):this.literally(t);makeTemplate=(e,...t)=>this.f.createTemplateExpression(this.f.createTemplateHead(e),t.map(([e,n=``],r)=>this.f.createTemplateSpan(typeof e==`string`?this.makeId(e):e,r===t.length-1?this.f.createTemplateTail(n):this.f.createTemplateMiddle(n))));makeParam=(e,{type:t,mod:n,initId:r,optional:i}={})=>this.f.createParameterDeclaration(n,void 0,e,i?this.f.createToken(this.ts.SyntaxKind.QuestionToken):void 0,t?this.ensureTypeNode(t):void 0,r?this.makeId(r):void 0);makeParams=e=>Object.entries(e).map(([e,t])=>this.makeParam(e,typeof t==`string`||typeof t==`number`||typeof t==`object`&&`kind`in t?{type:t}:t));makePublicConstructor=(e,t=[])=>this.f.createConstructorDeclaration(this.accessModifiers.public,e,this.f.createBlock(t));ensureTypeNode=(e,t)=>typeof e==`number`?this.f.createKeywordTypeNode(e):typeof e==`string`||this.ts.isIdentifier(e)?this.f.createTypeReferenceNode(e,t&&n.map(this.ensureTypeNode,t)):e;makeRecordStringAny=()=>this.ensureTypeNode(`Record`,[this.ts.SyntaxKind.StringKeyword,this.ts.SyntaxKind.AnyKeyword]);makeUnion=e=>{let t=new Map;for(let n of e)t.set(this.isPrimitive(n)?n.kind:n,n);return this.f.createUnionTypeNode(Array.from(t.values()))};makeInterfaceProp=(e,t,{isOptional:r,hasUndefined:i=r,isDeprecated:a,comment:o}={})=>{let s=this.ensureTypeNode(t),c=this.f.createPropertySignature(void 0,this.makePropertyIdentifier(e),r?this.f.createToken(this.ts.SyntaxKind.QuestionToken):void 0,i?this.makeUnion([s,this.ensureTypeNode(this.ts.SyntaxKind.UndefinedKeyword)]):s),l=n.reject(n.isNil,[a?`@deprecated`:void 0,o]);return l.length?this.addJsDoc(c,l.join(` `)):c};makeOneLine=e=>this.ts.setEmitFlags(e,this.ts.EmitFlags.SingleLine);makeDeconstruction=(...e)=>this.f.createArrayBindingPattern(e.map(e=>this.f.createBindingElement(void 0,void 0,e)));makeConst=(e,t,{type:n,expose:r}={})=>this.f.createVariableStatement(r&&this.exportModifier,this.f.createVariableDeclarationList([this.f.createVariableDeclaration(e,void 0,n?this.ensureTypeNode(n):void 0,t)],this.ts.NodeFlags.Const));makePublicLiteralType=(e,t)=>this.makeType(e,this.makeUnion(n.map(this.makeLiteralType,t)),{expose:!0});makeType=(e,t,{expose:n,comment:r,params:i}={})=>{let a=this.f.createTypeAliasDeclaration(n?this.exportModifier:void 0,e,i&&this.makeTypeParams(i),t);return r?this.addJsDoc(a,r):a};makePublicProperty=(e,t)=>this.f.createPropertyDeclaration(this.accessModifiers.public,e,void 0,this.ensureTypeNode(t),void 0);makePublicMethod=(e,t,n,{typeParams:r,returns:i,isStatic:a}={})=>this.f.createMethodDeclaration(a?this.accessModifiers.publicStatic:this.accessModifiers.public,void 0,e,void 0,r&&this.makeTypeParams(r),t,i,this.f.createBlock(n));makePublicClass=(e,t,{typeParams:n}={})=>this.f.createClassDeclaration(this.exportModifier,e,n&&this.makeTypeParams(n),void 0,t);makeKeyOf=e=>this.f.createTypeOperatorNode(this.ts.SyntaxKind.KeyOfKeyword,this.ensureTypeNode(e));makePromise=e=>this.ensureTypeNode(Promise.name,[e]);makeInterface=(e,t,{expose:n,comment:r}={})=>{let i=this.f.createInterfaceDeclaration(n?this.exportModifier:void 0,e,void 0,void 0,t);return r?this.addJsDoc(i,r):i};makeTypeParams=e=>(Array.isArray(e)?e.map(e=>n.pair(e,void 0)):Object.entries(e)).map(([e,t])=>{let{type:n,init:r}=typeof t==`object`&&`init`in t?t:{type:t};return this.f.createTypeParameterDeclaration([],e,n?this.ensureTypeNode(n):void 0,r?this.ensureTypeNode(r):void 0)});makeArrowFn=(e,t,{isAsync:r}={})=>this.f.createArrowFunction(r?this.asyncModifier:void 0,void 0,Array.isArray(e)?n.map(this.makeParam,e):this.makeParams(e),void 0,void 0,t);makeTernary=(...e)=>{let[t,n,r]=e.map(e=>typeof e==`string`?this.makeId(e):e);return this.f.createConditionalExpression(t,this.f.createToken(this.ts.SyntaxKind.QuestionToken),n,this.f.createToken(this.ts.SyntaxKind.ColonToken),r)};makeCall=(e,...t)=>(...n)=>this.f.createCallExpression(t.reduce((e,t)=>typeof t==`string`||this.ts.isIdentifier(t)?this.f.createPropertyAccessExpression(e,t):this.f.createElementAccessExpression(e,t),typeof e==`string`?this.makeId(e):e),void 0,n.map(e=>typeof e==`string`?this.makeId(e):e));makeNew=(e,...t)=>this.f.createNewExpression(this.makeId(e),void 0,t);makeExtract=(e,t)=>this.ensureTypeNode(`Extract`,[e,t]);makeAssignment=(e,t)=>this.f.createExpressionStatement(this.f.createBinaryExpression(typeof e==`string`?this.makeId(e):e,this.f.createToken(this.ts.SyntaxKind.EqualsToken),t));makeIndexed=(e,t)=>this.f.createIndexedAccessTypeNode(this.ensureTypeNode(e),this.ensureTypeNode(t));makeMaybeAsync=e=>this.makeUnion([this.ensureTypeNode(e),this.makePromise(e)]);makeFnType=(e,t)=>this.f.createFunctionTypeNode(void 0,this.makeParams(e),this.ensureTypeNode(t));literally=e=>typeof e==`number`?this.f.createNumericLiteral(e):typeof e==`bigint`?this.f.createBigIntLiteral(e.toString()):typeof e==`boolean`?e?this.f.createTrue():this.f.createFalse():e===null?this.f.createNull():this.f.createStringLiteral(e);makeLiteralType=e=>this.f.createLiteralTypeNode(this.literally(e));isPrimitive=e=>this.#e.includes(e.kind)};const Z=e=>e;var dr=class{serverUrl;api;paths=new Set;tags=new Map;registry=new Map;constructor(e,t){this.serverUrl=t,this.api=new ur(e)}#e={pathType:`Path`,implementationType:`Implementation`,keyParameter:`key`,pathParameter:`path`,paramsArgument:`params`,ctxArgument:`ctx`,methodParameter:`method`,requestParameter:`request`,eventParameter:`event`,dataParameter:`data`,handlerParameter:`handler`,msgParameter:`msg`,parseRequestFn:`parseRequest`,substituteFn:`substitute`,provideMethod:`provide`,onMethod:`on`,implementationArgument:`implementation`,hasBodyConst:`hasBody`,undefinedValue:`undefined`,responseConst:`response`,restConst:`rest`,searchParamsConst:`searchParams`,defaultImplementationConst:`defaultImplementation`,clientConst:`client`,contentTypeConst:`contentType`,isJsonConst:`isJSON`,sourceProp:`source`,methodType:`Method`,someOfType:`SomeOf`,requestType:`Request`,paginationType:`Pagination`};interfaces={input:`Input`,positive:`PositiveResponse`,negative:`NegativeResponse`,encoded:`EncodedResponse`,response:`Response`};makeMethodType=()=>this.api.makePublicLiteralType(this.#e.methodType,le);makeSomeOfType=()=>this.api.makeType(this.#e.someOfType,this.api.makeIndexed(`T`,this.api.makeKeyOf(`T`)),{params:[`T`]});makeRequestType=()=>this.api.makeType(this.#e.requestType,this.api.makeKeyOf(this.interfaces.input),{expose:!0});someOf=({name:e})=>this.api.ensureTypeNode(this.#e.someOfType,[e]);makePathType=()=>this.api.makePublicLiteralType(this.#e.pathType,Array.from(this.paths));makePublicInterfaces=()=>Object.keys(this.interfaces).map(e=>this.api.makeInterface(this.interfaces[e],Array.from(this.registry).map(([t,{store:n,isDeprecated:r}])=>this.api.makeInterfaceProp(t,n[e],{isDeprecated:r})),{expose:!0}));makeEndpointTags=()=>this.api.makeConst(`endpointTags`,this.api.f.createObjectLiteralExpression(Array.from(this.tags).map(([e,t])=>this.api.f.createPropertyAssignment(this.api.makePropertyIdentifier(e),this.api.f.createArrayLiteralExpression(n.map(this.api.literally,t))))),{expose:!0});makeImplementationType=()=>this.api.makeType(this.#e.implementationType,this.api.makeFnType({[this.#e.methodParameter]:this.#e.methodType,[this.#e.pathParameter]:this.api.ts.SyntaxKind.StringKeyword,[this.#e.paramsArgument]:this.api.makeRecordStringAny(),[this.#e.ctxArgument]:{optional:!0,type:`T`}},this.api.makePromise(this.api.ts.SyntaxKind.AnyKeyword)),{expose:!0,params:{T:{init:this.api.ts.SyntaxKind.UnknownKeyword}}});makeParseRequestFn=()=>this.api.makeConst(this.#e.parseRequestFn,this.api.makeArrowFn({[this.#e.requestParameter]:this.api.ts.SyntaxKind.StringKeyword},this.api.f.createAsExpression(this.api.makeCall(this.#e.requestParameter,Z(`split`))(this.api.f.createRegularExpressionLiteral(`/ (.+)/`),this.api.literally(2)),this.api.f.createTupleTypeNode([this.api.ensureTypeNode(this.#e.methodType),this.api.ensureTypeNode(this.#e.pathType)]))));makeSubstituteFn=()=>this.api.makeConst(this.#e.substituteFn,this.api.makeArrowFn({[this.#e.pathParameter]:this.api.ts.SyntaxKind.StringKeyword,[this.#e.paramsArgument]:this.api.makeRecordStringAny()},this.api.f.createBlock([this.api.makeConst(this.#e.restConst,this.api.f.createObjectLiteralExpression([this.api.f.createSpreadAssignment(this.api.makeId(this.#e.paramsArgument))])),this.api.f.createForInStatement(this.api.f.createVariableDeclarationList([this.api.f.createVariableDeclaration(this.#e.keyParameter)],this.api.ts.NodeFlags.Const),this.api.makeId(this.#e.paramsArgument),this.api.f.createBlock([this.api.makeAssignment(this.#e.pathParameter,this.api.makeCall(this.#e.pathParameter,Z(`replace`))(this.api.makeTemplate(`:`,[this.#e.keyParameter]),this.api.makeArrowFn([],this.api.f.createBlock([this.api.f.createExpressionStatement(this.api.f.createDeleteExpression(this.api.f.createElementAccessExpression(this.api.makeId(this.#e.restConst),this.api.makeId(this.#e.keyParameter)))),this.api.f.createReturnStatement(this.api.f.createElementAccessExpression(this.api.makeId(this.#e.paramsArgument),this.api.makeId(this.#e.keyParameter)))]))))])),this.api.f.createReturnStatement(this.api.f.createAsExpression(this.api.f.createArrayLiteralExpression([this.api.makeId(this.#e.pathParameter),this.api.makeId(this.#e.restConst)]),this.api.ensureTypeNode(`const`)))])));makePaginationType=()=>{let e=Z(`nextCursor`),t=Z(`total`),n=Z(`limit`),r=Z(`offset`),i=this.api.f.createTypeLiteralNode([this.api.makeInterfaceProp(e,this.api.makeUnion([this.api.ensureTypeNode(this.api.ts.SyntaxKind.StringKeyword),this.api.makeLiteralType(null)]))]),a=this.api.f.createTypeLiteralNode([t,n,r].map(e=>this.api.makeInterfaceProp(e,this.api.ts.SyntaxKind.NumberKeyword)));return this.api.makeType(this.#e.paginationType,this.api.makeUnion([i,a]))};#t=()=>{let e=this.api.makeId(this.#e.responseConst),t=Z(`nextCursor`),n=Z(`total`),r=Z(`limit`),i=Z(`offset`),a=this.api.f.createBinaryExpression(this.api.literally(t),this.api.ts.SyntaxKind.InKeyword,e),o=this.api.f.createReturnStatement(this.api.f.createBinaryExpression(this.api.f.createPropertyAccessExpression(e,t),this.api.ts.SyntaxKind.ExclamationEqualsEqualsToken,this.api.literally(null))),s=this.api.f.createBinaryExpression(this.api.f.createPropertyAccessExpression(e,i),this.api.ts.SyntaxKind.PlusToken,this.api.f.createPropertyAccessExpression(e,r)),c=this.api.f.createReturnStatement(this.api.f.createBinaryExpression(s,this.api.ts.SyntaxKind.LessThanToken,this.api.f.createPropertyAccessExpression(e,n)));return this.api.makePublicMethod(`hasMore`,[this.api.makeParam(e,{type:this.#e.paginationType})],[this.api.f.createIfStatement(a,o),c],{returns:this.api.ensureTypeNode(this.api.ts.SyntaxKind.BooleanKeyword),isStatic:!0})};#n=()=>this.api.makePublicMethod(this.#e.provideMethod,this.api.makeParams({[this.#e.requestParameter]:`K`,[this.#e.paramsArgument]:this.api.makeIndexed(this.interfaces.input,`K`),[this.#e.ctxArgument]:{optional:!0,type:`T`}}),[this.api.makeConst(this.api.makeDeconstruction(this.#e.methodParameter,this.#e.pathParameter),this.api.makeCall(this.#e.parseRequestFn)(this.#e.requestParameter)),this.api.f.createReturnStatement(this.api.makeCall(this.api.f.createThis(),this.#e.implementationArgument)(this.#e.methodParameter,this.api.f.createSpreadElement(this.api.makeCall(this.#e.substituteFn)(this.#e.pathParameter,this.#e.paramsArgument)),this.#e.ctxArgument))],{typeParams:{K:this.#e.requestType},returns:this.api.makePromise(this.api.makeIndexed(this.interfaces.response,`K`))});makeClientClass=e=>this.api.makePublicClass(e,[this.api.makePublicConstructor([this.api.makeParam(this.#e.implementationArgument,{type:this.api.ensureTypeNode(this.#e.implementationType,[`T`]),mod:this.api.accessModifiers.protectedReadonly,initId:this.#e.defaultImplementationConst})]),this.#n(),this.#t()],{typeParams:[`T`]});#r=e=>this.api.makeTemplate(`?`,[this.api.makeNew(URLSearchParams.name,this.api.makeId(e))]);#i=()=>this.api.makeNew(URL.name,this.api.makeTemplate(``,[this.#e.pathParameter],[this.#e.searchParamsConst]),this.api.literally(this.serverUrl));makeDefaultImplementation=()=>{let e=this.api.f.createPropertyAssignment(Z(`method`),this.api.makeCall(this.#e.methodParameter,Z(`toUpperCase`))()),t=this.api.f.createPropertyAssignment(Z(`headers`),this.api.makeTernary(this.#e.hasBodyConst,this.api.f.createObjectLiteralExpression([this.api.f.createPropertyAssignment(this.api.literally(`Content-Type`),this.api.literally(y.json))]),this.#e.undefinedValue)),n=this.api.f.createPropertyAssignment(Z(`body`),this.api.makeTernary(this.#e.hasBodyConst,this.api.makeCall(JSON[Symbol.toStringTag],Z(`stringify`))(this.#e.paramsArgument),this.#e.undefinedValue)),r=this.api.makeConst(this.#e.responseConst,this.api.f.createAwaitExpression(this.api.makeCall(fetch.name)(this.#i(),this.api.f.createObjectLiteralExpression([e,t,n])))),i=this.api.makeConst(this.#e.hasBodyConst,this.api.f.createLogicalNot(this.api.makeCall(this.api.f.createArrayLiteralExpression([this.api.literally(`get`),this.api.literally(`head`),this.api.literally(`delete`)]),Z(`includes`))(this.#e.methodParameter))),a=this.api.makeConst(this.#e.searchParamsConst,this.api.makeTernary(this.#e.hasBodyConst,this.api.literally(``),this.#r(this.#e.paramsArgument))),o=this.api.makeConst(this.#e.contentTypeConst,this.api.makeCall(this.#e.responseConst,Z(`headers`),Z(`get`))(this.api.literally(`content-type`))),s=this.api.f.createIfStatement(this.api.f.createPrefixUnaryExpression(this.api.ts.SyntaxKind.ExclamationToken,this.api.makeId(this.#e.contentTypeConst)),this.api.f.createReturnStatement()),c=this.api.makeConst(this.#e.isJsonConst,this.api.makeCall(this.#e.contentTypeConst,Z(`startsWith`))(this.api.literally(y.json))),l=this.api.f.createReturnStatement(this.api.makeCall(this.#e.responseConst,this.api.makeTernary(this.#e.isJsonConst,this.api.literally(Z(`json`)),this.api.literally(Z(`text`))))());return this.api.makeConst(this.#e.defaultImplementationConst,this.api.makeArrowFn([this.#e.methodParameter,this.#e.pathParameter,this.#e.paramsArgument],this.api.f.createBlock([i,a,r,o,s,c,l]),{isAsync:!0}),{type:this.#e.implementationType})};#a=()=>this.api.makePublicConstructor(this.api.makeParams({request:`K`,params:this.api.makeIndexed(this.interfaces.input,`K`)}),[this.api.makeConst(this.api.makeDeconstruction(this.#e.pathParameter,this.#e.restConst),this.api.makeCall(this.#e.substituteFn)(this.api.f.createElementAccessExpression(this.api.makeCall(this.#e.parseRequestFn)(this.#e.requestParameter),this.api.literally(1)),this.#e.paramsArgument)),this.api.makeConst(this.#e.searchParamsConst,this.#r(this.#e.restConst)),this.api.makeAssignment(this.api.f.createPropertyAccessExpression(this.api.f.createThis(),this.#e.sourceProp),this.api.makeNew(`EventSource`,this.#i()))]);#o=e=>this.api.f.createTypeLiteralNode([this.api.makeInterfaceProp(Z(`event`),e)]);#s=()=>this.api.makePublicMethod(this.#e.onMethod,this.api.makeParams({[this.#e.eventParameter]:`E`,[this.#e.handlerParameter]:this.api.makeFnType({[this.#e.dataParameter]:this.api.makeIndexed(this.api.makeExtract(`R`,this.api.makeOneLine(this.#o(`E`))),this.api.makeLiteralType(Z(`data`)))},this.api.makeMaybeAsync(this.api.ts.SyntaxKind.VoidKeyword))}),[this.api.f.createExpressionStatement(this.api.makeCall(this.api.f.createThis(),this.#e.sourceProp,Z(`addEventListener`))(this.#e.eventParameter,this.api.makeArrowFn([this.#e.msgParameter],this.api.makeCall(this.#e.handlerParameter)(this.api.makeCall(JSON[Symbol.toStringTag],Z(`parse`))(this.api.f.createPropertyAccessExpression(this.api.f.createParenthesizedExpression(this.api.f.createAsExpression(this.api.makeId(this.#e.msgParameter),this.api.ensureTypeNode(MessageEvent.name))),Z(`data`))))))),this.api.f.createReturnStatement(this.api.f.createThis())],{typeParams:{E:this.api.makeIndexed(`R`,this.api.makeLiteralType(Z(`event`)))}});makeSubscriptionClass=e=>this.api.makePublicClass(e,[this.api.makePublicProperty(this.#e.sourceProp,`EventSource`),this.#a(),this.#s()],{typeParams:{K:this.api.makeExtract(this.#e.requestType,this.api.f.createTemplateLiteralType(this.api.f.createTemplateHead(`get `),[this.api.f.createTemplateLiteralTypeSpan(this.api.ensureTypeNode(this.api.ts.SyntaxKind.StringKeyword),this.api.f.createTemplateTail(``))])),R:this.api.makeExtract(this.api.makeIndexed(this.interfaces.positive,`K`),this.api.makeOneLine(this.#o(this.api.ts.SyntaxKind.StringKeyword)))}});makeUsageStatements=(e,t)=>[this.api.makeConst(this.#e.clientConst,this.api.makeNew(e)),this.api.makeCall(this.#e.clientConst,this.#e.provideMethod)(this.api.literally(`get /v1/user/retrieve`),this.api.f.createObjectLiteralExpression([this.api.f.createPropertyAssignment(`id`,this.api.literally(`10`))])),this.api.makeCall(this.api.makeNew(t,this.api.literally(`get /v1/events/stream`),this.api.f.createObjectLiteralExpression()),this.#e.onMethod)(this.api.literally(`time`),this.api.makeArrowFn([`time`],this.api.f.createBlock([])))]};const fr=(e,{rules:t,onMissing:n,ctx:r={}})=>{let i=O(e),a=i&&i in t?t[i]:t[e._zod.def.type],o=e=>fr(e,{ctx:r,rules:t,onMissing:n});return a?a(e,{...r,next:o}):n(e,r)},pr={name:n.path([`name`,`text`]),type:n.path([`type`]),optional:n.path([`questionToken`])},mr=({_zod:{def:e}},{api:t})=>{let n=e.values.map(e=>e===void 0?t.ensureTypeNode(t.ts.SyntaxKind.UndefinedKeyword):t.makeLiteralType(e));return n.length===1?n[0]:t.makeUnion(n)},hr=({_zod:{def:e}},{next:t,api:n})=>{let{parts:r}=e,i=0,a=()=>{let e=``;for(;i<r.length;){let t=r[i];if(C(t))break;i++,e+=t??``}return e},o=n.f.createTemplateHead(a()),s=[];for(;i<r.length;){let e=t(r[i++]),o=a(),c=i<r.length?n.f.createTemplateMiddle:n.f.createTemplateTail;s.push(n.f.createTemplateLiteralTypeSpan(e,c(o)))}return s.length?n.f.createTemplateLiteralType(o,s):n.makeLiteralType(o.text)},gr=(n,{isResponse:r,next:i,makeAlias:a,api:o})=>{let s=()=>{let a=Object.entries(n._zod.def.shape).map(([n,a])=>{let{description:s,deprecated:c}=e.get(a)||{},l=(r?a._zod.optout:a._zod.optin)===`optional`,u=l&&!(a instanceof t.core.$ZodExactOptional);return o.makeInterfaceProp(n,i(a),{comment:s,isDeprecated:c,isOptional:l,hasUndefined:u})});return o.f.createTypeLiteralNode(a)};return Re(n,{io:r?`output`:`input`})?a(n,s):s()},_r=({_zod:{def:e}},{next:t,api:n})=>n.f.createArrayTypeNode(t(e.element)),vr=({_zod:{def:e}},{api:t})=>t.makeUnion(n.map(t.makeLiteralType,Object.values(e.entries))),yr=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion(e.options.map(t)),br=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion([t(e.innerType),n.makeLiteralType(null)]),xr=({_zod:{def:e}},{next:t,api:n})=>n.f.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:n.f.createRestTypeNode(t(e.rest)))),Sr=({_zod:{def:e}},{next:t,api:n})=>{let[r,i]=[e.keyType,e.valueType].map(t),a=n.ensureTypeNode(`Record`,[r,i]);return e.mode===`loose`?n.f.createIntersectionTypeNode([a,n.ensureTypeNode(`Record`,[`PropertyKey`,i])]):a},Cr=n.tryCatch((e,t)=>{if(!t.every(e.ts.isTypeLiteralNode))throw Error(`Not objects`);let r=n.chain(n.prop(`members`),t),i=n.uniqWith((...e)=>{if(!n.eqBy(pr.name,...e))return!1;if(n.both(n.eqBy(pr.type),n.eqBy(pr.optional))(...e))return!0;throw Error(`Has conflicting prop`)},r);return e.f.createTypeLiteralNode(i)},(e,t,n)=>t.f.createIntersectionTypeNode(n)),wr=({_zod:{def:e}},{next:t,api:n})=>Cr(n,[e.left,e.right].map(t)),Q=e=>({},{api:t})=>t.ensureTypeNode(t.ts.SyntaxKind[e]),$=({_zod:{def:e}},{next:t})=>t(e.innerType),Tr=(e,t)=>e.ensureTypeNode(t?e.ts.SyntaxKind.UnknownKeyword:e.ts.SyntaxKind.AnyKeyword),Er=({_zod:{def:e}},{next:t,isResponse:n,api:r})=>{let i=e[n?`out`:`in`],a=e[n?`in`:`out`];if(!C(i,`transform`))return t(i);let o=t(a),s={[r.ts.SyntaxKind.AnyKeyword]:``,[r.ts.SyntaxKind.BigIntKeyword]:BigInt(0),[r.ts.SyntaxKind.BooleanKeyword]:!1,[r.ts.SyntaxKind.NumberKeyword]:0,[r.ts.SyntaxKind.ObjectKeyword]:{},[r.ts.SyntaxKind.StringKeyword]:``,[r.ts.SyntaxKind.UndefinedKeyword]:void 0}[o.kind],c=be(i,s),l={number:r.ts.SyntaxKind.NumberKeyword,bigint:r.ts.SyntaxKind.BigIntKeyword,boolean:r.ts.SyntaxKind.BooleanKeyword,string:r.ts.SyntaxKind.StringKeyword,undefined:r.ts.SyntaxKind.UndefinedKeyword,object:r.ts.SyntaxKind.ObjectKeyword};return r.ensureTypeNode(c&&l[c]||Tr(r,n))},Dr=({},{api:e})=>e.makeLiteralType(null),Or=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),kr=({},{api:e})=>e.ensureTypeNode(`Buffer`),Ar=(e,{next:t})=>t(e._zod.def.shape.raw),jr={string:Q(`StringKeyword`),number:Q(`NumberKeyword`),bigint:Q(`BigIntKeyword`),boolean:Q(`BooleanKeyword`),any:Q(`AnyKeyword`),undefined:Q(`UndefinedKeyword`),[j]:Q(`StringKeyword`),[M]:Q(`StringKeyword`),never:Q(`NeverKeyword`),void:Q(`UndefinedKeyword`),unknown:Q(`UnknownKeyword`),null:Dr,array:_r,tuple:xr,record:Sr,object:gr,literal:mr,template_literal:hr,intersection:wr,union:yr,default:$,enum:vr,optional:$,nonoptional:$,nullable:br,catch:$,pipe:Er,lazy:Or,readonly:$,[A]:kr,[R]:Ar},Mr=(e,{brandHandling:t,ctx:n})=>fr(e,{rules:{...t,...jr},onMissing:({},{isResponse:e,api:t})=>Tr(t,e),ctx:n});var Nr=class e extends dr{#e=[this.makeSomeOfType()];#t=new Map;#n=[];#r(e,t){let n=this.#t.get(e)?.name?.text;if(!n){n=`Type${this.#t.size+1}`;let r=this.api.makeLiteralType(null);this.#t.set(e,this.api.makeType(n,r)),this.#t.set(e,this.api.makeType(n,t()))}return this.api.ensureTypeNode(n)}constructor({typescript:e,routing:r,config:i,brandHandling:a,variant:o=`client`,clientClassName:s=`Client`,subscriptionClassName:c=`Subscription`,serverUrl:l=`https://example.com`,noBodySchema:u=t.undefined(),hasHeadMethod:d=!0}){super(e,l);let f={makeAlias:this.#r.bind(this),api:this.api},p={brandHandling:a,ctx:{...f,isResponse:!1}},m={brandHandling:a,ctx:{...f,isResponse:!0}},h=(e,t,r)=>{let i=T.bind(null,e,t),{isDeprecated:a,inputSchema:o,tags:s}=r,c=`${e} ${t}`,l=this.api.makeType(i(`input`),Mr(o,p),{comment:c});this.#e.push(l);let d=Qe.reduce((t,a)=>{let o=r.getResponses(a),s=n.chain(([t,{schema:n,mimeTypes:r,statusCodes:o}])=>{let s=Se(e,r),l=this.api.makeType(i(a,`variant`,`${t+1}`),Mr(s?n:u,m),{comment:c});return this.#e.push(l),o.map(e=>this.api.makeInterfaceProp(e,l.name))},Array.from(o.entries())),l=this.api.makeInterface(i(a,`response`,`variants`),s,{comment:c});return this.#e.push(l),Object.assign(t,{[a]:l})},{});this.paths.add(t);let f=this.api.makeLiteralType(c),h={input:this.api.ensureTypeNode(l.name),positive:this.someOf(d.positive),negative:this.someOf(d.negative),response:this.api.makeUnion([this.api.makeIndexed(this.interfaces.positive,f),this.api.makeIndexed(this.interfaces.negative,f)]),encoded:this.api.f.createIntersectionTypeNode([this.api.ensureTypeNode(d.positive.name),this.api.ensureTypeNode(d.negative.name)])};this.registry.set(c,{isDeprecated:a,store:h}),this.tags.set(c,s)};It({routing:r,config:i,onEndpoint:d?kt(h):h}),this.#e.unshift(...this.#t.values()),this.#e.push(this.makePathType(),this.makeMethodType(),...this.makePublicInterfaces(),this.makeRequestType()),o!==`types`&&(this.#e.push(this.makeEndpointTags(),this.makeParseRequestFn(),this.makeSubstituteFn(),this.makeImplementationType(),this.makePaginationType(),this.makeDefaultImplementation(),this.makeClientClass(s),this.makeSubscriptionClass(c)),this.#n.push(...this.makeUsageStatements(s,c)))}static async create(t){return new e({...t,typescript:await J(`typescript`)})}#i(e){return this.#n.length?this.#n.map(t=>typeof t==`string`?t:this.api.printNode(t,e)).join(`
|
|
18
18
|
`):void 0}print(e){let t=this.#i(e),n=t&&this.api.ts.addSyntheticLeadingComment(this.api.ts.addSyntheticLeadingComment(this.api.f.createEmptyStatement(),this.api.ts.SyntaxKind.SingleLineCommentTrivia,` Usage example:`),this.api.ts.SyntaxKind.MultiLineCommentTrivia,`\n${t}`);return this.#e.concat(n||[]).map((t,n)=>this.api.printNode(t,n<this.#e.length?e:{...e,omitTrailingSemicolon:!0})).join(`
|
|
19
19
|
|
|
20
|
-
`)}async printFormatted({printerOptions:e,format:t}={}){let n=t;if(!n)try{let e=(await J(`prettier`)).format;n=t=>e(t,{filepath:`client.ts`})}catch{}let r=this.#i(e);this.#n=r&&n?[await n(r)]:this.#n;let i=this.print(e);return n?n(i):i}};const
|
|
21
|
-
`)).parse({event:t,data:n}),
|
|
20
|
+
`)}async printFormatted({printerOptions:e,format:t}={}){let n=t;if(!n)try{let e=(await J(`prettier`)).format;n=t=>e(t,{filepath:`client.ts`})}catch{}let r=this.#i(e);this.#n=r&&n?[await n(r)]:this.#n;let i=this.print(e);return n?n(i):i}};const Pr=(e,n)=>t.object({data:n,event:t.literal(e),id:t.string().optional(),retry:t.int().positive().optional()}),Fr=(e,t,n)=>Pr(String(t),e[t]).transform(e=>[`event: ${e.event}`,`data: ${JSON.stringify(e.data)}`,``,``].join(`
|
|
21
|
+
`)).parse({event:t,data:n}),Ir=e=>e.headersSent||e.writeHead(200,{connection:`keep-alive`,"content-type":y.sse,"cache-control":`no-cache`}),Lr=e=>new V({handler:async({request:t,response:n})=>{let r=new AbortController;return t.once(`close`,()=>{r.abort()}),setTimeout(()=>Ir(n),1e4),{isClosed:()=>n.writableEnded||n.closed,signal:r.signal,emit:(t,r)=>{Ir(n),n.write(Fr(e,t,r),`utf-8`),n.flush?.()}}}}),Rr=e=>new U({positive:()=>{let[n,...r]=Object.entries(e).map(([e,t])=>Pr(e,t));if(!n)throw new I(Error(`At least one SSE event is required.`));return{mimeType:y.sse,schema:r.length?t.discriminatedUnion(`event`,[n,...r]):n}},negative:{mimeType:`text/plain`,schema:t.string()},handler:async({response:e,error:t,logger:n,request:r,input:i})=>{if(t){let a=z(t);Ue(a,n,r,i),e.headersSent||e.status(a.statusCode).type(`text/plain`).write(B(a),`utf-8`)}e.end()}});var zr=class extends G{constructor(e){super(Rr(e)),this.middlewares=[Lr(e)]}};const Br=[`total`,`limit`,`offset`],Vr=[`nextCursor`,`limit`];function Hr({style:e,itemSchema:n,itemsName:r=`items`,maxLimit:i=100,defaultLimit:a=20}){if(!Number.isInteger(i)||i<1)throw Error(`ez.paginated: maxLimit must be a positive integer`);if(!Number.isInteger(a)||a<1)throw Error(`ez.paginated: defaultLimit must be a positive integer`);if(a>i)throw Error(`ez.paginated: defaultLimit must not be greater than maxLimit`);if(e===`offset`&&Br.includes(r))throw Error(`ez.paginated: itemsName must not match reserved keys for offset output (${Br.join(`, `)})`);if(e===`cursor`&&Vr.includes(r))throw Error(`ez.paginated: itemsName must not match reserved keys for cursor output (${Vr.join(`, `)})`);let o=t.coerce.number().int().min(1).max(i).default(a).describe(`Page size (number of ${r} per page)`);if(e===`offset`){let e=t.coerce.number().int().min(0).default(0).describe(`Number of ${r} to skip`);return{input:t.object({limit:o,offset:e}),output:t.object({[r]:t.array(n).describe(`Page of ${r}`),total:t.number().int().min(0).describe(`Total number of ${r}`),limit:t.number().int().min(1).describe(`Page size used`),offset:t.number().int().min(0).describe(`Offset used`)})}}let s=t.string().optional().describe(`Cursor for the next page; omit for first page`);return{input:t.object({cursor:s,limit:o}),output:t.object({[r]:t.array(n).describe(`Page of ${r}`),nextCursor:t.string().nullable().describe(`Cursor for the next page, or null if no more pages`),limit:t.number().int().min(1).describe(`Page size used`)})}}const Ur={dateIn:we,dateOut:Te,form:je,upload:Ne,raw:Ie,buffer:Ce,paginated:Hr};export{gt as BuiltinLogger,rr as Documentation,P as DocumentationError,G as EndpointsFactory,zr as EventStreamFactory,F as InputValidationError,Nr as Integration,V as Middleware,ke as MissingPeerError,Oe as OutputValidationError,U as ResultHandler,N as RoutingError,_t as ServeStatic,ut as arrayEndpointsFactory,nt as arrayResultHandler,ln as attachRouting,st as createCacheMiddleware,se as createConfig,ct as createCookieMiddleware,un as createServer,lt as defaultEndpointsFactory,W as defaultResultHandler,z as ensureHttpError,Ur as ez,S as getMessageFromError,cr as testEndpoint,lr as testMiddleware};
|
package/package.json
CHANGED