zod-openapi 4.2.3 → 4.2.4

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/README.md CHANGED
@@ -3,35 +3,35 @@
3
3
  <h1 align="center">zod-openapi</h1>
4
4
  </p>
5
5
  <p align="center">
6
- A Typescript library to use <a href="https://github.com/colinhacks/zod">Zod</a> Schemas to create OpenAPI v3.x documentation
6
+ A TypeScript library for using <a href="https://github.com/colinhacks/zod">Zod</a> schemas to generate OpenAPI v3.x documentation.
7
7
  </p>
8
8
  <div align="center">
9
- <a href="https://www.npmjs.com/package/zod-openapi"><img src="https://img.shields.io/npm/v/zod-openapi"/><a>
10
- <a href="https://www.npmjs.com/package/zod-openapi"><img src="https://img.shields.io/npm/dm/zod-openapi"/><a>
11
- <a href="https://nodejs.org/en/"><img src="https://img.shields.io/badge/node-%3E%3D%2018-brightgreen"/><a>
12
- <a href="https://github.com/samchungy/zod-openapi/actions/workflows/test.yml"><img src="https://github.com/samchungy/zod-openapi/actions/workflows/test.yml/badge.svg"/><a>
13
- <a href="https://github.com/samchungy/zod-openapi/actions/workflows/release.yml"><img src="https://github.com/samchungy/zod-openapi/actions/workflows/release.yml/badge.svg"/><a>
14
- <a href="https://github.com/seek-oss/skuba"><img src="https://img.shields.io/badge/🤿%20skuba-powered-009DC4"/><a>
9
+ <a href="https://www.npmjs.com/package/zod-openapi"><img src="https://img.shields.io/npm/v/zod-openapi"/></a>
10
+ <a href="https://www.npmjs.com/package/zod-openapi"><img src="https://img.shields.io/npm/dm/zod-openapi"/></a>
11
+ <a href="https://nodejs.org/en/"><img src="https://img.shields.io/badge/node-%3E%3D%2018-brightgreen"/></a>
12
+ <a href="https://github.com/samchungy/zod-openapi/actions/workflows/test.yml"><img src="https://github.com/samchungy/zod-openapi/actions/workflows/test.yml/badge.svg"/></a>
13
+ <a href="https://github.com/samchungy/zod-openapi/actions/workflows/release.yml"><img src="https://github.com/samchungy/zod-openapi/actions/workflows/release.yml/badge.svg"/></a>
14
+ <a href="https://github.com/seek-oss/skuba"><img src="https://img.shields.io/badge/🤿%20skuba-powered-009DC4"/></a>
15
15
  </div>
16
16
  <br>
17
17
 
18
- ## Install
18
+ ## Installation
19
19
 
20
- Install via `npm`, `yarn` or `pnpm`:
20
+ Install via `npm`, `yarn`, or `pnpm`:
21
21
 
22
22
  ```bash
23
23
  npm install zod zod-openapi
24
- ## or
24
+ # or
25
25
  yarn add zod zod-openapi
26
- ## or
26
+ # or
27
27
  pnpm install zod zod-openapi
28
28
  ```
29
29
 
30
30
  ## Usage
31
31
 
32
- ### Extend Zod
32
+ ### Extending Zod
33
33
 
34
- This mutates Zod to add an extra `.openapi()` method. Call this at the top of your entry point(s). You can achieve this in two different ways, depending on your preference.
34
+ This package extends Zod by adding an `.openapi()` method. Call this at the top of your entry point(s). You can apply this extension in two ways:
35
35
 
36
36
  #### Subpath Import
37
37
 
@@ -39,12 +39,12 @@ This mutates Zod to add an extra `.openapi()` method. Call this at the top of yo
39
39
  import 'zod-openapi/extend';
40
40
  import { z } from 'zod';
41
41
 
42
- z.string().openapi({ description: 'hello world!', example: 'hello world' });
42
+ z.string().openapi({ description: 'Hello world!', example: 'Hello world' });
43
43
  ```
44
44
 
45
45
  #### Manual Extension
46
46
 
47
- This is useful if you have a specific instance of Zod or a Zod instance from another library that you would like to target.
47
+ This method is useful if you have a specific instance of Zod or a Zod instance from another library that you want to extend.
48
48
 
49
49
  ```typescript
50
50
  import { z } from 'zod';
@@ -52,27 +52,27 @@ import { extendZodWithOpenApi } from 'zod-openapi';
52
52
 
53
53
  extendZodWithOpenApi(z);
54
54
 
55
- z.string().openapi({ description: 'hello world!', example: 'hello world' });
55
+ z.string().openapi({ description: 'Hello world!', example: 'hello world' });
56
56
  ```
57
57
 
58
- #### `.openapi()`
58
+ ### `.openapi()`
59
59
 
60
- Use the `.openapi()` method to add metadata to a specific Zod type. The `.openapi()` method takes an object with the following options:
60
+ Use the `.openapi()` method to add metadata to a Zod schema. It accepts an object with the following options:
61
61
 
62
- | Option | Description |
63
- | :-------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: |
64
- | OpenAPI Options | This will take any option you would put on a [SchemaObject](https://swagger.io/docs/specification/data-models/data-types/). |
65
- | `effectType` | Use to override the creation type for a [Zod Effect](#zod-effects) |
66
- | `header` | Use to provide metadata for [response headers](#response-headers) |
67
- | `param` | Use to provide metadata for [request parameters](#parameters) |
68
- | `ref` | Use this to [auto register a schema as a re-usable component](#creating-components) |
69
- | `refType` | Use this to set the creation type for a component which is not referenced in the document. |
70
- | `type` | Use this to override the generated type. If this is provided no metadata will be generated. |
71
- | `unionOneOf` | Set to `true` to force a single ZodUnion to output `oneOf` instead of `anyOf`. See [CreateDocumentOptions](#CreateDocumentOptions) for a global option |
62
+ | Option | Description |
63
+ | ----------------- | ------------------------------------------------------------------------------------------------------------------------- |
64
+ | `OpenAPI Options` | Accepts any option available for a [SchemaObject](https://swagger.io/docs/specification/data-models/data-types/). |
65
+ | `effectType` | Overrides the creation type for a [Zod Effect](#zod-effects). |
66
+ | `header` | Adds metadata for [response headers](#response-headers). |
67
+ | `param` | Adds metadata for [request parameters](#parameters). |
68
+ | `ref` | Registers a schema as a reusable OpenAPI component. |
69
+ | `refType` | Defines the creation type for a component not explicitly referenced in the document. |
70
+ | `type` | Overrides the generated type. If provided, no metadata will be generated. |
71
+ | `unionOneOf` | Forces a `oneOf` instead of `anyOf` for unions. See [CreateDocumentOptions](#CreateDocumentOptions) for a global setting. |
72
72
 
73
73
  ### `createDocument`
74
74
 
75
- Creates an OpenAPI documentation object
75
+ Generates an OpenAPI documentation object.
76
76
 
77
77
  ```typescript
78
78
  import 'zod-openapi/extend';
@@ -459,6 +459,10 @@ Another way to register schema instead of adding a `ref` is to add it to the com
459
459
  eg.
460
460
 
461
461
  ```typescript
462
+ const title = z.string().openapi({
463
+ description: 'Job title',
464
+ example: 'My job',
465
+ });
462
466
  createDocument({
463
467
  components: {
464
468
  schemas: {
@@ -468,7 +472,29 @@ createDocument({
468
472
  });
469
473
  ```
470
474
 
471
- Unfortunately, as a limitation of this library, you will need to attach an `.openapi()` field or `.describe()` to the schema that you are passing into the components or you will not reap the full benefits of component generation. As a result, I recommend utilising the auto registering components over manual registration.
475
+ Unfortunately, as a limitation of this library, you should attach an `.openapi()` field or `.describe()` to the schema that you are passing into the components or you will not reap the full benefits of component generation.
476
+
477
+ ```ts
478
+ // ❌ Avoid this
479
+ const title = z.string();
480
+
481
+ // ✅ Recommended ways
482
+ const title = z.string().describe('Job title');
483
+ const title = z.string().openapi({
484
+ description: 'Job title',
485
+ example: 'My job',
486
+ });
487
+
488
+ createDocument({
489
+ components: {
490
+ schemas: {
491
+ jobTitle: title,
492
+ },
493
+ },
494
+ });
495
+ ```
496
+
497
+ Overall, I recommend utilising the auto registering components over manual registration.
472
498
 
473
499
  #### Parameters
474
500
 
@@ -602,12 +602,26 @@ const createNullableSchema = (zodNullable, state) => {
602
602
  effects: schemaObject.effects
603
603
  };
604
604
  }
605
- const { type: type2, ...schema2 } = schemaObject.schema;
605
+ const { type: type2, const: schemaConst, ...schema2 } = schemaObject.schema;
606
+ if (schemaConst) {
607
+ return {
608
+ type: "schema",
609
+ schema: {
610
+ type: mapNullType(type2),
611
+ enum: [schemaConst, null],
612
+ ...schema2
613
+ },
614
+ effects: schemaObject.effects
615
+ };
616
+ }
606
617
  return {
607
618
  type: "schema",
608
619
  schema: {
609
620
  type: mapNullType(type2),
610
- ...schema2
621
+ ...schema2,
622
+ // https://github.com/json-schema-org/json-schema-spec/issues/258
623
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
624
+ ...schema2.enum && { enum: [...schema2.enum, null] }
611
625
  },
612
626
  effects: schemaObject.effects
613
627
  };
@@ -601,12 +601,26 @@ const createNullableSchema = (zodNullable, state) => {
601
601
  effects: schemaObject.effects
602
602
  };
603
603
  }
604
- const { type: type2, ...schema2 } = schemaObject.schema;
604
+ const { type: type2, const: schemaConst, ...schema2 } = schemaObject.schema;
605
+ if (schemaConst) {
606
+ return {
607
+ type: "schema",
608
+ schema: {
609
+ type: mapNullType(type2),
610
+ enum: [schemaConst, null],
611
+ ...schema2
612
+ },
613
+ effects: schemaObject.effects
614
+ };
615
+ }
605
616
  return {
606
617
  type: "schema",
607
618
  schema: {
608
619
  type: mapNullType(type2),
609
- ...schema2
620
+ ...schema2,
621
+ // https://github.com/json-schema-org/json-schema-spec/issues/258
622
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
623
+ ...schema2.enum && { enum: [...schema2.enum, null] }
610
624
  },
611
625
  effects: schemaObject.effects
612
626
  };
@@ -26,9 +26,7 @@ interface ZodOpenApiResponsesObject extends ISpecificationExtension {
26
26
  default?: ZodOpenApiResponseObject | ReferenceObject | ReferenceObject$1;
27
27
  [statuscode: `${1 | 2 | 3 | 4 | 5}${string}`]: ZodOpenApiResponseObject | ReferenceObject;
28
28
  }
29
- type ZodOpenApiParameters = {
30
- [type in ParameterLocation & ParameterLocation$1]?: ZodObjectInputType;
31
- };
29
+ type ZodOpenApiParameters = Partial<Record<ParameterLocation & ParameterLocation$1, ZodObjectInputType>>;
32
30
  interface ZodOpenApiCallbacksObject extends ISpecificationExtension {
33
31
  [name: string]: ZodOpenApiCallbackObject;
34
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod-openapi",
3
- "version": "4.2.3",
3
+ "version": "4.2.4",
4
4
  "description": "Convert Zod Schemas to OpenAPI v3.x documentation",
5
5
  "keywords": [
6
6
  "typescript",
@@ -74,13 +74,13 @@
74
74
  "devDependencies": {
75
75
  "@arethetypeswrong/cli": "0.17.2",
76
76
  "@crackle/cli": "0.15.5",
77
- "@redocly/cli": "1.27.0",
77
+ "@redocly/cli": "1.34.0",
78
78
  "@types/node": "^20.3.0",
79
- "eslint-plugin-zod-openapi": "^1.0.0-beta.0",
79
+ "eslint-plugin-zod-openapi": "1.0.0",
80
80
  "openapi3-ts": "4.4.0",
81
- "skuba": "9.1.0",
81
+ "skuba": "10.1.0",
82
82
  "yaml": "2.7.0",
83
- "zod": "3.24.1"
83
+ "zod": "3.24.2"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "zod": "^3.21.4"
@@ -97,6 +97,6 @@
97
97
  "entryPoint": "src/index.ts",
98
98
  "template": "oss-npm-package",
99
99
  "type": "package",
100
- "version": "9.1.0"
100
+ "version": "10.1.0"
101
101
  }
102
102
  }