express-zod-api 28.7.5 → 29.0.0-beta.2

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,52 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 29
4
+
5
+ ### v29.0.0
6
+
7
+ - Supported Node.js versions: `^22.19.0 || ^24.11.0 || ^26.0.0`;
8
+ - Breaking change to the `cors` config option:
9
+ - Changed from `boolean | HeadersProvider` to `boolean | RequestHandler`;
10
+ - You can now use the well-known `cors` package or pass a conventional `RequestHandler` directly.
11
+ - Body parsers are now applied globally rather than per-endpoint (`createServer` experience only):
12
+ - Endpoints can accept requests in different content types (e.g., either JSON or URL-encoded body);
13
+ - The `Documentation` generator continues to guess the desired request type from the input schema;
14
+ - Parsers retain the ability for configuration via `jsonParser`, `formParser`, and `rawParser` config options;
15
+ - If using `attachRouting()` in a DIY server, parsers have to be installed manually.
16
+ - Potentially breaking changes to the server lifecycle hooks:
17
+ - The hooks (`beforeRouting` and `afterRouting` config options) are no longer async;
18
+ - `beforeRouting` now runs after the installation of globally enabled parsers;
19
+ - Added new `beforeParsers` hook that runs before all parsers are installed.
20
+ - The static async method `Integration::create()` removed — use `new Integration()` instead;
21
+ - The `createServer()` function is now synchronous — that should simplify the daily routines for beginners;
22
+ - Added HTTP QUERY method support (RFC 10008):
23
+ - The QUERY method is like GET but with a body — safe, idempotent, and cacheable;
24
+ - Default input sources for QUERY: `["query", "body", "params"]` (from the lowest priority to highest);
25
+ - Supported by `Integration` and `Documentation` generators.
26
+ - Changes to `Documentation` constructor:
27
+ - `serverUrl` renamed to `server` and now also accepts OpenAPI's ServerObject;
28
+ - `title` and `version` must be wrapped into `info`, assignable with OpenAPI's InfoObject;
29
+ - The Documentation generator is featuring the OpenAPI 3.2.0 with better SSE support and other features;
30
+
31
+ ```diff
32
+ const config = createConfig({
33
+ - cors: () => ({ origin: "https://example.com" }),
34
+ + cors: cors({ origin: "https://example.com" }), // import cors from "cors"
35
+ });
36
+ - await Integration.create({});
37
+ + new Integration({});
38
+ - const {} = await createServer({});
39
+ + const {} = createServer({});
40
+ new Documentation({
41
+ + info: {
42
+ title: "Sample API",
43
+ version: "1.2.3",
44
+ + },
45
+ - serverUrl: "https://example.com",
46
+ + server: "https://example.com",
47
+ });
48
+ ```
49
+
3
50
  ## Version 28
4
51
 
5
52
  ### v28.7.5
@@ -4242,9 +4289,7 @@ import { z } from "express-zod-api";
4242
4289
 
4243
4290
  const endpoint = endpointsFactory.build({
4244
4291
  input: z
4245
- .object({
4246
- /* ... */
4247
- })
4292
+ .object({/* ... */})
4248
4293
  .refine(() => true)
4249
4294
  .refine(() => true)
4250
4295
  .refine(() => true),
@@ -4503,9 +4548,7 @@ const myMiddleware = createMiddleware({
4503
4548
  },
4504
4549
  },
4505
4550
  input: z.object({}),
4506
- middleware: async () => ({
4507
- /* ... */
4508
- }),
4551
+ middleware: async () => ({/* ... */}),
4509
4552
  });
4510
4553
 
4511
4554
  // example endpoint
@@ -4514,9 +4557,7 @@ const myEndpoint = defaultEndpointsFactory.addMiddleware(myMiddleware).build({
4514
4557
  method: "post",
4515
4558
  input: z.object({}),
4516
4559
  output: z.object({}),
4517
- handler: async () => ({
4518
- /* ... */
4519
- }),
4560
+ handler: async () => ({/* ... */}),
4520
4561
  });
4521
4562
  ```
4522
4563
 
@@ -5448,15 +5489,11 @@ const fileUploadEndpoint = defaultEndpointsFactory.build({
5448
5489
  input: z.object({
5449
5490
  avatar: z.upload(),
5450
5491
  }),
5451
- output: z.object({
5452
- /* ... */
5453
- }),
5492
+ output: z.object({/* ... */}),
5454
5493
  handler: async ({ input: { avatar } }) => {
5455
5494
  // avatar: {name, mv(), mimetype, encoding, data, truncated, size, etc}
5456
5495
  // avatar.truncated is true on failure
5457
- return {
5458
- /* ... */
5459
- };
5496
+ return {/* ... */};
5460
5497
  },
5461
5498
  });
5462
5499
  ```
@@ -5690,15 +5727,11 @@ import { EndpointOutput } from "express-zod-api";
5690
5727
 
5691
5728
  const myEndpointV1 = endpointsFactory.build({
5692
5729
  method: "get",
5693
- input: z.object({
5694
- /* ... */
5695
- }),
5730
+ input: z.object({/* ... */}),
5696
5731
  output: z.object({
5697
5732
  name: z.string(),
5698
5733
  }),
5699
- handler: async () => ({
5700
- /* ... */
5701
- }),
5734
+ handler: async () => ({/* ... */}),
5702
5735
  });
5703
5736
  type MyEndpointOutput = EndpointOutput<typeof myEndpointV1>; // => { name: string }
5704
5737
 
@@ -5707,15 +5740,11 @@ import { defaultEndpointsFactory, EndpointResponse } from "express-zod-api";
5707
5740
 
5708
5741
  const myEndpointV2 = defaultEndpointsFactory.build({
5709
5742
  method: "get",
5710
- input: z.object({
5711
- /* ... */
5712
- }),
5743
+ input: z.object({/* ... */}),
5713
5744
  output: z.object({
5714
5745
  name: z.string(),
5715
5746
  }),
5716
- handler: async () => ({
5717
- /* ... */
5718
- }),
5747
+ handler: async () => ({/* ... */}),
5719
5748
  });
5720
5749
  type MyEndpointResponse = EndpointResponse<typeof myEndpointV2>; // => the following type:
5721
5750
  // {
@@ -5729,13 +5758,9 @@ type MyEndpointResponse = EndpointResponse<typeof myEndpointV2>; // => the follo
5729
5758
 
5730
5759
  ```ts
5731
5760
  // before
5732
- new OpenAPI({
5733
- /* ... */
5734
- }).builder.getSpecAsYaml();
5761
+ new OpenAPI({/* ... */}).builder.getSpecAsYaml();
5735
5762
  // after
5736
- new OpenAPI({
5737
- /* ... */
5738
- }).getSpecAsYaml();
5763
+ new OpenAPI({/* ... */}).getSpecAsYaml();
5739
5764
  ```
5740
5765
 
5741
5766
  ```ts
@@ -5760,12 +5785,7 @@ const myResultHandlerV2 = createResultHandler({
5760
5785
  }),
5761
5786
  ["mime/type1", "mime/type2"], // optional, default: application/json
5762
5787
  ),
5763
- getNegativeResponse: () =>
5764
- createApiResponse(
5765
- z.object({
5766
- /* ... */
5767
- }),
5768
- ),
5788
+ getNegativeResponse: () => createApiResponse(z.object({/* ... */})),
5769
5789
  handler: ({ error, input, output, request, response, logger }) => {
5770
5790
  /* ... */
5771
5791
  },
package/README.md CHANGED
@@ -83,7 +83,7 @@ Therefore, many basic tasks can be achieved faster and easier, in particular:
83
83
  - All of your endpoints can respond consistently.
84
84
  - The expected endpoint input and response types can be exported to the frontend, giving you end-to-end type safety
85
85
  so you don't get confused about the field names when you implement the client for your API.
86
- - You can generate your API documentation in OpenAPI 3.1 and JSON Schema compatible format.
86
+ - You can generate your API documentation in OpenAPI 3.2 and JSON Schema compatible format.
87
87
 
88
88
  ## Contributors
89
89
 
@@ -171,7 +171,7 @@ Much can be customized to fit your needs.
171
171
  - Supports any logger having `info()`, `debug()`, `error()` and `warn()` methods;
172
172
  - Built-in console logger with colorful and pretty inspections by default.
173
173
  - Generators:
174
- - Documentation — [OpenAPI 3.1](https://github.com/metadevpro/openapi3-ts) (former Swagger);
174
+ - Documentation — [OpenAPI 3.2](https://github.com/metadevpro/openapi3-ts) (former Swagger);
175
175
  - Client side types — inspired by [zod-to-ts](https://github.com/sachinraja/zod-to-ts).
176
176
  - File uploads — [Express-FileUpload](https://github.com/richardgirges/express-fileupload)
177
177
  (based on [Busboy](https://github.com/mscdex/busboy)).
@@ -424,9 +424,9 @@ const resultHandlerWithCleanup = new ResultHandler({
424
424
 
425
425
  There are two ways of connecting the native express middlewares depending on their nature and your objective.
426
426
 
427
- In case it's a middleware establishing and serving its own routes, or somehow globally modifying the behaviour, or
428
- being an additional request parser (like `cookie-parser`), use the `beforeRouting` option. However, it might be better
429
- to avoid `cors` here [the framework handles it on its own](#cross-origin-resource-sharing).
427
+ In case it's middleware establishing and serving its own routes, or somehow globally modifying the behavior, use the
428
+ `beforeRouting` or `beforeParsers` hooks. Note that [CORS](#cross-origin-resource-sharing), cookies, compression, and
429
+ body parsing are already available as separate [config options](#set-up-config).
430
430
 
431
431
  ```ts
432
432
  import { createConfig } from "express-zod-api";
@@ -647,18 +647,27 @@ const listUsers = defaultEndpointsFactory.build({
647
647
  ## Cross-Origin Resource Sharing
648
648
 
649
649
  You can enable your API for other domains using the corresponding configuration option `cors`. The value is required to
650
- ensure you explicitly choose the correct setting. In addition to being a boolean, `cors` can also be assigned a
651
- function that overrides default CORS headers. That function has several parameters and can be asynchronous.
650
+ ensure you explicitly choose the correct setting: `false | true` disables/enables CORS for any origin, setting
651
+ `Access-Control-Allow-Origin: *` and `Access-Control-Allow-Headers: content-type`. You can also pass standard Express
652
+ middleware for full control, consider using the well-known [cors](https://www.npmjs.com/package/cors) package.
652
653
 
653
654
  ```ts
655
+ import cors from "cors";
654
656
  import { createConfig } from "express-zod-api";
655
657
 
656
- const config = createConfig({
657
- /** @link https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS */
658
- cors: ({ defaultHeaders, request, endpoint, logger }) => ({
659
- ...defaultHeaders,
660
- "Access-Control-Max-Age": "5000",
661
- }),
658
+ const configWithCorsPackage = createConfig({
659
+ cors: cors({ origin: "https://example.com" }),
660
+ });
661
+
662
+ const configWithCustomRequestHandler = createConfig({
663
+ cors: (req, res, next) => {
664
+ res.set({
665
+ "Access-Control-Allow-Origin": "https://example.com",
666
+ "Access-Control-Allow-Headers": "content-type",
667
+ "Access-Control-Max-Age": "5000",
668
+ });
669
+ next();
670
+ },
662
671
  });
663
672
  ```
664
673
 
@@ -683,9 +692,7 @@ const config = createConfig({
683
692
  }, // ... cors, logger, etc
684
693
  });
685
694
 
686
- // 'await' is only needed if you're going to use the returned entities.
687
- // For top level CJS you can wrap you code with (async () => { ... })()
688
- const { app, servers, logger } = await createServer(config, routing);
695
+ const { app, servers, logger } = createServer(config, routing);
689
696
  ```
690
697
 
691
698
  Ensure having `@types/node` package installed. At least you need to specify the port (usually it is 443) or UNIX socket,
@@ -787,6 +794,7 @@ createConfig({
787
794
  put: ["body", "params"],
788
795
  patch: ["body", "params"],
789
796
  delete: ["query", "params"],
797
+ query: ["query", "body", "params"],
790
798
  }, // ...
791
799
  });
792
800
  ```
@@ -1124,7 +1132,7 @@ errors yourself. In this regard `attachRouting()` provides you with `notFoundHan
1124
1132
  to your custom express app.
1125
1133
 
1126
1134
  Besides that, if you're looking to include additional request parsers, or a middleware that establishes its own routes,
1127
- then consider using the `beforeRouting` [option in config instead](#using-native-express-middlewares).
1135
+ install them on your custom `app` before calling `attachRouting()`.
1128
1136
 
1129
1137
  ## Testing endpoints
1130
1138
 
@@ -1241,9 +1249,8 @@ import { Documentation } from "express-zod-api";
1241
1249
  const yamlString = new Documentation({
1242
1250
  routing, // the same routing and config that you use to start the server
1243
1251
  config,
1244
- version: "1.2.3",
1245
- title: "Example API",
1246
- serverUrl: "https://example.com",
1252
+ info: { version: "1.2.3", title: "Example API" },
1253
+ server: "https://example.com",
1247
1254
  composition: "inline", // optional, or "components" for keeping schemas in a separate dedicated section using refs
1248
1255
  // descriptions: { positiveResponse, negativeResponse, requestParameter, requestBody }, // check out these features
1249
1256
  }).getSpecAsYaml();
package/SECURITY.md CHANGED
@@ -4,10 +4,11 @@
4
4
 
5
5
  | Version | Code name | Release | Supported |
6
6
  | ------: | :------------ | :------ | :----------------: |
7
+ | 29.x.x | Angie | 08.2026 | :white_check_mark: |
7
8
  | 28.x.x | Koko | 05.2026 | :white_check_mark: |
8
9
  | 27.x.x | Nikki | 02.2026 | :white_check_mark: |
9
10
  | 26.x.x | Lia | 12.2025 | :white_check_mark: |
10
- | 25.x.x | Sara | 08.2025 | :white_check_mark: |
11
+ | 25.x.x | Sara | 08.2025 | :x: |
11
12
  | 24.x.x | Ashley | 06.2025 | :x: |
12
13
  | 23.x.x | Sonia | 04.2025 | :x: |
13
14
  | 22.x.x | Tai | 01.2025 | :x: |