Skip to content

Commit

Permalink
fix: Support uniqueItems in Zod
Browse files Browse the repository at this point in the history
  • Loading branch information
stijnvanhulle committed Jan 22, 2025
1 parent c291bbf commit ce201f0
Show file tree
Hide file tree
Showing 9 changed files with 24 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-colts-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kubb/plugin-zod": patch
---

Support uniqueItems in Zod
3 changes: 3 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ title: Changelog

# Changelog

## 3.5.4
- [`plugin-zod`](/plugins/plugin-zod): Support uniqueItems in Zod

## 3.5.3
- [`plugin-client`](/plugins/plugin-client): allow exporting custom client fetch function and use generated fetch when `pluginClient` is available
- [`plugin-react-query`](/plugins/plugin-react-query/): allow exporting custom client fetch function and use generated fetch when `pluginClient` is available
Expand Down
1 change: 1 addition & 0 deletions examples/advanced/petStore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ paths:
application/json:
schema:
type: array
uniqueItems: true
minItems: 1
maxItems: 3
items:
Expand Down
2 changes: 1 addition & 1 deletion examples/advanced/src/gen/docs.html

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export type FindPetsByStatusPathParamsSchema = FindPetsByStatusPathParams
export const findPetsByStatus200Schema = z
.array(z.lazy(() => petSchema))
.min(1)
.max(3) as unknown as ToZod<FindPetsByStatus200>
.max(3)
.refine((items) => new Set(items).size === items.length, { message: 'Array entries must be unique' }) as unknown as ToZod<FindPetsByStatus200>

export type FindPetsByStatus200Schema = FindPetsByStatus200

Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-oas/src/SchemaGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ export class SchemaGenerator<
const min = schema.minimum ?? schema.minLength ?? schema.minItems ?? undefined
const max = schema.maximum ?? schema.maxLength ?? schema.maxItems ?? undefined
const items = this.parse({ schema: 'items' in schema ? (schema.items as SchemaObject) : [], name, parentName })
const unique = !!schema.uniqueItems

return [
{
Expand All @@ -865,6 +866,7 @@ export class SchemaGenerator<
items,
min,
max,
unique,
},
},
...baseItems.filter((item) => item.keyword !== schemaKeywords.min && item.keyword !== schemaKeywords.max),
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-oas/src/SchemaMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type SchemaKeywordMapper = {
tuple: { keyword: 'tuple'; args: { items: Schema[]; min?: number; max?: number } }
array: {
keyword: 'array'
args: { items: Schema[]; min?: number; max?: number }
args: { items: Schema[]; min?: number; max?: number; unique?: boolean }
}
enum: {
keyword: 'enum'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ exports[`SchemaGenerator core > 'Pets' 1`] = `
],
"max": undefined,
"min": undefined,
"unique": false,
},
"keyword": "array",
},
Expand Down
10 changes: 8 additions & 2 deletions packages/plugin-zod/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ const zodKeywordMapper = {
nullable: () => '.nullable()',
null: () => 'z.null()',
nullish: () => '.nullish()',
array: (items: string[] = [], min?: number, max?: number) => {
return [`z.array(${items?.join('')})`, min !== undefined ? `.min(${min})` : undefined, max !== undefined ? `.max(${max})` : undefined]
array: (items: string[] = [], min?: number, max?: number, unique?: boolean) => {
return [
`z.array(${items?.join('')})`,
min !== undefined ? `.min(${min})` : undefined,
max !== undefined ? `.max(${max})` : undefined,
unique ? `.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : undefined,
]
.filter(Boolean)
.join('')
},
Expand Down Expand Up @@ -226,6 +231,7 @@ export function parse({ parent, current, siblings }: SchemaTree, options: Parser
.filter(Boolean),
current.args.min,
current.args.max,
current.args.unique,
)
}

Expand Down

0 comments on commit ce201f0

Please sign in to comment.