express-zod-api 27.2.2 → 28.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/README.md +32 -17
- package/SECURITY.md +1 -0
- package/dist/index.d.ts +58 -71
- package/dist/index.js +5 -6
- package/package.json +12 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Version 28
|
|
4
|
+
|
|
5
|
+
### v28.0.0
|
|
6
|
+
|
|
7
|
+
- Supported Node.js versions: `^22.19.0 || ^24.0.0`;
|
|
8
|
+
- The Zod plugin is no longer installed automatically — it's an optional peer dependency now:
|
|
9
|
+
- To keep using `.example()`, `.label()`, `.remap()`, `.deprecated()` and `.brand()` methods on schemas
|
|
10
|
+
install the `@express-zod-api/zod-plugin` manually and import it (ideally at the top of a file declaring `Routing`);
|
|
11
|
+
- Breaking changes to the `createConfig()` argument (object):
|
|
12
|
+
- property `wrongMethodBehavior` (number) changed to `hintAllowedMethods` (boolean);
|
|
13
|
+
- property `methodLikeRouteBehavior` (string literal) changed to `recognizeMethodDependentRoutes` (boolean);
|
|
14
|
+
- Breaking change to the `EndpointsFactory::build()` argument (object):
|
|
15
|
+
- property `shortDescription` renamed to `summary`;
|
|
16
|
+
- Breaking change to the `Documentation` constructor argument (object):
|
|
17
|
+
- property `hasSummaryFromDescription` (boolean) replaced with `summarizer` (function);
|
|
18
|
+
- If used with `false` value, replace it with `summarizer: ({ summary, trim }) => trim(summary)` for same behavior;
|
|
19
|
+
- Featuring `summarizer` option to customize the summary of the Endpoint in the generated Documentation:
|
|
20
|
+
- The function receives `summary`, `description` and the default `trim()` function as arguments;
|
|
21
|
+
- The default summarizer uses `description` as a fallback for missing `summary`;
|
|
22
|
+
- The `trim()` function accepts a string and the limit (default: 50, best practice) that you can now customize;
|
|
23
|
+
- Breaking change to the `Integration` constructor argument (object):
|
|
24
|
+
- property `noContent` renamed to `noBodySchema`;
|
|
25
|
+
- Consider using [the automated migration](https://www.npmjs.com/package/@express-zod-api/migration).
|
|
26
|
+
|
|
27
|
+
```diff
|
|
28
|
+
createConfig({
|
|
29
|
+
- wrongMethodBehavior: 404,
|
|
30
|
+
+ hintAllowedMethods: false,
|
|
31
|
+
- methodLikeRouteBehavior: "path",
|
|
32
|
+
+ recognizeMethodDependentRoutes: false,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
factory.build({
|
|
36
|
+
- shortDescription: "Retrieves the user.",
|
|
37
|
+
+ summary: "Retrieves the user.",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
new Documentation({
|
|
41
|
+
- hasSummaryFromDescription: false,
|
|
42
|
+
+ summarizer: ({ summary, trim }) => trim(summary),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
new Integration({
|
|
46
|
+
- noContent: z.undefined(),
|
|
47
|
+
+ noBodySchema: z.undefined(),
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
3
51
|
## Version 27
|
|
4
52
|
|
|
5
53
|
### v27.2.2
|
package/README.md
CHANGED
|
@@ -164,7 +164,7 @@ Much can be customized to fit your needs.
|
|
|
164
164
|
|
|
165
165
|
- [Typescript](https://www.typescriptlang.org/) first.
|
|
166
166
|
- Web server — [Express.js](https://expressjs.com/) v5.
|
|
167
|
-
- Schema validation — [Zod 4.x](https://github.com/colinhacks/zod)
|
|
167
|
+
- Schema validation — [Zod 4.x](https://github.com/colinhacks/zod)
|
|
168
168
|
- For using with Zod 3.x, install the framework versions below 24.0.0.
|
|
169
169
|
- Supports any logger having `info()`, `debug()`, `error()` and `warn()` methods;
|
|
170
170
|
- Built-in console logger with colorful and pretty inspections by default.
|
|
@@ -243,7 +243,7 @@ const helloWorldEndpoint = defaultEndpointsFactory.build({
|
|
|
243
243
|
Connect your endpoint to the `/v1/hello` route:
|
|
244
244
|
|
|
245
245
|
```ts
|
|
246
|
-
import { Routing } from "express-zod-api";
|
|
246
|
+
import type { Routing } from "express-zod-api";
|
|
247
247
|
|
|
248
248
|
const routing: Routing = {
|
|
249
249
|
v1: {
|
|
@@ -920,7 +920,7 @@ it normalizes errors into consistent HTTP responses with sensible status codes.
|
|
|
920
920
|
- Routing, parsing and upload issues:
|
|
921
921
|
- Handled by `ResultHandler` configured as `errorHandler` (the defaults is `defaultResultHandler`);
|
|
922
922
|
- Parsing errors: passed through as-is (typically `HttpError` with `4XX` code used for response by default);
|
|
923
|
-
- Routing errors: `404` or `405`, based on `
|
|
923
|
+
- Routing errors: `404` or `405`, based on `hintAllowedMethods` configuration;
|
|
924
924
|
- Upload issues: thrown only if `upload.limitError` is configured (`HttpError::statusCode` can be used for response);
|
|
925
925
|
- For other errors the default status code is `500`;
|
|
926
926
|
- `ResultHandler` failures:
|
|
@@ -1100,8 +1100,21 @@ expect(output).toEqual({ collectedContext: ["prev"], testLength: 9 });
|
|
|
1100
1100
|
|
|
1101
1101
|
## Zod Plugin
|
|
1102
1102
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1103
|
+
The [@express-zod-api/zod-plugin](https://www.npmjs.com/package/@express-zod-api/zod-plugin) is an optional package
|
|
1104
|
+
that extends Zod with convenience methods:
|
|
1105
|
+
|
|
1106
|
+
- `.brand(name)` — enhanced with a shorthand for `.meta({ "x-brand": name })`;
|
|
1107
|
+
- `.example(value)` — shorthand for `.meta({ examples: [value] })`;
|
|
1108
|
+
- `.deprecated()` — shorthand for `.meta({ deprecated: true })`;
|
|
1109
|
+
- `.label(text)` — shorthand for `.meta({ default: text })` on `ZodDefault`;
|
|
1110
|
+
- `.remap(mapping)` — for renaming `ZodObject` shape properties;
|
|
1111
|
+
|
|
1112
|
+
To benefit from these methods, install `@express-zod-api/zod-plugin` and import it once, preferably at the top of a
|
|
1113
|
+
file declaring your `Routing`.
|
|
1114
|
+
|
|
1115
|
+
```ts
|
|
1116
|
+
import "@express-zod-api/zod-plugin"; // in your routing.ts file
|
|
1117
|
+
```
|
|
1105
1118
|
|
|
1106
1119
|
## End-to-End Type Safety
|
|
1107
1120
|
|
|
@@ -1162,12 +1175,12 @@ in the generated documentation of your API. Consider the following example:
|
|
|
1162
1175
|
import { defaultEndpointsFactory } from "express-zod-api";
|
|
1163
1176
|
|
|
1164
1177
|
const exampleEndpoint = defaultEndpointsFactory.build({
|
|
1165
|
-
|
|
1178
|
+
summary: "Retrieves the user.",
|
|
1166
1179
|
description: "The detailed explanaition on what this endpoint does.",
|
|
1167
1180
|
input: z.object({
|
|
1168
1181
|
id: z
|
|
1169
|
-
.string()
|
|
1170
|
-
.example("123") //
|
|
1182
|
+
.string() // input examples should be set before transformations
|
|
1183
|
+
.example("123") // requires Zod Plugin, or .meta({ examples: ["123"] })
|
|
1171
1184
|
.transform(Number)
|
|
1172
1185
|
.describe("the ID of the user"),
|
|
1173
1186
|
}),
|
|
@@ -1175,7 +1188,8 @@ const exampleEndpoint = defaultEndpointsFactory.build({
|
|
|
1175
1188
|
});
|
|
1176
1189
|
```
|
|
1177
1190
|
|
|
1178
|
-
You can also use
|
|
1191
|
+
Setting examples via `.example()` requires [Zod Plugin](#zod-plugin). You can also use `.meta({ examples: [] })` and
|
|
1192
|
+
`.meta({ id: "UniqueName" })` for custom schema naming.
|
|
1179
1193
|
_See the complete example of the generated documentation
|
|
1180
1194
|
[here](https://github.com/RobinTail/express-zod-api/blob/master/example/example.documentation.yaml)_
|
|
1181
1195
|
|
|
@@ -1213,18 +1227,18 @@ new Documentation({
|
|
|
1213
1227
|
|
|
1214
1228
|
## Deprecated schemas and routes
|
|
1215
1229
|
|
|
1216
|
-
As your API evolves, you may need to mark some parameters or routes as deprecated before deleting them.
|
|
1217
|
-
|
|
1218
|
-
|
|
1230
|
+
As your API evolves, you may need to mark some parameters or routes as deprecated before deleting them. This can be
|
|
1231
|
+
achieved using the corresponding method or metadata. The `.deprecated()` method on Zod schema requires to install the
|
|
1232
|
+
[Zod Plugin](#zod-plugin). Consider the following example:
|
|
1219
1233
|
|
|
1220
1234
|
```ts
|
|
1221
|
-
import { Routing } from "express-zod-api";
|
|
1235
|
+
import type { Routing } from "express-zod-api";
|
|
1222
1236
|
import { z } from "zod";
|
|
1223
1237
|
|
|
1224
1238
|
const someEndpoint = factory.build({
|
|
1225
1239
|
deprecated: true, // deprecates all routes the endpoint assigned to
|
|
1226
1240
|
input: z.object({
|
|
1227
|
-
prop: z.string().deprecated(), //
|
|
1241
|
+
prop: z.string().deprecated(), // requires Zod Plugin, or .meta({ deprecated: true })
|
|
1228
1242
|
}),
|
|
1229
1243
|
});
|
|
1230
1244
|
|
|
@@ -1236,8 +1250,9 @@ const routing: Routing = {
|
|
|
1236
1250
|
|
|
1237
1251
|
## Customizable brands handling
|
|
1238
1252
|
|
|
1239
|
-
You can customize handling rules for your schemas in Documentation and Integration.
|
|
1240
|
-
|
|
1253
|
+
You can customize handling rules for your schemas in Documentation and Integration. The framework treats your schema
|
|
1254
|
+
specially based on its `x-brand` metadata. When the [Zod Plugin](#zod-plugin) is installed you can conveniently use
|
|
1255
|
+
the `.brand()` enhanced method of the Zod schema, preferably with a symbol argument for its branding.
|
|
1241
1256
|
After that use the `brandHandling` feature of both constructors to declare your custom implementation. In case you need
|
|
1242
1257
|
to reuse a handling rule for multiple brands, use the exposed types `Depicter` and `Producer`.
|
|
1243
1258
|
|
|
@@ -1252,7 +1267,7 @@ import {
|
|
|
1252
1267
|
} from "express-zod-api";
|
|
1253
1268
|
|
|
1254
1269
|
const myBrand = Symbol("MamaToldMeImSpecial"); // I recommend to use symbols for this purpose
|
|
1255
|
-
const myBrandedSchema = z.string().brand(myBrand);
|
|
1270
|
+
const myBrandedSchema = z.string().brand(myBrand); // requires Zod Plugin, or .meta({ "x-brand": myBrand })
|
|
1256
1271
|
|
|
1257
1272
|
const ruleForDocs: Depicter = (
|
|
1258
1273
|
{ zodSchema, jsonSchema }, // jsonSchema is the default depiction
|
package/SECURITY.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Code name | Release | Supported |
|
|
6
6
|
| ------: | :------------ | :------ | :----------------: |
|
|
7
|
+
| 28.x.x | Koko | 04.2026 | :white_check_mark: |
|
|
7
8
|
| 27.x.x | Nikki | 02.2026 | :white_check_mark: |
|
|
8
9
|
| 26.x.x | Lia | 12.2025 | :white_check_mark: |
|
|
9
10
|
| 25.x.x | Sara | 08.2025 | :white_check_mark: |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "@express-zod-api/zod-plugin";
|
|
2
1
|
import * as _$zod from "zod";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import { HttpError } from "http-errors";
|
|
@@ -388,7 +387,7 @@ type GetLogger = (request?: Request) => ActualLogger;
|
|
|
388
387
|
* @example { "get /v1/books/:bookId": getBookEndpoint }
|
|
389
388
|
* @example { v1: { "patch /books/:bookId": changeBookEndpoint } }
|
|
390
389
|
* @example { dependsOnMethod: { get: retrieveEndpoint, post: createEndpoint } }
|
|
391
|
-
* @see CommonConfig.
|
|
390
|
+
* @see CommonConfig.recognizeMethodDependentRoutes
|
|
392
391
|
* */
|
|
393
392
|
interface Routing {
|
|
394
393
|
[K: string]: Routing | AbstractEndpoint | ServeStatic;
|
|
@@ -422,7 +421,7 @@ declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, CTX extends Fl
|
|
|
422
421
|
handler: Handler<z.output<IN>, z.input<OUT>, CTX>;
|
|
423
422
|
resultHandler: AbstractResultHandler;
|
|
424
423
|
description?: string;
|
|
425
|
-
|
|
424
|
+
summary?: string;
|
|
426
425
|
getOperationId?: (method: ClientMethod) => string | undefined;
|
|
427
426
|
methods?: Method[];
|
|
428
427
|
scopes?: string[];
|
|
@@ -461,20 +460,21 @@ interface CommonConfig {
|
|
|
461
460
|
*/
|
|
462
461
|
cors: boolean | HeadersProvider;
|
|
463
462
|
/**
|
|
464
|
-
* @desc
|
|
465
|
-
* @example
|
|
466
|
-
* @example
|
|
467
|
-
* @default
|
|
468
|
-
|
|
469
|
-
|
|
463
|
+
* @desc Controls how to respond to a request to an existing endpoint with an invalid HTTP method.
|
|
464
|
+
* @example true — respond with status code 405 and "Allow" header containing a list of valid methods
|
|
465
|
+
* @example false — respond with status code 404 (Not found)
|
|
466
|
+
* @default true
|
|
467
|
+
*/
|
|
468
|
+
hintAllowedMethods?: boolean;
|
|
470
469
|
/**
|
|
471
|
-
* @desc
|
|
472
|
-
* @
|
|
473
|
-
*
|
|
474
|
-
* @example
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
|
|
470
|
+
* @desc Controls how to treat Routing keys matching HTTP methods ("get", "post") and having Endpoint assigned.
|
|
471
|
+
* @example true — treat such keys as HTTP methods complementing their parent paths
|
|
472
|
+
* { users: { get: ... }} becomes GET /users
|
|
473
|
+
* @example false — treat such keys as nested path segments regardless of the name
|
|
474
|
+
* { users: { get: ... }} remains /users/get
|
|
475
|
+
* @default true
|
|
476
|
+
*/
|
|
477
|
+
recognizeMethodDependentRoutes?: boolean;
|
|
478
478
|
/**
|
|
479
479
|
* @desc The ResultHandler to use for handling routing, parsing and upload errors
|
|
480
480
|
* @default defaultResultHandler
|
|
@@ -651,10 +651,10 @@ interface BuildProps<
|
|
|
651
651
|
output: OUT;
|
|
652
652
|
/** @desc The Endpoint handler receiving the validated inputs, returns of added Middlewares (ctx) and a logger */
|
|
653
653
|
handler: Handler<z.output<FinalInputSchema<MIN, IN>>, z.input<OUT>, CTX>;
|
|
654
|
-
/** @desc The operation description for the generated Documentation */
|
|
654
|
+
/** @desc The operation description for the generated Documentation (may use Markdown) */
|
|
655
655
|
description?: string;
|
|
656
|
-
/** @desc The operation summary for the generated Documentation (
|
|
657
|
-
|
|
656
|
+
/** @desc The operation summary for the generated Documentation (short plain string) */
|
|
657
|
+
summary?: string;
|
|
658
658
|
/** @desc The operation ID for the generated Documentation (must be unique) */
|
|
659
659
|
operationId?: string | ((method: ClientMethod) => string);
|
|
660
660
|
/**
|
|
@@ -779,6 +779,8 @@ declare const depictTags: (
|
|
|
779
779
|
>
|
|
780
780
|
>,
|
|
781
781
|
) => TagObject[];
|
|
782
|
+
/** @desc Ensures the summary string does not exceed the limit */
|
|
783
|
+
declare const trimSummary: (summary?: string, limit?: number) => string | undefined;
|
|
782
784
|
type Component = "positiveResponse" | "negativeResponse" | "requestParameter" | "requestBody";
|
|
783
785
|
/** @desc user defined function that creates a component description from its properties */
|
|
784
786
|
type Descriptor = (
|
|
@@ -786,6 +788,7 @@ type Descriptor = (
|
|
|
786
788
|
statusCode?: number;
|
|
787
789
|
},
|
|
788
790
|
) => string;
|
|
791
|
+
type Summarizer = (params: { summary?: string; description?: string; trim: typeof trimSummary }) => string | undefined;
|
|
789
792
|
interface DocumentationParams {
|
|
790
793
|
title: string;
|
|
791
794
|
version: string;
|
|
@@ -798,8 +801,12 @@ interface DocumentationParams {
|
|
|
798
801
|
* @default () => `${method} ${path} ${component}`
|
|
799
802
|
* */
|
|
800
803
|
descriptions?: Partial<Record<Component, Descriptor>>;
|
|
801
|
-
/**
|
|
802
|
-
|
|
804
|
+
/**
|
|
805
|
+
* @desc The function that ensures the maximum length for summary fields. Can optionally make them from descriptions.
|
|
806
|
+
* @see defaultSummarizer
|
|
807
|
+
* @see trimSummary
|
|
808
|
+
* */
|
|
809
|
+
summarizer?: Summarizer;
|
|
803
810
|
/**
|
|
804
811
|
* @desc Depict the HEAD method for each Endpoint supporting the GET method (feature of Express)
|
|
805
812
|
* @default true
|
|
@@ -839,8 +846,8 @@ declare class Documentation extends OpenApiBuilder {
|
|
|
839
846
|
brandHandling,
|
|
840
847
|
tags,
|
|
841
848
|
isHeader,
|
|
842
|
-
hasSummaryFromDescription,
|
|
843
849
|
hasHeadMethod,
|
|
850
|
+
summarizer,
|
|
844
851
|
composition,
|
|
845
852
|
}: DocumentationParams);
|
|
846
853
|
}
|
|
@@ -916,7 +923,7 @@ declare const testEndpoint: <LOG extends FlatObject, REQ extends RequestOptions>
|
|
|
916
923
|
responseMock: _$node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
|
|
917
924
|
loggerMock: AbstractLogger &
|
|
918
925
|
LOG & {
|
|
919
|
-
_getLogs: () => Record<"
|
|
926
|
+
_getLogs: () => Record<"error" | "debug" | "info" | "warn", unknown[]>;
|
|
920
927
|
};
|
|
921
928
|
}>;
|
|
922
929
|
declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOptions>({
|
|
@@ -935,7 +942,7 @@ declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOption
|
|
|
935
942
|
responseMock: _$node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
|
|
936
943
|
loggerMock: AbstractLogger &
|
|
937
944
|
LOG & {
|
|
938
|
-
_getLogs: () => Record<"
|
|
945
|
+
_getLogs: () => Record<"error" | "debug" | "info" | "warn", unknown[]>;
|
|
939
946
|
};
|
|
940
947
|
output: FlatObject;
|
|
941
948
|
}>;
|
|
@@ -982,7 +989,7 @@ interface IntegrationParams {
|
|
|
982
989
|
* @desc The schema to use for responses without body such as 204
|
|
983
990
|
* @default z.undefined()
|
|
984
991
|
* */
|
|
985
|
-
|
|
992
|
+
noBodySchema?: z.ZodType;
|
|
986
993
|
/**
|
|
987
994
|
* @desc Depict the HEAD method for each Endpoint supporting the GET method (feature of Express)
|
|
988
995
|
* @default true
|
|
@@ -1015,7 +1022,7 @@ declare class Integration extends IntegrationBase {
|
|
|
1015
1022
|
clientClassName,
|
|
1016
1023
|
subscriptionClassName,
|
|
1017
1024
|
serverUrl,
|
|
1018
|
-
|
|
1025
|
+
noBodySchema,
|
|
1019
1026
|
hasHeadMethod,
|
|
1020
1027
|
}: IntegrationParams);
|
|
1021
1028
|
static create(params: Omit<IntegrationParams, "typescript">): Promise<Integration>;
|
|
@@ -1152,32 +1159,28 @@ declare function paginated<T extends z.ZodType, K extends string = typeof DEFAUL
|
|
|
1152
1159
|
): CursorPaginatedResult<T, K>;
|
|
1153
1160
|
declare const base: z.ZodObject<
|
|
1154
1161
|
{
|
|
1155
|
-
raw: z.
|
|
1162
|
+
raw: z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>;
|
|
1156
1163
|
},
|
|
1157
1164
|
z.core.$strip
|
|
1158
1165
|
>;
|
|
1159
|
-
type Base =
|
|
1166
|
+
type Base = typeof base;
|
|
1160
1167
|
declare const extended: <S extends z.core.$ZodShape>(
|
|
1161
1168
|
extra: S,
|
|
1162
|
-
) => z.
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
z.core.$strip
|
|
1178
|
-
>,
|
|
1179
|
-
symbol,
|
|
1180
|
-
"out"
|
|
1169
|
+
) => z.ZodObject<
|
|
1170
|
+
(
|
|
1171
|
+
"raw" & keyof S extends never
|
|
1172
|
+
? {
|
|
1173
|
+
raw: z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>;
|
|
1174
|
+
} & S
|
|
1175
|
+
: ({
|
|
1176
|
+
raw: z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>;
|
|
1177
|
+
} extends infer T_1 extends z.core.util.SomeObject
|
|
1178
|
+
? { [K in keyof T_1 as K extends keyof S ? never : K]: T_1[K] }
|
|
1179
|
+
: never) & { [K_1 in keyof S]: S[K_1] }
|
|
1180
|
+
) extends infer T
|
|
1181
|
+
? { [k in keyof T]: T[k] }
|
|
1182
|
+
: never,
|
|
1183
|
+
z.core.$strip
|
|
1181
1184
|
>;
|
|
1182
1185
|
declare function raw(): Base;
|
|
1183
1186
|
declare function raw<S extends z.core.$ZodShape>(extra: S): ReturnType<typeof extended<S>>;
|
|
@@ -1185,34 +1188,18 @@ declare const ez: {
|
|
|
1185
1188
|
dateIn: ({
|
|
1186
1189
|
examples,
|
|
1187
1190
|
...rest
|
|
1188
|
-
}?: DateInParams) => _$
|
|
1191
|
+
}?: DateInParams) => _$zod.ZodPipe<
|
|
1189
1192
|
_$zod.ZodPipe<
|
|
1190
|
-
_$zod.
|
|
1191
|
-
|
|
1192
|
-
_$zod.ZodTransform<Date, string>
|
|
1193
|
-
>,
|
|
1194
|
-
_$zod.ZodDate
|
|
1193
|
+
_$zod.ZodUnion<readonly [_$zod.ZodISODate, _$zod.ZodISODateTime, _$zod.ZodISODateTime]>,
|
|
1194
|
+
_$zod.ZodTransform<Date, string>
|
|
1195
1195
|
>,
|
|
1196
|
-
|
|
1197
|
-
"out"
|
|
1198
|
-
>;
|
|
1199
|
-
dateOut: (
|
|
1200
|
-
meta?: DateOutParams,
|
|
1201
|
-
) => _$zod_v4_core0.$ZodBranded<_$zod.ZodPipe<_$zod.ZodDate, _$zod.ZodTransform<string, Date>>, symbol, "out">;
|
|
1202
|
-
form: <S extends _$zod_v4_core0.$ZodShape>(
|
|
1203
|
-
base: S | _$zod.ZodObject<S>,
|
|
1204
|
-
) => _$zod_v4_core0.$ZodBranded<_$zod.ZodObject<S, _$zod_v4_core0.$strip>, symbol, "out">;
|
|
1205
|
-
upload: () => _$zod_v4_core0.$ZodBranded<
|
|
1206
|
-
_$zod.ZodCustom<_$express_fileupload0.UploadedFile, _$express_fileupload0.UploadedFile>,
|
|
1207
|
-
symbol,
|
|
1208
|
-
"out"
|
|
1196
|
+
_$zod.ZodDate
|
|
1209
1197
|
>;
|
|
1198
|
+
dateOut: (meta?: DateOutParams) => _$zod.ZodPipe<_$zod.ZodDate, _$zod.ZodTransform<string, Date>>;
|
|
1199
|
+
form: <S extends _$zod_v4_core0.$ZodShape>(base: S | _$zod.ZodObject<S>) => _$zod.ZodObject<S, _$zod_v4_core0.$strip>;
|
|
1200
|
+
upload: () => _$zod.ZodCustom<_$express_fileupload0.UploadedFile, _$express_fileupload0.UploadedFile>;
|
|
1210
1201
|
raw: typeof raw;
|
|
1211
|
-
buffer: () => _$
|
|
1212
|
-
_$zod.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>,
|
|
1213
|
-
symbol,
|
|
1214
|
-
"out"
|
|
1215
|
-
>;
|
|
1202
|
+
buffer: () => _$zod.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>;
|
|
1216
1203
|
paginated: typeof paginated;
|
|
1217
1204
|
};
|
|
1218
1205
|
export {
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import{getBrand as e}from"@express-zod-api/zod-plugin";import*as t from"ramda";import{globalRegistry as n,z as r}from"zod";import i,{isHttpError as a}from"http-errors";import{isPromise as o}from"node:util/types";import s,{blue as c,cyanBright as l,gray as u,green as d,hex as f,italic as p,red as m,whiteBright as h}from"ansis";import{inspect as g}from"node:util";import{performance as _}from"node:perf_hooks";import v from"express";import ee from"node:http";import te from"node:https";import{setInterval as y}from"node:timers/promises";import{OpenApiBuilder as ne,isReferenceObject as re,isSchemaObject as b}from"openapi3-ts/oas31";import{createRequest as ie,createResponse as ae}from"node-mocks-http";function oe(e){return e}const x={json:`application/json`,upload:`multipart/form-data`,raw:`application/octet-stream`,sse:`text/event-stream`,form:`application/x-www-form-urlencoded`},se=[`get`,`post`,`put`,`delete`,`patch`],ce=[...se,`head`],S=e=>se.includes(e),le=r.object({}),ue=/:([A-Za-z0-9_]+)/g,de=e=>e.match(ue)?.map(e=>e.slice(1))||[],fe=e=>{let t=(e.header(`content-type`)||``).toLowerCase().startsWith(x.upload);return`files`in e&&t},pe={get:[`query`,`params`],post:[`body`,`params`,`files`],put:[`body`,`params`],patch:[`body`,`params`],delete:[`query`,`params`]},me=[`body`,`query`,`params`],he=e=>e.method.toLowerCase(),ge=(e,t={})=>{if(e===`options`)return[];let n=e===`head`?`get`:S(e)?e:void 0;return(n?t[n]||pe[n]:void 0)||me},_e=(e,t={})=>ge(he(e),t).filter(t=>t===`files`?fe(e):!0).reduce((t,n)=>Object.assign(t,e[n]),{}),C=e=>e instanceof Error?e:e instanceof r.ZodError?new r.ZodRealError(e.issues):Error(String(e)),w=e=>e instanceof r.ZodError?e.issues.map(({path:e,message:t})=>`${e.length?`${r.core.toDotPath(e)}: `:``}${t}`).join(`; `):e.message,T=(e,n)=>O(e)&&`_zod`in e&&(n?t.path([`_zod`,`def`,`type`],e)===n:!0),E=(e,n,r)=>e.length&&n.length?t.xprod(e,n).map(r):e.concat(n),ve=e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase(),D=(...e)=>{let n=t.chain(e=>e.split(/[^A-Z0-9]/gi),e);return t.chain(e=>e.replaceAll(/[A-Z]+/g,e=>`/${e}`).split(`/`),n).map(ve).join(``)},ye=t.tryCatch((e,t)=>typeof r.parse(e,t),t.always(void 0)),O=e=>typeof e==`object`&&!!e,k=t.memoizeWith(()=>`static`,()=>process.env.NODE_ENV===`production`),be=(e,t)=>!!t&&e!==`head`,A=Symbol(`Buffer`),xe=()=>r.custom(e=>Buffer.isBuffer(e),{error:`Expected Buffer`}).brand(A),j=Symbol(`DateIn`),Se=({examples:e,...t}={})=>r.union([r.iso.date(),r.iso.datetime(),r.iso.datetime({local:!0})]).meta({examples:e}).transform(e=>new Date(e)).pipe(r.date()).brand(j).meta(t),M=Symbol(`DateOut`),Ce=(e={})=>r.date().transform(e=>e.toISOString()).brand(M).meta(e);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.`}},F=class extends Error{name=`IOSchemaError`},we=class extends F{name=`DeepCheckError`;constructor(e){super(`Found`,{cause:e}),this.cause=e}},Te=class extends F{name=`OutputValidationError`;constructor(e){let t=new r.ZodError(e.issues.map(({path:e,...t})=>({...t,path:[`output`,...e]})));super(w(t),{cause:e}),this.cause=e}},I=class extends F{name=`InputValidationError`;constructor(e){super(w(e),{cause:e}),this.cause=e}},Ee=class extends Error{name=`ResultHandlerError`;constructor(e,t){super(w(e),{cause:e}),this.cause=e,this.handled=t}},De=class extends Error{name=`MissingPeerError`;constructor(e){super(`Missing peer dependency: ${e}. Please install it to use the feature.`)}};const Oe=Symbol(`Form`),ke=e=>(e instanceof r.ZodObject?e:r.object(e)).brand(Oe),L=Symbol(`Upload`),Ae=()=>r.custom(e=>typeof e==`object`&&!!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&&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}`})}).brand(L),R=Symbol(`Raw`),je=r.object({raw:xe()}),Me=e=>je.extend(e).brand(R);function Ne(e){return e?Me(e):je.brand(R)}const Pe=(e,{io:n,condition:i})=>t.tryCatch(()=>void r.toJSONSchema(e,{io:n,unrepresentable:`any`,override:({zodSchema:e})=>{if(i(e))throw new we(e)}}),e=>e.cause)(),Fe=(e,{io:n})=>{let i=[r.toJSONSchema(e,{io:n,unrepresentable:`any`})];for(;i.length;){let e=i.shift();if(t.is(Object,e)){if(e.$ref===`#`)return!0;i.push(...t.values(e))}t.is(Array,e)&&i.push(...t.values(e))}return!1},Ie=t=>Pe(t,{condition:t=>{let n=e(t);return typeof n==`symbol`&&[L,R,Oe].includes(n)},io:`input`}),Le=[`nan`,`symbol`,`map`,`set`,`bigint`,`void`,`promise`,`never`,`function`],Re=(t,n)=>Pe(t,{io:n,condition:t=>{let r=e(t),{type:i}=t._zod.def;return!!(Le.includes(i)||r===A||n===`input`&&(i===`date`||r===M)||n===`output`&&(r===j||r===R||r===L))}}),ze=(e,{variant:t,args:n,...i})=>{if(typeof e==`function`&&(e=e(...n)),e instanceof r.ZodType)return[{schema:e,...i}];if(Array.isArray(e)&&!e.length)throw new Ee(Error(`At least one ${t} 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}))},Be=(e,t,{url:n},r)=>!e.expose&&t.error(`Server side error`,{error:e,url:n,payload:r}),z=e=>a(e)?e:i(e instanceof I?400:500,w(e),{cause:e.cause||e}),B=e=>k()&&!e.expose?i(e.statusCode).message:e.message,Ve=e=>Object.entries(e._zod.def.shape).reduce((e,[r,i])=>{let{examples:a=[]}=n.get(i)||{};return E(e,a.map(t.objOf(r)),([e,t])=>({...e,...t}))},[]),He=({error:e,logger:t,response:n})=>{t.error(`Result handler failure`,e);let r=B(i(500,`An error occurred while serving the result: ${e.message}.`+(e.handled?`\nOriginal error: ${e.handled.message}.`:``),{expose:a(e.cause)?e.cause.expose:!1}));n.status(500).type(`text/plain`).end(r)};var Ue=class{},V=class extends Ue{#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,...t}){try{let n=await(this.#e||le).parseAsync(e);return this.#n({...t,input:n})}catch(e){throw e instanceof r.ZodError?new I(e):e}}},We=class extends V{constructor(e,{provider:t=()=>({}),transformer:n=e=>e}={}){super({handler:async({request:r,response:i})=>new Promise((a,s)=>{let c=e=>{if(e&&e instanceof Error)return s(n(e));a(t(r,i))},l=e(r,i,c);o(l)&&l.catch(c)})})}},Ge=class{nest(e){return{...e,"":this}}},Ke=class i extends Ge{#e;#t=t.once(()=>{if(n.get(this.#e.outputSchema)?.examples?.length||!T(this.#e.outputSchema,`object`))return;let e=Ve(this.#e.outputSchema);if(!e.length)return;let t=this.#e.outputSchema.meta();n.remove(this.#e.outputSchema).add(this.#e.outputSchema,{...t,examples:e})});constructor(e){super(),this.#e=e}#n(e){return new i({...this.#e,...e})}deprecated(){return this.#n({deprecated:!0})}get isDeprecated(){return this.#e.deprecated||!1}get description(){return this.#e.description}get shortDescription(){return this.#e.shortDescription}get methods(){return Object.freeze(this.#e.methods)}get inputSchema(){return this.#e.inputSchema}get outputSchema(){return this.#t(),this.#e.outputSchema}get requestType(){let t=Ie(this.#e.inputSchema);if(t){let n=e(t);if(n===L)return`upload`;if(n===R)return`raw`;if(n===Oe)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=t.pluck(`security`,this.#e.middlewares||[]);return t.reject(t.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 r.ZodError?new Te(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 We))&&(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,...t}){let n;try{n=await this.#e.inputSchema.parseAsync(e)}catch(e){throw e instanceof r.ZodError?new I(e):e}return this.#e.handler({...t,input:n})}async#o(e){try{await this.#e.resultHandler.execute(e)}catch(t){He({...e,error:new Ee(C(t),e.error||void 0)})}}async execute({request:e,response:t,logger:n,config:r}){let i=he(e),a={},o={output:{},error:null},s=_e(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:C(e)}}await this.#o({...o,input:s,request:e,response:t,logger:n,ctx:a})}};const qe=(e,t)=>e&&t?e.and(t):e||t,Je=(e,t)=>e?e.and(t):t,H={positive:200,negative:400},Ye=Object.keys(H);var Xe=class{#e;constructor(e){this.#e=e}execute(...e){return this.#e(...e)}},U=class extends Xe{#e;#t;constructor(e){super(e.handler),this.#e=e.positive,this.#t=e.negative}getPositiveResponse(e){return ze(this.#e,{variant:`positive`,args:[e],statusCodes:[H.positive],mimeTypes:[x.json]})}getNegativeResponse(){return ze(this.#t,{variant:`negative`,args:[],statusCodes:[H.negative],mimeTypes:[x.json]})}};const Ze=r.object({status:r.literal(`error`),error:r.object({message:r.string()})});n.add(Ze,{examples:[{status:`error`,error:{message:`Sample error message`}}]});const W=new U({positive:e=>{let t=r.object({status:r.literal(`success`),data:e}),{examples:i}=n.get(e)||{};return i?.length&&n.add(t,{examples:i.map(e=>({status:`success`,data:e}))}),t},negative:Ze,handler:({error:e,input:t,output:n,request:r,response:i,logger:a})=>{if(e){let n=z(e);Be(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})}}),Qe=r.string();n.add(Qe,{examples:[`Sample error message`]});const $e=new U({positive:e=>{let t=e instanceof r.ZodObject&&`items`in e.shape&&e.shape.items instanceof r.ZodArray?e.shape.items:r.array(r.any());if(n.get(t)?.examples?.length)return t;let i=n.get(e)?.examples?.filter(e=>O(e)&&`items`in e&&Array.isArray(e.items)).map(e=>e.items);if(i?.length){let e=t.meta();n.remove(t).add(t,{...e,examples:i})}return t},negative:{schema:Qe,mimeType:`text/plain`},handler:({response:e,output:t,error:n,logger:r,request:i,input:a})=>{if(n){let t=z(n);Be(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{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=qe(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 We(...e))}addContext(e){return this.#e(new V({handler:e}))}build({input:e=le,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 Ke({...o,middlewares:s,outputSchema:t,resultHandler:c,scopes:d,tags:f,methods:l,getOperationId:u,inputSchema:Je(this.schema,e)})}buildVoid({handler:e,...t}){return this.build({...t,output:le,handler:async t=>(await e(t),{})})}};const et=new G(W),tt=new G($e),nt={debug:c,info:d,warn:f(`#FFA500`),error:m,ctx:l},K={debug:10,info:20,warn:30,error:40},rt=e=>O(e)&&Object.keys(K).some(t=>t in e),it=e=>e in K,at=(e,t)=>K[e]<K[t],q=t.memoizeWith((e,t)=>`${e}${t}`,(e,t=0)=>Intl.NumberFormat(void 0,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t,style:`unit`,unitDisplay:`long`,unit:e})),ot=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 st=class e{config;constructor({color:e=s.isSupported(),level:t=k()?`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 g(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`||at(e,r))return;let s=[new Date().toISOString()];i&&s.push(o?nt.ctx(i):i),s.push(o?`${nt[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=_.now();return()=>{let n=_.now()-t,{message:r,severity:i=`debug`,formatter:a=ot}=typeof e==`object`?e:{message:e};this.print(typeof i==`function`?i(n):i,r,a(n))}}},ct=class{#e;constructor(...e){this.#e=e}apply(e,t){return t(e,v.static(...this.#e))}};const J=async(e,t=`default`)=>{try{return(await import(e))[t]}catch{}throw new De(e)},lt=e=>e.type===`object`,ut=t.mergeDeepWith((e,n)=>{if(Array.isArray(e)&&Array.isArray(n))return t.concat(e,n);if(e===n)return n;throw Error(`Can not flatten properties`,{cause:{a:e,b:n}})}),dt=t.pipe(Object.keys,t.without([`type`,`properties`,`required`,`examples`,`description`,`additionalProperties`]),t.isEmpty),ft=t.pair(!0),Y=(e,n=`coerce`)=>{let r=[t.pair(!1,e)],i={type:`object`,properties:{}},a=[];for(;r.length;){let[e,o]=r.shift();if(o.description&&(i.description??=o.description),o.allOf&&r.push(...o.allOf.map(r=>{if(n===`throw`&&!(r.type===`object`&&dt(r)))throw Error(`Can not merge`);return t.pair(e,r)})),o.anyOf&&r.push(...t.map(ft,o.anyOf)),o.oneOf&&r.push(...t.map(ft,o.oneOf)),o.examples?.length&&(e?i.examples=t.concat(i.examples||[],o.examples):i.examples=E(i.examples?.filter(O)||[],o.examples.filter(O),([e,n])=>t.mergeDeepRight(e,n))),lt(o)&&(r.push([e,{examples:pt(o)}]),o.properties&&(i.properties=(n===`throw`?ut:t.mergeDeepRight)(i.properties,o.properties),!e&&o.required&&a.push(...o.required)),O(o.propertyNames))){let t=[];typeof o.propertyNames.const==`string`&&t.push(o.propertyNames.const),o.propertyNames.enum&&t.push(...o.propertyNames.enum.filter(e=>typeof e==`string`));let n={...Object(o.additionalProperties)};for(let e of t)i.properties[e]??=n;e||a.push(...t)}}return a.length&&(i.required=[...new Set(a)]),i},pt=e=>Object.entries(e.properties||{}).reduce((e,[n,r])=>{let{examples:i=[]}=O(r)?r:{};return E(e,i.map(t.objOf(n)),([e,t])=>({...e,...t}))},[]);var mt=class{#e=new WeakMap;constructor(e){this.logger=e}#t(e,t,n){if(!e.isSchemaChecked){for(let e of[`input`,`output`]){let i=[r.toJSONSchema(t[`${e}Schema`],{unrepresentable:`any`})];for(;i.length>0;){let t=i.shift();t.type&&t.type!==`object`&&this.logger.warn(`Endpoint ${e} schema is not object-based`,n);for(let e of[`allOf`,`oneOf`,`anyOf`])t[e]&&i.push(...t[e])}}if(t.requestType===`json`){let e=Re(t.inputSchema,`input`);e&&this.logger.warn(`The final input schema of the endpoint contains an unsupported JSON payload type.`,{...n,reason:e})}for(let e of Ye)for(let{mimeTypes:r,schema:i}of t.getResponses(e)){if(!r?.includes(x.json))continue;let t=Re(i,`output`);t&&this.logger.warn(`The final ${e} response schema of the endpoint contains an unsupported JSON payload type.`,{...n,reason:t})}e.isSchemaChecked=!0}}#n(e,t,n,i){if(e.paths.has(n))return;let a=de(n);if(a.length!==0){e.flat??=Y(r.toJSONSchema(t.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:n,param:t});e.paths.add(n)}}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 ht=e=>(t,...n)=>{e(t,...n),t===`get`&&e(`head`,...n)},gt=e=>{let[t,n]=e.trim().split(/ (.+)/,2);return n&&S(t)?[n,t]:[e]},_t=e=>e.trim().split(`/`).filter(Boolean).join(`/`),vt=({methodLikeRouteBehavior:e=`method`},t,n)=>{let r=e===`method`;return Object.entries(t).map(([e,t])=>{let[i,a]=r&&S(e)&&t instanceof Ge?[`/`,e]:gt(e);return[[n||``].concat(_t(i)||[]).join(`/`),t,a]})},yt=(e,t)=>{throw new N(`Route with explicit method can only be assigned with Endpoint`,e,t)},bt=(e,t,n)=>{if(!(!n||n.includes(e)))throw new N(`Method ${e} is not supported by the assigned Endpoint.`,e,t)},xt=(e,t,n)=>{let r=`${e} ${t}`;if(n.has(r))throw new N(`Route has a duplicate`,e,t);n.add(r)},St=({routing:e,config:t,onEndpoint:n,onStatic:r})=>{let i=vt(t,e),a=new Set;for(;i.length;){let[e,o,s]=i.shift();if(o instanceof Ge)if(s)xt(s,e,a),bt(s,e,o.methods),n(s,e,o);else{let{methods:t=[`get`]}=o;for(let r of t)xt(r,e,a),n(r,e,o)}else s&&yt(s,e),o instanceof ct?r&&o.apply(e,r):i.unshift(...vt(t,o,e))}},Ct=e=>e.sort((e,t)=>S(t)-+S(e)||e.localeCompare(t)).join(`, `).toUpperCase(),wt=e=>({method:t},n,r)=>{let a=Ct(e);n.set({Allow:a}),r(i(405,`${t} is not allowed`,{headers:{Allow:a}}))},Tt=e=>({"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":Ct(e),"Access-Control-Allow-Headers":`content-type`}),Et=({app:e,getLogger:n,config:r,routing:i,parsers:a})=>{let o=k()?void 0:new mt(n()),s=new Map;return St({routing:i,config:r,onEndpoint:(e,n,i)=>{o?.check(e,n,i);let c=a?.[i.requestType]||[],l=t.pair(c,i);s.has(n)||s.set(n,new Map(r.cors?[[`options`,l]]:[])),s.get(n)?.set(e,l)},onStatic:e.use.bind(e)}),s},Dt=({app:e,config:t,getLogger:n,...r})=>{let i=Et({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=s.slice().concat(async(e,r)=>{let i=n(e);return c.execute({request:e,response:r,logger:i,config:t})});t.cors&&o.unshift(async(e,r,a)=>{let o=n(e),s=Tt(i),l=typeof t.cors==`function`?await t.cors({request:e,endpoint:c,logger:o,defaultHeaders:s}):s;r.set(l),a()}),e[a](r,...o)}t.wrongMethodBehavior!==404&&a.set(r,wt(i))}for(let[t,n]of a)e.all(t,n)},Ot=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`,kt=e=>`server`in e&&typeof e.server==`object`&&e.server!==null&&`close`in e.server&&typeof e.server.close==`function`,At=e=>`encrypted`in e&&typeof e.encrypted==`boolean`&&e.encrypted,jt=({},e)=>void(!e.headersSent&&e.setHeader(`connection`,`close`)),Mt=e=>new Promise((t,n)=>void e.close(e=>e?n(e):t())),Nt=(e,{timeout:t=1e3,logger:n}={})=>{let r,i=new Set,a=e=>void i.delete(e.destroy()),o=e=>void(Ot(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`,jt);n?.info(`Graceful shutdown`,{sockets:i.size,timeout:t});for(let e of i)(At(e)||kt(e))&&o(e);for await(let e of y(10,Date.now()))if(i.size===0||Date.now()-e>=t)break;for(let e of i)a(e);return Promise.allSettled(e.map(Mt))};return{sockets:i,shutdown:()=>r??=c()}},Pt=Symbol.for(`express-zod-api`),Ft=({errorHandler:e,getLogger:t})=>async(n,r,i,a)=>n?e.execute({error:C(n),request:r,response:i,input:null,output:null,ctx:{},logger:t(r)}):a(),It=({errorHandler:e,getLogger:t})=>async(n,r)=>{let a=i(404,`Can not ${n.method} ${n.path}`),o=t(n);try{await e.execute({request:n,response:r,logger:o,error:a,input:null,output:null,ctx:{}})}catch(e){He({response:r,logger:o,error:new Ee(C(e),a)})}},Lt=e=>(t,{},n)=>{if(Object.values(t?.files||[]).flat().find(({truncated:e})=>e))return n(e);n()},Rt=e=>({log:e.debug.bind(e)}),zt=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:Rt(s)})(t,r,o)}),r&&o.push(Lt(r)),o},Bt=(e,{},t)=>{Buffer.isBuffer(e.body)&&(e.body={raw:e.body}),t()},Vt=({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[Pt]={logger:o}),a()},Ht=e=>t=>t?.res?.locals[Pt]?.logger||e,Ut=e=>process.on(`deprecation`,({message:t,namespace:n,name:r,stack:i})=>e.warn(`${r} (${n}): ${t}`,i.split(`
|
|
3
|
-
`).slice(1))),Wt=({servers:e,logger:t,options:{timeout:n,beforeExit:r,events:i=[`SIGINT`,`SIGTERM`]}})=>{let a=Nt(e,{logger:t,timeout:n}),o=async()=>{await a.shutdown(),await r?.(),process.exit()};for(let e of i)process.on(e,o)},Gt=e=>{if(e.columns<132)return;let t=p(`Proudly supports transgender community.`.padStart(109)),n=p(`Start your API server with I/O schema validation and custom middlewares in minutes.`.padStart(109)),r=p(`Thank you for choosing Express Zod API for your project.`.padStart(132)),i=p(`for Nikki`.padEnd(20)),a=f(`#F5A9B8`),o=f(`#5BCEFA`),s=Array(14).fill(o,1,3).fill(a,3,5).fill(h,5,7).fill(a,7,9).fill(o,9,12).fill(u,12,13),c=`
|
|
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{name=`DeepCheckError`;constructor(e){super(`Found`,{cause:e}),this.cause=e}},Oe=class extends Ee{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{name=`InputValidationError`;constructor(e){super(S(e),{cause:e}),this.cause=e}},ke=class extends Error{name=`ResultHandlerError`;constructor(e,t){super(S(e),{cause:e}),this.cause=e,this.handled=t}},Ae=class extends Error{name=`MissingPeerError`;constructor(e){super(`Missing peer dependency: ${e}. Please install it to use the feature.`)}};const je=Symbol(`Form`),Me=e=>(e instanceof t.ZodObject?e:t.object(e)).meta({[D]:je}),I=Symbol(`Upload`),Ne=()=>t.custom(e=>typeof e==`object`&&!!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&&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]:I}),L=Symbol(`Raw`),Pe=t.object({raw:Ce()}),Fe=e=>Pe.extend(e).meta({[D]:L});function Ie(e){return e?Fe(e):Pe.meta({[D]:L})}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(;i.length;){let e=i.shift();if(n.is(Object,e)){if(e.$ref===`#`)return!0;i.push(...n.values(e))}n.is(Array,e)&&i.push(...n.values(e))}return!1},ze=e=>Le(e,{condition:e=>{let t=O(e);return typeof t==`symbol`&&[I,L,je].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===L||n===I))}}),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 ke(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}),R=e=>i(e)?e:r(e instanceof F?400:500,S(e),{cause:e.cause||e}),z=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=z(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{},B=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 B{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.#t(),this.#e.outputSchema}get requestType(){let e=ze(this.#e.inputSchema);if(e){let t=O(e);if(t===I)return`upload`;if(t===L)return`raw`;if(t===je)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 ke(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,V={positive:200,negative:400},Qe=Object.keys(V);var $e=class{#e;constructor(e){this.#e=e}execute(...e){return this.#e(...e)}},H=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:[V.positive],mimeTypes:[y.json]})}getNegativeResponse(){return He(this.#t,{variant:`negative`,args:[],statusCodes:[V.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 U=new H({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=R(e);Ue(n,a,r,t),i.status(n.statusCode).set(n.headers).json({status:`error`,error:{message:z(n)}});return}i.status(V.positive).json({status:`success`,data:n})}}),tt=t.string();e.add(tt,{examples:[`Sample error message`]});const nt=new H({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=R(n);Ue(t,r,i,a),e.status(t.statusCode).type(`text/plain`).send(z(t));return}if(`items`in t&&Array.isArray(t.items)){e.status(V.positive).json(t.items);return}throw Error(`Property 'items' is missing in the endpoint output`)}});var W=class e{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 B?e:new B(e))}use=this.addExpressMiddleware;addExpressMiddleware(...e){return this.#e(new qe(...e))}addContext(e){return this.#e(new B({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 W(U),it=new W(nt),at={debug:s,info:u,warn:d(`#FFA500`),error:p,ctx:c},G={debug:10,info:20,warn:30,error:40},ot=e=>E(e)&&Object.keys(G).some(t=>t in e),st=e=>e in G,ct=(e,t)=>G[e]<G[t],K=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?K(`nanosecond`,3).format(e/1e-6):e<.001?K(`nanosecond`).format(e/1e-6):e<1?K(`microsecond`).format(e/.001):e<1e3?K(`millisecond`).format(e):e<6e4?K(`second`,2).format(e/1e3):K(`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))}}},dt=class{#e;constructor(...e){this.#e=e}apply(e,t){return t(e,_.static(...this.#e))}};const q=async(e,t=`default`)=>{try{return(await import(e))[t]}catch{}throw new Ae(e)},ft=e=>e.type===`object`,pt=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}})}),mt=n.pipe(Object.keys,n.without([`type`,`properties`,`required`,`examples`,`description`,`additionalProperties`]),n.isEmpty),ht=n.pair(!0),J=(e,t=`coerce`)=>{let r=[n.pair(!1,e)],i={type:`object`,properties:{}},a=[];for(;r.length;){let[e,o]=r.shift();if(o.description&&(i.description??=o.description),o.allOf&&r.push(...o.allOf.map(r=>{if(t===`throw`&&!(r.type===`object`&&mt(r)))throw Error(`Can not merge`);return n.pair(e,r)})),o.anyOf&&r.push(...n.map(ht,o.anyOf)),o.oneOf&&r.push(...n.map(ht,o.oneOf)),o.examples?.length&&(e?i.examples=n.concat(i.examples||[],o.examples):i.examples=w(i.examples?.filter(E)||[],o.examples.filter(E),([e,t])=>n.mergeDeepRight(e,t))),ft(o)&&(r.push([e,{examples:gt(o)}]),o.properties&&(i.properties=(t===`throw`?pt:n.mergeDeepRight)(i.properties,o.properties),!e&&o.required&&a.push(...o.required)),E(o.propertyNames))){let t=[];typeof o.propertyNames.const==`string`&&t.push(o.propertyNames.const),o.propertyNames.enum&&t.push(...o.propertyNames.enum.filter(e=>typeof e==`string`));let n={...Object(o.additionalProperties)};for(let e of t)i.properties[e]??=n;e||a.push(...t)}}return a.length&&(i.required=[...new Set(a)]),i},gt=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 _t=class{#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(;i.length>0;){let t=i.shift();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??=J(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 vt=e=>(t,...n)=>{e(t,...n),t===`get`&&e(`head`,...n)},yt=e=>{let[t,n]=e.trim().split(/ (.+)/,2);return n&&b(t)?[n,t]:[e]},bt=e=>e.trim().split(`/`).filter(Boolean).join(`/`),xt=({recognizeMethodDependentRoutes:e=!0},t,n)=>Object.entries(t).map(([t,r])=>{let[i,a]=e&&b(t)&&r instanceof Je?[`/`,t]:yt(t);return[[n||``].concat(bt(i)||[]).join(`/`),r,a]}),St=(e,t)=>{throw new N(`Route with explicit method can only be assigned with Endpoint`,e,t)},Ct=(e,t,n)=>{if(!(!n||n.includes(e)))throw new N(`Method ${e} is not supported by the assigned Endpoint.`,e,t)},wt=(e,t,n)=>{let r=`${e} ${t}`;if(n.has(r))throw new N(`Route has a duplicate`,e,t);n.add(r)},Tt=({routing:e,config:t,onEndpoint:n,onStatic:r})=>{let i=xt(t,e),a=new Set;for(;i.length;){let[e,o,s]=i.shift();if(o instanceof Je)if(s)wt(s,e,a),Ct(s,e,o.methods),n(s,e,o);else{let{methods:t=[`get`]}=o;for(let r of t)wt(r,e,a),n(r,e,o)}else s&&St(s,e),o instanceof dt?r&&o.apply(e,r):i.unshift(...xt(t,o,e))}},Et=e=>e.sort((e,t)=>b(t)-+b(e)||e.localeCompare(t)).join(`, `).toUpperCase(),Dt=e=>({method:t},n,i)=>{let a=Et(e);n.set({Allow:a}),i(r(405,`${t} is not allowed`,{headers:{Allow:a}}))},Ot=e=>({"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":Et(e),"Access-Control-Allow-Headers":`content-type`}),kt=({app:e,getLogger:t,config:r,routing:i,parsers:a})=>{let o=xe()?void 0:new _t(t()),s=new Map;return Tt({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},At=({app:e,config:t,getLogger:n,...r})=>{let i=kt({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=s.slice().concat(async(e,r)=>{let i=n(e);return c.execute({request:e,response:r,logger:i,config:t})});t.cors&&o.unshift(async(e,r,a)=>{let o=n(e),s=Ot(i),l=typeof t.cors==`function`?await t.cors({request:e,endpoint:c,logger:o,defaultHeaders:s}):s;r.set(l),a()}),e[a](r,...o)}t.hintAllowedMethods!==!1&&a.set(r,Dt(i))}for(let[t,n]of a)e.all(t,n)},jt=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`,Mt=e=>`server`in e&&typeof e.server==`object`&&e.server!==null&&`close`in e.server&&typeof e.server.close==`function`,Nt=e=>`encrypted`in e&&typeof e.encrypted==`boolean`&&e.encrypted,Pt=({},e)=>void(!e.headersSent&&e.setHeader(`connection`,`close`)),Ft=e=>{let{promise:t,resolve:n,reject:r}=Promise.withResolvers();return e.close(e=>e?r(e):n()),t},It=(e,{timeout:t=1e3,logger:n}={})=>{let r,i=new Set,a=e=>void i.delete(e.destroy()),o=e=>void(jt(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`,Pt);n?.info(`Graceful shutdown`,{sockets:i.size,timeout:t});for(let e of i)(Nt(e)||Mt(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(Ft))};return{sockets:i,shutdown:()=>r??=c()}},Lt=Symbol.for(`express-zod-api`),Rt=({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(),zt=({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 ke(x(e),a)})}},Bt=e=>(t,{},n)=>{if(Object.values(t?.files||[]).flat().find(({truncated:e})=>e))return n(e);n()},Vt=e=>({log:e.debug.bind(e)}),Ht=async({getLogger:e,config:t})=>{let n=await q(`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:Vt(s)})(t,r,o)}),r&&o.push(Bt(r)),o},Ut=(e,{},t)=>{Buffer.isBuffer(e.body)&&(e.body={raw:e.body}),t()},Wt=({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[Lt]={logger:o}),a()},Gt=e=>t=>t?.res?.locals[Lt]?.logger||e,Kt=e=>process.on(`deprecation`,({message:t,namespace:n,name:r,stack:i})=>e.warn(`${r} (${n}): ${t}`,i.split(`
|
|
2
|
+
`).slice(1))),qt=({servers:e,logger:t,options:{timeout:n,beforeExit:r,events:i=[`SIGINT`,`SIGTERM`]}})=>{let a=It(e,{logger:t,timeout:n}),o=async()=>{await a.shutdown(),await r?.(),process.exit()};for(let e of i)process.on(e,o)},Jt=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=`
|
|
4
3
|
8888888888 8888888888P 888 d8888 8888888b. 8888888
|
|
5
4
|
888 d88P 888 d88888 888 Y88b 888
|
|
6
5
|
888 d88P 888 d88P888 888 888 888
|
|
@@ -15,8 +14,8 @@ ${i}888${n}
|
|
|
15
14
|
${r}
|
|
16
15
|
`;e.write(c.split(`
|
|
17
16
|
`).map((e,t)=>s[t]?s[t](e):e).join(`
|
|
18
|
-
`))},Kt=e=>{e.startupLogo!==!1&&Gt(process.stdout);let t=e.errorHandler||W,n=rt(e.logger)?e.logger:new st(e.logger);n.debug(`Running`,{build:`v27.2.2`,env:process.env.NODE_ENV||`development`}),Ut(n);let r=Vt({logger:n,config:e}),i={getLogger:Ht(n),errorHandler:t},a=It(i),o=Ft(i);return{...i,logger:n,notFoundHandler:a,catcher:o,loggingMiddleware:r}},qt=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,loggingMiddleware:a}=Kt(e);return Dt({app:e.app.use(a),routing:t,getLogger:r,config:e}),{notFoundHandler:i,logger:n}},Jt=async(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,catcher:a,loggingMiddleware:o}=Kt(e),s=v().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))}await e.beforeRouting?.({app:s,getLogger:r}),Dt({app:s,routing:t,getLogger:r,config:e,parsers:{json:[e.jsonParser||v.json()],raw:[e.rawParser||v.raw(),Bt],form:[e.formParser||v.urlencoded()],upload:e.upload?await zt({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&&Wt({logger:n,servers:c,options:e.gracefulShutdown===!0?{}:e.gracefulShutdown}),{app:s,logger:n,servers:u.map(e=>e())}},Yt=e=>O(e)&&`or`in e,Xt=e=>O(e)&&`and`in e,Zt=e=>!Xt(e)&&!Yt(e),Qt=e=>{let n=t.filter(Zt,e),r=t.chain(t.prop(`and`),t.filter(Xt,e)),[i,a]=t.partition(Zt,r),o=t.concat(n,i),s=t.filter(Yt,e);return t.map(t.prop(`or`),t.concat(s,a)).reduce((e,n)=>E(e,t.map(e=>Zt(e)?[e]:e.and,n),([e,n])=>t.concat(e,n)),t.reject(t.isEmpty,[o]))};var $t=`a-im.accept.accept-additions.accept-ch.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.alternates.amp-cache-transform.apply-to-redirect-ref.authentication-control.authentication-info.authorization.available-dictionary.c-ext.c-man.c-opt.c-pep.c-pep-info.cache-control.cal-managed-id.caldav-timezones.capsule-protocol.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.cross-origin-embedder-policy.cross-origin-embedder-policy-report-only.cross-origin-opener-policy.cross-origin-opener-policy-report-only.cross-origin-resource-policy.cta-common-access-token.dasl.date.dav.default-style.delta-base.deprecation.depth.derived-from.destination.detached-jws.differential-id.dictionary-id.digest.dpop.dpop-nonce.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.nel.odata-entityid.odata-isolation.odata-maxversion.odata-version.opt.ordering-type.origin.origin-agent-cluster.oscore.oslc-core-version.overwrite.p3p.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.public.public-key-pins.public-key-pins-report-only.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.setprofile.signature.signature-input.slug.soapaction.status-uri.sunset.surrogate-capability.tcn.te.timeout.topic.traceparent.tracestate.trailer.transfer-encoding.ttl.upgrade.urgency.uri.use-as-dictionary.user-agent.variant-vary.via.want-content-digest.want-digest.want-repr-digest.warning.x-content-type-options.x-frame-options`.split(`.`);const en=`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString`,tn={integer:0,number:0,string:``,boolean:!1,object:{},null:null,array:[]},nn=e=>e.replace(ue,e=>`{${e.slice(1)}}`),rn=({},e)=>{if(e.isResponse)throw new P(`Please use ez.upload() only for input.`,e);return{type:`string`,format:`binary`}},an=({jsonSchema:e})=>({...e,externalDocs:{description:`raw binary data`,url:`https://swagger.io/specification/#working-with-binary-data`}}),on=({zodSchema:e,jsonSchema:t})=>{if(!T(e,`union`)||!(`discriminator`in e._zod.def))return t;let n=e._zod.def.discriminator;return{...t,discriminator:t.discriminator??{propertyName:n}}},sn=t.tryCatch(({jsonSchema:e})=>{if(!e.allOf)throw`no allOf`;return Y(e,`throw`)},(e,{jsonSchema:t})=>t),cn=({jsonSchema:e})=>{if(!e.anyOf)return e;let t=e.anyOf[0];return Object.assign(t,{type:mn(t.type)})},X=e=>e,ln=({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:en}};return e?.length&&(r.examples=e),r},un=({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:en}};return e?.length&&(r.examples=e),r},dn=()=>({type:`string`,format:`bigint`,pattern:`^-?\\d+$`}),fn=({zodSchema:e,jsonSchema:t})=>e._zod.def.rest===null?{...t,items:{not:{}}}:t,pn=e=>{let t=Array.isArray(e.type)?e.type[0]:e.type;return tn?.[t]},mn=e=>e===`null`?e:typeof e==`string`?[e,`null`]:e&&[...new Set(e).add(`null`)],hn=({zodSchema:e,jsonSchema:t},n)=>{let r=e._zod.def[n.isResponse?`out`:`in`],i=e._zod.def[n.isResponse?`in`:`out`];if(!T(r,`transform`))return t;let a=X(Sn(i,{ctx:n}));if(b(a))if(n.isResponse){let e=ye(r,pn(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},gn=({jsonSchema:e})=>{if(e.type!==`object`)return e;let t=e;return!t.properties||!(`raw`in t.properties)||!O(t.properties.raw)?e:t.properties.raw},_n=e=>e.length?t.fromPairs(t.zip(t.times(e=>`example${e+1}`,e.length),t.map(t.objOf(`value`),e))):void 0,vn=(e,t)=>t?.includes(e)||e.startsWith(`x-`)||$t.includes(e),yn=({path:e,method:n,request:r,inputSources:i,makeRef:a,composition:o,isHeader:s,security:c,description:l=`${n.toUpperCase()} ${e} Parameter`})=>{let u=Y(r),d=de(e),f=i.includes(`query`),p=i.includes(`params`),m=i.includes(`headers`),h=e=>p&&d.includes(e),g=t.chain(t.filter(e=>e.type===`header`),c??[]).map(({name:e})=>e),_=t=>m&&(s?.(t,n,e)??vn(t,g));return Object.entries(u.properties).reduce((e,[n,r])=>{if(!O(r))return e;let i=h(n)?`path`:_(n)?`header`:f?`query`:void 0;if(!i)return e;let s=X(r),c=o===`components`?a(r.id||JSON.stringify(r),s,r.id||D(l,n)):s;return e.concat({name:n,in:i,deprecated:r.deprecated,required:u.required?.includes(n)||!1,description:s.description||l,schema:c,examples:_n(b(s)&&s.examples?.length?s.examples:t.pluck(n,u.examples?.filter(t.both(O,t.has(n)))||[]))})},[])},bn={nullable:cn,union:on,bigint:dn,intersection:sn,tuple:fn,pipe:hn,[j]:ln,[M]:un,[L]:rn,[R]:gn,[A]:an},xn=(e,n,r)=>{let i=[e,n];for(;i.length;){let e=i.shift();if(t.is(Object,e)){if(re(e)&&!e.$ref.startsWith(`#/components`)){let t=n[e.$ref.split(`/`).pop()];t&&(e.$ref=r.makeRef(t.id||t,X(t),t.id).$ref);continue}i.push(...t.values(e))}t.is(Array,e)&&i.push(...t.values(e))}return e},Sn=(t,{ctx:n,rules:i=bn})=>{let{$defs:a={},properties:o={}}=r.toJSONSchema(r.object({subject:t}),{unrepresentable:`any`,io:n.isResponse?`output`:`input`,override:t=>{let r=e(t.zodSchema),a=i[r&&r in i?r:t.zodSchema._zod.def.type];if(a){let e={...a(t,n)};for(let e in t.jsonSchema)delete t.jsonSchema[e];Object.assign(t.jsonSchema,e)}}});return xn(O(o.subject)?o.subject:{},a,n)},Cn=(e,n)=>{if(re(e))return[e,!1];let r=!1,i=t.map(e=>{let[t,i]=Cn(e,n);return r||=i,t}),a=t.omit(n),o={properties:a,examples:t.map(a),required:t.without(n),allOf:i,oneOf:i,anyOf:i},s=t.evolve(o,e);return[s,r||!!s.required?.length]},wn=({method:e,path:n,schema:r,mimeTypes:i,variant:a,makeRef:o,composition:s,hasMultipleStatusCodes:c,statusCode:l,brandHandling:u,description:d=`${e.toUpperCase()} ${n} ${ve(a)} response ${c?l:``}`.trim()})=>{if(!be(e,i))return{description:d};let f=X(Sn(r,{rules:{...u,...bn},ctx:{isResponse:!0,makeRef:o,path:n,method:e}})),p=[];b(f)&&f.examples&&(p.push(...f.examples),delete f.examples);let m={schema:s===`components`?o(r,f,D(d)):f,examples:_n(p)};return{description:d,content:t.fromPairs(t.xprod(i,[m]))}},Tn=({format:e})=>{let t={type:`http`,scheme:`bearer`};return e&&(t.bearerFormat=e),t},En=({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},Dn=({name:e})=>({type:`apiKey`,in:`header`,name:e}),On=({name:e})=>({type:`apiKey`,in:`cookie`,name:e}),kn=({url:e})=>({type:`openIdConnect`,openIdConnectUrl:e}),An=({flows:e={}})=>({type:`oauth2`,flows:t.map(e=>({...e,scopes:e.scopes||{}}),t.reject(t.isNil,e))}),jn=(e,t=[])=>{let n=e=>e.type===`basic`?{type:`http`,scheme:`basic`}:e.type===`bearer`?Tn(e):e.type===`input`?En(e,t):e.type===`header`?Dn(e):e.type===`cookie`?On(e):e.type===`openid`?kn(e):An(e);return e.map(e=>e.map(n))},Mn=(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:[]})},{})),Nn=({schema:e,brandHandling:t,makeRef:n,path:r,method:i})=>Sn(e,{rules:{...t,...bn},ctx:{isResponse:!1,makeRef:n,path:r,method:i}}),Pn=({method:e,path:n,schema:r,request:i,mimeType:a,makeRef:o,composition:s,paramNames:c,description:l=`${e.toUpperCase()} ${n} Request body`})=>{let[u,d]=Cn(X(i),c),f=[];b(u)&&u.examples&&(f.push(...u.examples),delete u.examples);let p={schema:s===`components`?o(r,u,D(l)):u,examples:_n(f.length?f:Y(i).examples?.filter(e=>O(e)&&!Array.isArray(e)).map(t.omit(c))||[])},m={description:l,content:{[a]:p}};return(d||a===x.raw)&&(m.required=!0),m},Fn=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)},[]),In=e=>e.length<=50?e:e.slice(0,49)+`…`,Ln=e=>e.length?e.slice():void 0;var Rn=class extends ne{#e=new Map;#t=new Map;#n=new Map;#r(e,t,n){let r=this.#n.get(e);if(!r){let t=n?0:1;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||D(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:n,title:r,version:i,serverUrl:a,descriptions:o,brandHandling:s,tags:c,isHeader:l,hasSummaryFromDescription:u=!0,hasHeadMethod:d=!0,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,shortDescription:d,scopes:p,inputSchema:m}=i,h=d?In(d):u&&c?In(c):void 0,g=ge(e,n.inputSources),_=this.#i(r,e,i.getOperationId(e)),v=Nn({...a,schema:m}),ee=Qt(i.security),te=yn({...a,inputSources:g,isHeader:l,security:ee,request:v,description:o?.requestParameter?.call(null,{method:e,path:r,operationId:_})}),y={};for(let t of Ye){let n=i.getResponses(t);for(let{mimeTypes:i,schema:s,statusCodes:c}of n)for(let l of c)y[l]=wn({...a,variant:t,schema:s,mimeTypes:i,statusCode:l,hasMultipleStatusCodes:n.length>1||c.length>1,description:o?.[`${t}Response`]?.call(null,{method:e,path:r,operationId:_,statusCode:l})})}let ne=g.includes(`body`)?Pn({...a,request:v,paramNames:t.pluck(`name`,te),schema:m,mimeType:x[i.requestType],description:o?.requestBody?.call(null,{method:e,path:r,operationId:_})}):void 0,re=Mn(jn(ee,g),p,e=>{let t=this.#a(e);return this.addSecurityScheme(t,e),t}),b={operationId:_,summary:h,description:c,deprecated:i.isDeprecated||void 0,tags:Ln(i.tags),parameters:Ln(te),requestBody:ne,security:Ln(re),responses:y};this.addPath(nn(r),{[e]:b})};St({routing:e,config:n,onEndpoint:d?ht(p):p}),c&&(this.rootDoc.tags=Fn(c))}};const zn=e=>ie({...e,headers:{"content-type":x.json,...e?.headers}}),Bn=e=>ae(e),Vn=e=>{let t={warn:[],error:[],info:[],debug:[]};return new Proxy(e||{},{get(e,n,r){return n===`_getLogs`?()=>t:it(n)?(...e)=>t[n].push(e):Reflect.get(e,n,r)}})},Hn=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=zn(e),a=Bn({req:i,...t});a.req=t?.req||i,i.res=a;let o=Vn(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},Un=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=Hn(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},Wn=async({middleware:e,ctx:t={},...n})=>{let{requestMock:r,responseMock:i,loggerMock:a,configMock:{inputSources:o,errorHandler:s=W}}=Hn(n),c={request:r,response:i,logger:a,input:_e(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:C(e),output:null}),{requestMock:r,responseMock:i,loggerMock:a,output:{}}}};var Gn=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,n)=>typeof e==`number`?this.f.createKeywordTypeNode(e):typeof e==`string`||this.ts.isIdentifier(e)?this.f.createTypeReferenceNode(e,n&&t.map(this.ensureTypeNode,n)):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,n,{isOptional:r,hasUndefined:i=r,isDeprecated:a,comment:o}={})=>{let s=this.ensureTypeNode(n),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=t.reject(t.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,n)=>this.makeType(e,this.makeUnion(t.map(this.makeLiteralType,n)),{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=>t.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,n,{isAsync:r}={})=>this.f.createArrowFunction(r?this.asyncModifier:void 0,void 0,Array.isArray(e)?t.map(this.makeParam,e):this.makeParams(e),void 0,void 0,n);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 Kn=class{api;paths=new Set;tags=new Map;registry=new Map;constructor(e,t){this.serverUrl=t,this.api=new Gn(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,ce);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,n])=>this.api.f.createPropertyAssignment(this.api.makePropertyIdentifier(e),this.api.f.createArrayLiteralExpression(t.map(this.api.literally,n))))),{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(x.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(x.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 qn=(t,{rules:n,onMissing:r,ctx:i={}})=>{let a=e(t),o=a&&a in n?n[a]:n[t._zod.def.type],s=e=>qn(e,{ctx:i,rules:n,onMissing:r});return o?o(t,{...i,next:s}):r(t,i)},Jn={name:t.path([`name`,`text`]),type:t.path([`type`]),optional:t.path([`questionToken`])},Yn=({_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)},Xn=({_zod:{def:e}},{next:t,api:n})=>{let r=[...e.parts],i=()=>{let e=``;for(;r.length;){let t=r.shift();if(T(t)){r.unshift(t);break}e+=t??``}return e},a=n.f.createTemplateHead(i()),o=[];for(;r.length;){let e=t(r.shift()),a=i(),s=r.length?n.f.createTemplateMiddle:n.f.createTemplateTail;o.push(n.f.createTemplateLiteralTypeSpan(e,s(a)))}return o.length?n.f.createTemplateLiteralType(a,o):n.makeLiteralType(a.text)},Zn=(e,{isResponse:t,next:i,makeAlias:a,api:o})=>{let s=()=>{let a=Object.entries(e._zod.def.shape).map(([e,a])=>{let{description:s,deprecated:c}=n.get(a)||{},l=(t?a._zod.optout:a._zod.optin)===`optional`,u=l&&!(a instanceof r.core.$ZodExactOptional);return o.makeInterfaceProp(e,i(a),{comment:s,isDeprecated:c,isOptional:l,hasUndefined:u})});return o.f.createTypeLiteralNode(a)};return Fe(e,{io:t?`output`:`input`})?a(e,s):s()},Qn=({_zod:{def:e}},{next:t,api:n})=>n.f.createArrayTypeNode(t(e.element)),$n=({_zod:{def:e}},{api:n})=>n.makeUnion(t.map(n.makeLiteralType,Object.values(e.entries))),er=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion(e.options.map(t)),tr=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion([t(e.innerType),n.makeLiteralType(null)]),nr=({_zod:{def:e}},{next:t,api:n})=>n.f.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:n.f.createRestTypeNode(t(e.rest)))),rr=({_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},ir=t.tryCatch((e,n)=>{if(!n.every(e.ts.isTypeLiteralNode))throw Error(`Not objects`);let r=t.chain(t.prop(`members`),n),i=t.uniqWith((...e)=>{if(!t.eqBy(Jn.name,...e))return!1;if(t.both(t.eqBy(Jn.type),t.eqBy(Jn.optional))(...e))return!0;throw Error(`Has conflicting prop`)},r);return e.f.createTypeLiteralNode(i)},(e,t,n)=>t.f.createIntersectionTypeNode(n)),ar=({_zod:{def:e}},{next:t,api:n})=>ir(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),or=(e,t)=>e.ensureTypeNode(t?e.ts.SyntaxKind.UnknownKeyword:e.ts.SyntaxKind.AnyKeyword),sr=({_zod:{def:e}},{next:t,isResponse:n,api:r})=>{let i=e[n?`out`:`in`],a=e[n?`in`:`out`];if(!T(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=ye(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]||or(r,n))},cr=({},{api:e})=>e.makeLiteralType(null),lr=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),ur=({},{api:e})=>e.ensureTypeNode(`Buffer`),dr=(e,{next:t})=>t(e._zod.def.shape.raw),fr={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:cr,array:Qn,tuple:nr,record:rr,object:Zn,literal:Yn,template_literal:Xn,intersection:ar,union:er,default:$,enum:$n,optional:$,nonoptional:$,nullable:tr,catch:$,pipe:sr,lazy:lr,readonly:$,[A]:ur,[R]:dr},pr=(e,{brandHandling:t,ctx:n})=>qn(e,{rules:{...t,...fr},onMissing:({},{isResponse:e,api:t})=>or(t,e),ctx:n});var mr=class e extends Kn{#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:n,config:i,brandHandling:a,variant:o=`client`,clientClassName:s=`Client`,subscriptionClassName:c=`Subscription`,serverUrl:l=`https://example.com`,noContent:u=r.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,n,r)=>{let i=D.bind(null,e,n),{isDeprecated:a,inputSchema:o,tags:s}=r,c=`${e} ${n}`,l=this.api.makeType(i(`input`),pr(o,p),{comment:c});this.#e.push(l);let d=Ye.reduce((n,a)=>{let o=r.getResponses(a),s=t.chain(([t,{schema:n,mimeTypes:r,statusCodes:o}])=>{let s=be(e,r),l=this.api.makeType(i(a,`variant`,`${t+1}`),pr(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(n,{[a]:l})},{});this.paths.add(n);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)};St({routing:n,config:i,onEndpoint:d?ht(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
|
+
`))},Yt=e=>{e.startupLogo!==!1&&Jt(process.stdout);let t=e.errorHandler||U,n=ot(e.logger)?e.logger:new ut(e.logger);n.debug(`Running`,{build:`v28.0.0-beta.3`,env:process.env.NODE_ENV||`development`}),Kt(n);let r=Wt({logger:n,config:e}),i={getLogger:Gt(n),errorHandler:t},a=zt(i),o=Rt(i);return{...i,logger:n,notFoundHandler:a,catcher:o,loggingMiddleware:r}},Xt=(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,loggingMiddleware:a}=Yt(e);return At({app:e.app.use(a),routing:t,getLogger:r,config:e}),{notFoundHandler:i,logger:n}},Zt=async(e,t)=>{let{logger:n,getLogger:r,notFoundHandler:i,catcher:a,loggingMiddleware:o}=Yt(e),s=_().disable(`x-powered-by`).set(`query parser`,e.queryParser??`simple`).use(o);if(e.compression){let t=await q(`compression`);s.use(t(typeof e.compression==`object`?e.compression:void 0))}await e.beforeRouting?.({app:s,getLogger:r}),At({app:s,routing:t,getLogger:r,config:e,parsers:{json:[e.jsonParser||_.json()],raw:[e.rawParser||_.raw(),Ut],form:[e.formParser||_.urlencoded()],upload:e.upload?await Ht({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&&qt({logger:n,servers:c,options:e.gracefulShutdown===!0?{}:e.gracefulShutdown}),{app:s,logger:n,servers:u.map(e=>e())}},Qt=e=>E(e)&&`or`in e,$t=e=>E(e)&&`and`in e,en=e=>!$t(e)&&!Qt(e),tn=e=>{let t=n.filter(en,e),r=n.chain(n.prop(`and`),n.filter($t,e)),[i,a]=n.partition(en,r),o=n.concat(t,i),s=n.filter(Qt,e);return n.map(n.prop(`or`),n.concat(s,a)).reduce((e,t)=>w(e,n.map(e=>en(e)?[e]:e.and,t),([e,t])=>n.concat(e,t)),n.reject(n.isEmpty,[o]))};var nn=`a-im.accept.accept-additions.accept-ch.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.alternates.amp-cache-transform.apply-to-redirect-ref.authentication-control.authentication-info.authorization.available-dictionary.c-ext.c-man.c-opt.c-pep.c-pep-info.cache-control.cal-managed-id.caldav-timezones.capsule-protocol.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.cross-origin-embedder-policy.cross-origin-embedder-policy-report-only.cross-origin-opener-policy.cross-origin-opener-policy-report-only.cross-origin-resource-policy.cta-common-access-token.dasl.date.dav.default-style.delta-base.deprecation.depth.derived-from.destination.detached-jws.differential-id.dictionary-id.digest.dpop.dpop-nonce.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.nel.odata-entityid.odata-isolation.odata-maxversion.odata-version.opt.ordering-type.origin.origin-agent-cluster.oscore.oslc-core-version.overwrite.p3p.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.public.public-key-pins.public-key-pins-report-only.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.setprofile.signature.signature-input.slug.soapaction.status-uri.sunset.surrogate-capability.tcn.te.timeout.topic.traceparent.tracestate.trailer.transfer-encoding.ttl.upgrade.urgency.uri.use-as-dictionary.user-agent.variant-vary.via.want-content-digest.want-digest.want-repr-digest.warning.x-content-type-options.x-frame-options`.split(`.`);const rn=`https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString`,an={integer:0,number:0,string:``,boolean:!1,object:{},null:null,array:[]},on=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`}}),ln=({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}}},un=n.tryCatch(({jsonSchema:e})=>{if(!e.allOf)throw`no allOf`;return J(e,`throw`)},(e,{jsonSchema:t})=>t),dn=({jsonSchema:e})=>{if(!e.anyOf)return e;let t=e.anyOf[0];return Object.assign(t,{type:_n(t.type)})},Y=e=>e,fn=({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:rn}};return e?.length&&(r.examples=e),r},pn=({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:rn}};return e?.length&&(r.examples=e),r},mn=()=>({type:`string`,format:`bigint`,pattern:`^-?\\d+$`}),hn=({zodSchema:e,jsonSchema:t})=>e._zod.def.rest===null?{...t,items:{not:{}}}:t,gn=e=>{let t=Array.isArray(e.type)?e.type[0]:e.type;return an?.[t]},_n=e=>e===`null`?e:typeof e==`string`?[e,`null`]:e&&[...new Set(e).add(`null`)],vn=({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=Y(Tn(i,{ctx:n}));if(v(a))if(n.isResponse){let e=be(r,gn(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},yn=({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},bn=e=>e.length?n.fromPairs(n.zip(n.times(e=>`example${e+1}`,e.length),n.map(n.objOf(`value`),e))):void 0,xn=(e,t)=>t?.includes(e)||e.startsWith(`x-`)||nn.includes(e),Sn=({path:e,method:t,request:r,inputSources:i,makeRef:a,composition:o,isHeader:s,security:c,description:l=`${t.toUpperCase()} ${e} Parameter`})=>{let u=J(r),d=fe(e),f=i.includes(`query`),p=i.includes(`params`),m=i.includes(`headers`),h=e=>p&&d.includes(e),g=n.chain(n.filter(e=>e.type===`header`),c??[]).map(({name:e})=>e),_=n=>m&&(s?.(n,t,e)??xn(n,g));return Object.entries(u.properties).reduce((e,[t,r])=>{if(!E(r))return e;let i=h(t)?`path`:_(t)?`header`:f?`query`:void 0;if(!i)return e;let s=Y(r),c=o===`components`?a(r.id||JSON.stringify(r),s,r.id||T(l,t)):s;return e.concat({name:t,in:i,deprecated:r.deprecated,required:u.required?.includes(t)||!1,description:s.description||l,schema:c,examples:bn(v(s)&&s.examples?.length?s.examples:n.pluck(t,u.examples?.filter(n.both(E,n.has(t)))||[]))})},[])},Cn={nullable:dn,union:ln,bigint:mn,intersection:un,tuple:hn,pipe:vn,[j]:fn,[M]:pn,[I]:sn,[L]:yn,[A]:cn},wn=(e,t,r)=>{let i=[e,t];for(;i.length;){let e=i.shift();if(n.is(Object,e)){if(ie(e)&&!e.$ref.startsWith(`#/components`)){let n=t[e.$ref.split(`/`).pop()];n&&(e.$ref=r.makeRef(n.id||n,Y(n),n.id).$ref);continue}i.push(...n.values(e))}n.is(Array,e)&&i.push(...n.values(e))}return e},Tn=(e,{ctx:n,rules:r=Cn})=>{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 wn(E(a.subject)?a.subject:{},i,n)},En=(e,t)=>{if(ie(e))return[e,!1];let r=!1,i=n.map(e=>{let[n,i]=En(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]},Dn=({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=Y(Tn(r,{rules:{...u,...Cn},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:bn(p)};return{description:d,content:n.fromPairs(n.xprod(i,[m]))}},On=({format:e})=>{let t={type:`http`,scheme:`bearer`};return e&&(t.bearerFormat=e),t},kn=({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},An=({name:e})=>({type:`apiKey`,in:`header`,name:e}),jn=({name:e})=>({type:`apiKey`,in:`cookie`,name:e}),Mn=({url:e})=>({type:`openIdConnect`,openIdConnectUrl:e}),Nn=({flows:e={}})=>({type:`oauth2`,flows:n.map(e=>({...e,scopes:e.scopes||{}}),n.reject(n.isNil,e))}),Pn=(e,t=[])=>{let n=e=>e.type===`basic`?{type:`http`,scheme:`basic`}:e.type===`bearer`?On(e):e.type===`input`?kn(e,t):e.type===`header`?An(e):e.type===`cookie`?jn(e):e.type===`openid`?Mn(e):Nn(e);return e.map(e=>e.map(n))},Fn=(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:[]})},{})),In=({schema:e,brandHandling:t,makeRef:n,path:r,method:i})=>Tn(e,{rules:{...t,...Cn},ctx:{isResponse:!1,makeRef:n,path:r,method:i}}),Ln=({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]=En(Y(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:bn(f.length?f:J(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},Rn=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)},[]),zn=(e,t=50)=>!e||e.length<=t?e:e.slice(0,t-1)+`…`,Bn=e=>e.length?e.slice():void 0,Vn=({description:e,summary:t=e,trim:n})=>n(t);var Hn=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?0:1;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=Vn,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)),_=In({...a,schema:m}),ee=tn(i.security),te=Sn({...a,inputSources:h,isHeader:l,security:ee,request:_,description:o?.requestParameter?.({method:e,path:r,operationId:g})}),ne={};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)ne[l]=Dn({...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 re=h.includes(`body`)?Ln({...a,request:_,paramNames:n.pluck(`name`,te),schema:m,mimeType:y[i.requestType],description:o?.requestBody?.({method:e,path:r,operationId:g})}):void 0,ie=Fn(Pn(ee,h),p,e=>{let t=this.#a(e);return this.addSecurityScheme(t,e),t}),v={operationId:g,summary:d({summary:u,description:c,trim:zn}),description:c,deprecated:i.isDeprecated||void 0,tags:Bn(i.tags),parameters:Bn(te),requestBody:re,security:Bn(ie),responses:ne};this.addPath(on(r),{[e]:v})};Tt({routing:e,config:t,onEndpoint:u?vt(p):p}),c&&(this.rootDoc.tags=Rn(c))}};const Un=e=>ae({...e,headers:{"content-type":y.json,...e?.headers}}),Wn=e=>oe(e),Gn=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)}})},Kn=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=Un(e),a=Wn({req:i,...t});a.req=t?.req||i,i.res=a;let o=Gn(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},qn=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=Kn(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},Jn=async({middleware:e,ctx:t={},...n})=>{let{requestMock:r,responseMock:i,loggerMock:a,configMock:{inputSources:o,errorHandler:s=U}}=Kn(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 Yn=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 X=e=>e;var Xn=class{api;paths=new Set;tags=new Map;registry=new Map;constructor(e,t){this.serverUrl=t,this.api=new Yn(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,X(`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,X(`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=X(`nextCursor`),t=X(`total`),n=X(`limit`),r=X(`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=X(`nextCursor`),n=X(`total`),r=X(`limit`),i=X(`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(X(`method`),this.api.makeCall(this.#e.methodParameter,X(`toUpperCase`))()),t=this.api.f.createPropertyAssignment(X(`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(X(`body`),this.api.makeTernary(this.#e.hasBodyConst,this.api.makeCall(JSON[Symbol.toStringTag],X(`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`)]),X(`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,X(`headers`),X(`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,X(`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(X(`json`)),this.api.literally(X(`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(X(`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(X(`data`)))},this.api.makeMaybeAsync(this.api.ts.SyntaxKind.VoidKeyword))}),[this.api.f.createExpressionStatement(this.api.makeCall(this.api.f.createThis(),this.#e.sourceProp,X(`addEventListener`))(this.#e.eventParameter,this.api.makeArrowFn([this.#e.msgParameter],this.api.makeCall(this.#e.handlerParameter)(this.api.makeCall(JSON[Symbol.toStringTag],X(`parse`))(this.api.f.createPropertyAccessExpression(this.api.f.createParenthesizedExpression(this.api.f.createAsExpression(this.api.makeId(this.#e.msgParameter),this.api.ensureTypeNode(MessageEvent.name))),X(`data`))))))),this.api.f.createReturnStatement(this.api.f.createThis())],{typeParams:{E:this.api.makeIndexed(`R`,this.api.makeLiteralType(X(`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 Zn=(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=>Zn(e,{ctx:r,rules:t,onMissing:n});return a?a(e,{...r,next:o}):n(e,r)},Z={name:n.path([`name`,`text`]),type:n.path([`type`]),optional:n.path([`questionToken`])},Qn=({_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)},$n=({_zod:{def:e}},{next:t,api:n})=>{let r=[...e.parts],i=()=>{let e=``;for(;r.length;){let t=r.shift();if(C(t)){r.unshift(t);break}e+=t??``}return e},a=n.f.createTemplateHead(i()),o=[];for(;r.length;){let e=t(r.shift()),a=i(),s=r.length?n.f.createTemplateMiddle:n.f.createTemplateTail;o.push(n.f.createTemplateLiteralTypeSpan(e,s(a)))}return o.length?n.f.createTemplateLiteralType(a,o):n.makeLiteralType(a.text)},er=(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()},tr=({_zod:{def:e}},{next:t,api:n})=>n.f.createArrayTypeNode(t(e.element)),nr=({_zod:{def:e}},{api:t})=>t.makeUnion(n.map(t.makeLiteralType,Object.values(e.entries))),rr=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion(e.options.map(t)),ir=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion([t(e.innerType),n.makeLiteralType(null)]),ar=({_zod:{def:e}},{next:t,api:n})=>n.f.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:n.f.createRestTypeNode(t(e.rest)))),or=({_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},sr=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(Z.name,...e))return!1;if(n.both(n.eqBy(Z.type),n.eqBy(Z.optional))(...e))return!0;throw Error(`Has conflicting prop`)},r);return e.f.createTypeLiteralNode(i)},(e,t,n)=>t.f.createIntersectionTypeNode(n)),cr=({_zod:{def:e}},{next:t,api:n})=>sr(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),lr=(e,t)=>e.ensureTypeNode(t?e.ts.SyntaxKind.UnknownKeyword:e.ts.SyntaxKind.AnyKeyword),ur=({_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]||lr(r,n))},dr=({},{api:e})=>e.makeLiteralType(null),fr=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),pr=({},{api:e})=>e.ensureTypeNode(`Buffer`),mr=(e,{next:t})=>t(e._zod.def.shape.raw),hr={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:tr,tuple:ar,record:or,object:er,literal:Qn,template_literal:$n,intersection:cr,union:rr,default:$,enum:nr,optional:$,nonoptional:$,nullable:ir,catch:$,pipe:ur,lazy:fr,readonly:$,[A]:pr,[L]:mr},gr=(e,{brandHandling:t,ctx:n})=>Zn(e,{rules:{...t,...hr},onMissing:({},{isResponse:e,api:t})=>lr(t,e),ctx:n});var _r=class e extends Xn{#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`),gr(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}`),gr(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)};Tt({routing:r,config:i,onEndpoint:d?vt(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 q(`typescript`)})}#i(e){return this.#n.length?this.#n.map(t=>typeof t==`string`?t:this.api.printNode(t,e)).join(`
|
|
19
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(`
|
|
20
19
|
|
|
21
|
-
`)}async printFormatted({printerOptions:e,format:t}={}){let n=t;if(!n)try{let e=(await
|
|
22
|
-
`)).parse({event:t,data:n}),
|
|
20
|
+
`)}async printFormatted({printerOptions:e,format:t}={}){let n=t;if(!n)try{let e=(await q(`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 vr=(e,n)=>t.object({data:n,event:t.literal(e),id:t.string().optional(),retry:t.int().positive().optional()}),yr=(e,t,n)=>vr(String(t),e[t]).transform(e=>[`event: ${e.event}`,`data: ${JSON.stringify(e.data)}`,``,``].join(`
|
|
21
|
+
`)).parse({event:t,data:n}),br=e=>e.headersSent||e.writeHead(200,{connection:`keep-alive`,"content-type":y.sse,"cache-control":`no-cache`}),xr=e=>new B({handler:async({request:t,response:n})=>{let r=new AbortController;return t.once(`close`,()=>{r.abort()}),setTimeout(()=>br(n),1e4),{isClosed:()=>n.writableEnded||n.closed,signal:r.signal,emit:(t,r)=>{br(n),n.write(yr(e,t,r),`utf-8`),n.flush?.()}}}}),Sr=e=>new H({positive:()=>{let[n,...r]=Object.entries(e).map(([e,t])=>vr(e,t));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=R(t);Ue(a,n,r,i),e.headersSent||e.status(a.statusCode).type(`text/plain`).write(z(a),`utf-8`)}e.end()}});var Cr=class extends W{constructor(e){super(Sr(e)),this.middlewares=[xr(e)]}};const wr=[`total`,`limit`,`offset`],Tr=[`nextCursor`,`limit`];function Er({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`&&wr.includes(r))throw Error(`ez.paginated: itemsName must not match reserved keys for offset output (${wr.join(`, `)})`);if(e===`cursor`&&Tr.includes(r))throw Error(`ez.paginated: itemsName must not match reserved keys for cursor output (${Tr.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 Dr={dateIn:we,dateOut:Te,form:Me,upload:Ne,raw:Ie,buffer:Ce,paginated:Er};export{ut as BuiltinLogger,Hn as Documentation,P as DocumentationError,W as EndpointsFactory,Cr as EventStreamFactory,F as InputValidationError,_r as Integration,B as Middleware,Ae as MissingPeerError,Oe as OutputValidationError,H as ResultHandler,N as RoutingError,dt as ServeStatic,it as arrayEndpointsFactory,nt as arrayResultHandler,Xt as attachRouting,se as createConfig,Zt as createServer,rt as defaultEndpointsFactory,U as defaultResultHandler,R as ensureHttpError,Dr as ez,S as getMessageFromError,qn as testEndpoint,Jn as testMiddleware};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "express-zod-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "28.0.0-beta.3",
|
|
4
4
|
"description": "A Typescript framework to help you get an API server up and running with I/O schema validation and custom middlewares in minutes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"bugs": "https://github.com/RobinTail/express-zod-api/issues",
|
|
17
17
|
"funding": "https://github.com/sponsors/RobinTail",
|
|
18
18
|
"type": "module",
|
|
19
|
-
"sideEffects": true,
|
|
20
19
|
"main": "dist/index.js",
|
|
21
20
|
"types": "dist/index.d.ts",
|
|
22
21
|
"module": "dist/index.js",
|
|
@@ -31,14 +30,13 @@
|
|
|
31
30
|
"*.md"
|
|
32
31
|
],
|
|
33
32
|
"engines": {
|
|
34
|
-
"node": "^
|
|
33
|
+
"node": "^22.19.0 || ^24.0.0"
|
|
35
34
|
},
|
|
36
35
|
"dependencies": {
|
|
37
36
|
"ansis": "^4.2.0",
|
|
38
37
|
"node-mocks-http": "^1.17.2",
|
|
39
38
|
"openapi3-ts": "^4.5.0",
|
|
40
|
-
"ramda": "^0.32.0"
|
|
41
|
-
"@express-zod-api/zod-plugin": "^4.1.0"
|
|
39
|
+
"ramda": "^0.32.0"
|
|
42
40
|
},
|
|
43
41
|
"peerDependencies": {
|
|
44
42
|
"@types/compression": "^1.7.5",
|
|
@@ -50,9 +48,13 @@
|
|
|
50
48
|
"express-fileupload": "^1.5.0",
|
|
51
49
|
"http-errors": "^2.0.1",
|
|
52
50
|
"typescript": "^5.1.3 || ^6.0.2",
|
|
53
|
-
"zod": "^4.3.4"
|
|
51
|
+
"zod": "^4.3.4",
|
|
52
|
+
"@express-zod-api/zod-plugin": "^5.0.0-beta.3"
|
|
54
53
|
},
|
|
55
54
|
"peerDependenciesMeta": {
|
|
55
|
+
"@express-zod-api/zod-plugin": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
56
58
|
"@types/compression": {
|
|
57
59
|
"optional": true
|
|
58
60
|
},
|
|
@@ -94,8 +96,9 @@
|
|
|
94
96
|
"node-forge": "^1.3.3",
|
|
95
97
|
"snakify-ts": "^2.3.0",
|
|
96
98
|
"typescript": "^6.0.2",
|
|
97
|
-
"undici": "^
|
|
98
|
-
"zod": "^4.3.4"
|
|
99
|
+
"undici": "^8.0.0",
|
|
100
|
+
"zod": "^4.3.4",
|
|
101
|
+
"@express-zod-api/zod-plugin": "^5.0.0-beta.3"
|
|
99
102
|
},
|
|
100
103
|
"keywords": [
|
|
101
104
|
"nodejs",
|
|
@@ -120,7 +123,7 @@
|
|
|
120
123
|
"validation"
|
|
121
124
|
],
|
|
122
125
|
"scripts": {
|
|
123
|
-
"build": "tsdown
|
|
126
|
+
"build": "tsdown",
|
|
124
127
|
"pretest": "tsc",
|
|
125
128
|
"test": "vitest run --coverage",
|
|
126
129
|
"bench": "vitest bench --run ./bench"
|