express-zod-api 27.0.1 → 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 +32 -1
- package/README.md +86 -59
- package/dist/index.d.ts +130 -20
- package/dist/index.js +3 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,37 @@
|
|
|
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
|
+
|
|
5
36
|
### v27.0.1
|
|
6
37
|
|
|
7
38
|
- Removed debug-level comments from the declaration files in the distribution.
|
|
@@ -2186,7 +2217,7 @@ const labeledDefaultSchema = withMeta(
|
|
|
2186
2217
|
capabilities, so that the user could subscribe to subsequent updates initiated by the server;
|
|
2187
2218
|
- Check out an [example of the synergy between two frameworks](https://github.com/RobinTail/zod-sockets#subscriptions)
|
|
2188
2219
|
and the [Demo Chat application](https://github.com/RobinTail/chat);
|
|
2189
|
-
- The feature suggested by [@
|
|
2220
|
+
- The feature suggested by [@uxduck](https://github.com/uxduck).
|
|
2190
2221
|
|
|
2191
2222
|
### v18.1.0
|
|
2192
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. [
|
|
30
|
-
11. [
|
|
31
|
-
12. [Enabling
|
|
32
|
-
13. [
|
|
33
|
-
14. [
|
|
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. [
|
|
50
|
-
3. [Creating
|
|
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
|
|
70
|
-
data. It integrates and provides the capabilities of popular web server, logging, validation and documenting solutions.
|
|
71
|
-
Therefore, many basic tasks can be
|
|
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
|
|
80
|
-
- The expected endpoint input and response types can be exported to the frontend,
|
|
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/
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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).
|
|
844
|
-
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
1022
|
-
[node-mocks-http](https://www.npmjs.com/package/node-mocks-http) library
|
|
1023
|
-
settings additional properties and asserting
|
|
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
|
-
##
|
|
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
|
|
1080
|
-
`typescript` installed. Consider also installing `prettier`
|
|
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
|
|
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.
|
|
1129
|
-
|
|
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
|
|
1212
|
-
|
|
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
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
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
|
|
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](#
|
|
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
|
|
2
|
+
import * as zod from "zod";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { HttpError } from "http-errors";
|
|
5
|
-
import "
|
|
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,7 +14,7 @@ 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
|
|
17
|
+
import * as qs from "qs";
|
|
19
18
|
import ts from "typescript";
|
|
20
19
|
import * as zod_v4_core0 from "zod/v4/core";
|
|
21
20
|
declare const methods: ("get" | "post" | "put" | "delete" | "patch")[];
|
|
@@ -695,7 +694,7 @@ declare class EndpointsFactory<
|
|
|
695
694
|
subject: Middleware<CTX, RET, ASCO, AIN> | ConstructorParameters<typeof Middleware<CTX, RET, ASCO, AIN>>[0],
|
|
696
695
|
): EndpointsFactory<Extension<IN, AIN>, (CTX extends Record<string, never> ? RET : CTX) & RET, SCO & ASCO>;
|
|
697
696
|
use: <R extends Request, S extends Response, AOUT extends FlatObject = Record<string, never>>(
|
|
698
|
-
nativeMw: (request: R, response: S, next:
|
|
697
|
+
nativeMw: (request: R, response: S, next: express$1.NextFunction) => any,
|
|
699
698
|
params_1?:
|
|
700
699
|
| {
|
|
701
700
|
provider?: ((request: R, response: S) => AOUT | Promise<AOUT>) | undefined;
|
|
@@ -743,7 +742,7 @@ declare const attachRouting: (
|
|
|
743
742
|
express_serve_static_core0.ParamsDictionary,
|
|
744
743
|
any,
|
|
745
744
|
any,
|
|
746
|
-
|
|
745
|
+
qs.ParsedQs,
|
|
747
746
|
Record<string, any>
|
|
748
747
|
>;
|
|
749
748
|
logger: AbstractLogger | BuiltinLogger;
|
|
@@ -922,12 +921,12 @@ declare const testEndpoint: <LOG extends FlatObject, REQ extends RequestOptions>
|
|
|
922
921
|
endpoint: AbstractEndpoint;
|
|
923
922
|
}) => Promise<{
|
|
924
923
|
requestMock: node_mocks_http0.MockRequest<
|
|
925
|
-
Request<express_serve_static_core0.ParamsDictionary, any, any,
|
|
924
|
+
Request<express_serve_static_core0.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>> & REQ
|
|
926
925
|
>;
|
|
927
926
|
responseMock: node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
|
|
928
927
|
loggerMock: AbstractLogger &
|
|
929
928
|
LOG & {
|
|
930
|
-
_getLogs: () => Record<"
|
|
929
|
+
_getLogs: () => Record<"debug" | "info" | "warn" | "error", unknown[]>;
|
|
931
930
|
};
|
|
932
931
|
}>;
|
|
933
932
|
declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOptions>({
|
|
@@ -941,12 +940,12 @@ declare const testMiddleware: <LOG extends FlatObject, REQ extends RequestOption
|
|
|
941
940
|
ctx?: FlatObject;
|
|
942
941
|
}) => Promise<{
|
|
943
942
|
requestMock: node_mocks_http0.MockRequest<
|
|
944
|
-
Request<express_serve_static_core0.ParamsDictionary, any, any,
|
|
943
|
+
Request<express_serve_static_core0.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>> & REQ
|
|
945
944
|
>;
|
|
946
945
|
responseMock: node_mocks_http0.MockResponse<Response<any, Record<string, any>>>;
|
|
947
946
|
loggerMock: AbstractLogger &
|
|
948
947
|
LOG & {
|
|
949
|
-
_getLogs: () => Record<"
|
|
948
|
+
_getLogs: () => Record<"debug" | "info" | "warn" | "error", unknown[]>;
|
|
950
949
|
};
|
|
951
950
|
output: FlatObject;
|
|
952
951
|
}>;
|
|
@@ -1060,6 +1059,116 @@ interface DateInParams extends Omit<Parameters<z.ZodString["meta"]>[0], "example
|
|
|
1060
1059
|
interface DateOutParams extends Omit<Parameters<z.ZodString["meta"]>[0], "examples"> {
|
|
1061
1060
|
examples?: string[];
|
|
1062
1061
|
}
|
|
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>;
|
|
1063
1172
|
declare const base: z.ZodObject<
|
|
1064
1173
|
{
|
|
1065
1174
|
raw: z.core.$ZodBranded<z.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>, symbol, "out">;
|
|
@@ -1096,33 +1205,34 @@ declare const ez: {
|
|
|
1096
1205
|
examples,
|
|
1097
1206
|
...rest
|
|
1098
1207
|
}?: DateInParams) => zod_v4_core0.$ZodBranded<
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1208
|
+
zod.ZodPipe<
|
|
1209
|
+
zod.ZodPipe<
|
|
1210
|
+
zod.ZodUnion<readonly [zod.ZodISODate, zod.ZodISODateTime, zod.ZodISODateTime]>,
|
|
1211
|
+
zod.ZodTransform<Date, string>
|
|
1103
1212
|
>,
|
|
1104
|
-
|
|
1213
|
+
zod.ZodDate
|
|
1105
1214
|
>,
|
|
1106
1215
|
symbol,
|
|
1107
1216
|
"out"
|
|
1108
1217
|
>;
|
|
1109
1218
|
dateOut: (
|
|
1110
1219
|
meta?: DateOutParams,
|
|
1111
|
-
) => zod_v4_core0.$ZodBranded<
|
|
1220
|
+
) => zod_v4_core0.$ZodBranded<zod.ZodPipe<zod.ZodDate, zod.ZodTransform<string, Date>>, symbol, "out">;
|
|
1112
1221
|
form: <S extends zod_v4_core0.$ZodShape>(
|
|
1113
|
-
base: S |
|
|
1114
|
-
) => zod_v4_core0.$ZodBranded<
|
|
1222
|
+
base: S | zod.ZodObject<S>,
|
|
1223
|
+
) => zod_v4_core0.$ZodBranded<zod.ZodObject<S, zod_v4_core0.$strip>, symbol, "out">;
|
|
1115
1224
|
upload: () => zod_v4_core0.$ZodBranded<
|
|
1116
|
-
|
|
1225
|
+
zod.ZodCustom<express_fileupload0.UploadedFile, express_fileupload0.UploadedFile>,
|
|
1117
1226
|
symbol,
|
|
1118
1227
|
"out"
|
|
1119
1228
|
>;
|
|
1120
1229
|
raw: typeof raw;
|
|
1121
1230
|
buffer: () => zod_v4_core0.$ZodBranded<
|
|
1122
|
-
|
|
1231
|
+
zod.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>,
|
|
1123
1232
|
symbol,
|
|
1124
1233
|
"out"
|
|
1125
1234
|
>;
|
|
1235
|
+
paginated: typeof paginated;
|
|
1126
1236
|
};
|
|
1127
1237
|
export {
|
|
1128
1238
|
type ApiResponse,
|
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.1`,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,
|
|
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