express-zod-api 14.2.2 → 15.0.0-beta1
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 +60 -0
- package/README.md +62 -37
- package/SECURITY.md +3 -2
- package/dist/index.d.mts +71 -35
- package/dist/index.d.ts +71 -35
- package/dist/index.js +8 -8
- package/dist/index.mjs +8 -8
- package/package.json +34 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,67 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Version 15
|
|
4
|
+
|
|
5
|
+
### 15.0.0
|
|
6
|
+
|
|
7
|
+
- **Breaking changes**:
|
|
8
|
+
- `express-fileupload` and `compression` become optional peer dependencies;
|
|
9
|
+
- Methods `createServer()` and `attachRouting()` become async;
|
|
10
|
+
- Method `testEndpoint()` requires an additional argument;
|
|
11
|
+
- Method `createLogger()` removed as redundant;
|
|
12
|
+
- Read the migration guide below.
|
|
13
|
+
- Features:
|
|
14
|
+
- `winston` is now optional: supporting any logger having `debug()`, `warn()`, `info()` and `error()` methods;
|
|
15
|
+
- Introducing module augmentation approach for setting the type of chosen logger;
|
|
16
|
+
- Supporting both `jest` and `vitest` frameworks for `testEndpoint()`.
|
|
17
|
+
- How to migrate while maintaining previous functionality and behavior:
|
|
18
|
+
- If you're going to continue using `winston`:
|
|
19
|
+
- Near your `const config = createConfig(...)` add the module augmentation statement (see example below).
|
|
20
|
+
- If you have `upload` option enabled in your config:
|
|
21
|
+
- Install `express-fileupload` and `@types/express-fileupload` packages;
|
|
22
|
+
- If you have `compression` option enabled in your config:
|
|
23
|
+
- Install `compression` and `@types/compression` packages;
|
|
24
|
+
- If you're using `createLogger()` method:
|
|
25
|
+
- Place its argument as a value of `logger` property supplied to `createConfig()`.
|
|
26
|
+
- If you're using the entities returned from `createServer()` or `attachRouting()` methods:
|
|
27
|
+
- Add `await` before calling them: `const {...} = await createServer(...)`.
|
|
28
|
+
- If you can not use `await` (on the top level of CommonJS):
|
|
29
|
+
- Wrap your code with async IIFE or use `.then()` (see example below).
|
|
30
|
+
- If you're using `testEndpoint()` method:
|
|
31
|
+
- Specify either `fnMethod: jest.fn` or `fnMethod: vi.fn` within its object argument.
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import type { Logger } from "winston";
|
|
35
|
+
import { createConfig, createServer, testEndpoint } from "express-zod-api";
|
|
36
|
+
|
|
37
|
+
// The configuration remains the same
|
|
38
|
+
const config = createConfig({
|
|
39
|
+
logger: { level: "debug", color: true },
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Set the type of logger used near your configuration
|
|
43
|
+
declare module "express-zod-api" {
|
|
44
|
+
interface LoggerOverrides extends Logger {}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// await is only needed when you're using the returns of createServer() or attachRouting()
|
|
48
|
+
// For using await on the top level CJS, wrap it in async IIFE:
|
|
49
|
+
// (async () => { await ... })();
|
|
50
|
+
const { app, httpServer } = await createServer(config, routing);
|
|
51
|
+
|
|
52
|
+
// Adjust your tests:
|
|
53
|
+
const { responseMock } = await testEndpoint({
|
|
54
|
+
endpoint,
|
|
55
|
+
fnMethod: jest.fn, // or vi.fn from vitest, required
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
3
59
|
## Version 14
|
|
4
60
|
|
|
61
|
+
### v14.2.3
|
|
62
|
+
|
|
63
|
+
- `express-fileupload` version is 1.4.3.
|
|
64
|
+
|
|
5
65
|
### v14.2.2
|
|
6
66
|
|
|
7
67
|
- Hotfix: exporting `AppConfig` and `ServerConfig` types to in order to prevent the issue #952.
|
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ You can find the release notes and migration guides in [Changelog](CHANGELOG.md)
|
|
|
64
64
|
# Why and what is it for
|
|
65
65
|
|
|
66
66
|
I made this library because of the often repetitive tasks of starting a web server APIs with the need to validate input
|
|
67
|
-
data. It integrates and provides the capabilities of popular web server,
|
|
67
|
+
data. It integrates and provides the capabilities of popular web server, logging, validation and documenting solutions.
|
|
68
68
|
Therefore, many basic tasks can be accomplished faster and easier, in particular:
|
|
69
69
|
|
|
70
70
|
- You can describe web server routes as a hierarchical object.
|
|
@@ -85,7 +85,8 @@ Therefore, many basic tasks can be accomplished faster and easier, in particular
|
|
|
85
85
|
- [Typescript](https://www.typescriptlang.org/) first.
|
|
86
86
|
- Web server — [Express.js](https://expressjs.com/).
|
|
87
87
|
- Schema validation — [Zod 3.x](https://github.com/colinhacks/zod).
|
|
88
|
-
- Logger — [Winston](https://github.com/winstonjs/winston)
|
|
88
|
+
- Logger — [Winston](https://github.com/winstonjs/winston) by default,
|
|
89
|
+
- Supports any logger having `info()`, `debug()`, `error()` and `warn()` methods.
|
|
89
90
|
- Generators:
|
|
90
91
|
- Documentation — [OpenAPI 3.x](https://github.com/metadevpro/openapi3-ts) (Swagger Specification).
|
|
91
92
|
- Client side types — inspired by [zod-to-ts](https://github.com/sachinraja/zod-to-ts).
|
|
@@ -138,6 +139,7 @@ Create a minimal configuration. _See all available options
|
|
|
138
139
|
[in sources](https://github.com/RobinTail/express-zod-api/blob/master/src/config-type.ts)._
|
|
139
140
|
|
|
140
141
|
```typescript
|
|
142
|
+
import type { Logger } from "winston";
|
|
141
143
|
import { createConfig } from "express-zod-api";
|
|
142
144
|
|
|
143
145
|
const config = createConfig({
|
|
@@ -147,6 +149,11 @@ const config = createConfig({
|
|
|
147
149
|
cors: true,
|
|
148
150
|
logger: { level: "debug", color: true },
|
|
149
151
|
});
|
|
152
|
+
|
|
153
|
+
// Setting the type of logger used
|
|
154
|
+
declare module "express-zod-api" {
|
|
155
|
+
interface LoggerOverrides extends Logger {}
|
|
156
|
+
}
|
|
150
157
|
```
|
|
151
158
|
|
|
152
159
|
## Create an endpoints factory
|
|
@@ -483,7 +490,12 @@ const config = createConfig({
|
|
|
483
490
|
// ... cors, logger, etc
|
|
484
491
|
});
|
|
485
492
|
|
|
486
|
-
|
|
493
|
+
// 'await' is only needed if you're going to use the returned entities.
|
|
494
|
+
// For top level CJS you can wrap you code with (async () => { ... })()
|
|
495
|
+
const { app, httpServer, httpsServer, logger } = await createServer(
|
|
496
|
+
config,
|
|
497
|
+
routing,
|
|
498
|
+
);
|
|
487
499
|
```
|
|
488
500
|
|
|
489
501
|
Ensure having `@types/node` package installed. At least you need to specify the port (usually it is 443) or UNIX socket,
|
|
@@ -492,44 +504,48 @@ your API at [Let's Encrypt](https://letsencrypt.org/).
|
|
|
492
504
|
|
|
493
505
|
## Customizing logger
|
|
494
506
|
|
|
495
|
-
You can
|
|
507
|
+
You can uninstall `winston` (which is the default and recommended logger) and use another compatible one, having
|
|
508
|
+
`info()`, `debug()`, `error()` and `warn()` methods. For example, `pino` logger with `pino-pretty` extension:
|
|
496
509
|
|
|
497
510
|
```typescript
|
|
498
|
-
import
|
|
511
|
+
import pino, { Logger } from "pino";
|
|
499
512
|
import { createConfig } from "express-zod-api";
|
|
500
513
|
|
|
501
|
-
const logger =
|
|
502
|
-
|
|
514
|
+
const logger = pino({
|
|
515
|
+
transport: {
|
|
516
|
+
target: "pino-pretty",
|
|
517
|
+
options: { colorize: true },
|
|
518
|
+
},
|
|
503
519
|
});
|
|
504
|
-
const config = createConfig({ logger
|
|
520
|
+
const config = createConfig({ logger });
|
|
521
|
+
|
|
522
|
+
// Setting the type of logger used
|
|
523
|
+
declare module "express-zod-api" {
|
|
524
|
+
interface LoggerOverrides extends Logger {}
|
|
525
|
+
}
|
|
505
526
|
```
|
|
506
527
|
|
|
507
528
|
## Enabling compression
|
|
508
529
|
|
|
509
530
|
According to [Express.js best practices guide](http://expressjs.com/en/advanced/best-practice-performance.html)
|
|
510
|
-
it might be a good idea to enable GZIP compression of your API responses.
|
|
511
|
-
corresponding configuration option when using the `createServer()` method.
|
|
531
|
+
it might be a good idea to enable GZIP compression of your API responses.
|
|
512
532
|
|
|
513
|
-
|
|
514
|
-
`Accept-Encoding: gzip, deflate`. Only responses with compressible content types are subject to compression. There is
|
|
515
|
-
also a default threshold of 1KB that can be configured.
|
|
533
|
+
Install the following additional packages: `compression` and `@types/compression`, and enable or configure compression:
|
|
516
534
|
|
|
517
535
|
```typescript
|
|
518
536
|
import { createConfig } from "express-zod-api";
|
|
519
537
|
|
|
520
538
|
const config = createConfig({
|
|
521
539
|
server: {
|
|
522
|
-
|
|
523
|
-
compression: {
|
|
524
|
-
// @see https://www.npmjs.com/package/compression#options
|
|
525
|
-
threshold: "100b",
|
|
526
|
-
},
|
|
527
|
-
// ... other options
|
|
540
|
+
/** @link https://www.npmjs.com/package/compression#options */
|
|
541
|
+
compression: { threshold: "1kb" }, // or true
|
|
528
542
|
},
|
|
529
|
-
// ... other options
|
|
530
543
|
});
|
|
531
544
|
```
|
|
532
545
|
|
|
546
|
+
In order to receive a compressed response the client should include the following header in the request:
|
|
547
|
+
`Accept-Encoding: gzip, deflate`. Only responses with compressible content types are subject to compression.
|
|
548
|
+
|
|
533
549
|
# Advances features
|
|
534
550
|
|
|
535
551
|
## Customizing input sources
|
|
@@ -715,29 +731,34 @@ const fileStreamingEndpointsFactory = new EndpointsFactory(
|
|
|
715
731
|
|
|
716
732
|
## File uploads
|
|
717
733
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
Here is a simplified example:
|
|
734
|
+
Install the following additional packages: `express-fileupload` and `@types/express-fileupload`, and enable or
|
|
735
|
+
configure file uploads:
|
|
721
736
|
|
|
722
737
|
```typescript
|
|
723
|
-
import {
|
|
724
|
-
import { createConfig, ez, defaultEndpointsFactory } from "express-zod-api";
|
|
738
|
+
import { createConfig } from "express-zod-api";
|
|
725
739
|
|
|
726
740
|
const config = createConfig({
|
|
727
741
|
server: {
|
|
728
|
-
upload: true, //
|
|
729
|
-
// ...,
|
|
742
|
+
upload: true, // or options
|
|
730
743
|
},
|
|
731
744
|
});
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
Refer to [documentation](https://www.npmjs.com/package/express-fileupload#available-options) on available options.
|
|
748
|
+
Then you can change the `Endpoint` to handle requests having the `multipart/form-data` content type instead of JSON by
|
|
749
|
+
using `ez.upload()` schema. Together with a corresponding configuration option, this makes it possible to handle file
|
|
750
|
+
uploads. Here is a simplified example:
|
|
751
|
+
|
|
752
|
+
```typescript
|
|
753
|
+
import { z } from "zod";
|
|
754
|
+
import { ez, defaultEndpointsFactory } from "express-zod-api";
|
|
732
755
|
|
|
733
756
|
const fileUploadEndpoint = defaultEndpointsFactory.build({
|
|
734
757
|
method: "post",
|
|
735
758
|
input: z.object({
|
|
736
759
|
avatar: ez.upload(), // <--
|
|
737
760
|
}),
|
|
738
|
-
output: z.object({
|
|
739
|
-
/* ... */
|
|
740
|
-
}),
|
|
761
|
+
output: z.object({}),
|
|
741
762
|
handler: async ({ input: { avatar } }) => {
|
|
742
763
|
// avatar: {name, mv(), mimetype, data, size, etc}
|
|
743
764
|
// avatar.truncated is true on failure
|
|
@@ -782,12 +803,15 @@ const routing = {
|
|
|
782
803
|
/* ... */
|
|
783
804
|
};
|
|
784
805
|
|
|
785
|
-
|
|
806
|
+
// This async IIFE is only required for the top level CommonJS
|
|
807
|
+
(async () => {
|
|
808
|
+
const { notFoundHandler, logger } = await attachRouting(config, routing);
|
|
786
809
|
|
|
787
|
-
app.use(notFoundHandler); // optional
|
|
788
|
-
app.listen();
|
|
810
|
+
app.use(notFoundHandler); // optional
|
|
811
|
+
app.listen();
|
|
789
812
|
|
|
790
|
-
logger.info("Glory to science!");
|
|
813
|
+
logger.info("Glory to science!");
|
|
814
|
+
})();
|
|
791
815
|
```
|
|
792
816
|
|
|
793
817
|
**Please note** that in this case you probably need to parse `request.body`, call `app.listen()` and handle `404`
|
|
@@ -990,17 +1014,18 @@ const exampleEndpoint = taggedEndpointsFactory.build({
|
|
|
990
1014
|
|
|
991
1015
|
The way to test endpoints is to mock the request, response, and logger objects, invoke the `execute()` method, and
|
|
992
1016
|
assert the expectations for calls of certain mocked methods. The library provides a special method that makes mocking
|
|
993
|
-
easier, it requires `jest` (
|
|
1017
|
+
easier, it requires either `jest` (with `@types/jest`) or `vitest` to be installed, so the test might look this way:
|
|
994
1018
|
|
|
995
1019
|
```typescript
|
|
996
1020
|
import { testEndpoint } from "express-zod-api";
|
|
997
1021
|
|
|
998
1022
|
test("should respond successfully", async () => {
|
|
999
1023
|
const { responseMock, loggerMock } = await testEndpoint({
|
|
1024
|
+
fnMethod: jest.fn, // or vi.fn from vitest
|
|
1000
1025
|
endpoint: yourEndpoint,
|
|
1001
1026
|
requestProps: {
|
|
1002
1027
|
method: "POST", // default: GET
|
|
1003
|
-
body: {
|
|
1028
|
+
body: {}, // incoming data as if after parsing (JSON)
|
|
1004
1029
|
},
|
|
1005
1030
|
// responseProps, configProps, loggerProps
|
|
1006
1031
|
});
|
|
@@ -1008,7 +1033,7 @@ test("should respond successfully", async () => {
|
|
|
1008
1033
|
expect(responseMock.status).toHaveBeenCalledWith(200);
|
|
1009
1034
|
expect(responseMock.json).toHaveBeenCalledWith({
|
|
1010
1035
|
status: "success",
|
|
1011
|
-
data: {
|
|
1036
|
+
data: {},
|
|
1012
1037
|
});
|
|
1013
1038
|
});
|
|
1014
1039
|
```
|
package/SECURITY.md
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Release | Supported |
|
|
6
6
|
| ------: | :------ | :----------------: |
|
|
7
|
+
| 15.x.x | 12.2023 | :white_check_mark: |
|
|
7
8
|
| 14.x.x | 10.2023 | :white_check_mark: |
|
|
8
9
|
| 12.x.x | 09.2023 | :white_check_mark: |
|
|
9
|
-
| 11.x.x | 06.2023 |
|
|
10
|
+
| 11.x.x | 06.2023 | :x: |
|
|
10
11
|
| 10.x.x | 03.2023 | :x: |
|
|
11
12
|
| 9.x.x | 03.2023 | :x: |
|
|
12
13
|
| 8.x.x | 09.2022 | :x: |
|
|
@@ -24,6 +25,6 @@
|
|
|
24
25
|
Found a vulnerability or other security issue?
|
|
25
26
|
|
|
26
27
|
Please urgently inform me privately by
|
|
27
|
-
[email](https://github.com/RobinTail/express-zod-api/blob/master/package.json#
|
|
28
|
+
[email](https://github.com/RobinTail/express-zod-api/blob/master/package.json#L140).
|
|
28
29
|
|
|
29
30
|
I will try to fix it as soon as possible.
|
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,6 @@ import compression from 'compression';
|
|
|
2
2
|
import express, { Request, Response, NextFunction, RequestHandler, Express } from 'express';
|
|
3
3
|
import fileUpload, { UploadedFile } from 'express-fileupload';
|
|
4
4
|
import https, { ServerOptions } from 'node:https';
|
|
5
|
-
import winston, { Logger } from 'winston';
|
|
6
5
|
import { z, ZodTypeDef, ZodType, ParseInput, ParseReturnType, ZodError } from 'zod';
|
|
7
6
|
import { HttpError } from 'http-errors';
|
|
8
7
|
import { ListenOptions } from 'node:net';
|
|
@@ -93,12 +92,26 @@ interface OAuth2Security<S extends string> {
|
|
|
93
92
|
* */
|
|
94
93
|
type Security<K extends string = string, S extends string = string> = BasicSecurity | BearerSecurity | InputSecurity<K> | CustomHeaderSecurity | CookieSecurity | OpenIdSecurity | OAuth2Security<S>;
|
|
95
94
|
|
|
95
|
+
/**
|
|
96
|
+
* @desc Using module augmentation approach you can set the type of the actual logger used
|
|
97
|
+
* @example declare module "express-zod-api" { interface LoggerOverrides extends winston.Logger {} }
|
|
98
|
+
* @link https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
|
|
99
|
+
* */
|
|
100
|
+
interface LoggerOverrides {
|
|
101
|
+
}
|
|
102
|
+
/** @desc You can use any logger compatible with this type. */
|
|
103
|
+
type AbstractLogger = Record<"info" | "debug" | "warn" | "error", (message: string, meta?: any) => any> & LoggerOverrides;
|
|
104
|
+
interface SimplifiedWinstonConfig {
|
|
105
|
+
level: "silent" | "warn" | "debug";
|
|
106
|
+
color: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
96
109
|
interface MiddlewareParams<IN, OPT> {
|
|
97
110
|
input: IN;
|
|
98
111
|
options: OPT;
|
|
99
112
|
request: Request;
|
|
100
113
|
response: Response;
|
|
101
|
-
logger:
|
|
114
|
+
logger: AbstractLogger;
|
|
102
115
|
}
|
|
103
116
|
type Middleware<IN, OPT, OUT> = (params: MiddlewareParams<IN, OPT>) => Promise<OUT>;
|
|
104
117
|
interface MiddlewareCreationProps<IN extends IOSchema<"strip">, OPT, OUT extends FlatObject, SCO extends string> {
|
|
@@ -261,6 +274,10 @@ declare class InputValidationError extends IOSchemaError {
|
|
|
261
274
|
readonly originalError: ZodError;
|
|
262
275
|
constructor(originalError: ZodError);
|
|
263
276
|
}
|
|
277
|
+
declare class MissingPeerError extends Error {
|
|
278
|
+
name: string;
|
|
279
|
+
constructor(module: string);
|
|
280
|
+
}
|
|
264
281
|
|
|
265
282
|
interface ResultHandlerParams<RES> {
|
|
266
283
|
/** null in case of failure to parse or to find the matching endpoint (error: not found) */
|
|
@@ -270,7 +287,7 @@ interface ResultHandlerParams<RES> {
|
|
|
270
287
|
error: Error | null;
|
|
271
288
|
request: Request;
|
|
272
289
|
response: Response<RES>;
|
|
273
|
-
logger:
|
|
290
|
+
logger: AbstractLogger;
|
|
274
291
|
}
|
|
275
292
|
type ResultHandler<RES> = (params: ResultHandlerParams<RES>) => void | Promise<void>;
|
|
276
293
|
interface ResultHandlerDefinition<POS extends z.ZodTypeAny, NEG extends z.ZodTypeAny> {
|
|
@@ -407,7 +424,7 @@ declare const arrayResultHandler: ResultHandlerDefinition<z.ZodArray<z.ZodTypeAn
|
|
|
407
424
|
type Handler<IN, OUT, OPT> = (params: {
|
|
408
425
|
input: IN;
|
|
409
426
|
options: OPT;
|
|
410
|
-
logger:
|
|
427
|
+
logger: AbstractLogger;
|
|
411
428
|
}) => Promise<OUT>;
|
|
412
429
|
type DescriptionVariant = "short" | "long";
|
|
413
430
|
type IOVariant = "input" | "output";
|
|
@@ -417,7 +434,7 @@ declare abstract class AbstractEndpoint {
|
|
|
417
434
|
abstract execute(params: {
|
|
418
435
|
request: Request;
|
|
419
436
|
response: Response;
|
|
420
|
-
logger:
|
|
437
|
+
logger: AbstractLogger;
|
|
421
438
|
config: CommonConfig;
|
|
422
439
|
}): Promise<void>;
|
|
423
440
|
abstract getDescription(variant: DescriptionVariant): string | undefined;
|
|
@@ -467,15 +484,11 @@ declare class Endpoint<IN extends IOSchema, OUT extends IOSchema, OPT extends Fl
|
|
|
467
484
|
execute({ request, response, logger, config, }: {
|
|
468
485
|
request: Request;
|
|
469
486
|
response: Response;
|
|
470
|
-
logger:
|
|
487
|
+
logger: AbstractLogger;
|
|
471
488
|
config: CommonConfig;
|
|
472
489
|
}): Promise<void>;
|
|
473
490
|
}
|
|
474
491
|
|
|
475
|
-
interface LoggerConfig {
|
|
476
|
-
level: "silent" | "warn" | "debug";
|
|
477
|
-
color: boolean;
|
|
478
|
-
}
|
|
479
492
|
type InputSource = keyof Pick<Request, "query" | "body" | "files" | "params" | "headers">;
|
|
480
493
|
type InputSources = Record<Method, InputSource[]>;
|
|
481
494
|
type Headers = Record<string, string>;
|
|
@@ -484,7 +497,7 @@ type HeadersProvider = (params: {
|
|
|
484
497
|
defaultHeaders: Headers;
|
|
485
498
|
request: Request;
|
|
486
499
|
endpoint: AbstractEndpoint;
|
|
487
|
-
logger:
|
|
500
|
+
logger: AbstractLogger;
|
|
488
501
|
}) => Headers | Promise<Headers>;
|
|
489
502
|
type TagsConfig<TAG extends string> = Record<TAG, string | {
|
|
490
503
|
description: string;
|
|
@@ -503,8 +516,11 @@ interface CommonConfig<TAG extends string = string> {
|
|
|
503
516
|
* @see defaultResultHandler
|
|
504
517
|
*/
|
|
505
518
|
errorHandler?: AnyResultHandlerDefinition;
|
|
506
|
-
/**
|
|
507
|
-
|
|
519
|
+
/**
|
|
520
|
+
* @desc Logger configuration (winston) or instance of any other logger.
|
|
521
|
+
* @example { level: "debug", color: true }
|
|
522
|
+
* */
|
|
523
|
+
logger: SimplifiedWinstonConfig | AbstractLogger;
|
|
508
524
|
/**
|
|
509
525
|
* @desc You can disable the startup logo.
|
|
510
526
|
* @default true
|
|
@@ -539,11 +555,13 @@ interface ServerConfig<TAG extends string = string> extends CommonConfig<TAG> {
|
|
|
539
555
|
/**
|
|
540
556
|
* @desc Enable or configure uploads handling.
|
|
541
557
|
* @default false
|
|
558
|
+
* @requires express-fileupload
|
|
542
559
|
* */
|
|
543
560
|
upload?: boolean | UploadOptions;
|
|
544
561
|
/**
|
|
545
562
|
* @desc Enable or configure response compression.
|
|
546
563
|
* @default false
|
|
564
|
+
* @requires compression
|
|
547
565
|
*/
|
|
548
566
|
compression?: boolean | CompressionOptions;
|
|
549
567
|
/**
|
|
@@ -594,11 +612,8 @@ declare class EndpointsFactory<POS extends z.ZodTypeAny, NEG extends z.ZodTypeAn
|
|
|
594
612
|
#private;
|
|
595
613
|
protected resultHandler: ResultHandlerDefinition<POS, NEG>;
|
|
596
614
|
protected middlewares: AnyMiddlewareDef[];
|
|
615
|
+
/** @desc Consider using the "config" prop with the "tags" option to enforce constraints on tagging the endpoints */
|
|
597
616
|
constructor(resultHandler: ResultHandlerDefinition<POS, NEG>);
|
|
598
|
-
/**
|
|
599
|
-
* @desc Consider using the "config" prop with the "tags" option to enforce constraints on tagging the endpoints
|
|
600
|
-
* @todo in next major release consider making config required for using in Endpoint::constructor
|
|
601
|
-
* */
|
|
602
617
|
constructor(params: {
|
|
603
618
|
resultHandler: ResultHandlerDefinition<POS, NEG>;
|
|
604
619
|
config?: CommonConfig<TAG>;
|
|
@@ -733,8 +748,6 @@ declare const arrayEndpointsFactory: EndpointsFactory<z.ZodArray<z.ZodTypeAny, "
|
|
|
733
748
|
example: (example: string) => z.ZodString & any;
|
|
734
749
|
}, null, {}, string, string>;
|
|
735
750
|
|
|
736
|
-
declare const createLogger: (loggerConfig: LoggerConfig) => winston.Logger;
|
|
737
|
-
|
|
738
751
|
declare class DependsOnMethod {
|
|
739
752
|
readonly endpoints: Partial<Record<Method, AbstractEndpoint>>;
|
|
740
753
|
constructor(endpoints: Partial<Record<Method, AbstractEndpoint>>);
|
|
@@ -752,16 +765,16 @@ interface Routing {
|
|
|
752
765
|
[SEGMENT: string]: Routing | DependsOnMethod | AbstractEndpoint | ServeStatic;
|
|
753
766
|
}
|
|
754
767
|
|
|
755
|
-
declare const attachRouting: (config: AppConfig, routing: Routing) => {
|
|
768
|
+
declare const attachRouting: (config: AppConfig, routing: Routing) => Promise<{
|
|
756
769
|
notFoundHandler: express.RequestHandler<express_serve_static_core.ParamsDictionary, any, any, qs.ParsedQs, Record<string, any>>;
|
|
757
|
-
logger:
|
|
758
|
-
}
|
|
759
|
-
declare const createServer: (config: ServerConfig, routing: Routing) => {
|
|
760
|
-
logger:
|
|
770
|
+
logger: AbstractLogger;
|
|
771
|
+
}>;
|
|
772
|
+
declare const createServer: (config: ServerConfig, routing: Routing) => Promise<{
|
|
773
|
+
logger: AbstractLogger;
|
|
761
774
|
httpServer: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
762
775
|
httpsServer: https.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined;
|
|
763
776
|
app: express_serve_static_core.Express;
|
|
764
|
-
}
|
|
777
|
+
}>;
|
|
765
778
|
|
|
766
779
|
interface DocumentationParams {
|
|
767
780
|
title: string;
|
|
@@ -793,28 +806,51 @@ declare class Documentation extends OpenApiBuilder {
|
|
|
793
806
|
constructor({ routing, config, title, version, serverUrl, successfulResponseDescription, errorResponseDescription, hasSummaryFromDescription, composition, serializer, }: DocumentationParams);
|
|
794
807
|
}
|
|
795
808
|
|
|
796
|
-
|
|
809
|
+
type MockFunction = <S>(implementation?: (...args: any[]) => any) => S;
|
|
810
|
+
interface TestEndpointProps<REQ, RES, LOG, FN> {
|
|
811
|
+
/** @desc The endpoint to test */
|
|
797
812
|
endpoint: AbstractEndpoint;
|
|
813
|
+
/**
|
|
814
|
+
* @desc Additional properties to set on Request mock
|
|
815
|
+
* @default { method: "GET", header: () => "application/json" }
|
|
816
|
+
* */
|
|
798
817
|
requestProps?: REQ;
|
|
818
|
+
/**
|
|
819
|
+
* @desc Additional properties to set on Response mock
|
|
820
|
+
* @default { writableEnded, statusCode, statusMessage, set, setHeader, header, status, json, send, end }
|
|
821
|
+
* */
|
|
799
822
|
responseProps?: RES;
|
|
823
|
+
/**
|
|
824
|
+
* @desc Additional properties to set on config mock
|
|
825
|
+
* @default { cors: false, logger }
|
|
826
|
+
* */
|
|
800
827
|
configProps?: Partial<CommonConfig>;
|
|
828
|
+
/**
|
|
829
|
+
* @desc Additional properties to set on logger mock
|
|
830
|
+
* @default { info, warn, error, debug }
|
|
831
|
+
* */
|
|
801
832
|
loggerProps?: LOG;
|
|
802
|
-
/**
|
|
803
|
-
|
|
833
|
+
/**
|
|
834
|
+
* @example jest.fn
|
|
835
|
+
* @example vi.fn
|
|
836
|
+
* */
|
|
837
|
+
fnMethod: FN;
|
|
804
838
|
}
|
|
805
839
|
/**
|
|
806
|
-
* @
|
|
807
|
-
|
|
808
|
-
|
|
840
|
+
* @desc You need to install either jest (with @types/jest) or vitest in order to use this method
|
|
841
|
+
* @requires jest
|
|
842
|
+
* @requires vitest
|
|
843
|
+
* */
|
|
844
|
+
declare const testEndpoint: <FN extends MockFunction, LOG extends Record<string, any>, REQ extends Record<string, any>, RES extends Record<string, any>>({ endpoint, requestProps, responseProps, configProps, loggerProps, fnMethod, }: TestEndpointProps<REQ, RES, LOG, FN>) => Promise<{
|
|
809
845
|
requestMock: {
|
|
810
846
|
method: string;
|
|
811
|
-
} & Record<"header",
|
|
847
|
+
} & Record<"header", ReturnType<FN>> & REQ;
|
|
812
848
|
responseMock: {
|
|
813
849
|
writableEnded: boolean;
|
|
814
850
|
statusCode: number;
|
|
815
851
|
statusMessage: string;
|
|
816
|
-
} & Record<"status" | "set" | "header" | "end" | "
|
|
817
|
-
loggerMock: Record<"
|
|
852
|
+
} & Record<"status" | "set" | "header" | "end" | "setHeader" | "json" | "send", ReturnType<FN>> & RES;
|
|
853
|
+
loggerMock: Record<"info" | "debug" | "warn" | "error", ReturnType<FN>> & LOG;
|
|
818
854
|
}>;
|
|
819
855
|
|
|
820
856
|
interface Registry {
|
|
@@ -887,4 +923,4 @@ declare namespace proprietarySchemas {
|
|
|
887
923
|
export { proprietarySchemas_dateIn as dateIn, proprietarySchemas_dateOut as dateOut, proprietarySchemas_file as file, proprietarySchemas_raw as raw, proprietarySchemas_upload as upload };
|
|
888
924
|
}
|
|
889
925
|
|
|
890
|
-
export { AbstractEndpoint, type AppConfig, type BasicSecurity, type BearerSecurity, type CommonConfig, type CookieSecurity, type CustomHeaderSecurity, DependsOnMethod, Documentation, DocumentationError, EndpointsFactory, type FlatObject, type IOSchema, type InputSecurity, InputValidationError, Integration, type
|
|
926
|
+
export { AbstractEndpoint, type AppConfig, type BasicSecurity, type BearerSecurity, type CommonConfig, type CookieSecurity, type CustomHeaderSecurity, DependsOnMethod, Documentation, DocumentationError, EndpointsFactory, type FlatObject, type IOSchema, type InputSecurity, InputValidationError, Integration, type LoggerOverrides, type Metadata, type Method, type MiddlewareDefinition, MissingPeerError, type OAuth2Security, type OpenIdSecurity, OutputValidationError, type ResultHandlerDefinition, type Routing, RoutingError, ServeStatic, type ServerConfig, type ZodDateInDef, type ZodDateOutDef, type ZodFileDef, type ZodUploadDef, arrayEndpointsFactory, arrayResultHandler, attachRouting, createConfig, createMiddleware, createResultHandler, createServer, defaultEndpointsFactory, defaultResultHandler, proprietarySchemas as ez, getExamples, getMessageFromError, getStatusCodeFromError, testEndpoint, withMeta };
|