express-zod-api 23.6.1 → 24.0.0-beta.10
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 +72 -0
- package/README.md +69 -77
- package/SECURITY.md +1 -0
- package/dist/index.cjs +10 -10
- package/dist/index.d.cts +107 -178
- package/dist/index.d.ts +107 -178
- package/dist/index.js +10 -10
- package/migration/index.cjs +1 -1
- package/migration/index.d.cts +2 -2
- package/migration/index.d.ts +2 -2
- package/migration/index.js +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Version 24
|
|
4
|
+
|
|
5
|
+
### v24.0.0
|
|
6
|
+
|
|
7
|
+
- Switched to Zod 4:
|
|
8
|
+
- Minimum supported version of `zod` is 3.25.1, BUT imports MUST be from `zod/v4`;
|
|
9
|
+
- Read the [Explanation of the versioning strategy](https://github.com/colinhacks/zod/issues/4371);
|
|
10
|
+
- Express Zod API, however, is not aiming to support both Zod 3 and Zod 4 simultaneously due to:
|
|
11
|
+
- incompatibility of data structures;
|
|
12
|
+
- operating composite schemas (need to avoid mixing schemas of different versions);
|
|
13
|
+
- the temporary nature of this transition;
|
|
14
|
+
- the advantages of Zod 4 that provide opportunities to simplifications and corrections of known issues.
|
|
15
|
+
- `IOSchema` type had to be simplified down to a schema resulting to an `object`, but not an `array`;
|
|
16
|
+
- Refer to [Migration guide on Zod 4](https://v4.zod.dev/v4/changelog) for adjusting your schemas;
|
|
17
|
+
- Changes to `ZodType::example()` (Zod plugin method):
|
|
18
|
+
- Now acts as an alias for `ZodType::meta({ examples })`;
|
|
19
|
+
- The argument has to be the output type of the schema (used to be the opposite):
|
|
20
|
+
- This change is only breaking for transforming schemas;
|
|
21
|
+
- In order to specify an example for an input schema the `.example()` method must be called before `.transform()`;
|
|
22
|
+
- The transforming proprietary schemas `ez.dateIn()` and `ez.dateOut()` now accept metadata as its argument:
|
|
23
|
+
- This allows to set examples before transformation (`ez.dateIn()`) and to avoid the examples "branding";
|
|
24
|
+
- Changes to `Documentation`:
|
|
25
|
+
- Generating Documentation is mostly delegated to Zod 4 `z.toJSONSchema()`;
|
|
26
|
+
- Express Zod API implements some overrides and improvements to fit it into OpenAPI 3.1 that extends JSON Schema;
|
|
27
|
+
- The `numericRange` option removed from `Documentation` class constructor argument;
|
|
28
|
+
- The `Depicter` type signature changed: became a postprocessing function returning an overridden JSON Schema;
|
|
29
|
+
- Changes to `Integration`:
|
|
30
|
+
- The `optionalPropStyle` option removed from `Integration` class constructor:
|
|
31
|
+
- Use `.optional()` to add question mark to the object property as well as `undefined` to its type;
|
|
32
|
+
- Use `.or(z.undefined())` to add `undefined` to the type of the object property;
|
|
33
|
+
- See the [reasoning](https://x.com/colinhacks/status/1919292504861491252);
|
|
34
|
+
- `z.any()` and `z.unknown()` are required: [details](https://v4.zod.dev/v4/changelog#changes-zunknown-optionality);
|
|
35
|
+
- Added types generation for `z.never()`, `z.void()` and `z.unknown()` schemas;
|
|
36
|
+
- The fallback type for unsupported schemas and unclear transformations in response changed from `any` to `unknown`;
|
|
37
|
+
- The argument of `ResultHandler::handler` is now discriminated: either `output` or `error` is `null`, not both;
|
|
38
|
+
- The `getExamples()` public helper removed — use `.meta()?.examples` instead;
|
|
39
|
+
- Added the new proprietary schema `ez.buffer()`;
|
|
40
|
+
- The `ez.file()` schema removed: use `z.string()`, `z.base64()`, `ez.buffer()` or their union;
|
|
41
|
+
- Consider the automated migration using the built-in ESLint rule.
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
// eslint.config.mjs — minimal ESLint 9 config to apply migrations automatically using "eslint --fix"
|
|
45
|
+
import parser from "@typescript-eslint/parser";
|
|
46
|
+
import migration from "express-zod-api/migration";
|
|
47
|
+
|
|
48
|
+
export default [
|
|
49
|
+
{ languageOptions: { parser }, plugins: { migration } },
|
|
50
|
+
{ files: ["**/*.ts"], rules: { "migration/v24": "error" } },
|
|
51
|
+
];
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```diff
|
|
55
|
+
- import { z } from "zod";
|
|
56
|
+
+ import { z } from "zod/v4";
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```diff
|
|
60
|
+
input: z.string()
|
|
61
|
+
+ .example("123")
|
|
62
|
+
.transform(Number)
|
|
63
|
+
- .example("123")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```diff
|
|
67
|
+
- ez.dateIn().example("2021-12-31");
|
|
68
|
+
+ ez.dateIn({ examples: ["2021-12-31"] });
|
|
69
|
+
- ez.file("base64");
|
|
70
|
+
+ z.base64();
|
|
71
|
+
- ez.file("buffer");
|
|
72
|
+
+ ez.buffer();
|
|
73
|
+
```
|
|
74
|
+
|
|
3
75
|
## Version 23
|
|
4
76
|
|
|
5
77
|
### v23.6.1
|
package/README.md
CHANGED
|
@@ -36,9 +36,9 @@ Start your API server with I/O schema validation and custom middlewares in minut
|
|
|
36
36
|
2. [Headers as input source](#headers-as-input-source)
|
|
37
37
|
3. [Response customization](#response-customization)
|
|
38
38
|
4. [Empty response](#empty-response)
|
|
39
|
-
5. [
|
|
40
|
-
6. [
|
|
41
|
-
7. [
|
|
39
|
+
5. [Non-JSON response](#non-json-response) including file downloads
|
|
40
|
+
6. [Error handling](#error-handling)
|
|
41
|
+
7. [Production mode](#production-mode)
|
|
42
42
|
8. [HTML Forms (URL encoded)](#html-forms-url-encoded)
|
|
43
43
|
9. [File uploads](#file-uploads)
|
|
44
44
|
10. [Connect to your own express app](#connect-to-your-own-express-app)
|
|
@@ -58,8 +58,7 @@ Start your API server with I/O schema validation and custom middlewares in minut
|
|
|
58
58
|
5. [Deprecated schemas and routes](#deprecated-schemas-and-routes)
|
|
59
59
|
6. [Customizable brands handling](#customizable-brands-handling)
|
|
60
60
|
8. [Caveats](#caveats)
|
|
61
|
-
1. [
|
|
62
|
-
2. [Excessive properties in endpoint output](#excessive-properties-in-endpoint-output)
|
|
61
|
+
1. [Excessive properties in endpoint output](#excessive-properties-in-endpoint-output)
|
|
63
62
|
9. [Your input to my output](#your-input-to-my-output)
|
|
64
63
|
|
|
65
64
|
You can find the release notes and migration guides in [Changelog](CHANGELOG.md).
|
|
@@ -151,7 +150,8 @@ Much can be customized to fit your needs.
|
|
|
151
150
|
|
|
152
151
|
- [Typescript](https://www.typescriptlang.org/) first.
|
|
153
152
|
- Web server — [Express.js](https://expressjs.com/) v5.
|
|
154
|
-
- Schema validation — [Zod
|
|
153
|
+
- Schema validation — [Zod 4.x](https://github.com/colinhacks/zod) including [Zod Plugin](#zod-plugin):
|
|
154
|
+
- For using with Zod 3.x install the framework versions below 24.0.0.
|
|
155
155
|
- Supports any logger having `info()`, `debug()`, `error()` and `warn()` methods;
|
|
156
156
|
- Built-in console logger with colorful and pretty inspections by default.
|
|
157
157
|
- Generators:
|
|
@@ -169,7 +169,7 @@ Install the framework, its peer dependencies and type assistance packages using
|
|
|
169
169
|
|
|
170
170
|
```shell
|
|
171
171
|
# example for yarn:
|
|
172
|
-
yarn add express-zod-api express zod
|
|
172
|
+
yarn add express-zod-api express zod typescript http-errors
|
|
173
173
|
yarn add -D @types/express @types/node @types/http-errors
|
|
174
174
|
```
|
|
175
175
|
|
|
@@ -214,7 +214,7 @@ import { defaultEndpointsFactory } from "express-zod-api";
|
|
|
214
214
|
The endpoint responds with "Hello, World" or "Hello, {name}" if the name is supplied within `GET` request payload.
|
|
215
215
|
|
|
216
216
|
```typescript
|
|
217
|
-
import { z } from "zod";
|
|
217
|
+
import { z } from "zod/v4";
|
|
218
218
|
|
|
219
219
|
const helloWorldEndpoint = defaultEndpointsFactory.build({
|
|
220
220
|
// method: "get" (default) or array ["get", "post", ...]
|
|
@@ -326,7 +326,7 @@ Inputs of middlewares are also available to endpoint handlers within `input`.
|
|
|
326
326
|
Here is an example of the authentication middleware, that checks a `key` from input and `token` from headers:
|
|
327
327
|
|
|
328
328
|
```typescript
|
|
329
|
-
import { z } from "zod";
|
|
329
|
+
import { z } from "zod/v4";
|
|
330
330
|
import createHttpError from "http-errors";
|
|
331
331
|
import { Middleware } from "express-zod-api";
|
|
332
332
|
|
|
@@ -456,7 +456,7 @@ You can implement additional validations within schemas using refinements.
|
|
|
456
456
|
Validation errors are reported in a response with a status code `400`.
|
|
457
457
|
|
|
458
458
|
```typescript
|
|
459
|
-
import { z } from "zod";
|
|
459
|
+
import { z } from "zod/v4";
|
|
460
460
|
import { Middleware } from "express-zod-api";
|
|
461
461
|
|
|
462
462
|
const nicknameConstraintMiddleware = new Middleware({
|
|
@@ -479,7 +479,7 @@ By the way, you can also refine the whole I/O object, for example in case you ne
|
|
|
479
479
|
const endpoint = endpointsFactory.build({
|
|
480
480
|
input: z
|
|
481
481
|
.object({
|
|
482
|
-
email: z.
|
|
482
|
+
email: z.email().optional(),
|
|
483
483
|
id: z.string().optional(),
|
|
484
484
|
otherThing: z.string().optional(),
|
|
485
485
|
})
|
|
@@ -497,7 +497,7 @@ Since parameters of GET requests come in the form of strings, there is often a n
|
|
|
497
497
|
arrays of numbers.
|
|
498
498
|
|
|
499
499
|
```typescript
|
|
500
|
-
import { z } from "zod";
|
|
500
|
+
import { z } from "zod/v4";
|
|
501
501
|
|
|
502
502
|
const getUserEndpoint = endpointsFactory.build({
|
|
503
503
|
input: z.object({
|
|
@@ -528,7 +528,7 @@ Here is a recommended solution: it is important to use shallow transformations o
|
|
|
528
528
|
```ts
|
|
529
529
|
import camelize from "camelize-ts";
|
|
530
530
|
import snakify from "snakify-ts";
|
|
531
|
-
import { z } from "zod";
|
|
531
|
+
import { z } from "zod/v4";
|
|
532
532
|
|
|
533
533
|
const endpoint = endpointsFactory.build({
|
|
534
534
|
input: z
|
|
@@ -562,7 +562,7 @@ in actual response by calling
|
|
|
562
562
|
which in turn calls
|
|
563
563
|
[toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString).
|
|
564
564
|
It is also impossible to transmit the `Date` in its original form to your endpoints within JSON. Therefore, there is
|
|
565
|
-
confusion with original method ~~z.date()~~ that
|
|
565
|
+
confusion with original method ~~z.date()~~ that is not recommended to use without transformations.
|
|
566
566
|
|
|
567
567
|
In order to solve this problem, the framework provides two custom methods for dealing with dates: `ez.dateIn()` and
|
|
568
568
|
`ez.dateOut()` for using within input and output schemas accordingly.
|
|
@@ -578,20 +578,20 @@ provides your endpoint handler or middleware with a `Date`. It supports the foll
|
|
|
578
578
|
```
|
|
579
579
|
|
|
580
580
|
`ez.dateOut()`, on the contrary, accepts a `Date` and provides `ResultHandler` with a `string` representation in ISO
|
|
581
|
-
format for the response transmission. Consider the following
|
|
581
|
+
format for the response transmission. Both schemas accept metadata as an argument. Consider the following example:
|
|
582
582
|
|
|
583
583
|
```typescript
|
|
584
|
-
import { z } from "zod";
|
|
584
|
+
import { z } from "zod/v4";
|
|
585
585
|
import { ez, defaultEndpointsFactory } from "express-zod-api";
|
|
586
586
|
|
|
587
587
|
const updateUserEndpoint = defaultEndpointsFactory.build({
|
|
588
588
|
method: "post",
|
|
589
589
|
input: z.object({
|
|
590
590
|
userId: z.string(),
|
|
591
|
-
birthday: ez.dateIn(), // string -> Date in handler
|
|
591
|
+
birthday: ez.dateIn({ examples: ["1963-04-21"] }), // string -> Date in handler
|
|
592
592
|
}),
|
|
593
593
|
output: z.object({
|
|
594
|
-
createdAt: ez.dateOut(), // Date -> string in response
|
|
594
|
+
createdAt: ez.dateOut({ examples: ["2021-12-31"] }), // Date -> string in response
|
|
595
595
|
}),
|
|
596
596
|
handler: async ({ input }) => ({
|
|
597
597
|
createdAt: new Date("2022-01-22"), // 2022-01-22T00:00:00.000Z
|
|
@@ -791,7 +791,7 @@ In a similar way you can enable request headers as the input source. This is an
|
|
|
791
791
|
|
|
792
792
|
```typescript
|
|
793
793
|
import { createConfig, Middleware } from "express-zod-api";
|
|
794
|
-
import { z } from "zod";
|
|
794
|
+
import { z } from "zod/v4";
|
|
795
795
|
|
|
796
796
|
createConfig({
|
|
797
797
|
inputSources: {
|
|
@@ -826,7 +826,7 @@ type DefaultResponse<OUT> =
|
|
|
826
826
|
You can create your own result handler by using this example as a template:
|
|
827
827
|
|
|
828
828
|
```typescript
|
|
829
|
-
import { z } from "zod";
|
|
829
|
+
import { z } from "zod/v4";
|
|
830
830
|
import {
|
|
831
831
|
ResultHandler,
|
|
832
832
|
ensureHttpError,
|
|
@@ -872,6 +872,33 @@ const resultHandler = new ResultHandler({
|
|
|
872
872
|
});
|
|
873
873
|
```
|
|
874
874
|
|
|
875
|
+
## Non-JSON response
|
|
876
|
+
|
|
877
|
+
To configure a non-JSON responses (for example, to send an image file) you should specify its MIME type.
|
|
878
|
+
|
|
879
|
+
You can find two approaches to `EndpointsFactory` and `ResultHandler` implementation
|
|
880
|
+
[in this example](https://github.com/RobinTail/express-zod-api/blob/master/example/factories.ts).
|
|
881
|
+
One of them implements file streaming, in this case the endpoint just has to provide the filename.
|
|
882
|
+
The response schema can be `z.string()`, `z.base64()` or `ez.buffer()` to reflect the data accordingly in the
|
|
883
|
+
[generated documentation](#creating-a-documentation).
|
|
884
|
+
|
|
885
|
+
```typescript
|
|
886
|
+
const fileStreamingEndpointsFactory = new EndpointsFactory(
|
|
887
|
+
new ResultHandler({
|
|
888
|
+
positive: { schema: ez.buffer(), mimeType: "image/*" },
|
|
889
|
+
negative: { schema: z.string(), mimeType: "text/plain" },
|
|
890
|
+
handler: ({ response, error, output }) => {
|
|
891
|
+
if (error) return void response.status(400).send(error.message);
|
|
892
|
+
if ("filename" in output)
|
|
893
|
+
fs.createReadStream(output.filename).pipe(
|
|
894
|
+
response.attachment(output.filename),
|
|
895
|
+
);
|
|
896
|
+
else response.status(400).send("Filename is missing");
|
|
897
|
+
},
|
|
898
|
+
}),
|
|
899
|
+
);
|
|
900
|
+
```
|
|
901
|
+
|
|
875
902
|
## Error handling
|
|
876
903
|
|
|
877
904
|
All runtime errors are handled by a `ResultHandler`. The default is `defaultResultHandler`. Using `ensureHttpError()`
|
|
@@ -915,34 +942,6 @@ createHttpError(500, "Something is broken"); // —> "Internal Server Error"
|
|
|
915
942
|
createHttpError(501, "We didn't make it yet", { expose: true }); // —> "We didn't make it yet"
|
|
916
943
|
```
|
|
917
944
|
|
|
918
|
-
## Non-object response
|
|
919
|
-
|
|
920
|
-
Thus, you can configure non-object responses too, for example, to send an image file.
|
|
921
|
-
|
|
922
|
-
You can find two approaches to `EndpointsFactory` and `ResultHandler` implementation
|
|
923
|
-
[in this example](https://github.com/RobinTail/express-zod-api/blob/master/example/factories.ts).
|
|
924
|
-
One of them implements file streaming, in this case the endpoint just has to provide the filename.
|
|
925
|
-
The response schema generally may be just `z.string()`, but I made more specific `ez.file()` that also supports
|
|
926
|
-
`ez.file("binary")` and `ez.file("base64")` variants which are reflected in the
|
|
927
|
-
[generated documentation](#creating-a-documentation).
|
|
928
|
-
|
|
929
|
-
```typescript
|
|
930
|
-
const fileStreamingEndpointsFactory = new EndpointsFactory(
|
|
931
|
-
new ResultHandler({
|
|
932
|
-
positive: { schema: ez.file("buffer"), mimeType: "image/*" },
|
|
933
|
-
negative: { schema: z.string(), mimeType: "text/plain" },
|
|
934
|
-
handler: ({ response, error, output }) => {
|
|
935
|
-
if (error) return void response.status(400).send(error.message);
|
|
936
|
-
if ("filename" in output)
|
|
937
|
-
fs.createReadStream(output.filename).pipe(
|
|
938
|
-
response.type(output.filename),
|
|
939
|
-
);
|
|
940
|
-
else response.status(400).send("Filename is missing");
|
|
941
|
-
},
|
|
942
|
-
}),
|
|
943
|
-
);
|
|
944
|
-
```
|
|
945
|
-
|
|
946
945
|
## HTML Forms (URL encoded)
|
|
947
946
|
|
|
948
947
|
Use the proprietary schema `ez.form()` with an object shape or a custom `z.object()` with form fields in order to
|
|
@@ -952,13 +951,13 @@ which is `express.urlencoded()` by default. The request content type should be `
|
|
|
952
951
|
|
|
953
952
|
```ts
|
|
954
953
|
import { defaultEndpointsFactory, ez } from "express-zod-api";
|
|
955
|
-
import { z } from "zod";
|
|
954
|
+
import { z } from "zod/v4";
|
|
956
955
|
|
|
957
956
|
export const submitFeedbackEndpoint = defaultEndpointsFactory.build({
|
|
958
957
|
method: "post",
|
|
959
958
|
input: ez.form({
|
|
960
959
|
name: z.string().min(1),
|
|
961
|
-
email: z.
|
|
960
|
+
email: z.email(),
|
|
962
961
|
message: z.string().min(1),
|
|
963
962
|
}),
|
|
964
963
|
});
|
|
@@ -992,7 +991,7 @@ const config = createConfig({
|
|
|
992
991
|
Then use `ez.upload()` schema for a corresponding property. The request content type must be `multipart/form-data`:
|
|
993
992
|
|
|
994
993
|
```typescript
|
|
995
|
-
import { z } from "zod";
|
|
994
|
+
import { z } from "zod/v4";
|
|
996
995
|
import { ez, defaultEndpointsFactory } from "express-zod-api";
|
|
997
996
|
|
|
998
997
|
const fileUploadEndpoint = defaultEndpointsFactory.build({
|
|
@@ -1070,7 +1069,7 @@ from outputs of previous middlewares, if the one being tested somehow depends on
|
|
|
1070
1069
|
either by `errorHandler` configured within given `configProps` or `defaultResultHandler`.
|
|
1071
1070
|
|
|
1072
1071
|
```typescript
|
|
1073
|
-
import { z } from "zod";
|
|
1072
|
+
import { z } from "zod/v4";
|
|
1074
1073
|
import { Middleware, testMiddleware } from "express-zod-api";
|
|
1075
1074
|
|
|
1076
1075
|
const middleware = new Middleware({
|
|
@@ -1110,7 +1109,7 @@ new ResultHandler({
|
|
|
1110
1109
|
negative: [
|
|
1111
1110
|
{
|
|
1112
1111
|
statusCode: 409, // conflict: entity already exists
|
|
1113
|
-
schema: z.object({ status: z.literal("exists"), id: z.
|
|
1112
|
+
schema: z.object({ status: z.literal("exists"), id: z.int() }),
|
|
1114
1113
|
},
|
|
1115
1114
|
{
|
|
1116
1115
|
statusCode: [400, 500], // validation or internal error
|
|
@@ -1148,7 +1147,7 @@ const rawAcceptingEndpoint = defaultEndpointsFactory.build({
|
|
|
1148
1147
|
input: ez.raw({
|
|
1149
1148
|
/* the place for additional inputs, like route params, if needed */
|
|
1150
1149
|
}),
|
|
1151
|
-
output: z.object({ length: z.
|
|
1150
|
+
output: z.object({ length: z.int().nonnegative() }),
|
|
1152
1151
|
handler: async ({ input: { raw } }) => ({
|
|
1153
1152
|
length: raw.length, // raw is Buffer
|
|
1154
1153
|
}),
|
|
@@ -1182,12 +1181,12 @@ Client application can subscribe to the event stream using `EventSource` class i
|
|
|
1182
1181
|
the implementation emitting the `time` event each second.
|
|
1183
1182
|
|
|
1184
1183
|
```typescript
|
|
1185
|
-
import { z } from "zod";
|
|
1184
|
+
import { z } from "zod/v4";
|
|
1186
1185
|
import { EventStreamFactory } from "express-zod-api";
|
|
1187
1186
|
import { setTimeout } from "node:timers/promises";
|
|
1188
1187
|
|
|
1189
1188
|
const subscriptionEndpoint = new EventStreamFactory({
|
|
1190
|
-
time: z.
|
|
1189
|
+
time: z.int().positive(),
|
|
1191
1190
|
}).buildVoid({
|
|
1192
1191
|
input: z.object({}), // optional input schema
|
|
1193
1192
|
handler: async ({ options: { emit, isClosed } }) => {
|
|
@@ -1225,7 +1224,6 @@ import { Integration } from "express-zod-api";
|
|
|
1225
1224
|
const client = new Integration({
|
|
1226
1225
|
routing,
|
|
1227
1226
|
variant: "client", // <— optional, see also "types" for a DIY solution
|
|
1228
|
-
optionalPropStyle: { withQuestionMark: true, withUndefined: true }, // optional
|
|
1229
1227
|
});
|
|
1230
1228
|
|
|
1231
1229
|
const prettierFormattedTypescriptCode = await client.printFormatted(); // or just .print() for unformatted
|
|
@@ -1274,7 +1272,11 @@ const exampleEndpoint = defaultEndpointsFactory.build({
|
|
|
1274
1272
|
shortDescription: "Retrieves the user.", // <—— this becomes the summary line
|
|
1275
1273
|
description: "The detailed explanaition on what this endpoint does.",
|
|
1276
1274
|
input: z.object({
|
|
1277
|
-
id: z
|
|
1275
|
+
id: z
|
|
1276
|
+
.string()
|
|
1277
|
+
.example("123") // input examples should be set before transformations
|
|
1278
|
+
.transform(Number)
|
|
1279
|
+
.describe("the ID of the user"),
|
|
1278
1280
|
}),
|
|
1279
1281
|
// ..., similarly for output and middlewares
|
|
1280
1282
|
});
|
|
@@ -1323,7 +1325,7 @@ You can also deprecate all routes the `Endpoint` assigned to by setting `Endpoin
|
|
|
1323
1325
|
|
|
1324
1326
|
```ts
|
|
1325
1327
|
import { Routing, DependsOnMethod } from "express-zod-api";
|
|
1326
|
-
import { z } from "zod";
|
|
1328
|
+
import { z } from "zod/v4";
|
|
1327
1329
|
|
|
1328
1330
|
const someEndpoint = factory.build({
|
|
1329
1331
|
deprecated: true, // deprecates all routes the endpoint assigned to
|
|
@@ -1348,7 +1350,7 @@ need to reuse a handling rule for multiple brands, use the exposed types `Depict
|
|
|
1348
1350
|
|
|
1349
1351
|
```ts
|
|
1350
1352
|
import ts from "typescript";
|
|
1351
|
-
import { z } from "zod";
|
|
1353
|
+
import { z } from "zod/v4";
|
|
1352
1354
|
import {
|
|
1353
1355
|
Documentation,
|
|
1354
1356
|
Integration,
|
|
@@ -1360,12 +1362,12 @@ const myBrand = Symbol("MamaToldMeImSpecial"); // I recommend to use symbols for
|
|
|
1360
1362
|
const myBrandedSchema = z.string().brand(myBrand);
|
|
1361
1363
|
|
|
1362
1364
|
const ruleForDocs: Depicter = (
|
|
1363
|
-
|
|
1364
|
-
{
|
|
1365
|
-
) => {
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
};
|
|
1365
|
+
{ zodSchema, jsonSchema }, // jsonSchema is the default depiction
|
|
1366
|
+
{ path, method, isResponse },
|
|
1367
|
+
) => ({
|
|
1368
|
+
...jsonSchema,
|
|
1369
|
+
summary: "Special type of data",
|
|
1370
|
+
});
|
|
1369
1371
|
|
|
1370
1372
|
const ruleForClient: Producer = (
|
|
1371
1373
|
schema: typeof myBrandedSchema, // you should assign type yourself
|
|
@@ -1386,16 +1388,6 @@ new Integration({
|
|
|
1386
1388
|
There are some well-known issues and limitations, or third party bugs that cannot be fixed in the usual way, but you
|
|
1387
1389
|
should be aware of them.
|
|
1388
1390
|
|
|
1389
|
-
## Coercive schema of Zod
|
|
1390
|
-
|
|
1391
|
-
Despite being supported by the framework, `z.coerce.*` schema
|
|
1392
|
-
[does not work intuitively](https://github.com/RobinTail/express-zod-api/issues/759).
|
|
1393
|
-
Please be aware that `z.coerce.number()` and `z.number({ coerce: true })` (being typed not well) still will NOT allow
|
|
1394
|
-
you to assign anything but number. Moreover, coercive schemas are not fail-safe and their methods `.isOptional()` and
|
|
1395
|
-
`.isNullable()` [are buggy](https://github.com/colinhacks/zod/issues/1911). If possible, try to avoid using this type
|
|
1396
|
-
of schema. This issue [will NOT be fixed](https://github.com/colinhacks/zod/issues/1760#issuecomment-1407816838) in
|
|
1397
|
-
Zod version 3.x.
|
|
1398
|
-
|
|
1399
1391
|
## Excessive properties in endpoint output
|
|
1400
1392
|
|
|
1401
1393
|
The schema validator removes excessive properties by default. However, Typescript
|
|
@@ -1404,7 +1396,7 @@ in this case during development. You can achieve this verification by assigning
|
|
|
1404
1396
|
reusing it in forced type of the output:
|
|
1405
1397
|
|
|
1406
1398
|
```typescript
|
|
1407
|
-
import { z } from "zod";
|
|
1399
|
+
import { z } from "zod/v4";
|
|
1408
1400
|
|
|
1409
1401
|
const output = z.object({
|
|
1410
1402
|
anything: z.number(),
|
package/SECURITY.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Code name | Release | Supported |
|
|
6
6
|
| ------: | :------------ | :------ | :----------------: |
|
|
7
|
+
| 24.x.x | Ashley | 06.2025 | :white_check_mark: |
|
|
7
8
|
| 23.x.x | Sonia | 04.2025 | :white_check_mark: |
|
|
8
9
|
| 22.x.x | Tai | 01.2025 | :white_check_mark: |
|
|
9
10
|
| 21.x.x | Kesaria | 11.2024 | :white_check_mark: |
|