Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## Version 24

### v24.7.4

- This patch fixes the issue for users facing `TypeError: .example is not a function`, but not using that method:
- Some environments fail to load Zod plugin properly so that the usage of `ZodType::example()` (plugin method)
internally by the framework itself could cause that error;
- This version fixes the problem by replacing the usage of `.example()` with `globalRegistry.add()`;
- The issue was found and reported by [@misha-z1nchuk](https://github.com/misha-z1nchuk).

### v24.7.3

- Fixed the depiction of the negative response to `HEAD` requests:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Therefore, many basic tasks can be accomplished faster and easier, in particular

These people contributed to the improvement of the framework by reporting bugs, making changes and suggesting ideas:

[<img src="https://github.com/misha-z1nchuk.png" alt="@misha-z1nchuk" width="50px" />](https://github.com/misha-z1nchuk)
[<img src="https://github.com/pepegc.png" alt="@pepegc" width="50px" />](https://github.com/pepegc)
[<img src="https://github.com/MichaelHindley.png" alt="@MichaelHindley" width="50px" />](https://github.com/MichaelHindley)
[<img src="https://github.com/zoton2.png" alt="@zoton2" width="50px" />](https://github.com/zoton2)
Expand Down
8 changes: 8 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ const importConcerns = [
})),
];

const compatibilityConcerns = [
{
selector: "CallExpression > MemberExpression[property.name='example']",
message: "avoid using example() method to operate without zod plugin",
},
];

const performanceConcerns = [
{
selector: "ImportDeclaration[source.value=/assert/]", // #2169
Expand Down Expand Up @@ -210,6 +217,7 @@ export default tsPlugin.config(
"warn",
...importConcerns,
...performanceConcerns,
...compatibilityConcerns,
],
},
},
Expand Down
2 changes: 1 addition & 1 deletion express-zod-api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "express-zod-api",
"version": "24.7.3",
"version": "24.7.4-beta.1",
"description": "A Typescript framework to help you get an API server up and running with I/O schema validation and custom middlewares in minutes.",
"license": "MIT",
"repository": {
Expand Down
32 changes: 19 additions & 13 deletions express-zod-api/src/result-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ export class ResultHandler<
}
}

const defaultNegativeSchema = z.object({
status: z.literal("error"),
error: z.object({ message: z.string() }),
});
globalRegistry.add(defaultNegativeSchema, {
examples: [
{ status: "error", error: { message: "Sample error message" } },
] satisfies z.output<typeof defaultNegativeSchema>[],
});

export const defaultResultHandler = new ResultHandler({
positive: (output) => {
const responseSchema = z.object({
Expand All @@ -112,15 +122,7 @@ export const defaultResultHandler = new ResultHandler({
}
return responseSchema;
},
negative: z
.object({
status: z.literal("error"),
error: z.object({ message: z.string() }),
})
.example({
status: "error",
error: { message: "Sample error message" },
}),
negative: defaultNegativeSchema,
handler: ({ error, input, output, request, response, logger }) => {
if (error) {
const httpError = ensureHttpError(error);
Expand All @@ -139,6 +141,13 @@ export const defaultResultHandler = new ResultHandler({
},
});

const arrayNegativeSchema = z.string();
globalRegistry.add(arrayNegativeSchema, {
examples: ["Sample error message"] satisfies z.output<
typeof arrayNegativeSchema
>[],
});

/**
* @deprecated Resist the urge of using it: this handler is designed only to simplify the migration of legacy APIs.
* @desc Responding with array is a bad practice keeping your endpoints from evolving without breaking changes.
Expand Down Expand Up @@ -169,10 +178,7 @@ export const arrayResultHandler = new ResultHandler({
}
return responseSchema;
},
negative: {
schema: z.string().example("Sample error message"),
mimeType: "text/plain",
},
negative: { schema: arrayNegativeSchema, mimeType: "text/plain" },
handler: ({ response, output, error, logger, request, input }) => {
if (error) {
const httpError = ensureHttpError(error);
Expand Down