express-zod-api 27.0.0 → 27.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,10 +2,45 @@
2
2
 
3
3
  ## Version 27
4
4
 
5
+ ### v27.1.0
6
+
7
+ - Introducing `ez.paginated()` helper for creating paginated endpoints:
8
+ - The configurable helper returns `input` and `output` schemas for your Endpoint;
9
+ - Use the `style` option to choose between `offset` and `cursor` pagination;
10
+ - The `itemsName` option configures the name of the property containing the items array;
11
+ - The `Integration` generator now equips the `Client` with a static `hasMore()` method;
12
+ - The `Incremental` added to the list of well-known recognizable request headers.
13
+
14
+ ```ts
15
+ import { z } from "zod";
16
+ import { ez, defaultEndpointsFactory } from "express-zod-api";
17
+
18
+ const pagination = ez.paginated({
19
+ style: "offset", // or "cursor"
20
+ itemSchema: z.object({ id: z.number(), name: z.string() }),
21
+ itemsName: "users", // defines the output name of the items array
22
+ maxLimit: 100,
23
+ defaultLimit: 20,
24
+ });
25
+
26
+ const listUsers = defaultEndpointsFactory.build({
27
+ input: pagination.input,
28
+ output: pagination.output,
29
+ handler: async ({ input: { limit, offset } }) => {
30
+ const { users, total } = await db.getUsers(limit, offset);
31
+ return { users, total, limit, offset }; // or { users, nextCursor, limit } for cursor pagination
32
+ },
33
+ });
34
+ ```
35
+
36
+ ### v27.0.1
37
+
38
+ - Removed debug-level comments from the declaration files in the distribution.
39
+
5
40
  ### v27.0.0
6
41
 
7
42
  - Supported `zod` versions: `^4.3.4`;
8
- - The new version of Zod Plugin utilizes the inheritable metadata feature of Zod 4.3;
43
+ - The new version of Zod Plugin uses the inheritable metadata feature of Zod 4.3;
9
44
  - The `typescript` dependency is now optional and only required for making `Integration`:
10
45
  - Either import and assign the `typescript` property to its constructor argument;
11
46
  - Or use the new static async method `create()` to delegate the import;
@@ -2182,7 +2217,7 @@ const labeledDefaultSchema = withMeta(
2182
2217
  capabilities, so that the user could subscribe to subsequent updates initiated by the server;
2183
2218
  - Check out an [example of the synergy between two frameworks](https://github.com/RobinTail/zod-sockets#subscriptions)
2184
2219
  and the [Demo Chat application](https://github.com/RobinTail/chat);
2185
- - The feature suggested by [@ben-xD](https://github.com/ben-xD).
2220
+ - The feature suggested by [@uxduck](https://github.com/uxduck).
2186
2221
 
2187
2222
  ### v18.1.0
2188
2223
 
package/README.md CHANGED
@@ -26,14 +26,15 @@ Start your API server with I/O schema validation and custom middlewares in minut
26
26
  7. [Transformations](#transformations)
27
27
  8. [Top level transformations and mapping](#top-level-transformations-and-mapping)
28
28
  9. [Dealing with dates](#dealing-with-dates)
29
- 10. [Cross-Origin Resource Sharing](#cross-origin-resource-sharing) (CORS)
30
- 11. [Enabling HTTPS](#enabling-https)
31
- 12. [Enabling compression](#enabling-compression)
32
- 13. [Customizing logger](#customizing-logger)
33
- 14. [Child logger](#child-logger)
29
+ 10. [Pagination](#pagination)
30
+ 11. [Cross-Origin Resource Sharing](#cross-origin-resource-sharing) (CORS)
31
+ 12. [Enabling HTTPS](#enabling-https)
32
+ 13. [Enabling compression](#enabling-compression)
33
+ 14. [Customizing logger](#customizing-logger)
34
+ 15. [Child logger](#child-logger)
34
35
  5. [Advanced features](#advanced-features)
35
36
  1. [Customizing input sources](#customizing-input-sources)
36
- 2. [Headers as input source](#headers-as-input-source)
37
+ 2. [Headers as input source](#headers-as-an-input-source)
37
38
  3. [Response customization](#response-customization)
38
39
  4. [Empty response](#empty-response)
39
40
  5. [Non-JSON response](#non-json-response) including file downloads
@@ -46,8 +47,8 @@ Start your API server with I/O schema validation and custom middlewares in minut
46
47
  12. [Testing middlewares](#testing-middlewares)
47
48
  6. [Integration and Documentation](#integration-and-documentation)
48
49
  1. [Zod Plugin](#zod-plugin)
49
- 2. [Generating a Frontend Client](#generating-a-frontend-client)
50
- 3. [Creating a documentation](#creating-a-documentation)
50
+ 2. [End-to-End Type Safety](#end-to-end-type-safety)
51
+ 3. [Creating documentation](#creating-documentation)
51
52
  4. [Tagging the endpoints](#tagging-the-endpoints)
52
53
  5. [Deprecated schemas and routes](#deprecated-schemas-and-routes)
53
54
  6. [Customizable brands handling](#customizable-brands-handling)
@@ -66,9 +67,9 @@ See also [Changelog](CHANGELOG.md) and [automated migration](https://www.npmjs.c
66
67
 
67
68
  # Overview
68
69
 
69
- I made this framework because of the often repetitive tasks of starting a web server APIs with the need to validate input
70
- data. It integrates and provides the capabilities of popular web server, logging, validation and documenting solutions.
71
- Therefore, many basic tasks can be accomplished faster and easier, in particular:
70
+ I made this framework because of the often repetitive tasks of starting web server APIs with the need to validate input
71
+ data. It integrates and provides the capabilities of popular web server, logging, validation, and documenting solutions.
72
+ Therefore, many basic tasks can be achieved faster and easier, in particular:
72
73
 
73
74
  - You can describe web server routes as a hierarchical object.
74
75
  - You can keep the endpoint's input and output type declarations right next to its handler.
@@ -76,14 +77,14 @@ Therefore, many basic tasks can be accomplished faster and easier, in particular
76
77
  you expect a number.
77
78
  - Variables within an endpoint handler have types according to the declared schema, so your IDE and TypeScript will
78
79
  provide you with necessary hints to focus on bringing your vision to life.
79
- - All of your endpoints can respond in a consistent way.
80
- - The expected endpoint input and response types can be exported to the frontend, so you don't get confused about the
81
- field names when you implement the client for your API.
80
+ - All of your endpoints can respond consistently.
81
+ - The expected endpoint input and response types can be exported to the frontend, giving you end-to-end type safety
82
+ so you don't get confused about the field names when you implement the client for your API.
82
83
  - You can generate your API documentation in OpenAPI 3.1 and JSON Schema compatible format.
83
84
 
84
85
  ## Contributors
85
86
 
86
- These people contributed to the improvement of the framework by reporting bugs, making changes and suggesting ideas:
87
+ These people contributed to the improvement of the framework by reporting bugs, making changes, and suggesting ideas:
87
88
 
88
89
  [<img src="https://github.com/pycanis.png" alt="@pycanis" width="50" />](https://github.com/pycanis)
89
90
  [<img src="https://github.com/arlyon.png" alt="@arlyon" width="50" />](https://github.com/arlyon)
@@ -116,7 +117,7 @@ These people contributed to the improvement of the framework by reporting bugs,
116
117
  [<img src="https://github.com/rottmann.png" alt="@rottmann" width="50" />](https://github.com/rottmann)
117
118
  [<img src="https://github.com/boarush.png" alt="@boarush" width="50" />](https://github.com/boarush)
118
119
  [<img src="https://github.com/shawncarr.png" alt="@shawncarr" width="50" />](https://github.com/shawncarr)
119
- [<img src="https://github.com/ben-xD.png" alt="@ben-xD" width="50" />](https://github.com/ben-xD)
120
+ [<img src="https://github.com/uxduck.png" alt="@uxduck" width="50" />](https://github.com/uxduck)
120
121
  [<img src="https://github.com/daniel-white.png" alt="@daniel-white" width="50" />](https://github.com/daniel-white)
121
122
  [<img src="https://github.com/kotsmile.png" alt="@kotsmile" width="50" />](https://github.com/kotsmile)
122
123
  [<img src="https://github.com/elee1766.png" alt="@elee1766" width="50" />](https://github.com/elee1766)
@@ -164,7 +165,7 @@ Much can be customized to fit your needs.
164
165
  - [Typescript](https://www.typescriptlang.org/) first.
165
166
  - Web server — [Express.js](https://expressjs.com/) v5.
166
167
  - Schema validation — [Zod 4.x](https://github.com/colinhacks/zod) including [Zod Plugin](#zod-plugin):
167
- - For using with Zod 3.x install the framework versions below 24.0.0.
168
+ - For using with Zod 3.x, install the framework versions below 24.0.0.
168
169
  - Supports any logger having `info()`, `debug()`, `error()` and `warn()` methods;
169
170
  - Built-in console logger with colorful and pretty inspections by default.
170
171
  - Generators:
@@ -320,7 +321,7 @@ const routing: Routing = {
320
321
  };
321
322
  ```
322
323
 
323
- Same Endpoint can be reused on different routes or handle multiple methods if needed. Path parameters (the `:id` above)
324
+ The same Endpoint can be reused on different routes or handle multiple methods. Path parameters (the `:id` above)
324
325
  should be declared in the endpoint’s input schema. Properties assigned with Endpoint can explicitly declare a method.
325
326
  If no method is specified, the methods supported by the endpoint are used (or `get` as a fallback).
326
327
 
@@ -372,7 +373,7 @@ const yourEndpoint = defaultEndpointsFactory
372
373
 
373
374
  You can create a new factory by connecting as many middlewares as you want — they will be executed in the specified
374
375
  order for all the endpoints produced on that factory. You may also use a shorter inline syntax within the
375
- `.addMiddleware()` method, and have access to the output of the previously executed middlewares in chain as `ctx`:
376
+ `.addMiddleware()` method, and have access to the output of the previously executed middlewares in a chain as `ctx`:
376
377
 
377
378
  ```ts
378
379
  import { defaultEndpointsFactory } from "express-zod-api";
@@ -479,7 +480,7 @@ const nicknameConstraintMiddleware = new Middleware({
479
480
  });
480
481
  ```
481
482
 
482
- By the way, you can also refine the whole I/O object, for example in case you need a complex validation of its props.
483
+ By the way, you can also refine the whole I/O object, for example, in case you need a complex validation of its props.
483
484
 
484
485
  ```ts
485
486
  const endpoint = endpointsFactory.build({
@@ -532,7 +533,7 @@ For some APIs it may be important that public interfaces such as query parameter
532
533
  implementation itself requires camel case for internal naming. In order to facilitate interoperability between the
533
534
  different naming standards you can `.transform()` the entire `input` schema into another object using a well-typed
534
535
  mapping library, such as [camelize-ts](https://www.npmjs.com/package/camelize-ts). However, that approach would not be
535
- enough for the `output` schema if you're also aiming to [generate a valid documentation](#creating-a-documentation),
536
+ enough for the `output` schema if you're also aiming to [generate valid documentation](#creating-documentation),
536
537
  because the transformations themselves do not contain schemas. Addressing this case, the framework offers the `.remap()`
537
538
  method of the object schema, a part of the [Zod plugin](#zod-plugin), which under the hood, in addition to the
538
539
  transformation, also `.pipe()` the transformed object into a new object schema.
@@ -575,7 +576,7 @@ in actual response by calling
575
576
  which in turn calls
576
577
  [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString).
577
578
  It is also impossible to transmit the `Date` in its original form to your endpoints within JSON. Therefore, there is
578
- confusion with original method ~~z.date()~~ that is not recommended to use without transformations.
579
+ confusion with the original method ~~z.date()~~ that is not recommended to use without transformations.
579
580
 
580
581
  In order to solve this problem, the framework provides two custom methods for dealing with dates: `ez.dateIn()` and
581
582
  `ez.dateOut()` for using within input and output schemas accordingly.
@@ -612,6 +613,34 @@ const updateUserEndpoint = defaultEndpointsFactory.build({
612
613
  });
613
614
  ```
614
615
 
616
+ ## Pagination
617
+
618
+ Consider using `ez.paginated()` to get reusable `input` and `output` schemas for offset or cursor-based pagination.
619
+ Attach schemas to your endpoint and compose with other params (e.g. `.and(z.object({ ... }))`).
620
+ To check if more pages are available, use [Client::hasMore()](#end-to-end-type-safety).
621
+
622
+ ```ts
623
+ import { z } from "zod";
624
+ import { ez, defaultEndpointsFactory } from "express-zod-api";
625
+
626
+ const pagination = ez.paginated({
627
+ style: "offset", // or "cursor"
628
+ itemSchema: z.object({ id: z.number(), name: z.string() }),
629
+ itemsName: "users", // defines the output name of the items array
630
+ maxLimit: 100,
631
+ defaultLimit: 20,
632
+ });
633
+
634
+ const listUsers = defaultEndpointsFactory.build({
635
+ input: pagination.input,
636
+ output: pagination.output,
637
+ handler: async ({ input: { limit, offset } }) => {
638
+ const { users, total } = await db.getUsers(limit, offset);
639
+ return { users, total, limit, offset }; // or { users, nextCursor, limit } for cursor pagination
640
+ },
641
+ });
642
+ ```
643
+
615
644
  ## Cross-Origin Resource Sharing
616
645
 
617
646
  You can enable your API for other domains using the corresponding configuration option `cors`. The value is required to
@@ -662,7 +691,7 @@ your API at [Let's Encrypt](https://letsencrypt.org/).
662
691
 
663
692
  ## Enabling compression
664
693
 
665
- According to [Express.js best practices guide](https://expressjs.com/en/advanced/best-practice-performance.html)
694
+ According to [Express.js best practices guide](https://expressjs.com/en/advanced/best-practice-performance.html),
666
695
  it might be a good idea to enable GZIP and Brotli compression for your API responses.
667
696
 
668
697
  Install `compression` and `@types/compression`, and enable or configure compression:
@@ -676,7 +705,7 @@ const config = createConfig({
676
705
  });
677
706
  ```
678
707
 
679
- In order to receive a compressed response the client should include the following header in the request:
708
+ To receive a compressed response, the client should include the following header in the request:
680
709
  `Accept-Encoding: br, gzip, deflate`. Only responses with compressible content types are subject to compression.
681
710
 
682
711
  ## Customizing logger
@@ -695,7 +724,7 @@ const config = createConfig({
695
724
  ```
696
725
 
697
726
  You can also replace it with a one having at least the following methods: `info()`, `debug()`, `error()` and `warn()`.
698
- Winston and Pino support is well known. Here is an example configuring `pino` logger with `pino-pretty` extension:
727
+ Winston and Pino support is well-known. Here is an example configuring `pino` logger with `pino-pretty` extension:
699
728
 
700
729
  ```ts
701
730
  import pino, { Logger } from "pino";
@@ -759,11 +788,11 @@ createConfig({
759
788
  });
760
789
  ```
761
790
 
762
- ## Headers as input source
791
+ ## Headers as an input source
763
792
 
764
- In a similar way you can enable request headers as the input source. This is an opt-in feature. Please note:
793
+ Similarly, you can enable request headers as the input source. This is an opt-in feature. Please note:
765
794
 
766
- - consider giving `headers` the lowest priority among other `inputSources` to avoid overwrites;
795
+ - consider giving `headers` the lowest priority among other `inputSources` to avoid overwriting;
767
796
  - consider handling headers in `Middleware` and declaring them within `security` property to improve `Documentation`;
768
797
  - the request headers acquired that way are always lowercase when describing their validation schemas.
769
798
 
@@ -840,8 +869,8 @@ const endpointsFactory = new EndpointsFactory(yourResultHandler);
840
869
 
841
870
  ## Empty response
842
871
 
843
- For some REST APIs, empty responses are typical: with status code `204` (No Content) and redirects (302). In order to
844
- describe it set the `mimeType` to `null` and `schema` to `z.never()`:
872
+ For some REST APIs, empty responses are typical: with status code `204` (No Content) and redirects (302). To describe
873
+ it, set the `mimeType` to `null` and `schema` to `z.never()`:
845
874
 
846
875
  ```ts
847
876
  const resultHandler = new ResultHandler({
@@ -852,13 +881,13 @@ const resultHandler = new ResultHandler({
852
881
 
853
882
  ## Non-JSON response
854
883
 
855
- To configure a non-JSON responses (for example, to send an image file) you should specify its MIME type.
884
+ To configure a non-JSON response (for example, to send an image file), you should specify its MIME type.
856
885
 
857
886
  You can find two approaches to `EndpointsFactory` and `ResultHandler` implementation
858
887
  [in this example](https://github.com/RobinTail/express-zod-api/blob/master/example/factories.ts).
859
888
  One of them implements file streaming, in this case the endpoint just has to provide the filename.
860
889
  The response schema can be `z.string()`, `z.base64()` or `ez.buffer()` to reflect the data accordingly in the
861
- [generated documentation](#creating-a-documentation).
890
+ [generated documentation](#creating-documentation).
862
891
 
863
892
  ```ts
864
893
  const fileStreamingEndpointsFactory = new EndpointsFactory(
@@ -906,7 +935,7 @@ Consider enabling production mode by setting `NODE_ENV` environment variable to
906
935
  - Express activates some [performance optimizations](https://expressjs.com/en/advanced/best-practice-performance.html);
907
936
  - Self-diagnosis for potential problems is disabled to ensure faster startup;
908
937
  - The `defaultResultHandler`, `defaultEndpointsFactory` and `LastResortHandler` generalize server-side error messages
909
- in negative responses in order to improve the security of your API by not disclosing the exact causes of errors:
938
+ in negative responses to improve the security of your API by not disclosing the exact causes of errors:
910
939
  - Throwing errors that have or imply `5XX` status codes become just `Internal Server Error` message in response;
911
940
  - You can control that behavior by throwing errors using `createHttpError()` and using its `expose` option:
912
941
 
@@ -947,7 +976,7 @@ _Hint: for unlisted extra fields use the following syntax: `ez.form( z.object({}
947
976
 
948
977
  Install the following additional packages: `express-fileupload` and `@types/express-fileupload`, and enable or
949
978
  configure file uploads. Refer to [documentation](https://www.npmjs.com/package/express-fileupload#available-options) on
950
- available options. The `limitHandler` option is replaced by the `limitError` one. You can also connect an additional
979
+ available options. The `limitHandler` option is replaced by the `limitError` one. You can also connect additional
951
980
  middleware for restricting the ability to upload using the `beforeUpload` option. So the configuration for the limited
952
981
  and restricted upload might look this way:
953
982
 
@@ -1017,10 +1046,10 @@ then consider using the `beforeRouting` [option in config instead](#using-native
1017
1046
  ## Testing endpoints
1018
1047
 
1019
1048
  The way to test endpoints is to mock the request, response, and logger objects, invoke the `execute()` method, and
1020
- assert the expectations on status, headers and payload. The framework provides a special method `testEndpoint` that
1021
- makes mocking easier. Under the hood, request and response object are mocked using the
1022
- [node-mocks-http](https://www.npmjs.com/package/node-mocks-http) library, therefore you can utilize its API for
1023
- settings additional properties and asserting expectation using the provided getters, such as `._getStatusCode()`.
1049
+ assert the expectations on status, headers, and payload. The framework provides a special method `testEndpoint` that
1050
+ makes mocking easier. Under the hood, the request and response objects are mocked using the
1051
+ [node-mocks-http](https://www.npmjs.com/package/node-mocks-http) library; therefore, you can use its API for
1052
+ settings additional properties and asserting expectations using the provided getters, such as `._getStatusCode()`.
1024
1053
 
1025
1054
  ```ts
1026
1055
  import { testEndpoint } from "express-zod-api";
@@ -1074,10 +1103,11 @@ expect(output).toEqual({ collectedContext: ["prev"], testLength: 9 });
1074
1103
  Express Zod API augments Zod using [Zod Plugin](https://www.npmjs.com/package/@express-zod-api/zod-plugin),
1075
1104
  adding the runtime helpers the framework relies on.
1076
1105
 
1077
- ## Generating a Frontend Client
1106
+ ## End-to-End Type Safety
1078
1107
 
1079
- You can generate a TypeScript file containing the IO types of your API and a client for it. Make sure you have
1080
- `typescript` installed. Consider also installing `prettier` and using the async `printFormatted()` method.
1108
+ You can generate a TypeScript file containing the IO types of your API and a client for it, giving you end-to-end type
1109
+ safety between your API and frontend. Make sure you have `typescript` installed. Consider also installing `prettier`
1110
+ and using the async `printFormatted()` method.
1081
1111
 
1082
1112
  ```ts
1083
1113
  import typescript from "typescript";
@@ -1107,7 +1137,7 @@ client.provide("post /v1/user/:id", { id: "10" }); // it also substitutes path p
1107
1137
  new Subscription("get /v1/events/stream", {}).on("time", (time) => {}); // Server-sent events (SSE)
1108
1138
  ```
1109
1139
 
1110
- ## Creating a documentation
1140
+ ## Creating documentation
1111
1141
 
1112
1142
  You can generate the specification of your API and write it to a `.yaml` file, that can be used as the documentation:
1113
1143
 
@@ -1125,8 +1155,8 @@ const yamlString = new Documentation({
1125
1155
  }).getSpecAsYaml();
1126
1156
  ```
1127
1157
 
1128
- You can add descriptions and examples to your endpoints, their I/O schemas and their properties. It will be included
1129
- into the generated documentation of your API. Consider the following example:
1158
+ You can add descriptions and examples to your endpoints, their I/O schemas, and their properties. They will be included
1159
+ in the generated documentation of your API. Consider the following example:
1130
1160
 
1131
1161
  ```ts
1132
1162
  import { defaultEndpointsFactory } from "express-zod-api";
@@ -1208,8 +1238,8 @@ const routing: Routing = {
1208
1238
 
1209
1239
  You can customize handling rules for your schemas in Documentation and Integration. Use the `.brand()` method on your
1210
1240
  schema to make it special and distinguishable for the framework in runtime. Using symbols is recommended for branding.
1211
- After that utilize the `brandHandling` feature of both constructors to declare your custom implementation. In case you
1212
- need to reuse a handling rule for multiple brands, use the exposed types `Depicter` and `Producer`.
1241
+ After that use the `brandHandling` feature of both constructors to declare your custom implementation. In case you need
1242
+ to reuse a handling rule for multiple brands, use the exposed types `Depicter` and `Producer`.
1213
1243
 
1214
1244
  ```ts
1215
1245
  import ts from "typescript";
@@ -1251,7 +1281,7 @@ new Integration({
1251
1281
  ## Different responses for different status codes
1252
1282
 
1253
1283
  In some special cases you may want the ResultHandler to respond slightly differently depending on the status code,
1254
- for example if your API strictly follows REST standards. It may also be necessary to reflect this difference in the
1284
+ for example, if your API strictly follows REST standards. It may also be necessary to reflect this difference in the
1255
1285
  generated Documentation. For that purpose, the constructor of `ResultHandler` accepts flexible declaration of possible
1256
1286
  response schemas and their corresponding status codes.
1257
1287
 
@@ -1281,13 +1311,10 @@ new ResultHandler({
1281
1311
 
1282
1312
  ## Array response
1283
1313
 
1284
- Please avoid doing this in new projects: responding with array is a bad practice keeping your endpoints from evolving
1285
- in backward compatible way (without making breaking changes). Nevertheless, for the purpose of easier migration of
1286
- legacy APIs to this framework consider using `arrayResultHandler` or `arrayEndpointsFactory` instead of default ones,
1287
- or implement your own ones in a similar way.
1288
- The `arrayResultHandler` expects your endpoint to have `items` property in the `output` object schema. The array
1289
- assigned to that property is used as the response. This approach also supports examples, as well as documentation and
1290
- client generation. Check out [the example endpoint](/example/endpoints/list-users.ts) for more details.
1314
+ Responding with a bare array is not recommended for new APIs (it blocks backward‑compatible changes).
1315
+ For new endpoints, prefer [Pagination](#pagination). For migrating legacy APIs, use `arrayResultHandler` or
1316
+ `arrayEndpointsFactory`: the endpoint output must have an `items` array, which is sent as the response body.
1317
+ See the [bad](/example/endpoints/list-users.ts) and [good](/example/endpoints/list-users-paginated.ts) examples.
1291
1318
 
1292
1319
  ## Accepting raw data
1293
1320
 
@@ -1331,7 +1358,7 @@ doExpensiveOperation();
1331
1358
  done(); // debug: expensive operation '555 milliseconds'
1332
1359
  ```
1333
1360
 
1334
- You can also customize the profiler with your own formatter, chosen severity or even performance assessment function:
1361
+ You can also customize the profiler with your own formatter, chosen severity, or even performance assessment function:
1335
1362
 
1336
1363
  ```ts
1337
1364
  logger.profile({
@@ -1363,10 +1390,10 @@ createConfig({
1363
1390
 
1364
1391
  ## Subscriptions
1365
1392
 
1366
- If you want the user of a client application to be able to subscribe to subsequent updates initiated by the server,
1367
- consider [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) (SSE) feature.
1393
+ If you want the user of a client application to be able to subscribe to further updates initiated by the server,
1394
+ consider the [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) (SSE) feature.
1368
1395
  Client application can subscribe to the event stream using `EventSource` class instance or the
1369
- [instance of the generated](#generating-a-frontend-client) `Subscription` class. The following example demonstrates
1396
+ [instance of the generated](#end-to-end-type-safety) `Subscription` class. The following example demonstrates
1370
1397
  the implementation emitting the `time` event each second.
1371
1398
 
1372
1399
  ```ts
@@ -1400,7 +1427,7 @@ should be aware of them.
1400
1427
  The schema validator removes excessive properties by default. However, TypeScript
1401
1428
  [does not yet display errors](https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks)
1402
1429
  in this case during development. You can achieve this verification by assigning the output schema to a constant and
1403
- reusing it in forced type of the output:
1430
+ reusing it in the forced type of the output:
1404
1431
 
1405
1432
  ```ts
1406
1433
  const output = z.object({ anything: z.number() });
package/dist/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import "@express-zod-api/zod-plugin";
2
- import * as zod0 from "zod";
2
+ import * as zod from "zod";
3
3
  import { z } from "zod";
4
4
  import { HttpError } from "http-errors";
5
- import "ansis";
6
- import * as express0 from "express";
5
+ import * as express$1 from "express";
7
6
  import express, { IRouter, NextFunction, Request, RequestHandler, Response } from "express";
8
7
  import http from "node:http";
9
8
  import https, { ServerOptions } from "node:https";
@@ -15,10 +14,9 @@ import * as express_fileupload0 from "express-fileupload";
15
14
  import fileUpload from "express-fileupload";
16
15
  import { ListenOptions } from "node:net";
17
16
  import * as express_serve_static_core0 from "express-serve-static-core";
18
- import * as qs0 from "qs";
17
+ import * as qs from "qs";
19
18
  import ts from "typescript";
20
19
  import * as zod_v4_core0 from "zod/v4/core";
21
- //#region src/method.d.ts
22
20
  declare const methods: ("get" | "post" | "put" | "delete" | "patch")[];
23
21
  declare const clientMethods: ("get" | "post" | "put" | "delete" | "patch" | "head")[];
24
22
  /**
@@ -33,8 +31,6 @@ type Method = (typeof methods)[number];
33
31
  * @example Method | "head"
34
32
  * */
35
33
  type ClientMethod = (typeof clientMethods)[number];
36
- //#endregion
37
- //#region src/api-response.d.ts
38
34
  /** @public this is the user facing configuration */
39
35
  interface ApiResponse<S extends z.ZodType> {
40
36
  schema: S;
@@ -46,8 +42,6 @@ interface ApiResponse<S extends z.ZodType> {
46
42
  * */
47
43
  mimeType?: string | [string, ...string[]] | null;
48
44
  }
49
- //#endregion
50
- //#region src/common-helpers.d.ts
51
45
  /** @since zod 3.25.61 output type fixed */
52
46
  declare const emptySchema: z.ZodObject<{}, z.core.$strip>;
53
47
  type EmptySchema = typeof emptySchema;
@@ -64,8 +58,6 @@ type NoNever<T, F> = [T] extends [never] ? F : T;
64
58
  interface TagOverrides {}
65
59
  type Tag = NoNever<keyof TagOverrides, string>;
66
60
  declare const getMessageFromError: (error: Error) => string;
67
- //#endregion
68
- //#region src/logger-helpers.d.ts
69
61
  declare const severity: {
70
62
  debug: number;
71
63
  info: number;
@@ -82,8 +74,6 @@ type AbstractLogger = Record<Severity, (message: string, meta?: any) => any>;
82
74
  * */
83
75
  interface LoggerOverrides {}
84
76
  type ActualLogger = AbstractLogger & LoggerOverrides;
85
- //#endregion
86
- //#region src/builtin-logger.d.ts
87
77
  interface Context extends FlatObject {
88
78
  requestId?: string;
89
79
  }
@@ -135,8 +125,6 @@ declare class BuiltinLogger implements AbstractLogger {
135
125
  profile(message: string): () => void;
136
126
  profile(options: ProfilerOptions): () => void;
137
127
  }
138
- //#endregion
139
- //#region src/io-schema.d.ts
140
128
  type Base$1 = object & {
141
129
  [Symbol.iterator]?: never;
142
130
  };
@@ -153,8 +141,6 @@ type FinalInputSchema<FIN extends IOSchema | undefined, BIN extends IOSchema> =
153
141
  FIN extends IOSchema ? FIN : BIN,
154
142
  BIN
155
143
  >;
156
- //#endregion
157
- //#region src/logical-container.d.ts
158
144
  type LogicalOr<T> = {
159
145
  or: T[];
160
146
  };
@@ -162,8 +148,6 @@ type LogicalAnd<T> = {
162
148
  and: T[];
163
149
  };
164
150
  type LogicalContainer<T> = LogicalOr<T | LogicalAnd<T>> | LogicalAnd<T | LogicalOr<T>> | T;
165
- //#endregion
166
- //#region src/security.d.ts
167
151
  interface BasicSecurity {
168
152
  type: "basic";
169
153
  }
@@ -243,8 +227,6 @@ type Security<K extends string = string, S extends string = string> =
243
227
  | CookieSecurity
244
228
  | OpenIdSecurity
245
229
  | OAuth2Security<S>;
246
- //#endregion
247
- //#region src/middleware.d.ts
248
230
  type Handler$2<IN, CTX, RET> = (params: {
249
231
  /** @desc The inputs from the enabled input sources validated against the input schema of the Middleware */
250
232
  input: IN;
@@ -320,8 +302,6 @@ declare class ExpressMiddleware<R extends Request, S extends Response, RET exten
320
302
  },
321
303
  );
322
304
  }
323
- //#endregion
324
- //#region src/result-helpers.d.ts
325
305
  type ResultSchema<R extends Result> = R extends Result<infer S> ? S : never;
326
306
  type DiscriminatedResult =
327
307
  | {
@@ -337,8 +317,6 @@ type DiscriminatedResult =
337
317
  * @example Error —> InternalServerError(500)
338
318
  * */
339
319
  declare const ensureHttpError: (error: Error) => HttpError;
340
- //#endregion
341
- //#region src/result-handler.d.ts
342
320
  type Handler$1<RES = unknown> = (
343
321
  params: DiscriminatedResult & {
344
322
  /** null in case of failure to parse or to find the matching endpoint (error: not found) */
@@ -401,19 +379,13 @@ declare const arrayResultHandler: ResultHandler<
401
379
  mimeType: string;
402
380
  }
403
381
  >;
404
- //#endregion
405
- //#region src/serve-static.d.ts
406
382
  type OriginalStatic = typeof express.static;
407
383
  declare class ServeStatic {
408
384
  #private;
409
385
  constructor(...params: Parameters<OriginalStatic>);
410
386
  }
411
- //#endregion
412
- //#region src/server-helpers.d.ts
413
387
  /** @desc Returns child logger for the given request (if configured) or the configured logger otherwise */
414
388
  type GetLogger = (request?: Request) => ActualLogger;
415
- //#endregion
416
- //#region src/routing.d.ts
417
389
  /**
418
390
  * @example { v1: { books: { ":bookId": getBookEndpoint } } }
419
391
  * @example { "v1/books/:bookId": getBookEndpoint }
@@ -425,8 +397,6 @@ type GetLogger = (request?: Request) => ActualLogger;
425
397
  interface Routing {
426
398
  [K: string]: Routing | AbstractEndpoint | ServeStatic;
427
399
  }
428
- //#endregion
429
- //#region src/endpoint.d.ts
430
400
  type Handler<IN, OUT, CTX> = (params: {
431
401
  /** @desc The inputs from the enabled input sources validated against the final input schema (incl. Middlewares) */
432
402
  input: IN;
@@ -476,8 +446,6 @@ declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, CTX extends Fl
476
446
  config: CommonConfig;
477
447
  }): Promise<undefined>;
478
448
  }
479
- //#endregion
480
- //#region src/config-type.d.ts
481
449
  type InputSource = keyof Pick<Request, "query" | "body" | "files" | "params" | "headers">;
482
450
  type InputSources = Record<Method, InputSource[]>;
483
451
  type Headers = Record<string, string>;
@@ -671,8 +639,6 @@ interface AppConfig extends CommonConfig {
671
639
  }
672
640
  declare function createConfig(config: ServerConfig): ServerConfig;
673
641
  declare function createConfig(config: AppConfig): AppConfig;
674
- //#endregion
675
- //#region src/endpoints-factory.d.ts
676
642
  interface BuildProps<
677
643
  IN extends IOSchema,
678
644
  OUT extends IOSchema | z.ZodVoid,
@@ -728,7 +694,7 @@ declare class EndpointsFactory<
728
694
  subject: Middleware<CTX, RET, ASCO, AIN> | ConstructorParameters<typeof Middleware<CTX, RET, ASCO, AIN>>[0],
729
695
  ): EndpointsFactory<Extension<IN, AIN>, (CTX extends Record<string, never> ? RET : CTX) & RET, SCO & ASCO>;
730
696
  use: <R extends Request, S extends Response, AOUT extends FlatObject = Record<string, never>>(
731
- nativeMw: (request: R, response: S, next: express0.NextFunction) => any,
697
+ nativeMw: (request: R, response: S, next: express$1.NextFunction) => any,
732
698
  params_1?:
733
699
  | {
734
700
  provider?: ((request: R, response: S) => AOUT | Promise<AOUT>) | undefined;
@@ -768,8 +734,6 @@ declare const defaultEndpointsFactory: EndpointsFactory<undefined, Record<string
768
734
  * @desc The result handler of this factory expects your endpoint to have the property 'items' in the output schema
769
735
  */
770
736
  declare const arrayEndpointsFactory: EndpointsFactory<undefined, Record<string, never>, string>;
771
- //#endregion
772
- //#region src/server.d.ts
773
737
  declare const attachRouting: (
774
738
  config: AppConfig,
775
739
  routing: Routing,
@@ -778,7 +742,7 @@ declare const attachRouting: (
778
742
  express_serve_static_core0.ParamsDictionary,
779
743
  any,
780
744
  any,
781
- qs0.ParsedQs,
745
+ qs.ParsedQs,
782
746
  Record<string, any>
783
747
  >;
784
748
  logger: AbstractLogger | BuiltinLogger;
@@ -794,8 +758,6 @@ declare const createServer: (
794
758
  | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse>
795
759
  )[];
796
760
  }>;
797
- //#endregion
798
- //#region src/documentation-helpers.d.ts
799
761
  interface ReqResCommons {
800
762
  makeRef: (key: object | string, value: SchemaObject | ReferenceObject, proposedName?: string) => ReferenceObject;
801
763
  path: string;
@@ -826,8 +788,6 @@ declare const depictTags: (
826
788
  >
827
789
  >,
828
790
  ) => TagObject[];
829
- //#endregion
830
- //#region src/documentation.d.ts
831
791
  type Component = "positiveResponse" | "negativeResponse" | "requestParameter" | "requestBody";
832
792
  /** @desc user defined function that creates a component description from its properties */
833
793
  type Descriptor = (
@@ -894,8 +854,6 @@ declare class Documentation extends OpenApiBuilder {
894
854
  composition,
895
855
  }: DocumentationParams);
896
856
  }
897
- //#endregion
898
- //#region src/errors.d.ts
899
857
  /** @desc An error related to the wrong Routing declaration */
900
858
  declare class RoutingError extends Error {
901
859
  name: string;
@@ -933,8 +891,6 @@ declare class MissingPeerError extends Error {
933
891
  name: string;
934
892
  constructor(module: string);
935
893
  }
936
- //#endregion
937
- //#region src/testing.d.ts
938
894
  interface TestingProps<REQ, LOG> {
939
895
  /**
940
896
  * @desc Additional properties to set on Request mock
@@ -965,7 +921,7 @@ declare const testEndpoint: <LOG extends FlatObject, REQ extends RequestOptions>
965
921
  endpoint: AbstractEndpoint;
966
922
  }) => Promise<{
967
923
  requestMock: node_mocks_http0.MockRequest<
968
- Request<express_serve_static_core0.ParamsDictionary, any, any, qs0.ParsedQs, Record<string, any>> & REQ
924
+ Request<express_serve_static_core0.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>> & REQ
969
925
  >;
970
926
  responseMock: node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
971
927
  loggerMock: AbstractLogger &
@@ -984,7 +940,7 @@ declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOption
984
940
  ctx?: FlatObject;
985
941
  }) => Promise<{
986
942
  requestMock: node_mocks_http0.MockRequest<
987
- Request<express_serve_static_core0.ParamsDictionary, any, any, qs0.ParsedQs, Record<string, any>> & REQ
943
+ Request<express_serve_static_core0.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>> & REQ
988
944
  >;
989
945
  responseMock: node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
990
946
  loggerMock: AbstractLogger &
@@ -993,15 +949,11 @@ declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOption
993
949
  };
994
950
  output: FlatObject;
995
951
  }>;
996
- //#endregion
997
- //#region src/integration-base.d.ts
998
952
  declare abstract class IntegrationBase {
999
953
  #private;
1000
954
  protected readonly serverUrl: string;
1001
955
  protected constructor(typescript: typeof ts, serverUrl: string);
1002
956
  }
1003
- //#endregion
1004
- //#region src/schema-walker.d.ts
1005
957
  interface NextHandlerInc<U> {
1006
958
  next: (schema: z.core.$ZodType) => U;
1007
959
  }
@@ -1019,15 +971,11 @@ type SchemaHandler<
1019
971
  type HandlingRules<U, Context extends FlatObject = EmptyObject, K extends string | symbol = string | symbol> = Partial<
1020
972
  Record<K, SchemaHandler<U, Context>>
1021
973
  >;
1022
- //#endregion
1023
- //#region src/zts-helpers.d.ts
1024
974
  interface ZTSContext extends FlatObject {
1025
975
  isResponse: boolean;
1026
976
  makeAlias: (key: object, produce: () => ts.TypeNode) => ts.TypeNode;
1027
977
  }
1028
978
  type Producer = SchemaHandler<ts.TypeNode, ZTSContext>;
1029
- //#endregion
1030
- //#region src/integration.d.ts
1031
979
  interface IntegrationParams {
1032
980
  typescript: typeof ts;
1033
981
  routing: Routing;
@@ -1093,8 +1041,6 @@ declare class Integration extends IntegrationBase {
1093
1041
  print(printerOptions?: ts.PrinterOptions): string;
1094
1042
  printFormatted({ printerOptions, format: userDefined }?: FormattedPrintingOptions): Promise<string>;
1095
1043
  }
1096
- //#endregion
1097
- //#region src/sse.d.ts
1098
1044
  type EventsMap = Record<string, z.ZodType>;
1099
1045
  interface Emitter<E extends EventsMap> extends FlatObject {
1100
1046
  /** @desc Returns true when the connection was closed or terminated */
@@ -1107,18 +1053,122 @@ interface Emitter<E extends EventsMap> extends FlatObject {
1107
1053
  declare class EventStreamFactory<E extends EventsMap> extends EndpointsFactory<undefined, Emitter<E>> {
1108
1054
  constructor(events: E);
1109
1055
  }
1110
- //#endregion
1111
- //#region src/date-in-schema.d.ts
1112
1056
  interface DateInParams extends Omit<Parameters<z.ZodString["meta"]>[0], "examples"> {
1113
1057
  examples?: string[];
1114
1058
  }
1115
- //#endregion
1116
- //#region src/date-out-schema.d.ts
1117
1059
  interface DateOutParams extends Omit<Parameters<z.ZodString["meta"]>[0], "examples"> {
1118
1060
  examples?: string[];
1119
1061
  }
1120
- //#endregion
1121
- //#region src/raw-schema.d.ts
1062
+ declare const DEFAULT_ITEMS_NAME: "items";
1063
+ /** @desc Common pagination config: shared by offset and cursor styles. */
1064
+ interface CommonPaginationConfig<T extends z.ZodType = z.ZodType, K extends string = typeof DEFAULT_ITEMS_NAME> {
1065
+ /** @desc Zod schema for each item in the paginated list. */
1066
+ itemSchema: T;
1067
+ /**
1068
+ * @desc The name of the property containing the list of items.
1069
+ * @default "items"
1070
+ * */
1071
+ itemsName?: K;
1072
+ /**
1073
+ * @desc Maximum allowed page size (client request is capped to this).
1074
+ * @default 100
1075
+ */
1076
+ maxLimit?: number;
1077
+ /**
1078
+ * @desc Default page size when the client omits the limit parameter.
1079
+ * @default 20
1080
+ */
1081
+ defaultLimit?: number;
1082
+ }
1083
+ /**
1084
+ * @desc Configuration for offset-based pagination (limit and offset).
1085
+ * @example { style: "offset", itemSchema, maxLimit: 50, defaultLimit: 10 }
1086
+ */
1087
+ interface OffsetPaginatedConfig<
1088
+ T extends z.ZodType = z.ZodType,
1089
+ K extends string = typeof DEFAULT_ITEMS_NAME,
1090
+ > extends CommonPaginationConfig<T, K> {
1091
+ /** @desc Discriminator for offset-style pagination. */
1092
+ style: "offset";
1093
+ }
1094
+ /**
1095
+ * @desc Configuration for cursor-based pagination (cursor and limit).
1096
+ * @example { style: "cursor", itemSchema, maxLimit: 50, defaultLimit: 10 }
1097
+ */
1098
+ interface CursorPaginatedConfig<
1099
+ T extends z.ZodType = z.ZodType,
1100
+ K extends string = typeof DEFAULT_ITEMS_NAME,
1101
+ > extends CommonPaginationConfig<T, K> {
1102
+ /** @desc Discriminator for cursor-style pagination. */
1103
+ style: "cursor";
1104
+ }
1105
+ /** @desc Request params for offset pagination. */
1106
+ type OffsetInput = z.ZodObject<{
1107
+ /** @desc Page size (number of items per page). */
1108
+ limit: z.ZodDefault<z.ZodCoercedNumber>;
1109
+ /** @desc Number of items to skip from the start of the list. */
1110
+ offset: z.ZodDefault<z.ZodCoercedNumber>;
1111
+ }>;
1112
+ /** @desc Request params for cursor pagination. */
1113
+ type CursorInput = z.ZodObject<{
1114
+ /** @desc Opaque cursor for the next page; omit for the first page. */
1115
+ cursor: z.ZodOptional<z.ZodString>;
1116
+ /** @desc Page size (number of items per page). */
1117
+ limit: z.ZodDefault<z.ZodCoercedNumber>;
1118
+ }>;
1119
+ /** @desc Response shape for offset pagination. */
1120
+ type OffsetOutput<T extends z.ZodType, K extends string> = z.ZodObject<
1121
+ { [ITEMS in K]: z.ZodArray<T> } & {
1122
+ /** @desc Total number of items across all pages. */
1123
+ total: z.ZodNumber;
1124
+ /** @desc Page size used for this response. */
1125
+ limit: z.ZodNumber;
1126
+ /** @desc Offset used for this response. */
1127
+ offset: z.ZodNumber;
1128
+ }
1129
+ >;
1130
+ /** @desc Response shape for cursor pagination. */
1131
+ type CursorOutput<T extends z.ZodType, K extends string> = z.ZodObject<
1132
+ { [ITEMS in K]: z.ZodArray<T> } & {
1133
+ /** @desc Cursor for the next page, or null if there are no more pages. */
1134
+ nextCursor: z.ZodNullable<z.ZodString>;
1135
+ /** @desc Page size used for this response. */
1136
+ limit: z.ZodNumber;
1137
+ }
1138
+ >;
1139
+ /** @desc Return type of ez.paginated() for offset style. */
1140
+ interface OffsetPaginatedResult<T extends z.ZodType = z.ZodType, K extends string = typeof DEFAULT_ITEMS_NAME> {
1141
+ /** @desc Zod schema for offset pagination request params. */
1142
+ input: OffsetInput;
1143
+ /** @desc Zod schema for offset pagination response. */
1144
+ output: OffsetOutput<T, K>;
1145
+ }
1146
+ /** @desc Return type of ez.paginated() for cursor style. */
1147
+ interface CursorPaginatedResult<T extends z.ZodType = z.ZodType, K extends string = typeof DEFAULT_ITEMS_NAME> {
1148
+ /** @desc Zod schema for cursor pagination request params. */
1149
+ input: CursorInput;
1150
+ /** @desc Zod schema for cursor pagination response. */
1151
+ output: CursorOutput<T, K>;
1152
+ }
1153
+ /**
1154
+ * @desc Creates a pagination helper with a single config for both request params and response shape.
1155
+ * Use the returned `.input` as the endpoint input schema and `.output` as the response schema.
1156
+ * Compose with other params via `.input.and(z.object({ ... }))`.
1157
+ *
1158
+ * @param config - Pagination config; `style` discriminates offset vs cursor; `itemSchema` defines each list item.
1159
+ * @returns Object with `input` (Zod schema for pagination params) and `output` (Zod schema for paginated response).
1160
+ *
1161
+ * @example
1162
+ * const pagination = ez.paginated({ style: "offset", maxLimit: 100, defaultLimit: 20, itemSchema: userSchema });
1163
+ * endpoint.input = pagination.input.and(z.object({ ... }));
1164
+ * endpoint.output = pagination.output;
1165
+ */
1166
+ declare function paginated<T extends z.ZodType, K extends string = typeof DEFAULT_ITEMS_NAME>(
1167
+ config: OffsetPaginatedConfig<T, K>,
1168
+ ): OffsetPaginatedResult<T, K>;
1169
+ declare function paginated<T extends z.ZodType, K extends string = typeof DEFAULT_ITEMS_NAME>(
1170
+ config: CursorPaginatedConfig<T, K>,
1171
+ ): CursorPaginatedResult<T, K>;
1122
1172
  declare const base: z.ZodObject<
1123
1173
  {
1124
1174
  raw: z.core.$ZodBranded<z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>, symbol, "out">;
@@ -1150,42 +1200,40 @@ declare const extended: <S extends z.core.$ZodShape>(
1150
1200
  >;
1151
1201
  declare function raw(): Base;
1152
1202
  declare function raw<S extends z.core.$ZodShape>(extra: S): ReturnType<typeof extended<S>>;
1153
- //#endregion
1154
- //#region src/proprietary-schemas.d.ts
1155
1203
  declare const ez: {
1156
1204
  dateIn: ({
1157
1205
  examples,
1158
1206
  ...rest
1159
1207
  }?: DateInParams) => zod_v4_core0.$ZodBranded<
1160
- zod0.ZodPipe<
1161
- zod0.ZodPipe<
1162
- zod0.ZodUnion<readonly [zod0.ZodISODate, zod0.ZodISODateTime, zod0.ZodISODateTime]>,
1163
- zod0.ZodTransform<Date, string>
1208
+ zod.ZodPipe<
1209
+ zod.ZodPipe<
1210
+ zod.ZodUnion<readonly [zod.ZodISODate, zod.ZodISODateTime, zod.ZodISODateTime]>,
1211
+ zod.ZodTransform<Date, string>
1164
1212
  >,
1165
- zod0.ZodDate
1213
+ zod.ZodDate
1166
1214
  >,
1167
1215
  symbol,
1168
1216
  "out"
1169
1217
  >;
1170
1218
  dateOut: (
1171
1219
  meta?: DateOutParams,
1172
- ) => zod_v4_core0.$ZodBranded<zod0.ZodPipe<zod0.ZodDate, zod0.ZodTransform<string, Date>>, symbol, "out">;
1220
+ ) => zod_v4_core0.$ZodBranded<zod.ZodPipe<zod.ZodDate, zod.ZodTransform<string, Date>>, symbol, "out">;
1173
1221
  form: <S extends zod_v4_core0.$ZodShape>(
1174
- base: S | zod0.ZodObject<S>,
1175
- ) => zod_v4_core0.$ZodBranded<zod0.ZodObject<S, zod_v4_core0.$strip>, symbol, "out">;
1222
+ base: S | zod.ZodObject<S>,
1223
+ ) => zod_v4_core0.$ZodBranded<zod.ZodObject<S, zod_v4_core0.$strip>, symbol, "out">;
1176
1224
  upload: () => zod_v4_core0.$ZodBranded<
1177
- zod0.ZodCustom<express_fileupload0.UploadedFile, express_fileupload0.UploadedFile>,
1225
+ zod.ZodCustom<express_fileupload0.UploadedFile, express_fileupload0.UploadedFile>,
1178
1226
  symbol,
1179
1227
  "out"
1180
1228
  >;
1181
1229
  raw: typeof raw;
1182
1230
  buffer: () => zod_v4_core0.$ZodBranded<
1183
- zod0.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>,
1231
+ zod.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>,
1184
1232
  symbol,
1185
1233
  "out"
1186
1234
  >;
1235
+ paginated: typeof paginated;
1187
1236
  };
1188
- //#endregion
1189
1237
  export {
1190
1238
  type ApiResponse,
1191
1239
  type AppConfig,
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+
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 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 v from"node:https";import{setInterval as te}from"node:timers/promises";import{OpenApiBuilder as ne,isReferenceObject as re,isSchemaObject as y}from"openapi3-ts/oas31";import{createRequest as ie,createResponse as ae}from"node-mocks-http";function oe(e){return e}const b={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`],x=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(b.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`:x(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]),{}),S=e=>e instanceof Error?e:e instanceof r.ZodError?new r.ZodRealError(e.issues):Error(String(e)),C=e=>e instanceof r.ZodError?e.issues.map(({path:e,message:t})=>`${e.length?`${r.core.toDotPath(e)}: `:``}${t}`).join(`; `):e.message,w=(e,n)=>D(e)&&`_zod`in e&&(n?t.path([`_zod`,`def`,`type`],e)===n:!0),T=(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(),E=(...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)),D=e=>typeof e==`object`&&!!e,be=t.memoizeWith(()=>`static`,()=>process.env.NODE_ENV===`production`),xe=(e,t)=>!!t&&e!==`head`,O=Symbol(`Buffer`),Se=()=>r.custom(e=>Buffer.isBuffer(e),{error:`Expected Buffer`}).brand(O),k=Symbol(`DateIn`),Ce=({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(k).meta(t),A=Symbol(`DateOut`),we=(e={})=>r.date().transform(e=>e.toISOString()).brand(A).meta(e);var j=class extends Error{name=`RoutingError`;cause;constructor(e,t,n){super(e),this.cause={method:t,path:n}}},M=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.`}},Te=class extends Error{name=`IOSchemaError`},Ee=class extends Te{name=`DeepCheckError`;constructor(e){super(`Found`,{cause:e}),this.cause=e}},De=class extends Te{name=`OutputValidationError`;constructor(e){let t=new r.ZodError(e.issues.map(({path:e,...t})=>({...t,path:[`output`,...e]})));super(C(t),{cause:e}),this.cause=e}},N=class extends Te{name=`InputValidationError`;constructor(e){super(C(e),{cause:e}),this.cause=e}},Oe=class extends Error{name=`ResultHandlerError`;constructor(e,t){super(C(e),{cause:e}),this.cause=e,this.handled=t}},ke=class extends Error{name=`MissingPeerError`;constructor(e){super(`Missing peer dependency: ${e}. Please install it to use the feature.`)}};const Ae=Symbol(`Form`),je=e=>(e instanceof r.ZodObject?e:r.object(e)).brand(Ae),P=Symbol(`Upload`),Me=()=>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(P),F=Symbol(`Raw`),Ne=r.object({raw:Se()}),Pe=e=>Ne.extend(e).brand(F);function Fe(e){return e?Pe(e):Ne.brand(F)}const Ie=(e,{io:n,condition:i})=>t.tryCatch(()=>void r.toJSONSchema(e,{io:n,unrepresentable:`any`,override:({zodSchema:e})=>{if(i(e))throw new Ee(e)}}),e=>e.cause)(),Le=(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},Re=t=>Ie(t,{condition:t=>{let n=e(t);return typeof n==`symbol`&&[P,F,Ae].includes(n)},io:`input`}),ze=[`nan`,`symbol`,`map`,`set`,`bigint`,`void`,`promise`,`never`,`function`],Be=(t,n)=>Ie(t,{io:n,condition:t=>{let r=e(t),{type:i}=t._zod.def;return!!(ze.includes(i)||r===O||n===`input`&&(i===`date`||r===A)||n===`output`&&(r===k||r===F||r===P))}}),Ve=(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 Oe(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}))},He=(e,t,{url:n},r)=>!e.expose&&t.error(`Server side error`,{error:e,url:n,payload:r}),I=e=>a(e)?e:i(e instanceof N?400:500,C(e),{cause:e.cause||e}),L=e=>be()&&!e.expose?i(e.statusCode).message:e.message,Ue=e=>Object.entries(e._zod.def.shape).reduce((e,[r,i])=>{let{examples:a=[]}=n.get(i)||{};return T(e,a.map(t.objOf(r)),([e,t])=>({...e,...t}))},[]),We=({error:e,logger:t,response:n})=>{t.error(`Result handler failure`,e);let r=L(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 Ge=class{},R=class extends Ge{#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 N(e):e}}},Ke=class extends R{constructor(e,{provider:t=()=>({}),transformer:n=e=>e}={}){super({handler:async({request:r,response:i})=>new Promise((a,o)=>{let s=e=>{if(e&&e instanceof Error)return o(n(e));a(t(r,i))};e(r,i,s)?.catch(s)})})}},z=class{nest(e){return{...e,"":this}}},qe=class i extends z{#e;#t=t.once(()=>{if(n.get(this.#e.outputSchema)?.examples?.length||!w(this.#e.outputSchema,`object`))return;let e=Ue(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=Re(this.#e.inputSchema);if(t){let n=e(t);if(n===P)return`upload`;if(n===F)return`raw`;if(n===Ae)return`form`}return`json`}getResponses(e){return e===`positive`&&this.#t(),Object.freeze(e===`negative`?this.#e.resultHandler.getNegativeResponse():this.#e.resultHandler.getPositiveResponse(this.#e.outputSchema))}get security(){let e=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 De(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 Ke))&&(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 N(e):e}return this.#e.handler({...t,input:n})}async#o(e){try{await this.#e.resultHandler.execute(e)}catch(t){We({...e,error:new Oe(S(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:S(e)}}await this.#o({...o,input:s,request:e,response:t,logger:n,ctx:a})}};const Je=(e,t)=>e&&t?e.and(t):e||t,Ye=(e,t)=>e?e.and(t):t,B={positive:200,negative:400},V=Object.keys(B);var Xe=class{#e;constructor(e){this.#e=e}execute(...e){return this.#e(...e)}},H=class extends Xe{#e;#t;constructor(e){super(e.handler),this.#e=e.positive,this.#t=e.negative}getPositiveResponse(e){return Ve(this.#e,{variant:`positive`,args:[e],statusCodes:[B.positive],mimeTypes:[b.json]})}getNegativeResponse(){return Ve(this.#t,{variant:`negative`,args:[],statusCodes:[B.negative],mimeTypes:[b.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 U=new H({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=I(e);He(n,a,r,t),i.status(n.statusCode).set(n.headers).json({status:`error`,error:{message:L(n)}});return}i.status(B.positive).json({status:`success`,data:n})}}),Qe=r.string();n.add(Qe,{examples:[`Sample error message`]});const $e=new H({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=>D(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=I(n);He(t,r,i,a),e.status(t.statusCode).type(`text/plain`).send(L(t));return}if(`items`in t&&Array.isArray(t.items)){e.status(B.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=Je(this.schema,t.schema),n}addMiddleware(e){return this.#e(e instanceof R?e:new R(e))}use=this.addExpressMiddleware;addExpressMiddleware(...e){return this.#e(new Ke(...e))}addContext(e){return this.#e(new R({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 qe({...o,middlewares:s,outputSchema:t,resultHandler:c,scopes:d,tags:f,methods:l,getOperationId:u,inputSchema:Ye(this.schema,e)})}buildVoid({handler:e,...t}){return this.build({...t,output:le,handler:async t=>(await e(t),{})})}};const et=new W(U),tt=new W($e),nt={debug:s,info:u,warn:d(`#FFA500`),error:p,ctx:c},G={debug:10,info:20,warn:30,error:40},rt=e=>D(e)&&Object.keys(G).some(t=>t in e),it=e=>e in G,at=(e,t)=>G[e]<G[t],K=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?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 st=class e{config;constructor({color:e=o.isSupported(),level:t=be()?`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`||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=g.now();return()=>{let n=g.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,_.static(...this.#e))}};const q=async(e,t=`default`)=>{try{return(await import(e))[t]}catch{}throw new ke(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),J=(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=T(i.examples?.filter(D)||[],o.examples.filter(D),([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)),D(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=[]}=D(r)?r:{};return T(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=Be(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 V)for(let{mimeTypes:r,schema:i}of t.getResponses(e)){if(!r?.includes(b.json))continue;let t=Be(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??=J(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&&x(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&&x(e)&&t instanceof z?[`/`,e]:gt(e);return[[n||``].concat(_t(i)||[]).join(`/`),t,a]})},yt=(e,t)=>{throw new j(`Route with explicit method can only be assigned with Endpoint`,e,t)},bt=(e,t,n)=>{if(!(!n||n.includes(e)))throw new j(`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 j(`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 z)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)=>x(t)-+x(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=be()?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 te(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:S(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){We({response:r,logger:o,error:new Oe(S(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 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: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(`
2
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=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 Nikki`.padEnd(20)),a=d(`#F5A9B8`),o=d(`#5BCEFA`),s=Array(14).fill(o,1,3).fill(a,3,5).fill(m,5,7).fill(a,7,9).fill(o,9,12).fill(l,12,13),c=`
3
4
  8888888888 8888888888P 888 d8888 8888888b. 8888888
@@ -14,8 +15,8 @@ ${i}888${n}
14
15
  ${r}
15
16
  `;e.write(c.split(`
16
17
  `).map((e,t)=>s[t]?s[t](e):e).join(`
17
- `))},Kt=e=>{e.startupLogo!==!1&&Gt(process.stdout);let t=e.errorHandler||U,n=rt(e.logger)?e.logger:new st(e.logger);n.debug(`Running`,{build:`v27.0.0`,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=_().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}),Dt({app:s,routing:t,getLogger:r,config:e,parsers:{json:[e.jsonParser||_.json()],raw:[e.rawParser||_.raw(),Bt],form:[e.formParser||_.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=v.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=>D(e)&&`or`in e,Xt=e=>D(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)=>T(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.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 M(`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(!w(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 J(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)})},Y=e=>e,ln=({jsonSchema:{examples:e,description:t}},n)=>{if(n.isResponse)throw new M(`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 M(`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(!w(r,`transform`))return t;let a=Y(Sn(i,{ctx:n}));if(y(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)||!D(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=J(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(!D(r))return e;let i=h(n)?`path`:_(n)?`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||E(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(y(s)&&s.examples?.length?s.examples:t.pluck(n,u.examples?.filter(t.both(D,t.has(n)))||[]))})},[])},bn={nullable:cn,union:on,bigint:dn,intersection:sn,tuple:fn,pipe:hn,[k]:ln,[A]:un,[P]:rn,[F]:gn,[O]: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,Y(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(D(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(!xe(e,i))return{description:d};let f=Y(Sn(r,{rules:{...u,...bn},ctx:{isResponse:!0,makeRef:o,path:n,method:e}})),p=[];y(f)&&f.examples&&(p.push(...f.examples),delete f.examples);let m={schema:s===`components`?o(r,f,E(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(Y(i),c),f=[];y(u)&&u.examples&&(f.push(...u.examples),delete u.examples);let p={schema:s===`components`?o(r,u,E(l)):u,examples:_n(f.length?f:J(i).examples?.filter(e=>D(e)&&!Array.isArray(e)).map(t.omit(c))||[])},m={description:l,content:{[a]:p}};return(d||a===b.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)+`…`,X=e=>e.length?e.slice():void 0;var Ln=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||E(t,e),i=this.#t.get(r);if(i===void 0)return this.#t.set(r,1),r;if(n)throw new M(`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)),ee=Nn({...a,schema:m}),v=Qt(i.security),te=yn({...a,inputSources:g,isHeader:l,security:v,request:ee,description:o?.requestParameter?.call(null,{method:e,path:r,operationId:_})}),ne={};for(let t of V){let n=i.getResponses(t);for(let{mimeTypes:i,schema:s,statusCodes:c}of n)for(let l of c)ne[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 re=g.includes(`body`)?Pn({...a,request:ee,paramNames:t.pluck(`name`,te),schema:m,mimeType:b[i.requestType],description:o?.requestBody?.call(null,{method:e,path:r,operationId:_})}):void 0,y=Mn(jn(v,g),p,e=>{let t=this.#a(e);return this.addSecurityScheme(t,e),t}),ie={operationId:_,summary:h,description:c,deprecated:i.isDeprecated||void 0,tags:X(i.tags),parameters:X(te),requestBody:re,security:X(y),responses:ne};this.addPath(nn(r),{[e]:ie})};St({routing:e,config:n,onEndpoint:d?ht(p):p}),c&&(this.rootDoc.tags=Fn(c))}};const Rn=e=>ie({...e,headers:{"content-type":b.json,...e?.headers}}),zn=e=>ae(e),Bn=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)}})},Vn=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=Rn(e),a=zn({req:i,...t});a.req=t?.req||i,i.res=a;let o=Bn(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},Hn=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=Vn(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},Un=async({middleware:e,ctx:t={},...n})=>{let{requestMock:r,responseMock:i,loggerMock:a,configMock:{inputSources:o,errorHandler:s=U}}=Vn(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:S(e),output:null}),{requestMock:r,responseMock:i,loggerMock:a,output:{}}}};var Wn=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)],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}={})=>this.f.createMethodDeclaration(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 Gn=class{api;paths=new Set;tags=new Map;registry=new Map;constructor(e,t){this.serverUrl=t,this.api=new Wn(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`};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`)))])));#t=()=>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.#t()],{typeParams:[`T`]});#n=e=>this.api.makeTemplate(`?`,[this.api.makeNew(URLSearchParams.name,this.api.makeId(e))]);#r=()=>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(b.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.#r(),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.#n(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(b.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})};#i=()=>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.#n(this.#e.restConst)),this.api.makeAssignment(this.api.f.createPropertyAccessExpression(this.api.f.createThis(),this.#e.sourceProp),this.api.makeNew(`EventSource`,this.#r()))]);#a=e=>this.api.f.createTypeLiteralNode([this.api.makeInterfaceProp(Z(`event`),e)]);#o=()=>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.#a(`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.#i(),this.#o()],{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.#a(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 Kn=(t,{onEach:n,rules:r,onMissing:i,ctx:a={}})=>{let o=e(t),s=o&&o in r?r[o]:r[t._zod.def.type],c=e=>Kn(e,{ctx:a,onEach:n,rules:r,onMissing:i}),l=s?s(t,{...a,next:c}):i(t,a),u=n&&n(t,{prev:l,...a});return u?{...l,...u}:l},qn={name:t.path([`name`,`text`]),type:t.path([`type`]),optional:t.path([`questionToken`])},Jn=({_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)},Yn=({_zod:{def:e}},{next:t,api:n})=>{let r=[...e.parts],i=()=>{let e=``;for(;r.length;){let t=r.shift();if(w(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)},Xn=(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 Le(e,{io:t?`output`:`input`})?a(e,s):s()},Zn=({_zod:{def:e}},{next:t,api:n})=>n.f.createArrayTypeNode(t(e.element)),Qn=({_zod:{def:e}},{api:n})=>n.makeUnion(t.map(n.makeLiteralType,Object.values(e.entries))),$n=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion(e.options.map(t)),er=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion([t(e.innerType),n.makeLiteralType(null)]),tr=({_zod:{def:e}},{next:t,api:n})=>n.f.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:n.f.createRestTypeNode(t(e.rest)))),nr=({_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},rr=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(qn.name,...e))return!1;if(t.both(t.eqBy(qn.type),t.eqBy(qn.optional))(...e))return!0;throw Error(`Has conflicting prop`)},r);return e.f.createTypeLiteralNode(i)},(e,t,n)=>t.f.createIntersectionTypeNode(n)),ir=({_zod:{def:e}},{next:t,api:n})=>rr(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),ar=(e,t)=>e.ensureTypeNode(t?e.ts.SyntaxKind.UnknownKeyword:e.ts.SyntaxKind.AnyKeyword),or=({_zod:{def:e}},{next:t,isResponse:n,api:r})=>{let i=e[n?`out`:`in`],a=e[n?`in`:`out`];if(!w(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]||ar(r,n))},sr=({},{api:e})=>e.makeLiteralType(null),cr=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),lr=({},{api:e})=>e.ensureTypeNode(`Buffer`),ur=(e,{next:t})=>t(e._zod.def.shape.raw),dr={string:Q(`StringKeyword`),number:Q(`NumberKeyword`),bigint:Q(`BigIntKeyword`),boolean:Q(`BooleanKeyword`),any:Q(`AnyKeyword`),undefined:Q(`UndefinedKeyword`),[k]:Q(`StringKeyword`),[A]:Q(`StringKeyword`),never:Q(`NeverKeyword`),void:Q(`UndefinedKeyword`),unknown:Q(`UnknownKeyword`),null:sr,array:Zn,tuple:tr,record:nr,object:Xn,literal:Jn,template_literal:Yn,intersection:ir,union:$n,default:$,enum:Qn,optional:$,nonoptional:$,nullable:er,catch:$,pipe:or,lazy:cr,readonly:$,[O]:lr,[F]:ur},fr=(e,{brandHandling:t,ctx:n})=>Kn(e,{rules:{...t,...dr},onMissing:({},{isResponse:e,api:t})=>ar(t,e),ctx:n});var pr=class e extends Gn{#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=E.bind(null,e,n),{isDeprecated:a,inputSchema:o,tags:s}=r,c=`${e} ${n}`,l=this.api.makeType(i(`input`),fr(o,p),{comment:c});this.#e.push(l);let d=V.reduce((n,a)=>{let o=r.getResponses(a),s=t.chain(([t,{schema:n,mimeTypes:r,statusCodes:o}])=>{let s=xe(e,r),l=this.api.makeType(i(a,`variant`,`${t+1}`),fr(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.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(`
18
+ `))},Kt=e=>{e.startupLogo!==!1&&Gt(process.stdout);let t=e.errorHandler||U,n=rt(e.logger)?e.logger:new st(e.logger);n.debug(`Running`,{build:`v27.1.0`,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=_().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}),Dt({app:s,routing:t,getLogger:r,config:e,parsers:{json:[e.jsonParser||_.json()],raw:[e.rawParser||_.raw(),Bt],form:[e.formParser||_.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=v.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=>D(e)&&`or`in e,Xt=e=>D(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)=>T(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 M(`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(!w(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 J(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)})},Y=e=>e,ln=({jsonSchema:{examples:e,description:t}},n)=>{if(n.isResponse)throw new M(`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 M(`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(!w(r,`transform`))return t;let a=Y(Sn(i,{ctx:n}));if(y(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)||!D(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=J(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(!D(r))return e;let i=h(n)?`path`:_(n)?`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||E(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(y(s)&&s.examples?.length?s.examples:t.pluck(n,u.examples?.filter(t.both(D,t.has(n)))||[]))})},[])},bn={nullable:cn,union:on,bigint:dn,intersection:sn,tuple:fn,pipe:hn,[k]:ln,[A]:un,[P]:rn,[F]:gn,[O]: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,Y(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(D(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(!xe(e,i))return{description:d};let f=Y(Sn(r,{rules:{...u,...bn},ctx:{isResponse:!0,makeRef:o,path:n,method:e}})),p=[];y(f)&&f.examples&&(p.push(...f.examples),delete f.examples);let m={schema:s===`components`?o(r,f,E(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(Y(i),c),f=[];y(u)&&u.examples&&(f.push(...u.examples),delete u.examples);let p={schema:s===`components`?o(r,u,E(l)):u,examples:_n(f.length?f:J(i).examples?.filter(e=>D(e)&&!Array.isArray(e)).map(t.omit(c))||[])},m={description:l,content:{[a]:p}};return(d||a===b.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)+`…`,X=e=>e.length?e.slice():void 0;var Ln=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||E(t,e),i=this.#t.get(r);if(i===void 0)return this.#t.set(r,1),r;if(n)throw new M(`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)),ee=Nn({...a,schema:m}),v=Qt(i.security),te=yn({...a,inputSources:g,isHeader:l,security:v,request:ee,description:o?.requestParameter?.call(null,{method:e,path:r,operationId:_})}),ne={};for(let t of V){let n=i.getResponses(t);for(let{mimeTypes:i,schema:s,statusCodes:c}of n)for(let l of c)ne[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 re=g.includes(`body`)?Pn({...a,request:ee,paramNames:t.pluck(`name`,te),schema:m,mimeType:b[i.requestType],description:o?.requestBody?.call(null,{method:e,path:r,operationId:_})}):void 0,y=Mn(jn(v,g),p,e=>{let t=this.#a(e);return this.addSecurityScheme(t,e),t}),ie={operationId:_,summary:h,description:c,deprecated:i.isDeprecated||void 0,tags:X(i.tags),parameters:X(te),requestBody:re,security:X(y),responses:ne};this.addPath(nn(r),{[e]:ie})};St({routing:e,config:n,onEndpoint:d?ht(p):p}),c&&(this.rootDoc.tags=Fn(c))}};const Rn=e=>ie({...e,headers:{"content-type":b.json,...e?.headers}}),zn=e=>ae(e),Bn=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)}})},Vn=({requestProps:e,responseOptions:t,configProps:n,loggerProps:r})=>{let i=Rn(e),a=zn({req:i,...t});a.req=t?.req||i,i.res=a;let o=Bn(r);return{requestMock:i,responseMock:a,loggerMock:o,configMock:{cors:!1,logger:o,...n}}},Hn=async({endpoint:e,...t})=>{let{requestMock:n,responseMock:r,loggerMock:i,configMock:a}=Vn(t);return await e.execute({request:n,response:r,config:a,logger:i}),{requestMock:n,responseMock:r,loggerMock:i}},Un=async({middleware:e,ctx:t={},...n})=>{let{requestMock:r,responseMock:i,loggerMock:a,configMock:{inputSources:o,errorHandler:s=U}}=Vn(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:S(e),output:null}),{requestMock:r,responseMock:i,loggerMock:a,output:{}}}};var Wn=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 Gn=class{api;paths=new Set;tags=new Map;registry=new Map;constructor(e,t){this.serverUrl=t,this.api=new Wn(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(b.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(b.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 Kn=(t,{onEach:n,rules:r,onMissing:i,ctx:a={}})=>{let o=e(t),s=o&&o in r?r[o]:r[t._zod.def.type],c=e=>Kn(e,{ctx:a,onEach:n,rules:r,onMissing:i}),l=s?s(t,{...a,next:c}):i(t,a),u=n&&n(t,{prev:l,...a});return u?{...l,...u}:l},qn={name:t.path([`name`,`text`]),type:t.path([`type`]),optional:t.path([`questionToken`])},Jn=({_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)},Yn=({_zod:{def:e}},{next:t,api:n})=>{let r=[...e.parts],i=()=>{let e=``;for(;r.length;){let t=r.shift();if(w(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)},Xn=(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 Le(e,{io:t?`output`:`input`})?a(e,s):s()},Zn=({_zod:{def:e}},{next:t,api:n})=>n.f.createArrayTypeNode(t(e.element)),Qn=({_zod:{def:e}},{api:n})=>n.makeUnion(t.map(n.makeLiteralType,Object.values(e.entries))),$n=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion(e.options.map(t)),er=({_zod:{def:e}},{next:t,api:n})=>n.makeUnion([t(e.innerType),n.makeLiteralType(null)]),tr=({_zod:{def:e}},{next:t,api:n})=>n.f.createTupleTypeNode(e.items.map(t).concat(e.rest===null?[]:n.f.createRestTypeNode(t(e.rest)))),nr=({_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},rr=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(qn.name,...e))return!1;if(t.both(t.eqBy(qn.type),t.eqBy(qn.optional))(...e))return!0;throw Error(`Has conflicting prop`)},r);return e.f.createTypeLiteralNode(i)},(e,t,n)=>t.f.createIntersectionTypeNode(n)),ir=({_zod:{def:e}},{next:t,api:n})=>rr(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),ar=(e,t)=>e.ensureTypeNode(t?e.ts.SyntaxKind.UnknownKeyword:e.ts.SyntaxKind.AnyKeyword),or=({_zod:{def:e}},{next:t,isResponse:n,api:r})=>{let i=e[n?`out`:`in`],a=e[n?`in`:`out`];if(!w(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]||ar(r,n))},sr=({},{api:e})=>e.makeLiteralType(null),cr=({_zod:{def:e}},{makeAlias:t,next:n})=>t(e.getter,()=>n(e.getter())),lr=({},{api:e})=>e.ensureTypeNode(`Buffer`),ur=(e,{next:t})=>t(e._zod.def.shape.raw),dr={string:Q(`StringKeyword`),number:Q(`NumberKeyword`),bigint:Q(`BigIntKeyword`),boolean:Q(`BooleanKeyword`),any:Q(`AnyKeyword`),undefined:Q(`UndefinedKeyword`),[k]:Q(`StringKeyword`),[A]:Q(`StringKeyword`),never:Q(`NeverKeyword`),void:Q(`UndefinedKeyword`),unknown:Q(`UnknownKeyword`),null:sr,array:Zn,tuple:tr,record:nr,object:Xn,literal:Jn,template_literal:Yn,intersection:ir,union:$n,default:$,enum:Qn,optional:$,nonoptional:$,nullable:er,catch:$,pipe:or,lazy:cr,readonly:$,[O]:lr,[F]:ur},fr=(e,{brandHandling:t,ctx:n})=>Kn(e,{rules:{...t,...dr},onMissing:({},{isResponse:e,api:t})=>ar(t,e),ctx:n});var pr=class e extends Gn{#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=E.bind(null,e,n),{isDeprecated:a,inputSchema:o,tags:s}=r,c=`${e} ${n}`,l=this.api.makeType(i(`input`),fr(o,p),{comment:c});this.#e.push(l);let d=V.reduce((n,a)=>{let o=r.getResponses(a),s=t.chain(([t,{schema:n,mimeTypes:r,statusCodes:o}])=>{let s=xe(e,r),l=this.api.makeType(i(a,`variant`,`${t+1}`),fr(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 q(`typescript`)})}#i(e){return this.#n.length?this.#n.map(t=>typeof t==`string`?t:this.api.printNode(t,e)).join(`
18
19
  `):void 0}print(e){let t=this.#i(e),n=t&&this.api.ts.addSyntheticLeadingComment(this.api.ts.addSyntheticLeadingComment(this.api.f.createEmptyStatement(),this.api.ts.SyntaxKind.SingleLineCommentTrivia,` Usage example:`),this.api.ts.SyntaxKind.MultiLineCommentTrivia,`\n${t}`);return this.#e.concat(n||[]).map((t,n)=>this.api.printNode(t,n<this.#e.length?e:{...e,omitTrailingSemicolon:!0})).join(`
19
20
 
20
21
  `)}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 mr=(e,t)=>r.object({data:t,event:r.literal(e),id:r.string().optional(),retry:r.int().positive().optional()}),hr=(e,t,n)=>mr(String(t),e[t]).transform(e=>[`event: ${e.event}`,`data: ${JSON.stringify(e.data)}`,``,``].join(`
21
- `)).parse({event:t,data:n}),gr=e=>e.headersSent||e.writeHead(200,{connection:`keep-alive`,"content-type":b.sse,"cache-control":`no-cache`}),_r=e=>new R({handler:async({request:t,response:n})=>{let r=new AbortController;return t.once(`close`,()=>{r.abort()}),setTimeout(()=>gr(n),1e4),{isClosed:()=>n.writableEnded||n.closed,signal:r.signal,emit:(t,r)=>{gr(n),n.write(hr(e,t,r),`utf-8`),n.flush?.()}}}}),vr=e=>new H({positive:()=>{let[t,...n]=Object.entries(e).map(([e,t])=>mr(e,t));return{mimeType:b.sse,schema:n.length?r.discriminatedUnion(`event`,[t,...n]):t}},negative:{mimeType:`text/plain`,schema:r.string()},handler:async({response:e,error:t,logger:n,request:r,input:i})=>{if(t){let a=I(t);He(a,n,r,i),e.headersSent||e.status(a.statusCode).type(`text/plain`).write(L(a),`utf-8`)}e.end()}});var yr=class extends W{constructor(e){super(vr(e)),this.middlewares=[_r(e)]}};const br={dateIn:Ce,dateOut:we,form:je,upload:Me,raw:Fe,buffer:Se};export{st as BuiltinLogger,Ln as Documentation,M as DocumentationError,W as EndpointsFactory,yr as EventStreamFactory,N as InputValidationError,pr as Integration,R as Middleware,ke as MissingPeerError,De as OutputValidationError,H as ResultHandler,j as RoutingError,ct as ServeStatic,tt as arrayEndpointsFactory,$e as arrayResultHandler,qt as attachRouting,oe as createConfig,Jt as createServer,et as defaultEndpointsFactory,U as defaultResultHandler,I as ensureHttpError,br as ez,C as getMessageFromError,Hn as testEndpoint,Un as testMiddleware};
22
+ `)).parse({event:t,data:n}),gr=e=>e.headersSent||e.writeHead(200,{connection:`keep-alive`,"content-type":b.sse,"cache-control":`no-cache`}),_r=e=>new R({handler:async({request:t,response:n})=>{let r=new AbortController;return t.once(`close`,()=>{r.abort()}),setTimeout(()=>gr(n),1e4),{isClosed:()=>n.writableEnded||n.closed,signal:r.signal,emit:(t,r)=>{gr(n),n.write(hr(e,t,r),`utf-8`),n.flush?.()}}}}),vr=e=>new H({positive:()=>{let[t,...n]=Object.entries(e).map(([e,t])=>mr(e,t));return{mimeType:b.sse,schema:n.length?r.discriminatedUnion(`event`,[t,...n]):t}},negative:{mimeType:`text/plain`,schema:r.string()},handler:async({response:e,error:t,logger:n,request:r,input:i})=>{if(t){let a=I(t);He(a,n,r,i),e.headersSent||e.status(a.statusCode).type(`text/plain`).write(L(a),`utf-8`)}e.end()}});var yr=class extends W{constructor(e){super(vr(e)),this.middlewares=[_r(e)]}};const br=[`total`,`limit`,`offset`],xr=[`nextCursor`,`limit`];function Sr({style:e,itemSchema:t,itemsName:n=`items`,maxLimit:i=100,defaultLimit:a=20}){if(!Number.isInteger(i)||i<1)throw Error(`ez.paginated: maxLimit must be a positive integer`);if(!Number.isInteger(a)||a<1)throw Error(`ez.paginated: defaultLimit must be a positive integer`);if(a>i)throw Error(`ez.paginated: defaultLimit must not be greater than maxLimit`);if(e===`offset`&&br.includes(n))throw Error(`ez.paginated: itemsName must not match reserved keys for offset output (${br.join(`, `)})`);if(e===`cursor`&&xr.includes(n))throw Error(`ez.paginated: itemsName must not match reserved keys for cursor output (${xr.join(`, `)})`);let o=r.coerce.number().int().min(1).max(i).default(a).describe(`Page size (number of ${n} per page)`);if(e===`offset`){let e=r.coerce.number().int().min(0).default(0).describe(`Number of ${n} to skip`);return{input:r.object({limit:o,offset:e}),output:r.object({[n]:r.array(t).describe(`Page of ${n}`),total:r.number().int().min(0).describe(`Total number of ${n}`),limit:r.number().int().min(1).describe(`Page size used`),offset:r.number().int().min(0).describe(`Offset used`)})}}let s=r.string().optional().describe(`Cursor for the next page; omit for first page`);return{input:r.object({cursor:s,limit:o}),output:r.object({[n]:r.array(t).describe(`Page of ${n}`),nextCursor:r.string().nullable().describe(`Cursor for the next page, or null if no more pages`),limit:r.number().int().min(1).describe(`Page size used`)})}}const Cr={dateIn:Ce,dateOut:we,form:je,upload:Me,raw:Fe,buffer:Se,paginated:Sr};export{st as BuiltinLogger,Ln as Documentation,M as DocumentationError,W as EndpointsFactory,yr as EventStreamFactory,N as InputValidationError,pr as Integration,R as Middleware,ke as MissingPeerError,De as OutputValidationError,H as ResultHandler,j as RoutingError,ct as ServeStatic,tt as arrayEndpointsFactory,$e as arrayResultHandler,qt as attachRouting,oe as createConfig,Jt as createServer,et as defaultEndpointsFactory,U as defaultResultHandler,I as ensureHttpError,Cr as ez,C as getMessageFromError,Hn as testEndpoint,Un as testMiddleware};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-zod-api",
3
- "version": "27.0.0",
3
+ "version": "27.1.0",
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": {
@@ -38,7 +38,7 @@
38
38
  "node-mocks-http": "^1.17.2",
39
39
  "openapi3-ts": "^4.5.0",
40
40
  "ramda": "^0.32.0",
41
- "@express-zod-api/zod-plugin": "^4.0.0"
41
+ "@express-zod-api/zod-plugin": "^4.0.1"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@types/compression": "^1.7.5",