Skip to content

Commit

Permalink
Merge branch 'main' into openapi-3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
A5rocks authored Jan 18, 2024
2 parents 89578a7 + 1cfb5ef commit 68bbd74
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 17 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,9 @@
"tslib": "^2.6.0",
"typescript": "5.1.6",
"validator": "^13.9.0",
"zod": "^3.21.4"
"zod": "^3.22.4"
},
"workspaces": [
"packages/**"
]
}

2 changes: 2 additions & 0 deletions packages/zod-openapi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).

### [2.2.2](https://github.com/anatine/zod-plugins/compare/zod-openapi-2.2.1...zod-openapi-2.2.2) (2023-12-15)

### [2.2.1](https://github.com/anatine/zod-plugins/compare/zod-openapi-2.2.0...zod-openapi-2.2.1) (2023-10-31)

## [2.2.0](https://github.com/anatine/zod-plugins/compare/zod-openapi-2.1.0...zod-openapi-2.2.0) (2023-08-22)
Expand Down
2 changes: 1 addition & 1 deletion packages/zod-openapi/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@anatine/zod-openapi",
"version": "2.2.1",
"version": "2.2.2",
"description": "Zod to OpenAPI converter",
"main": "src/index.js",
"types": "src/index.d.ts",
Expand Down
68 changes: 68 additions & 0 deletions packages/zod-openapi/src/lib/zod-openapi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -961,4 +961,72 @@ describe('zodOpenapi', () => {
maximum: 10,
} satisfies SchemaObject);
});


it('should work with ZodTransform and correctly set nullable and optional', () => {
type Type = string;
const schema = z.object({
item: extendApi(
z.custom<Type>((data) => true),
generateSchema(z.string().nullable())
),
});
expect(generateSchema(schema)).toEqual({
properties: {
item: {
type: ['string', 'null'],
},
},
type: 'object',
});
const schema2 = z.object({
item: extendApi(
z.custom<Type>((data) => !!data),
generateSchema(z.string())
),
});
expect(generateSchema(schema2)).toEqual({
properties: {
item: {
type: 'string',
},
},
required: ['item'],
type: 'object',
});

});

test('should work with ZodReadonly', () => {
expect(generateSchema(z.object({ field: z.string() })))
.toMatchInlineSnapshot(`
Object {
"properties": Object {
"field": Object {
"type": "string",
},
},
"required": Array [
"field",
],
"type": "object",
}
`);

expect(generateSchema(z.object({ field: z.string() }).readonly()))
.toMatchInlineSnapshot(`
Object {
"properties": Object {
"field": Object {
"type": "string",
},
},
"required": Array [
"field",
],
"type": "object",
}
`);

});
});
38 changes: 31 additions & 7 deletions packages/zod-openapi/src/lib/zod-openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,20 +310,31 @@ function parseNull({ zodRef, schemas }: ParsingArgs<z.ZodNull>): SchemaObject {
);
}

function parseOptionalNullable({
function parseOptional({
schemas,
zodRef,
useOutput,
}: ParsingArgs<
z.ZodOptional<OpenApiZodAny> | z.ZodNullable<OpenApiZodAny>
>): SchemaObject {
}: ParsingArgs<z.ZodOptional<OpenApiZodAny>>): SchemaObject {
return merge(
generateSchema(zodRef.unwrap(), useOutput),
zodRef.description ? { description: zodRef.description } : {},
...schemas
);
}

function parseNullable({
schemas,
zodRef,
useOutput,
}: ParsingArgs<z.ZodNullable<OpenApiZodAny>>): SchemaObject {
const schema = generateSchema(zodRef.unwrap(), useOutput);
return merge(
{ ...schema, type: [schema.type, 'null'] as SchemaObjectType[] },
zodRef.description ? { description: zodRef.description } : {},
...schemas
);
}

function parseDefault({
schemas,
zodRef,
Expand Down Expand Up @@ -523,6 +534,18 @@ function parsePipeline({
return generateSchema(zodRef._def.in, useOutput);
}

function parseReadonly({
zodRef,
useOutput,
schemas,
}: ParsingArgs<z.ZodReadonly<z.ZodAny>>): SchemaObject {
return merge(
generateSchema(zodRef._def.innerType, useOutput),
zodRef.description ? { description: zodRef.description } : {},
...schemas
);
}

const workerMap = {
ZodObject: parseObject,
ZodRecord: parseRecord,
Expand All @@ -532,8 +555,8 @@ const workerMap = {
ZodBoolean: parseBoolean,
ZodDate: parseDate,
ZodNull: parseNull,
ZodOptional: parseOptionalNullable,
ZodNullable: parseOptionalNullable,
ZodOptional: parseOptional,
ZodNullable: parseNullable,
ZodDefault: parseDefault,
ZodArray: parseArray,
ZodLiteral: parseLiteral,
Expand All @@ -558,6 +581,7 @@ const workerMap = {
ZodUnknown: catchAllParser,
ZodVoid: catchAllParser,
ZodPipeline: parsePipeline,
ZodReadonly: parseReadonly,
};
type WorkerKeys = keyof typeof workerMap;

Expand All @@ -567,10 +591,10 @@ export function generateSchema(
): SchemaObject {
const { metaOpenApi = {} } = zodRef;
const schemas = [
// todo: is this necessary?
zodRef.isNullable && zodRef.isNullable() ? { type: ['null'] } as SchemaObject : {},
...(Array.isArray(metaOpenApi) ? metaOpenApi : [metaOpenApi]),
];

try {
const typeName = zodRef._def.typeName as WorkerKeys;
if (typeName in workerMap) {
Expand Down

0 comments on commit 68bbd74

Please sign in to comment.