zod-openapi 2.13.0 → 2.14.0
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 +12 -10
- package/lib-commonjs/index.js +27 -5
- package/lib-esm/index.mjs +27 -5
- package/lib-types/create/document.d.ts +3 -2
- package/lib-types/create/parameters.d.ts +3 -2
- package/lib-types/extendZod.d.ts +25 -6
- package/lib-types/openapi3-ts/dist/model/openapi31.d.ts +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -17,12 +17,14 @@ A Typescript library to use <a href="https://github.com/colinhacks/zod">Zod</a>
|
|
|
17
17
|
|
|
18
18
|
## Install
|
|
19
19
|
|
|
20
|
-
Install via `npm` or `
|
|
20
|
+
Install via `npm`, `yarn` or `pnpm`:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
npm install zod zod-openapi
|
|
24
24
|
## or
|
|
25
25
|
yarn add zod zod-openapi
|
|
26
|
+
## or
|
|
27
|
+
pnpm install zod zod-openapi
|
|
26
28
|
```
|
|
27
29
|
|
|
28
30
|
## Usage
|
|
@@ -48,8 +50,8 @@ Use the `.openapi()` method to add metadata to a specific Zod type. The `.openap
|
|
|
48
50
|
| :-------------: | :-------------------------------------------------------------------------------------------------------------------------: |
|
|
49
51
|
| OpenAPI Options | This will take any option you would put on a [SchemaObject](https://swagger.io/docs/specification/data-models/data-types/). |
|
|
50
52
|
| `effectType` | Use to override the creation type for a [Zod Effect](#zod-effects) |
|
|
51
|
-
| `param` | Use to provide metadata for [request parameters](#parameters) |
|
|
52
53
|
| `header` | Use to provide metadata for [response headers](#response-headers) |
|
|
54
|
+
| `param` | Use to provide metadata for [request parameters](#parameters) |
|
|
53
55
|
| `ref` | Use this to [auto register a schema](#creating-components) |
|
|
54
56
|
| `refType` | Use this to set the creation type for a component which is not referenced in the document. |
|
|
55
57
|
| `type` | Use this to override the generated type. If this is provided no metadata will be generated. |
|
|
@@ -328,13 +330,13 @@ createDocument({
|
|
|
328
330
|
|
|
329
331
|
##### Zod Effects
|
|
330
332
|
|
|
331
|
-
`.transform()` and `.pipe()` are complicated because they technically comprise of two types (input & output). This means that we need to understand which type you are creating. In particular with transform it is very difficult to infer the output type. This library will automatically select which _type_ to use by checking how the schema is used based on the following rules:
|
|
333
|
+
`.transform()`, `.default()` and `.pipe()` are complicated because they technically comprise of two types (input & output). This means that we need to understand which type you are creating. In particular with transform it is very difficult to infer the output type. This library will automatically select which _type_ to use by checking how the schema is used based on the following rules:
|
|
332
334
|
|
|
333
335
|
_Input_: Request Bodies, Request Parameters, Headers
|
|
334
336
|
|
|
335
337
|
_Output_: Responses, Response Headers
|
|
336
338
|
|
|
337
|
-
If a registered schema with a transform or pipeline is used in both a request and response schema you will receive an error because the created schema for each will be different. To override the creation type for a specific ZodEffect, add an `.openapi()` field on it and set the `effectType` field to `input`, `output` or `same`. This will force this library to always generate the input/output type even if we are creating a response (output) or request (input) type. You typically want to set this when you know the type has not changed in the transform. `same` is the recommended choice as it will
|
|
339
|
+
If a registered schema with a transform or pipeline is used in both a request and response schema you will receive an error because the created schema for each will be different. To override the creation type for a specific ZodEffect, add an `.openapi()` field on it and set the `effectType` field to `input`, `output` or `same`. This will force this library to always generate the input/output type even if we are creating a response (output) or request (input) type. You typically want to set this when you know the type has not changed in the transform. `same` is the recommended choice as it will generate a TypeScript compiler error if the input and output types in the transform drift.
|
|
338
340
|
|
|
339
341
|
`.preprocess()` will always return the `output` type even if we are creating an input schema. If a different input type is required you can achieve this with a `.transform()` combined with a `.pipe()` or simply declare a manual `type` in `.openapi()`.
|
|
340
342
|
|
|
@@ -578,27 +580,27 @@ See the library in use in the [examples](./examples/) folder.
|
|
|
578
580
|
### Prerequisites
|
|
579
581
|
|
|
580
582
|
- Node.js LTS
|
|
581
|
-
-
|
|
583
|
+
- pnpm
|
|
582
584
|
|
|
583
585
|
```shell
|
|
584
|
-
|
|
585
|
-
|
|
586
|
+
pnpm
|
|
587
|
+
pnpm build
|
|
586
588
|
```
|
|
587
589
|
|
|
588
590
|
### Test
|
|
589
591
|
|
|
590
592
|
```shell
|
|
591
|
-
|
|
593
|
+
pnpm test
|
|
592
594
|
```
|
|
593
595
|
|
|
594
596
|
### Lint
|
|
595
597
|
|
|
596
598
|
```shell
|
|
597
599
|
# Fix issues
|
|
598
|
-
|
|
600
|
+
pnpm format
|
|
599
601
|
|
|
600
602
|
# Check for issues
|
|
601
|
-
|
|
603
|
+
pnpm lint
|
|
602
604
|
```
|
|
603
605
|
|
|
604
606
|
### Release
|
package/lib-commonjs/index.js
CHANGED
|
@@ -178,11 +178,11 @@ var throwTransformError = (effect) => {
|
|
|
178
178
|
|
|
179
179
|
This may cause the schema to render incorrectly and is most likely a mistake. You can resolve this by:
|
|
180
180
|
|
|
181
|
-
1. Setting an \`effectType\` on the
|
|
181
|
+
1. Setting an \`effectType\` on one of the transformations to \`same\` (Not applicable for ZodDefault), \`input\` or \`output\` eg. \`.openapi({type: 'same'})\`
|
|
182
182
|
2. Wrapping the transformation in a ZodPipeline
|
|
183
183
|
3. Assigning a manual type to the transformation eg. \`.openapi({type: 'string'})\`
|
|
184
184
|
4. Removing the transformation
|
|
185
|
-
5.
|
|
185
|
+
5. Deregister the component containing the transformation`
|
|
186
186
|
);
|
|
187
187
|
};
|
|
188
188
|
var resolveSingleEffect = (effect, state) => {
|
|
@@ -1442,11 +1442,12 @@ var createParamOrRef = (zodSchema, components, subpath, type, name) => {
|
|
|
1442
1442
|
}
|
|
1443
1443
|
return paramObject;
|
|
1444
1444
|
};
|
|
1445
|
-
var createParameters = (type,
|
|
1446
|
-
if (!
|
|
1445
|
+
var createParameters = (type, zodObjectType, components, subpath) => {
|
|
1446
|
+
if (!zodObjectType) {
|
|
1447
1447
|
return [];
|
|
1448
1448
|
}
|
|
1449
|
-
|
|
1449
|
+
const zodObject = getZodObject(zodObjectType, "input").shape;
|
|
1450
|
+
return Object.entries(zodObject).map(
|
|
1450
1451
|
([key, zodSchema]) => createParamOrRef(zodSchema, components, [...subpath, key], type, key)
|
|
1451
1452
|
);
|
|
1452
1453
|
};
|
|
@@ -1500,6 +1501,27 @@ var createParametersObject = (parameters, requestParams, components, subpath) =>
|
|
|
1500
1501
|
];
|
|
1501
1502
|
return combinedParameters.length ? combinedParameters : void 0;
|
|
1502
1503
|
};
|
|
1504
|
+
var getZodObject = (schema, type) => {
|
|
1505
|
+
if (isZodType(schema, "ZodObject")) {
|
|
1506
|
+
return schema;
|
|
1507
|
+
}
|
|
1508
|
+
if (isZodType(schema, "ZodLazy")) {
|
|
1509
|
+
return getZodObject(schema.schema, type);
|
|
1510
|
+
}
|
|
1511
|
+
if (isZodType(schema, "ZodEffects")) {
|
|
1512
|
+
return getZodObject(schema.innerType(), type);
|
|
1513
|
+
}
|
|
1514
|
+
if (isZodType(schema, "ZodBranded")) {
|
|
1515
|
+
return getZodObject(schema.unwrap(), type);
|
|
1516
|
+
}
|
|
1517
|
+
if (isZodType(schema, "ZodPipeline")) {
|
|
1518
|
+
if (type === "input") {
|
|
1519
|
+
return getZodObject(schema._def.in, type);
|
|
1520
|
+
}
|
|
1521
|
+
return getZodObject(schema._def.out, type);
|
|
1522
|
+
}
|
|
1523
|
+
throw new Error("failed to find ZodObject in schema");
|
|
1524
|
+
};
|
|
1503
1525
|
|
|
1504
1526
|
// src/create/content.ts
|
|
1505
1527
|
var createMediaTypeSchema = (schemaObject, components, type, subpath) => {
|
package/lib-esm/index.mjs
CHANGED
|
@@ -154,11 +154,11 @@ var throwTransformError = (effect) => {
|
|
|
154
154
|
|
|
155
155
|
This may cause the schema to render incorrectly and is most likely a mistake. You can resolve this by:
|
|
156
156
|
|
|
157
|
-
1. Setting an \`effectType\` on the
|
|
157
|
+
1. Setting an \`effectType\` on one of the transformations to \`same\` (Not applicable for ZodDefault), \`input\` or \`output\` eg. \`.openapi({type: 'same'})\`
|
|
158
158
|
2. Wrapping the transformation in a ZodPipeline
|
|
159
159
|
3. Assigning a manual type to the transformation eg. \`.openapi({type: 'string'})\`
|
|
160
160
|
4. Removing the transformation
|
|
161
|
-
5.
|
|
161
|
+
5. Deregister the component containing the transformation`
|
|
162
162
|
);
|
|
163
163
|
};
|
|
164
164
|
var resolveSingleEffect = (effect, state) => {
|
|
@@ -1418,11 +1418,12 @@ var createParamOrRef = (zodSchema, components, subpath, type, name) => {
|
|
|
1418
1418
|
}
|
|
1419
1419
|
return paramObject;
|
|
1420
1420
|
};
|
|
1421
|
-
var createParameters = (type,
|
|
1422
|
-
if (!
|
|
1421
|
+
var createParameters = (type, zodObjectType, components, subpath) => {
|
|
1422
|
+
if (!zodObjectType) {
|
|
1423
1423
|
return [];
|
|
1424
1424
|
}
|
|
1425
|
-
|
|
1425
|
+
const zodObject = getZodObject(zodObjectType, "input").shape;
|
|
1426
|
+
return Object.entries(zodObject).map(
|
|
1426
1427
|
([key, zodSchema]) => createParamOrRef(zodSchema, components, [...subpath, key], type, key)
|
|
1427
1428
|
);
|
|
1428
1429
|
};
|
|
@@ -1476,6 +1477,27 @@ var createParametersObject = (parameters, requestParams, components, subpath) =>
|
|
|
1476
1477
|
];
|
|
1477
1478
|
return combinedParameters.length ? combinedParameters : void 0;
|
|
1478
1479
|
};
|
|
1480
|
+
var getZodObject = (schema, type) => {
|
|
1481
|
+
if (isZodType(schema, "ZodObject")) {
|
|
1482
|
+
return schema;
|
|
1483
|
+
}
|
|
1484
|
+
if (isZodType(schema, "ZodLazy")) {
|
|
1485
|
+
return getZodObject(schema.schema, type);
|
|
1486
|
+
}
|
|
1487
|
+
if (isZodType(schema, "ZodEffects")) {
|
|
1488
|
+
return getZodObject(schema.innerType(), type);
|
|
1489
|
+
}
|
|
1490
|
+
if (isZodType(schema, "ZodBranded")) {
|
|
1491
|
+
return getZodObject(schema.unwrap(), type);
|
|
1492
|
+
}
|
|
1493
|
+
if (isZodType(schema, "ZodPipeline")) {
|
|
1494
|
+
if (type === "input") {
|
|
1495
|
+
return getZodObject(schema._def.in, type);
|
|
1496
|
+
}
|
|
1497
|
+
return getZodObject(schema._def.out, type);
|
|
1498
|
+
}
|
|
1499
|
+
throw new Error("failed to find ZodObject in schema");
|
|
1500
|
+
};
|
|
1479
1501
|
|
|
1480
1502
|
// src/create/content.ts
|
|
1481
1503
|
var createMediaTypeSchema = (schemaObject, components, type, subpath) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyZodObject, ZodType } from 'zod';
|
|
1
|
+
import type { AnyZodObject, ZodType, ZodTypeDef } from 'zod';
|
|
2
2
|
import type { OpenApiVersion } from '../openapi';
|
|
3
3
|
import type { oas30, oas31 } from '../openapi3-ts/dist';
|
|
4
4
|
export interface ZodOpenApiMediaTypeObject extends Omit<oas31.MediaTypeObject & oas30.MediaTypeObject, 'schema'> {
|
|
@@ -24,7 +24,7 @@ export interface ZodOpenApiResponsesObject extends oas31.ISpecificationExtension
|
|
|
24
24
|
[statuscode: `${1 | 2 | 3 | 4 | 5}${string}`]: ZodOpenApiResponseObject | oas31.ReferenceObject;
|
|
25
25
|
}
|
|
26
26
|
export type ZodOpenApiParameters = {
|
|
27
|
-
[type in oas31.ParameterLocation & oas30.ParameterLocation]?:
|
|
27
|
+
[type in oas31.ParameterLocation & oas30.ParameterLocation]?: ZodObjectInputType;
|
|
28
28
|
};
|
|
29
29
|
export interface ZodOpenApiOperationObject extends Omit<oas31.OperationObject & oas30.OperationObject, 'requestBody' | 'responses' | 'parameters'> {
|
|
30
30
|
parameters?: Array<ZodType | oas31.ParameterObject | oas30.ParameterObject | oas31.ReferenceObject | oas30.ReferenceObject>;
|
|
@@ -59,4 +59,5 @@ export interface ZodOpenApiObject extends Omit<oas31.OpenAPIObject, 'openapi' |
|
|
|
59
59
|
webhooks?: ZodOpenApiPathsObject;
|
|
60
60
|
components?: ZodOpenApiComponentsObject;
|
|
61
61
|
}
|
|
62
|
+
export type ZodObjectInputType<Output = unknown, Def extends ZodTypeDef = ZodTypeDef, Input = Record<string, unknown>> = ZodType<Output, Def, Input>;
|
|
62
63
|
export declare const createDocument: (zodOpenApiObject: ZodOpenApiObject) => oas31.OpenAPIObject;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { ZodType } from 'zod';
|
|
1
|
+
import type { AnyZodObject, ZodType } from 'zod';
|
|
2
2
|
import type { oas30, oas31 } from '../openapi3-ts/dist';
|
|
3
3
|
import type { ComponentsObject } from './components';
|
|
4
|
-
import type { ZodOpenApiParameters } from './document';
|
|
4
|
+
import type { ZodObjectInputType, ZodOpenApiParameters } from './document';
|
|
5
5
|
export declare const createComponentParamRef: (ref: string) => string;
|
|
6
6
|
export declare const createBaseParameter: (schema: ZodType, components: ComponentsObject, subpath: string[]) => oas31.BaseParameterObject;
|
|
7
7
|
export declare const createParamOrRef: (zodSchema: ZodType, components: ComponentsObject, subpath: string[], type?: keyof ZodOpenApiParameters, name?: string) => oas31.ParameterObject | oas31.ReferenceObject;
|
|
8
8
|
export declare const createManualParameters: (parameters: Array<oas31.ParameterObject | oas31.ReferenceObject | oas30.ParameterObject | oas30.ReferenceObject | ZodType> | undefined, components: ComponentsObject, subpath: string[]) => Array<oas31.ParameterObject | oas31.ReferenceObject>;
|
|
9
9
|
export declare const createParametersObject: (parameters: Array<oas31.ParameterObject | oas31.ReferenceObject | oas30.ParameterObject | oas30.ReferenceObject | ZodType> | undefined, requestParams: ZodOpenApiParameters | undefined, components: ComponentsObject, subpath: string[]) => Array<oas31.ParameterObject | oas31.ReferenceObject> | undefined;
|
|
10
|
+
export declare const getZodObject: (schema: ZodObjectInputType, type: 'input' | 'output') => AnyZodObject;
|
package/lib-types/extendZod.d.ts
CHANGED
|
@@ -2,51 +2,70 @@ import type { UnknownKeysParam, ZodDate, ZodObject, ZodRawShape, ZodTypeAny, z }
|
|
|
2
2
|
import type { CreationType } from './create/components';
|
|
3
3
|
import type { oas30, oas31 } from './openapi3-ts/dist';
|
|
4
4
|
type SchemaObject = oas30.SchemaObject & oas31.SchemaObject;
|
|
5
|
+
/**
|
|
6
|
+
* zod-openapi metadata
|
|
7
|
+
*/
|
|
5
8
|
interface ZodOpenApiMetadata<T extends ZodTypeAny, TInferred = z.input<T> | z.output<T>> extends SchemaObject {
|
|
6
9
|
example?: TInferred;
|
|
7
10
|
examples?: [TInferred, ...TInferred[]];
|
|
8
11
|
default?: T extends ZodDate ? string : TInferred;
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
13
|
+
* Used to set the output of a ZodUnion to be `oneOf` instead of `allOf`
|
|
11
14
|
*/
|
|
12
15
|
unionOneOf?: boolean;
|
|
13
16
|
/**
|
|
14
|
-
*
|
|
17
|
+
* Used to output this Zod Schema in the components schemas section. Any usage of this Zod Schema will then be transformed into a $ref.
|
|
15
18
|
*/
|
|
16
19
|
ref?: string;
|
|
17
20
|
/**
|
|
18
|
-
*
|
|
21
|
+
* Used when you are manually adding a Zod Schema to the components section. This controls whether this should be rendered as request (`input`) or response (`output`). Defaults to `output`
|
|
19
22
|
*/
|
|
20
23
|
refType?: CreationType;
|
|
21
24
|
/**
|
|
22
|
-
*
|
|
25
|
+
* Used to set the created type of an effect.
|
|
23
26
|
*/
|
|
24
27
|
effectType?: CreationType | (z.input<T> extends z.output<T> ? z.output<T> extends z.input<T> ? 'same' : never : never);
|
|
28
|
+
/**
|
|
29
|
+
* Used to set metadata for a parameter, request header or cookie
|
|
30
|
+
*/
|
|
25
31
|
param?: Partial<oas31.ParameterObject> & {
|
|
26
32
|
example?: TInferred;
|
|
27
33
|
examples?: Record<string, (oas31.ExampleObject & {
|
|
28
34
|
value: TInferred;
|
|
29
35
|
}) | oas31.ReferenceObject>;
|
|
30
36
|
/**
|
|
31
|
-
*
|
|
37
|
+
* Used to output this Zod Schema in the components parameters section. Any usage of this Zod Schema will then be transformed into a $ref.
|
|
32
38
|
*/
|
|
33
39
|
ref?: string;
|
|
34
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Used to set data for a response header
|
|
43
|
+
*/
|
|
35
44
|
header?: Partial<oas31.HeaderObject & oas30.HeaderObject> & {
|
|
36
45
|
/**
|
|
37
|
-
*
|
|
46
|
+
* Used to output this Zod Schema in the components headers section. Any usage of this Zod Schema will then be transformed into a $ref.
|
|
38
47
|
*/
|
|
39
48
|
ref?: string;
|
|
40
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Used to override the generated type. If this is provided no metadata will be generated.
|
|
52
|
+
*/
|
|
53
|
+
type?: SchemaObject['type'];
|
|
41
54
|
}
|
|
42
55
|
interface ZodOpenApiExtendMetadata {
|
|
43
56
|
extends: ZodObject<any, any, any, any, any>;
|
|
44
57
|
}
|
|
45
58
|
declare module 'zod' {
|
|
46
59
|
interface ZodType<Output, Def extends ZodTypeDef, Input = Output> {
|
|
60
|
+
/**
|
|
61
|
+
* Add OpenAPI metadata to a Zod Type
|
|
62
|
+
*/
|
|
47
63
|
openapi<T extends ZodTypeAny>(this: T, metadata: ZodOpenApiMetadata<T>): T;
|
|
48
64
|
}
|
|
49
65
|
interface ZodTypeDef {
|
|
66
|
+
/**
|
|
67
|
+
* OpenAPI metadata
|
|
68
|
+
*/
|
|
50
69
|
openapi?: ZodOpenApiMetadata<ZodTypeAny>;
|
|
51
70
|
}
|
|
52
71
|
interface ZodObjectDef<T extends ZodRawShape = ZodRawShape, UnknownKeys extends UnknownKeysParam = UnknownKeysParam, Catchall extends ZodTypeAny = ZodTypeAny> extends ZodTypeDef {
|
|
@@ -88,7 +88,7 @@ export interface OperationObject extends ISpecificationExtension {
|
|
|
88
88
|
operationId?: string;
|
|
89
89
|
parameters?: (ParameterObject | ReferenceObject)[];
|
|
90
90
|
requestBody?: RequestBodyObject | ReferenceObject;
|
|
91
|
-
responses
|
|
91
|
+
responses?: ResponsesObject;
|
|
92
92
|
callbacks?: CallbacksObject;
|
|
93
93
|
deprecated?: boolean;
|
|
94
94
|
security?: SecurityRequirementObject[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zod-openapi",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "Convert Zod Schemas to OpenAPI v3.x documentation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -37,24 +37,24 @@
|
|
|
37
37
|
"lib*/**/*.json"
|
|
38
38
|
],
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build": "
|
|
40
|
+
"build": "pnpm copy:types && node esbuild.mjs && node esbuild.esm.mjs && tsc --allowJS false --declaration --emitDeclarationOnly --outDir lib-types --project tsconfig.build.json",
|
|
41
41
|
"copy:types": "skuba node scripts/copyTypes.ts",
|
|
42
42
|
"create:docs": " skuba node examples/simple/createSchema.ts && redocly build-docs examples/simple/openapi.yml --output=examples/simple/redoc-static.html",
|
|
43
43
|
"format": "skuba format",
|
|
44
44
|
"lint": "skuba lint",
|
|
45
|
-
"prepare": "
|
|
45
|
+
"prepare": "pnpm build",
|
|
46
46
|
"test": "skuba test",
|
|
47
47
|
"test:ci": "skuba test --coverage",
|
|
48
48
|
"test:watch": "skuba test --watch"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@redocly/cli": "1.
|
|
52
|
+
"@redocly/cli": "1.9.1",
|
|
53
53
|
"@types/node": "^20.3.0",
|
|
54
54
|
"eslint-plugin-zod-openapi": "^0.1.0",
|
|
55
|
-
"openapi3-ts": "4.2.
|
|
56
|
-
"skuba": "7.
|
|
57
|
-
"yaml": "2.
|
|
55
|
+
"openapi3-ts": "4.2.2",
|
|
56
|
+
"skuba": "7.5.0",
|
|
57
|
+
"yaml": "2.4.0",
|
|
58
58
|
"zod": "3.22.4"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
@@ -71,6 +71,6 @@
|
|
|
71
71
|
"entryPoint": "src/index.ts",
|
|
72
72
|
"template": "oss-npm-package",
|
|
73
73
|
"type": "package",
|
|
74
|
-
"version": "
|
|
74
|
+
"version": "7.4.1"
|
|
75
75
|
}
|
|
76
76
|
}
|