express-zod-api 12.5.1 → 14.0.0-beta2

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
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 14
4
+
5
+ ### v14.0.0
6
+
7
+ - **Breaking changes**:
8
+ - `http-errors` becomes a peer dependency — you have to install it manually.
9
+ - You might also need to install `@types/http-errors` if you're using `createHttpError` in your implementation.
10
+ - `typescript` is a required peer dependency.
11
+ - Minimum version of `zod` is 3.22.3.
12
+ - The class `DependsOnMethodError` is removed — catch `RoutingError` instead if needed.
13
+ - **Potentially breaking changes**:
14
+ - The type `FlatObject` changed from `Record<string, any>` to `Record<string, unknown>`.
15
+ - If a custom `ResultHandler` handles properties of the `output`, it might need to ensure its actual type.
16
+ - In case of body parsing failure the `ResultHandler` receives `null` into its `input` argument instead of raw body.
17
+ - Utilize the `request.body` within a custom `ResultHandler` in that case if needed.
18
+ - The type of `ResultHandler`'s arguments `input` and `output` is changed from `any` to `FlatObject | null`.
19
+ - Other changes:
20
+ - Ensure having the following packages installed for the types assistance:
21
+ - `yarn add --dev @types/express @types/node @types/http-errors`
22
+ - or `npm install -D @types/express @types/node @types/http-errors`
23
+ - The property `DependsOnMethod::methods` is renamed to `endpoints`.
24
+
25
+ ```typescript
26
+ // before
27
+ import { createHttpError } from "express-zod-api";
28
+ // after
29
+ import createHttpError from "http-errors";
30
+ ```
31
+
3
32
  ## Version 12
4
33
 
5
34
  ### v12.5.1
package/README.md CHANGED
@@ -104,14 +104,18 @@ Much can be customized to fit your needs.
104
104
 
105
105
  ## Installation
106
106
 
107
- Run one of the following commands to install the library and its peer dependencies.
108
- Typescript is an optional dependency, however, it's required if you're going to
109
- [generate a frontend client](#generating-a-frontend-client) for your API.
107
+ Run one of the following commands to install the library, its peer dependencies and packages for types assistance.
110
108
 
111
109
  ```shell
112
- yarn add express-zod-api express zod winston typescript
113
- # or
114
- npm install express-zod-api express zod winston typescript
110
+ yarn add express-zod-api express zod winston typescript http-errors
111
+ yarn add --dev @types/express @types/node @types/http-errors
112
+ ```
113
+
114
+ or
115
+
116
+ ```shell
117
+ npm install express-zod-api express zod winston typescript http-errors
118
+ npm install -D @types/express @types/node @types/http-errors
115
119
  ```
116
120
 
117
121
  Add the following option to your `tsconfig.json` file in order to make it work as expected:
@@ -252,7 +256,8 @@ Here is an example of the authentication middleware, that checks a `key` from in
252
256
 
253
257
  ```typescript
254
258
  import { z } from "zod";
255
- import { createMiddleware, createHttpError } from "express-zod-api";
259
+ import createHttpError from "http-errors";
260
+ import { createMiddleware } from "express-zod-api";
256
261
 
257
262
  const authMiddleware = createMiddleware({
258
263
  security: {
@@ -589,8 +594,9 @@ There are also two optional features available: a provider of options and an err
589
594
  In case the error in middleware is not a `HttpError`, the `ResultHandler` will send the status `500`.
590
595
 
591
596
  ```typescript
592
- import { defaultEndpointsFactory, createHttpError } from "express-zod-api";
597
+ import { defaultEndpointsFactory } from "express-zod-api";
593
598
  import cors from "cors";
599
+ import createHttpError from "http-errors";
594
600
  import { auth } from "express-oauth2-jwt-bearer";
595
601
 
596
602
  const simpleUsage = defaultEndpointsFactory.addExpressMiddleware(
@@ -820,9 +826,9 @@ const config = createConfig({
820
826
  const { app, httpServer, httpsServer, logger } = createServer(config, routing);
821
827
  ```
822
828
 
823
- At least you need to specify the port or socket (usually it is 443), certificate and the key, issued by the
824
- certifying authority. For example, you can acquire a free TLS certificate for your API at
825
- [Let's Encrypt](https://letsencrypt.org/).
829
+ Ensure having `@types/node` package installed. At least you need to specify the port or socket (usually it is 443),
830
+ certificate and the key, issued by the certifying authority. For example, you can acquire a free TLS certificate for
831
+ your API at [Let's Encrypt](https://letsencrypt.org/).
826
832
 
827
833
  ## Generating a Frontend Client
828
834
 
package/SECURITY.md CHANGED
@@ -2,27 +2,28 @@
2
2
 
3
3
  ## Supported Versions
4
4
 
5
- | Version | Supported |
6
- | ------: | :----------------: |
7
- | 12.x.x | :white_check_mark: |
8
- | 11.x.x | :white_check_mark: |
9
- | 10.x.x | :x: |
10
- | 9.x.x | :x: |
11
- | 8.x.x | :x: |
12
- | 7.x.x | :x: |
13
- | 6.x.x | :x: |
14
- | 5.x.x | :x: |
15
- | 4.x.x | :x: |
16
- | 3.x.x | :x: |
17
- | 2.x.x | :x: |
18
- | 1.x.x | :x: |
19
- | 0.x.x | :x: |
5
+ | Version | Release | Supported |
6
+ | ------: | :------ | :----------------: |
7
+ | 14.x.x | 10.2023 | :white_check_mark: |
8
+ | 12.x.x | 09.2023 | :white_check_mark: |
9
+ | 11.x.x | 06.2023 | :white_check_mark: |
10
+ | 10.x.x | 03.2023 | :x: |
11
+ | 9.x.x | 03.2023 | :x: |
12
+ | 8.x.x | 09.2022 | :x: |
13
+ | 7.x.x | 05.2022 | :x: |
14
+ | 6.x.x | 03.2022 | :x: |
15
+ | 5.x.x | 12.2021 | :x: |
16
+ | 4.x.x | 11.2021 | :x: |
17
+ | 3.x.x | 11.2021 | :x: |
18
+ | 2.x.x | 07.2021 | :x: |
19
+ | 1.x.x | 05.2021 | :x: |
20
+ | 0.x.x | 03.2021 | :x: |
20
21
 
21
22
  ## Reporting a Vulnerability
22
23
 
23
24
  Found a vulnerability or other security issue?
24
25
 
25
26
  Please urgently inform me privately by
26
- [email](https://github.com/RobinTail/express-zod-api/blob/master/package.json#L135).
27
+ [email](https://github.com/RobinTail/express-zod-api/blob/master/package.json#L137).
27
28
 
28
29
  I will try to fix it as soon as possible.
package/dist/index.d.mts CHANGED
@@ -1,12 +1,10 @@
1
1
  import compression from 'compression';
2
- import { NextHandleFunction } from 'connect';
3
- import express, { Request, Response, Express } from 'express';
2
+ import express, { Request, Response, NextFunction, RequestHandler, Express } from 'express';
4
3
  import fileUpload, { UploadedFile } from 'express-fileupload';
5
4
  import https, { ServerOptions } from 'node:https';
6
5
  import winston, { Logger } from 'winston';
7
6
  import { z, ZodTypeDef, ZodType, ParseInput, ParseReturnType, ZodError } from 'zod';
8
7
  import { HttpError } from 'http-errors';
9
- export { default as createHttpError } from 'http-errors';
10
8
  import * as qs from 'qs';
11
9
  import * as express_serve_static_core from 'express-serve-static-core';
12
10
  import * as http from 'http';
@@ -112,7 +110,7 @@ interface MiddlewareDefinition<IN extends IOSchema<"strip">, OPT, OUT extends Fl
112
110
  }
113
111
  type AnyMiddlewareDef = MiddlewareDefinition<any, any, any, any>;
114
112
  declare const createMiddleware: <IN extends IOSchema<"strip">, OPT, OUT extends FlatObject, SCO extends string>(props: MiddlewareCreationProps<IN, OPT, OUT, SCO>) => MiddlewareDefinition<IN, OPT, OUT, SCO>;
115
- type ExpressMiddleware<R extends Request, S extends Response> = (request: R, response: S, next: (error?: any) => void) => void | Promise<void>;
113
+ type ExpressMiddleware<R extends Request, S extends Response> = (request: R, response: S, next: NextFunction) => void | Promise<void>;
116
114
  interface ExpressMiddlewareFeatures<R extends Request, S extends Response, OUT extends FlatObject> {
117
115
  provider?: (request: R, response: S) => OUT | Promise<OUT>;
118
116
  transformer?: (err: Error) => HttpError | Error;
@@ -127,13 +125,8 @@ type IOSchema<U extends z.UnknownKeysParam = any> = z.ZodObject<any, U> | z.ZodU
127
125
  type ProbableIntersection<A extends IOSchema<"strip"> | null, B extends IOSchema> = A extends null ? B : A extends IOSchema<"strip"> ? z.ZodIntersection<A, B> : never;
128
126
 
129
127
  type Method = "get" | "post" | "put" | "delete" | "patch";
130
- type MethodsDefinition<M extends Method> = {
131
- methods: M[];
132
- } | {
133
- method: M;
134
- };
135
128
 
136
- type FlatObject = Record<string, any>;
129
+ type FlatObject = Record<string, unknown>;
137
130
  declare const getMessageFromError: (error: Error) => string;
138
131
  declare const getStatusCodeFromError: (error: Error) => number;
139
132
  declare const getExamples: <T extends z.ZodTypeAny, V extends "original" | "parsed" | undefined>({ schema, variant, validate, }: {
@@ -153,13 +146,12 @@ declare const getExamples: <T extends z.ZodTypeAny, V extends "original" | "pars
153
146
  }) => readonly (V extends "parsed" ? z.output<T> : z.input<T>)[];
154
147
  type ErrMessage = Exclude<Parameters<typeof z.ZodString.prototype.email>[0], undefined>;
155
148
 
149
+ interface Metadata<T extends z.ZodTypeAny> {
150
+ examples: z.input<T>[];
151
+ }
156
152
  declare const metaProp = "expressZodApiMeta";
157
153
  type MetaProp = typeof metaProp;
158
- type MetaDef<T extends z.ZodTypeAny> = {
159
- [K in MetaProp]: {
160
- examples: z.input<T>[];
161
- };
162
- };
154
+ type MetaDef<T extends z.ZodTypeAny> = Record<MetaProp, Metadata<T>>;
163
155
  type ExampleSetter<T extends z.ZodTypeAny> = (example: z.input<T>) => WithMeta<T>;
164
156
  type WithMeta<T extends z.ZodTypeAny> = T & {
165
157
  _def: T["_def"] & MetaDef<T>;
@@ -231,7 +223,7 @@ declare class ZodUpload extends ZodType<UploadedFile, ZodUploadDef> {
231
223
  static create: () => ZodUpload;
232
224
  }
233
225
 
234
- interface OpenAPIContext {
226
+ interface OpenAPIContext extends FlatObject {
235
227
  isResponse: boolean;
236
228
  serializer: (schema: z.ZodTypeAny) => string;
237
229
  getRef: (name: string) => ReferenceObject | undefined;
@@ -244,10 +236,6 @@ interface OpenAPIContext {
244
236
  declare class RoutingError extends Error {
245
237
  name: string;
246
238
  }
247
- /** @desc An error related to the issues of using DependsOnMethod class */
248
- declare class DependsOnMethodError extends RoutingError {
249
- name: string;
250
- }
251
239
  /**
252
240
  * @desc An error related to the generating of the documentation
253
241
  * */
@@ -275,9 +263,11 @@ declare class InputValidationError extends IOSchemaError {
275
263
  }
276
264
 
277
265
  interface ResultHandlerParams<RES> {
266
+ /** null in case of failure to parse or to find the matching endpoint (error: not found) */
267
+ input: FlatObject | null;
268
+ /** null in case of errors or failures */
269
+ output: FlatObject | null;
278
270
  error: Error | null;
279
- input: any;
280
- output: any;
281
271
  request: Request;
282
272
  response: Response<RES>;
283
273
  logger: Logger;
@@ -288,6 +278,7 @@ interface ResultHandlerDefinition<POS extends z.ZodTypeAny, NEG extends z.ZodTyp
288
278
  getNegativeResponse: () => NEG | ApiResponse<NEG>;
289
279
  handler: ResultHandler<z.output<POS> | z.output<NEG>>;
290
280
  }
281
+ type AnyResultHandlerDefinition = ResultHandlerDefinition<z.ZodTypeAny, z.ZodTypeAny>;
291
282
  declare const createResultHandler: <POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny>(definition: ResultHandlerDefinition<POS, NEG>) => ResultHandlerDefinition<POS, NEG>;
292
283
  declare const defaultResultHandler: ResultHandlerDefinition<z.ZodObject<{
293
284
  status: z.ZodLiteral<"success">;
@@ -405,9 +396,9 @@ declare const defaultResultHandler: ResultHandlerDefinition<z.ZodObject<{
405
396
  * @desc Responding with array is a bad practice keeping your endpoints from evolving without breaking changes.
406
397
  * @desc This handler expects your endpoint to have the property 'items' in the output object schema
407
398
  * */
408
- declare const arrayResultHandler: ResultHandlerDefinition<z.ZodArray<any, "many"> & {
409
- _def: z.ZodArrayDef<any> & MetaDef<z.ZodArray<any, "many">>;
410
- example: (example: any[]) => z.ZodArray<any, "many"> & any;
399
+ declare const arrayResultHandler: ResultHandlerDefinition<z.ZodArray<z.ZodTypeAny, "many"> & {
400
+ _def: z.ZodArrayDef<z.ZodTypeAny> & MetaDef<z.ZodArray<z.ZodTypeAny, "many">>;
401
+ example: (example: any[]) => z.ZodArray<z.ZodTypeAny, "many"> & any;
411
402
  }, z.ZodString & {
412
403
  _def: z.ZodStringDef & MetaDef<z.ZodString>;
413
404
  example: (example: string) => z.ZodString & any;
@@ -441,34 +432,28 @@ declare abstract class AbstractEndpoint {
441
432
  abstract _setSiblingMethods(methods: Method[]): void;
442
433
  abstract getOperationId(method: Method): string | undefined;
443
434
  }
444
- type EndpointProps<IN extends IOSchema, OUT extends IOSchema, OPT extends FlatObject, M extends Method, POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, SCO extends string, TAG extends string> = {
445
- middlewares: AnyMiddlewareDef[];
446
- inputSchema: IN;
447
- outputSchema: OUT;
448
- handler: Handler<z.output<IN>, z.input<OUT>, OPT>;
449
- resultHandler: ResultHandlerDefinition<POS, NEG>;
450
- description?: string;
451
- shortDescription?: string;
452
- operationId?: string | ((method: Method) => string);
453
- } & ({
454
- scopes?: SCO[];
455
- } | {
456
- scope?: SCO;
457
- }) & ({
458
- tags?: TAG[];
459
- } | {
460
- tag?: TAG;
461
- }) & MethodsDefinition<M>;
462
- declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, OPT extends FlatObject, M extends Method, POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, SCO extends string, TAG extends string> extends AbstractEndpoint {
435
+ declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, OPT extends FlatObject, POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, SCO extends string, TAG extends string> extends AbstractEndpoint {
463
436
  #private;
464
- constructor({ middlewares, inputSchema, outputSchema, handler, resultHandler, description, shortDescription, ...rest }: EndpointProps<IN, OUT, OPT, M, POS, NEG, SCO, TAG>);
437
+ constructor({ methods, inputSchema, outputSchema, handler, resultHandler, getOperationId, scopes, middlewares, tags, description: long, shortDescription: short, }: {
438
+ middlewares?: AnyMiddlewareDef[];
439
+ inputSchema: IN;
440
+ outputSchema: OUT;
441
+ handler: Handler<z.output<IN>, z.input<OUT>, OPT>;
442
+ resultHandler: ResultHandlerDefinition<POS, NEG>;
443
+ description?: string;
444
+ shortDescription?: string;
445
+ getOperationId?: (method: Method) => string | undefined;
446
+ methods: Method[];
447
+ scopes?: SCO[];
448
+ tags?: TAG[];
449
+ });
465
450
  /**
466
451
  * @desc Sets the other methods supported by the same path. Used by Routing in DependsOnMethod case, for options.
467
452
  * @deprecated This method is for internal needs of the library, please avoid using it.
468
453
  * */
469
454
  _setSiblingMethods(methods: Method[]): void;
470
455
  getDescription(variant: DescriptionVariant): string | undefined;
471
- getMethods(): M[];
456
+ getMethods(): Method[];
472
457
  getSchema(variant: "input"): IN;
473
458
  getSchema(variant: "output"): OUT;
474
459
  getSchema(variant: "positive"): POS;
@@ -507,7 +492,7 @@ interface ServerConfig {
507
492
  * @desc Custom JSON parser.
508
493
  * @default express.json()
509
494
  * */
510
- jsonParser?: NextHandleFunction;
495
+ jsonParser?: RequestHandler;
511
496
  /**
512
497
  * @desc Enable or configure uploads handling.
513
498
  * @default false
@@ -557,7 +542,7 @@ interface CommonConfig<TAG extends string = string> {
557
542
  * @default defaultResultHandler
558
543
  * @see defaultResultHandler
559
544
  */
560
- errorHandler?: ResultHandlerDefinition<any, any>;
545
+ errorHandler?: AnyResultHandlerDefinition;
561
546
  /** @desc Logger configuration or your custom winston logger. */
562
547
  logger: LoggerConfig | Logger;
563
548
  /**
@@ -580,7 +565,7 @@ interface CommonConfig<TAG extends string = string> {
580
565
  }
581
566
  declare const createConfig: <TAG extends string, T extends (ServerConfig | AppConfig) & CommonConfig<TAG>>(config: T) => T;
582
567
 
583
- type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<"strip"> | null, OPT extends FlatObject, M extends Method, SCO extends string, TAG extends string> = {
568
+ type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<"strip"> | null, OPT extends FlatObject, SCO extends string, TAG extends string> = {
584
569
  input: IN;
585
570
  output: OUT;
586
571
  handler: Handler<z.output<ProbableIntersection<MIN, IN>>, z.input<OUT>, OPT>;
@@ -588,6 +573,10 @@ type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<
588
573
  shortDescription?: string;
589
574
  operationId?: string | ((method: Method) => string);
590
575
  } & ({
576
+ method: Method;
577
+ } | {
578
+ methods: Method[];
579
+ }) & ({
591
580
  scopes?: SCO[];
592
581
  } | {
593
582
  scope?: SCO;
@@ -595,7 +584,7 @@ type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<
595
584
  tags?: TAG[];
596
585
  } | {
597
586
  tag?: TAG;
598
- }) & MethodsDefinition<M>;
587
+ });
599
588
  declare class EndpointsFactory<POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, IN extends IOSchema<"strip"> | null = null, OUT extends FlatObject = {}, SCO extends string = string, TAG extends string = string> {
600
589
  #private;
601
590
  protected resultHandler: ResultHandlerDefinition<POS, NEG>;
@@ -610,7 +599,7 @@ declare class EndpointsFactory<POS extends z.ZodTypeAny, NEG extends z.ZodTypeAn
610
599
  use: <R extends Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, S extends Response<any, Record<string, any>>, AOUT extends FlatObject = {}>(middleware: ExpressMiddleware<R, S>, features?: ExpressMiddlewareFeatures<R, S, AOUT> | undefined) => EndpointsFactory<POS, NEG, IN, OUT & AOUT, SCO, TAG>;
611
600
  addExpressMiddleware<R extends Request, S extends Response, AOUT extends FlatObject = {}>(middleware: ExpressMiddleware<R, S>, features?: ExpressMiddlewareFeatures<R, S, AOUT>): EndpointsFactory<POS, NEG, IN, OUT & AOUT, SCO, TAG>;
612
601
  addOptions<AOUT extends FlatObject>(options: AOUT): EndpointsFactory<POS, NEG, IN, OUT & AOUT, SCO, TAG>;
613
- build<BIN extends IOSchema, BOUT extends IOSchema, M extends Method>({ input, handler, output: outputSchema, ...rest }: BuildProps<BIN, BOUT, IN, OUT, M, SCO, TAG>): Endpoint<ProbableIntersection<IN, BIN>, BOUT, OUT, M, POS, NEG, SCO, TAG>;
602
+ build<BIN extends IOSchema, BOUT extends IOSchema>({ input, handler, output: outputSchema, description, shortDescription, operationId, ...rest }: BuildProps<BIN, BOUT, IN, OUT, SCO, TAG>): Endpoint<ProbableIntersection<IN, BIN>, BOUT, OUT, POS, NEG, SCO, TAG>;
614
603
  }
615
604
  declare const defaultEndpointsFactory: EndpointsFactory<z.ZodObject<{
616
605
  status: z.ZodLiteral<"success">;
@@ -728,9 +717,9 @@ declare const defaultEndpointsFactory: EndpointsFactory<z.ZodObject<{
728
717
  * @desc Responding with array is a bad practice keeping your endpoints from evolving without breaking changes.
729
718
  * @desc The result handler of this factory expects your endpoint to have the property 'items' in the output schema
730
719
  */
731
- declare const arrayEndpointsFactory: EndpointsFactory<z.ZodArray<any, "many"> & {
732
- _def: z.ZodArrayDef<any> & MetaDef<z.ZodArray<any, "many">>;
733
- example: (example: any[]) => z.ZodArray<any, "many"> & any;
720
+ declare const arrayEndpointsFactory: EndpointsFactory<z.ZodArray<z.ZodTypeAny, "many"> & {
721
+ _def: z.ZodArrayDef<z.ZodTypeAny> & MetaDef<z.ZodArray<z.ZodTypeAny, "many">>;
722
+ example: (example: any[]) => z.ZodArray<z.ZodTypeAny, "many"> & any;
734
723
  }, z.ZodString & {
735
724
  _def: z.ZodStringDef & MetaDef<z.ZodString>;
736
725
  example: (example: string) => z.ZodString & any;
@@ -739,12 +728,8 @@ declare const arrayEndpointsFactory: EndpointsFactory<z.ZodArray<any, "many"> &
739
728
  declare const createLogger: (loggerConfig: LoggerConfig) => winston.Logger;
740
729
 
741
730
  declare class DependsOnMethod {
742
- readonly methods: {
743
- [K in Method]?: Endpoint<any, any, any, K, any, any, any, any> | Endpoint<any, any, any, Method, any, any, any, any>;
744
- };
745
- constructor(methods: {
746
- [K in Method]?: Endpoint<any, any, any, K, any, any, any, any> | Endpoint<any, any, any, Method, any, any, any, any>;
747
- });
731
+ readonly endpoints: Partial<Record<Method, AbstractEndpoint>>;
732
+ constructor(endpoints: Partial<Record<Method, AbstractEndpoint>>);
748
733
  }
749
734
 
750
735
  type OriginalStatic = typeof express.static;
@@ -820,7 +805,7 @@ declare const testEndpoint: <REQ extends Partial<Record<keyof Request<express_se
820
805
  writableEnded: boolean;
821
806
  statusCode: number;
822
807
  statusMessage: string;
823
- } & Record<"status" | "header" | "set" | "json" | "end" | "send" | "setHeader", jest.Mock<any, any, any>> & (RES extends undefined ? {} : RES);
808
+ } & Record<"status" | "header" | "set" | "end" | "send" | "json" | "setHeader", jest.Mock<any, any, any>> & (RES extends undefined ? {} : RES);
824
809
  loggerMock: Record<"error" | "warn" | "debug" | "info", jest.Mock<any, any, any>> & (LOG extends undefined ? {} : LOG);
825
810
  }>;
826
811
 
@@ -890,4 +875,4 @@ declare namespace proprietarySchemas {
890
875
  };
891
876
  }
892
877
 
893
- export { AbstractEndpoint, BasicSecurity, BearerSecurity, CommonConfig, CookieSecurity, CustomHeaderSecurity, DependsOnMethod, DependsOnMethodError, Documentation, DocumentationError, EndpointsFactory, FlatObject, IOSchema, InputSecurity, InputValidationError, Integration, LoggerConfig, Method, MiddlewareDefinition, OAuth2Security, OpenIdSecurity, OutputValidationError, ResultHandlerDefinition, Routing, RoutingError, ServeStatic, ZodDateInDef, ZodDateOutDef, ZodFileDef, ZodUploadDef, arrayEndpointsFactory, arrayResultHandler, attachRouting, createConfig, createLogger, createMiddleware, createResultHandler, createServer, defaultEndpointsFactory, defaultResultHandler, proprietarySchemas as ez, getExamples, getMessageFromError, getStatusCodeFromError, testEndpoint, withMeta };
878
+ export { AbstractEndpoint, BasicSecurity, BearerSecurity, CommonConfig, CookieSecurity, CustomHeaderSecurity, DependsOnMethod, Documentation, DocumentationError, EndpointsFactory, FlatObject, IOSchema, InputSecurity, InputValidationError, Integration, LoggerConfig, Method, MiddlewareDefinition, OAuth2Security, OpenIdSecurity, OutputValidationError, ResultHandlerDefinition, Routing, RoutingError, ServeStatic, ZodDateInDef, ZodDateOutDef, ZodFileDef, ZodUploadDef, arrayEndpointsFactory, arrayResultHandler, attachRouting, createConfig, createLogger, createMiddleware, createResultHandler, createServer, defaultEndpointsFactory, defaultResultHandler, proprietarySchemas as ez, getExamples, getMessageFromError, getStatusCodeFromError, testEndpoint, withMeta };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,10 @@
1
1
  import compression from 'compression';
2
- import { NextHandleFunction } from 'connect';
3
- import express, { Request, Response, Express } from 'express';
2
+ import express, { Request, Response, NextFunction, RequestHandler, Express } from 'express';
4
3
  import fileUpload, { UploadedFile } from 'express-fileupload';
5
4
  import https, { ServerOptions } from 'node:https';
6
5
  import winston, { Logger } from 'winston';
7
6
  import { z, ZodTypeDef, ZodType, ParseInput, ParseReturnType, ZodError } from 'zod';
8
7
  import { HttpError } from 'http-errors';
9
- export { default as createHttpError } from 'http-errors';
10
8
  import * as qs from 'qs';
11
9
  import * as express_serve_static_core from 'express-serve-static-core';
12
10
  import * as http from 'http';
@@ -112,7 +110,7 @@ interface MiddlewareDefinition<IN extends IOSchema<"strip">, OPT, OUT extends Fl
112
110
  }
113
111
  type AnyMiddlewareDef = MiddlewareDefinition<any, any, any, any>;
114
112
  declare const createMiddleware: <IN extends IOSchema<"strip">, OPT, OUT extends FlatObject, SCO extends string>(props: MiddlewareCreationProps<IN, OPT, OUT, SCO>) => MiddlewareDefinition<IN, OPT, OUT, SCO>;
115
- type ExpressMiddleware<R extends Request, S extends Response> = (request: R, response: S, next: (error?: any) => void) => void | Promise<void>;
113
+ type ExpressMiddleware<R extends Request, S extends Response> = (request: R, response: S, next: NextFunction) => void | Promise<void>;
116
114
  interface ExpressMiddlewareFeatures<R extends Request, S extends Response, OUT extends FlatObject> {
117
115
  provider?: (request: R, response: S) => OUT | Promise<OUT>;
118
116
  transformer?: (err: Error) => HttpError | Error;
@@ -127,13 +125,8 @@ type IOSchema<U extends z.UnknownKeysParam = any> = z.ZodObject<any, U> | z.ZodU
127
125
  type ProbableIntersection<A extends IOSchema<"strip"> | null, B extends IOSchema> = A extends null ? B : A extends IOSchema<"strip"> ? z.ZodIntersection<A, B> : never;
128
126
 
129
127
  type Method = "get" | "post" | "put" | "delete" | "patch";
130
- type MethodsDefinition<M extends Method> = {
131
- methods: M[];
132
- } | {
133
- method: M;
134
- };
135
128
 
136
- type FlatObject = Record<string, any>;
129
+ type FlatObject = Record<string, unknown>;
137
130
  declare const getMessageFromError: (error: Error) => string;
138
131
  declare const getStatusCodeFromError: (error: Error) => number;
139
132
  declare const getExamples: <T extends z.ZodTypeAny, V extends "original" | "parsed" | undefined>({ schema, variant, validate, }: {
@@ -153,13 +146,12 @@ declare const getExamples: <T extends z.ZodTypeAny, V extends "original" | "pars
153
146
  }) => readonly (V extends "parsed" ? z.output<T> : z.input<T>)[];
154
147
  type ErrMessage = Exclude<Parameters<typeof z.ZodString.prototype.email>[0], undefined>;
155
148
 
149
+ interface Metadata<T extends z.ZodTypeAny> {
150
+ examples: z.input<T>[];
151
+ }
156
152
  declare const metaProp = "expressZodApiMeta";
157
153
  type MetaProp = typeof metaProp;
158
- type MetaDef<T extends z.ZodTypeAny> = {
159
- [K in MetaProp]: {
160
- examples: z.input<T>[];
161
- };
162
- };
154
+ type MetaDef<T extends z.ZodTypeAny> = Record<MetaProp, Metadata<T>>;
163
155
  type ExampleSetter<T extends z.ZodTypeAny> = (example: z.input<T>) => WithMeta<T>;
164
156
  type WithMeta<T extends z.ZodTypeAny> = T & {
165
157
  _def: T["_def"] & MetaDef<T>;
@@ -231,7 +223,7 @@ declare class ZodUpload extends ZodType<UploadedFile, ZodUploadDef> {
231
223
  static create: () => ZodUpload;
232
224
  }
233
225
 
234
- interface OpenAPIContext {
226
+ interface OpenAPIContext extends FlatObject {
235
227
  isResponse: boolean;
236
228
  serializer: (schema: z.ZodTypeAny) => string;
237
229
  getRef: (name: string) => ReferenceObject | undefined;
@@ -244,10 +236,6 @@ interface OpenAPIContext {
244
236
  declare class RoutingError extends Error {
245
237
  name: string;
246
238
  }
247
- /** @desc An error related to the issues of using DependsOnMethod class */
248
- declare class DependsOnMethodError extends RoutingError {
249
- name: string;
250
- }
251
239
  /**
252
240
  * @desc An error related to the generating of the documentation
253
241
  * */
@@ -275,9 +263,11 @@ declare class InputValidationError extends IOSchemaError {
275
263
  }
276
264
 
277
265
  interface ResultHandlerParams<RES> {
266
+ /** null in case of failure to parse or to find the matching endpoint (error: not found) */
267
+ input: FlatObject | null;
268
+ /** null in case of errors or failures */
269
+ output: FlatObject | null;
278
270
  error: Error | null;
279
- input: any;
280
- output: any;
281
271
  request: Request;
282
272
  response: Response<RES>;
283
273
  logger: Logger;
@@ -288,6 +278,7 @@ interface ResultHandlerDefinition<POS extends z.ZodTypeAny, NEG extends z.ZodTyp
288
278
  getNegativeResponse: () => NEG | ApiResponse<NEG>;
289
279
  handler: ResultHandler<z.output<POS> | z.output<NEG>>;
290
280
  }
281
+ type AnyResultHandlerDefinition = ResultHandlerDefinition<z.ZodTypeAny, z.ZodTypeAny>;
291
282
  declare const createResultHandler: <POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny>(definition: ResultHandlerDefinition<POS, NEG>) => ResultHandlerDefinition<POS, NEG>;
292
283
  declare const defaultResultHandler: ResultHandlerDefinition<z.ZodObject<{
293
284
  status: z.ZodLiteral<"success">;
@@ -405,9 +396,9 @@ declare const defaultResultHandler: ResultHandlerDefinition<z.ZodObject<{
405
396
  * @desc Responding with array is a bad practice keeping your endpoints from evolving without breaking changes.
406
397
  * @desc This handler expects your endpoint to have the property 'items' in the output object schema
407
398
  * */
408
- declare const arrayResultHandler: ResultHandlerDefinition<z.ZodArray<any, "many"> & {
409
- _def: z.ZodArrayDef<any> & MetaDef<z.ZodArray<any, "many">>;
410
- example: (example: any[]) => z.ZodArray<any, "many"> & any;
399
+ declare const arrayResultHandler: ResultHandlerDefinition<z.ZodArray<z.ZodTypeAny, "many"> & {
400
+ _def: z.ZodArrayDef<z.ZodTypeAny> & MetaDef<z.ZodArray<z.ZodTypeAny, "many">>;
401
+ example: (example: any[]) => z.ZodArray<z.ZodTypeAny, "many"> & any;
411
402
  }, z.ZodString & {
412
403
  _def: z.ZodStringDef & MetaDef<z.ZodString>;
413
404
  example: (example: string) => z.ZodString & any;
@@ -441,34 +432,28 @@ declare abstract class AbstractEndpoint {
441
432
  abstract _setSiblingMethods(methods: Method[]): void;
442
433
  abstract getOperationId(method: Method): string | undefined;
443
434
  }
444
- type EndpointProps<IN extends IOSchema, OUT extends IOSchema, OPT extends FlatObject, M extends Method, POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, SCO extends string, TAG extends string> = {
445
- middlewares: AnyMiddlewareDef[];
446
- inputSchema: IN;
447
- outputSchema: OUT;
448
- handler: Handler<z.output<IN>, z.input<OUT>, OPT>;
449
- resultHandler: ResultHandlerDefinition<POS, NEG>;
450
- description?: string;
451
- shortDescription?: string;
452
- operationId?: string | ((method: Method) => string);
453
- } & ({
454
- scopes?: SCO[];
455
- } | {
456
- scope?: SCO;
457
- }) & ({
458
- tags?: TAG[];
459
- } | {
460
- tag?: TAG;
461
- }) & MethodsDefinition<M>;
462
- declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, OPT extends FlatObject, M extends Method, POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, SCO extends string, TAG extends string> extends AbstractEndpoint {
435
+ declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, OPT extends FlatObject, POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, SCO extends string, TAG extends string> extends AbstractEndpoint {
463
436
  #private;
464
- constructor({ middlewares, inputSchema, outputSchema, handler, resultHandler, description, shortDescription, ...rest }: EndpointProps<IN, OUT, OPT, M, POS, NEG, SCO, TAG>);
437
+ constructor({ methods, inputSchema, outputSchema, handler, resultHandler, getOperationId, scopes, middlewares, tags, description: long, shortDescription: short, }: {
438
+ middlewares?: AnyMiddlewareDef[];
439
+ inputSchema: IN;
440
+ outputSchema: OUT;
441
+ handler: Handler<z.output<IN>, z.input<OUT>, OPT>;
442
+ resultHandler: ResultHandlerDefinition<POS, NEG>;
443
+ description?: string;
444
+ shortDescription?: string;
445
+ getOperationId?: (method: Method) => string | undefined;
446
+ methods: Method[];
447
+ scopes?: SCO[];
448
+ tags?: TAG[];
449
+ });
465
450
  /**
466
451
  * @desc Sets the other methods supported by the same path. Used by Routing in DependsOnMethod case, for options.
467
452
  * @deprecated This method is for internal needs of the library, please avoid using it.
468
453
  * */
469
454
  _setSiblingMethods(methods: Method[]): void;
470
455
  getDescription(variant: DescriptionVariant): string | undefined;
471
- getMethods(): M[];
456
+ getMethods(): Method[];
472
457
  getSchema(variant: "input"): IN;
473
458
  getSchema(variant: "output"): OUT;
474
459
  getSchema(variant: "positive"): POS;
@@ -507,7 +492,7 @@ interface ServerConfig {
507
492
  * @desc Custom JSON parser.
508
493
  * @default express.json()
509
494
  * */
510
- jsonParser?: NextHandleFunction;
495
+ jsonParser?: RequestHandler;
511
496
  /**
512
497
  * @desc Enable or configure uploads handling.
513
498
  * @default false
@@ -557,7 +542,7 @@ interface CommonConfig<TAG extends string = string> {
557
542
  * @default defaultResultHandler
558
543
  * @see defaultResultHandler
559
544
  */
560
- errorHandler?: ResultHandlerDefinition<any, any>;
545
+ errorHandler?: AnyResultHandlerDefinition;
561
546
  /** @desc Logger configuration or your custom winston logger. */
562
547
  logger: LoggerConfig | Logger;
563
548
  /**
@@ -580,7 +565,7 @@ interface CommonConfig<TAG extends string = string> {
580
565
  }
581
566
  declare const createConfig: <TAG extends string, T extends (ServerConfig | AppConfig) & CommonConfig<TAG>>(config: T) => T;
582
567
 
583
- type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<"strip"> | null, OPT extends FlatObject, M extends Method, SCO extends string, TAG extends string> = {
568
+ type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<"strip"> | null, OPT extends FlatObject, SCO extends string, TAG extends string> = {
584
569
  input: IN;
585
570
  output: OUT;
586
571
  handler: Handler<z.output<ProbableIntersection<MIN, IN>>, z.input<OUT>, OPT>;
@@ -588,6 +573,10 @@ type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<
588
573
  shortDescription?: string;
589
574
  operationId?: string | ((method: Method) => string);
590
575
  } & ({
576
+ method: Method;
577
+ } | {
578
+ methods: Method[];
579
+ }) & ({
591
580
  scopes?: SCO[];
592
581
  } | {
593
582
  scope?: SCO;
@@ -595,7 +584,7 @@ type BuildProps<IN extends IOSchema, OUT extends IOSchema, MIN extends IOSchema<
595
584
  tags?: TAG[];
596
585
  } | {
597
586
  tag?: TAG;
598
- }) & MethodsDefinition<M>;
587
+ });
599
588
  declare class EndpointsFactory<POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny, IN extends IOSchema<"strip"> | null = null, OUT extends FlatObject = {}, SCO extends string = string, TAG extends string = string> {
600
589
  #private;
601
590
  protected resultHandler: ResultHandlerDefinition<POS, NEG>;
@@ -610,7 +599,7 @@ declare class EndpointsFactory<POS extends z.ZodTypeAny, NEG extends z.ZodTypeAn
610
599
  use: <R extends Request<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>, S extends Response<any, Record<string, any>>, AOUT extends FlatObject = {}>(middleware: ExpressMiddleware<R, S>, features?: ExpressMiddlewareFeatures<R, S, AOUT> | undefined) => EndpointsFactory<POS, NEG, IN, OUT & AOUT, SCO, TAG>;
611
600
  addExpressMiddleware<R extends Request, S extends Response, AOUT extends FlatObject = {}>(middleware: ExpressMiddleware<R, S>, features?: ExpressMiddlewareFeatures<R, S, AOUT>): EndpointsFactory<POS, NEG, IN, OUT & AOUT, SCO, TAG>;
612
601
  addOptions<AOUT extends FlatObject>(options: AOUT): EndpointsFactory<POS, NEG, IN, OUT & AOUT, SCO, TAG>;
613
- build<BIN extends IOSchema, BOUT extends IOSchema, M extends Method>({ input, handler, output: outputSchema, ...rest }: BuildProps<BIN, BOUT, IN, OUT, M, SCO, TAG>): Endpoint<ProbableIntersection<IN, BIN>, BOUT, OUT, M, POS, NEG, SCO, TAG>;
602
+ build<BIN extends IOSchema, BOUT extends IOSchema>({ input, handler, output: outputSchema, description, shortDescription, operationId, ...rest }: BuildProps<BIN, BOUT, IN, OUT, SCO, TAG>): Endpoint<ProbableIntersection<IN, BIN>, BOUT, OUT, POS, NEG, SCO, TAG>;
614
603
  }
615
604
  declare const defaultEndpointsFactory: EndpointsFactory<z.ZodObject<{
616
605
  status: z.ZodLiteral<"success">;
@@ -728,9 +717,9 @@ declare const defaultEndpointsFactory: EndpointsFactory<z.ZodObject<{
728
717
  * @desc Responding with array is a bad practice keeping your endpoints from evolving without breaking changes.
729
718
  * @desc The result handler of this factory expects your endpoint to have the property 'items' in the output schema
730
719
  */
731
- declare const arrayEndpointsFactory: EndpointsFactory<z.ZodArray<any, "many"> & {
732
- _def: z.ZodArrayDef<any> & MetaDef<z.ZodArray<any, "many">>;
733
- example: (example: any[]) => z.ZodArray<any, "many"> & any;
720
+ declare const arrayEndpointsFactory: EndpointsFactory<z.ZodArray<z.ZodTypeAny, "many"> & {
721
+ _def: z.ZodArrayDef<z.ZodTypeAny> & MetaDef<z.ZodArray<z.ZodTypeAny, "many">>;
722
+ example: (example: any[]) => z.ZodArray<z.ZodTypeAny, "many"> & any;
734
723
  }, z.ZodString & {
735
724
  _def: z.ZodStringDef & MetaDef<z.ZodString>;
736
725
  example: (example: string) => z.ZodString & any;
@@ -739,12 +728,8 @@ declare const arrayEndpointsFactory: EndpointsFactory<z.ZodArray<any, "many"> &
739
728
  declare const createLogger: (loggerConfig: LoggerConfig) => winston.Logger;
740
729
 
741
730
  declare class DependsOnMethod {
742
- readonly methods: {
743
- [K in Method]?: Endpoint<any, any, any, K, any, any, any, any> | Endpoint<any, any, any, Method, any, any, any, any>;
744
- };
745
- constructor(methods: {
746
- [K in Method]?: Endpoint<any, any, any, K, any, any, any, any> | Endpoint<any, any, any, Method, any, any, any, any>;
747
- });
731
+ readonly endpoints: Partial<Record<Method, AbstractEndpoint>>;
732
+ constructor(endpoints: Partial<Record<Method, AbstractEndpoint>>);
748
733
  }
749
734
 
750
735
  type OriginalStatic = typeof express.static;
@@ -820,7 +805,7 @@ declare const testEndpoint: <REQ extends Partial<Record<keyof Request<express_se
820
805
  writableEnded: boolean;
821
806
  statusCode: number;
822
807
  statusMessage: string;
823
- } & Record<"status" | "header" | "set" | "json" | "end" | "send" | "setHeader", jest.Mock<any, any, any>> & (RES extends undefined ? {} : RES);
808
+ } & Record<"status" | "header" | "set" | "end" | "send" | "json" | "setHeader", jest.Mock<any, any, any>> & (RES extends undefined ? {} : RES);
824
809
  loggerMock: Record<"error" | "warn" | "debug" | "info", jest.Mock<any, any, any>> & (LOG extends undefined ? {} : LOG);
825
810
  }>;
826
811
 
@@ -890,4 +875,4 @@ declare namespace proprietarySchemas {
890
875
  };
891
876
  }
892
877
 
893
- export { AbstractEndpoint, BasicSecurity, BearerSecurity, CommonConfig, CookieSecurity, CustomHeaderSecurity, DependsOnMethod, DependsOnMethodError, Documentation, DocumentationError, EndpointsFactory, FlatObject, IOSchema, InputSecurity, InputValidationError, Integration, LoggerConfig, Method, MiddlewareDefinition, OAuth2Security, OpenIdSecurity, OutputValidationError, ResultHandlerDefinition, Routing, RoutingError, ServeStatic, ZodDateInDef, ZodDateOutDef, ZodFileDef, ZodUploadDef, arrayEndpointsFactory, arrayResultHandler, attachRouting, createConfig, createLogger, createMiddleware, createResultHandler, createServer, defaultEndpointsFactory, defaultResultHandler, proprietarySchemas as ez, getExamples, getMessageFromError, getStatusCodeFromError, testEndpoint, withMeta };
878
+ export { AbstractEndpoint, BasicSecurity, BearerSecurity, CommonConfig, CookieSecurity, CustomHeaderSecurity, DependsOnMethod, Documentation, DocumentationError, EndpointsFactory, FlatObject, IOSchema, InputSecurity, InputValidationError, Integration, LoggerConfig, Method, MiddlewareDefinition, OAuth2Security, OpenIdSecurity, OutputValidationError, ResultHandlerDefinition, Routing, RoutingError, ServeStatic, ZodDateInDef, ZodDateOutDef, ZodFileDef, ZodUploadDef, arrayEndpointsFactory, arrayResultHandler, attachRouting, createConfig, createLogger, createMiddleware, createResultHandler, createServer, defaultEndpointsFactory, defaultResultHandler, proprietarySchemas as ez, getExamples, getMessageFromError, getStatusCodeFromError, testEndpoint, withMeta };