Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v19 is for Dime #1692

Merged
merged 65 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
b6cd78e
Adjusting workflow triggers.
RobinTail Apr 22, 2024
4308342
Next: Drop support `zod` 3.22 (#1693)
RobinTail Apr 22, 2024
addfdae
Dedication: for Dime.
RobinTail Apr 22, 2024
e02ea03
Merge branch 'master' into make-v19
RobinTail Apr 24, 2024
3aca212
Merge branch 'master' into make-v19
RobinTail Apr 25, 2024
c08f7b6
Drop Node below 18.18 (#1705)
RobinTail Apr 25, 2024
839668a
Changelog: 19.0.0 draft.
RobinTail Apr 25, 2024
f5178d6
Removing condition on compat test for jest in v19 (#1707)
RobinTail Apr 27, 2024
9d2e3dc
Drop Node 20 below 20.9.0 (#1708)
RobinTail Apr 27, 2024
7044d27
Merge branch 'master' into make-v19
RobinTail Apr 29, 2024
83c6912
Merge branch 'master' into make-v19
RobinTail Apr 30, 2024
90ec641
Rev: fixed swc code in compat test
RobinTail Apr 30, 2024
7315c83
Cancel rev: fixed swc core in compat test
RobinTail Apr 30, 2024
926a4f8
Merge branch 'master' into make-v19
RobinTail May 1, 2024
7d13dc7
Merge branch 'master' into make-v19
RobinTail May 3, 2024
4f7f31e
Merge branch 'master' into make-v19
RobinTail May 4, 2024
f66de3f
Removing the deprecated withMeta() (#1726)
RobinTail May 4, 2024
53ab7d3
Merge branch 'master' into make-v19
RobinTail May 4, 2024
3a29e71
Security: planning for June, deprecating v15
RobinTail May 4, 2024
81cb922
Merge branch 'master' into make-v19
RobinTail May 5, 2024
572ba79
Merge branch 'master' into make-v19
RobinTail May 6, 2024
ce3b2c1
Merge branch 'master' into make-v19
RobinTail May 7, 2024
2e0c2e1
Fix: freezing arrays returned by public methods (#1736)
RobinTail May 7, 2024
a780096
Merge branch 'master' into make-v19
RobinTail May 7, 2024
a2d5092
Merge branch 'master' into make-v19
RobinTail May 7, 2024
cc1fc6c
Merge branch 'master' into make-v19
RobinTail May 7, 2024
9cc3ec7
Feat: Selective parsers with child logger (#1741)
RobinTail May 8, 2024
5fbc249
Changelog: structuring the notes for 19.0.0.
RobinTail May 8, 2024
1a146fa
Readme: adjusting the beforeUpload example.
RobinTail May 8, 2024
e1e3d92
Merge branch 'master' into make-v19
RobinTail May 8, 2024
234fec6
Merge branch 'master' into make-v19
RobinTail May 9, 2024
4ef6ba6
Complete `zod` plugin with proprietary brands (#1730)
RobinTail May 9, 2024
93aa7b6
Automatic default raw parser (#1745)
RobinTail May 9, 2024
944eca1
19.0.0-beta.1
RobinTail May 9, 2024
976347f
Fix TS2527 for unique symbol (v19) (#1747)
RobinTail May 9, 2024
4cbbaa5
Reverting stict version for SWC core in compat test.
RobinTail May 9, 2024
fc97438
19.0.0-beta.2
RobinTail May 9, 2024
3ca5502
Logger adjustments for v19 (#1748)
RobinTail May 9, 2024
909d414
Ref: removing type argument from Metadata.
RobinTail May 9, 2024
d172bc7
Ref: unexposing Metadata (no longer needed after removing withMeta).
RobinTail May 9, 2024
ef64bab
Merge branch 'master' into make-v19
RobinTail May 10, 2024
51a55ba
Merge branch 'master' into make-v19
RobinTail May 10, 2024
ce7971f
19.0.0-beta.3
RobinTail May 10, 2024
f5d0f51
Readme: Notice on Zod Plugin.
RobinTail May 11, 2024
438e8f1
Readme: add plugin article to index.
RobinTail May 11, 2024
0c276c4
Merge branch 'master' into make-v19
RobinTail May 11, 2024
f6c5982
Merge branch 'master' into make-v19
RobinTail May 11, 2024
b6fccb4
Drop static options (#1755)
RobinTail May 11, 2024
2c33a66
Changelog: shortening.
RobinTail May 11, 2024
cb5fb58
19.0.0-beta.4
RobinTail May 11, 2024
6331783
Merge branch 'master' into make-v19
RobinTail May 11, 2024
8d32a37
Fix: child logger should be available when using `attachRouting()` (#…
RobinTail May 11, 2024
1345882
Merge branch 'master' into make-v19
RobinTail May 12, 2024
8162694
Merge branch 'master' into make-v19
RobinTail May 12, 2024
9a5f45e
Increasing minimal versions of express and upload peers (#1760)
RobinTail May 12, 2024
1548d84
Merge branch 'master' into make-v19
RobinTail May 12, 2024
28ed00e
Cleanup: Removing the requirement on configuring rawParser (#1762)
RobinTail May 12, 2024
7d39981
Fix test name.
RobinTail May 13, 2024
e1ca69e
Security: releasing earlier
RobinTail May 13, 2024
ba1e559
Changelog: reviewed
RobinTail May 13, 2024
3483635
Merge branch 'master' into make-v19
RobinTail May 13, 2024
9941017
19.0.0-beta.5
RobinTail May 13, 2024
6d84c5a
Notice: `beforeRouting` now called before parsing as well (#1766)
RobinTail May 13, 2024
2ad5b19
19.0.0-beta.6
RobinTail May 13, 2024
02a10ef
CI: no more PRs to v19
RobinTail May 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ name: "CodeQL"

on:
push:
branches: [ master, v15, v16, v17 ]
branches: [ master, v16, v17, v18 ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, v15, v16, v17 ]
branches: [ master, v16, v17, v18 ]
schedule:
- cron: '26 8 * * 1'

Expand Down
22 changes: 4 additions & 18 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ name: Node.js CI

on:
push:
branches: [ master, v15, v16, v17 ]
branches: [ master, v16, v17, v18 ]
pull_request:
branches: [ master, v15, v16, v17 ]
branches: [ master, v16, v17, v18 ]

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [18.0.0, 18.x, 20.0.0, 20.x, 22.0.0, 22.x]
node-version: [18.18.0, 18.x, 20.9.0, 20.x, 22.0.0, 22.x]
RobinTail marked this conversation as resolved.
Show resolved Hide resolved
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- name: Get yarn cache dir
Expand All @@ -41,13 +41,7 @@ jobs:
timeout_seconds: 15
max_attempts: 3
on_retry_command: yarn config set registry https://registry.npmjs.org
# todo use regular "yarn install" when min Node version increased to 18.18
# @typescript/eslint group compatibility issue fixed by ignoring engines for dev dependencies only:
command: |
npm pkg delete devDependencies
yarn install
git checkout -- .
yarn install --ignore-engines
command: yarn install
- name: Lint
run: yarn lint
- name: Test
Expand Down Expand Up @@ -75,15 +69,7 @@ jobs:
max_attempts: 3
on_retry_command: yarn config set registry https://registry.npmjs.org
command: yarn test:esm
- name: Check Jest 30 compatibility
uses: madhead/semver-utils@v4
id: jest30compat
with:
version: ${{ steps.setup-node.outputs.node-version }}
satisfies: '>=18.12.0'
lenient: false # require to parse or fail
- name: Compatibility test
if: steps.jest30compat.outputs.satisfies == 'true'
uses: nick-fields/retry@v3
with:
timeout_seconds: 15
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/swagger.yml
RobinTail marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: OpenAPI Validation

on:
push:
branches: [ master, v15, v16, v17 ]
branches: [ master, v16, v17, v18 ]
pull_request:
branches: [ master, v15, v16, v17 ]
branches: [ master, v16, v17, v18 ]


jobs:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ yarn-error.log
coverage
tests/**/yarn.lock
tests/**/quick-start.ts
tests/issue952/*.d.ts
90 changes: 90 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,95 @@
# Changelog

## Version 19

### v19.0.0

- **Breaking changes**:
- Increased the minimum supported versions:
- For Node.js: 18.18.0, 20.9.0 or 22.0.0;
- For `zod`: 3.23.0;
- For `express`: [4.19.2](https://github.com/expressjs/express/security/advisories/GHSA-rv95-896h-c2vc);
- For `express-fileupload` and `@types/express-fileupload`: 1.5.0.
- Removed the deprecated method ~~`withMeta()`~~ (see [v18.5.0](#v1850) for details);
- Removed support for static options by `EndpointsFactory::addOptions()` (see [v18.6.0](#v1860) for details);
- Freezed the arrays returned by the methods or exposed by properties of `Endpoint` and `DependsOnMethod`;
- Changed interface for `ez.raw()`: additional properties should be supplied as its argument, not via `.extend()`;
- Changed the following config options:
- The function assigned to `server.upload.beforeUpload` now accepts `request` instead of `app`;
- The function assigned to `server.beforeRouting` is now called before parsing too.
- Features:
- New configurable level `info` for built-in logger (higher than `debug`, but lower than `warn`);
- Selective parsers equipped with a child logger:
- There are 3 types of endpoints depending on their input schema: having `ez.upload()`, having `ez.raw()`, others;
- Depending on that type, only the parsers needed for certain endpoint are processed;
- This makes all requests eligible for the assigned parsers and reverts changes made in [v18.5.2](#v1852);
- Specifying `rawParser` in config is no longer needed to enable the feature.
- Non-breaking significant changes:
- Request logging reflects the actual path instead of the configured route, and it's placed in front of parsing:
- The severity of those messaged reduced from `info` to `debug`;
- The debug messages from uploader are enabled by default when the logger level is set to `debug`;
- How to migrate confidently:
- Upgrade Node.js, `zod`, `express`, `express-fileupload` and `@types/express-fileupload` accordingly;
- Avoid mutating the readonly arrays;
- If you're using ~~`withMeta()`~~:
- Remove it and unwrap your schemas — you can use `.example()` method directly.
- If you're using `.addOptions()` on `EndpointsFactory` instance:
- Replace the argument with an async function returning those options;
- Or assign those options to `const` and import them where needed.
- If you're using `ez.raw().extend()` for additional properties:
- Supply them directly as an argument to `ez.raw()` — see the example below.
- If you're using `beforeUpload` in your config:
- Adjust the implementation according to the example below.
- If you're using `beforeRouting` in your config for anything that requires a parsed request body:
- Add the required parsers using `app.use()` statements to the assigned function.
- If you're having `rawParser: express.raw()` in your config:
- You can now remove this line (it's the default value now), unless you're having any customizations.

```ts
import createHttpError from "http-errors";
import { createConfig } from "express-zod-api";

const before = createConfig({
server: {
upload: {
beforeUpload: ({ app, logger }) => {
app.use((req, res, next) => {
if (req.is("multipart/form-data") && !canUpload(req)) {
return next(createHttpError(403, "Not authorized"));
}
next();
});
},
},
},
});

const after = createConfig({
server: {
upload: {
beforeUpload: ({ request, logger }) => {
if (!canUpload(request)) {
throw createHttpError(403, "Not authorized");
}
},
},
},
});
```

```ts
import { z } from "zod";
import { ez } from "express-zod-api";

const before = ez.raw().extend({
pathParameter: z.string(),
});

const after = ez.raw({
pathParameter: z.string(),
});
```

## Version 18

### v18.6.2
Expand Down
62 changes: 26 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ Start your API server with I/O schema validation and custom middlewares in minut
4. [Accepting raw data](#accepting-raw-data)
5. [Subscriptions](#subscriptions)
7. [Integration and Documentation](#integration-and-documentation)
1. [Generating a Frontend Client](#generating-a-frontend-client)
2. [Creating a documentation](#creating-a-documentation)
3. [Tagging the endpoints](#tagging-the-endpoints)
1. [Zod Plugin](#zod-plugin)
2. [Generating a Frontend Client](#generating-a-frontend-client)
3. [Creating a documentation](#creating-a-documentation)
4. [Tagging the endpoints](#tagging-the-endpoints)
8. [Caveats](#caveats)
1. [Coercive schema of Zod](#coercive-schema-of-zod)
2. [Excessive properties in endpoint output](#excessive-properties-in-endpoint-output)
Expand Down Expand Up @@ -87,7 +88,7 @@ Therefore, many basic tasks can be accomplished faster and easier, in particular

- [Typescript](https://www.typescriptlang.org/) first.
- Web server — [Express.js](https://expressjs.com/).
- Schema validation — [Zod 3.x](https://github.com/colinhacks/zod).
- Schema validation — [Zod 3.x](https://github.com/colinhacks/zod) including [Zod Plugin](#zod-plugin).
- Supports any logger having `info()`, `debug()`, `error()` and `warn()` methods;
- Built-in console logger with colorful and pretty inspections by default.
- Generators:
Expand Down Expand Up @@ -801,16 +802,8 @@ const config = createConfig({
```

Refer to [documentation](https://www.npmjs.com/package/express-fileupload#available-options) on available options.
Some options are forced in order to ensure the correct workflow:

```json5
{
abortOnLimit: false,
parseNested: true,
logger: {}, // the configured logger, using its .debug() method
}
```

Some options are forced in order to ensure the correct workflow: `abortOnLimit: false`, `parseNested: true`, `logger`
is assigned with `.debug()` method of the configured logger, and `debug` is enabled by default.
The `limitHandler` option is replaced by the `limitError` one. You can also connect an additional middleware for
restricting the ability to upload using the `beforeUpload` option. So the configuration for the limited and restricted
upload might look this way:
Expand All @@ -823,13 +816,10 @@ const config = createConfig({
upload: {
limits: { fileSize: 51200 }, // 50 KB
limitError: createHttpError(413, "The file is too large"), // handled by errorHandler in config
beforeUpload: ({ app, logger }) => {
app.use((req, res, next) => {
if (req.is("multipart/form-data") && !canUpload(req)) {
return next(createHttpError(403, "Not authorized"));
}
next();
});
beforeUpload: ({ request, logger }) => {
if (!canUpload(request)) {
throw createHttpError(403, "Not authorized");
}
},
},
},
Expand Down Expand Up @@ -1019,26 +1009,18 @@ defaultEndpointsFactory.build({
## Accepting raw data

Some APIs may require an endpoint to be able to accept and process raw data, such as streaming or uploading a binary
file as an entire body of request. In order to enable this feature you need to set the `rawParser` config feature to
`express.raw()`. See also its options [in Express.js documentation](https://expressjs.com/en/4x/api.html#express.raw).
The raw data is placed into `request.body.raw` property, having type `Buffer`. Then use the proprietary `ez.raw()`
schema (which is an alias for `z.object({ raw: ez.file("buffer") })`) as the input schema of your endpoint.
file as an entire body of request. Use the proprietary `ez.raw()` schema as the input schema of your endpoint.
The default parser in this case is `express.raw()`. You can customize it by assigning the `rawParser` option in config.
The raw data is placed into `request.body.raw` property, having type `Buffer`.

```typescript
import express from "express";
import { createConfig, defaultEndpointsFactory, ez } from "express-zod-api";

const config = createConfig({
server: {
rawParser: express.raw(), // enables the feature
},
});
import { defaultEndpointsFactory, ez } from "express-zod-api";

const rawAcceptingEndpoint = defaultEndpointsFactory.build({
method: "post",
input: ez
.raw() // accepts the featured { raw: Buffer }
.extend({}), // for additional inputs, like route params, if needed
input: ez.raw({
/* the place for additional inputs, like route params, if needed */
}),
output: z.object({ length: z.number().int().nonnegative() }),
handler: async ({ input: { raw } }) => ({
length: raw.length, // raw is Buffer
Expand All @@ -1059,6 +1041,14 @@ https://github.com/RobinTail/zod-sockets#subscriptions

# Integration and Documentation

## Zod Plugin

Express Zod API acts as a plugin for Zod, extending its functionality once you import anything from `express-zod-api`:

- Adds `.example()` method to all Zod schemas for storing examples and reflecting them in the generated documentation;
- Adds `.label()` method to `ZodDefault` for replacing the default value in documentation with a label;
- Alters the `.brand()` method on all Zod schemas by making the assigned brand available in runtime.

## Generating a Frontend Client

You can generate a Typescript file containing the IO types of your API and a client for it.
Expand Down
3 changes: 2 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

| Version | Release | Supported |
| ------: | :------ | :----------------: |
| 19.x.x | 05.2024 | :white_check_mark: |
| 18.x.x | 04.2024 | :white_check_mark: |
| 17.x.x | 02.2024 | :white_check_mark: |
| 16.x.x | 12.2023 | :white_check_mark: |
| 15.x.x | 12.2023 | :white_check_mark: |
| 15.x.x | 12.2023 | :x: |
| 14.x.x | 10.2023 | :x: |
| 12.x.x | 09.2023 | :x: |
| 11.x.x | 06.2023 | :x: |
Expand Down
3 changes: 0 additions & 3 deletions example/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import express from "express";
import { createConfig } from "../src";
import ui from "swagger-ui-express";
import yaml from "yaml";
Expand All @@ -9,12 +8,10 @@ export const config = createConfig({
server: {
listen: 8090,
upload: {
debug: true,
limits: { fileSize: 51200 },
limitError: createHttpError(413, "The file is too large"), // affects uploadAvatarEndpoint
},
compression: true, // affects sendAvatarEndpoint
rawParser: express.raw(), // required for rawAcceptingEndpoint
beforeRouting: async ({ app }) => {
// third-party middlewares serving their own routes or establishing their own routing besides the API
const documentation = yaml.parse(
Expand Down
8 changes: 4 additions & 4 deletions example/endpoints/accept-raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { taggedEndpointsFactory } from "../factories";
export const rawAcceptingEndpoint = taggedEndpointsFactory.build({
method: "post",
tag: "files",
input: ez
.raw() // requires to enable rawParser option in server config
.extend({}), // additional inputs, route params for example, if needed
input: ez.raw({
/* the place for additional inputs, like route params, if needed */
}),
output: z.object({ length: z.number().int().nonnegative() }),
handler: async ({ input: { raw } }) => ({
length: raw.length, // input.raw is populated automatically when rawParser is set in config
length: raw.length, // input.raw is populated automatically by the corresponding parser
}),
});
2 changes: 1 addition & 1 deletion example/example.documentation.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.1.0
info:
title: Example API
version: 18.6.2
version: 19.0.0-beta.6
paths:
/v1/user/retrieve:
get:
Expand Down
Loading