express-zod-api 28.1.1 → 28.3.0

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