@kubb/plugin-zod 3.0.0-alpha.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/LICENSE +21 -0
- package/README.md +44 -0
- package/dist/Operations-BlQtRP31.d.cts +47 -0
- package/dist/Operations-BlQtRP31.d.ts +47 -0
- package/dist/chunk-7IAXQL4T.cjs +1291 -0
- package/dist/chunk-7IAXQL4T.cjs.map +1 -0
- package/dist/chunk-OXCOZC6T.js +1291 -0
- package/dist/chunk-OXCOZC6T.js.map +1 -0
- package/dist/components.cjs +11 -0
- package/dist/components.cjs.map +1 -0
- package/dist/components.d.cts +28 -0
- package/dist/components.d.ts +28 -0
- package/dist/components.js +11 -0
- package/dist/components.js.map +1 -0
- package/dist/index.cjs +16 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +156 -0
- package/dist/index.d.ts +156 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/package.json +97 -0
- package/src/OperationGenerator.tsx +54 -0
- package/src/SchemaGenerator.tsx +31 -0
- package/src/components/OperationSchema.tsx +66 -0
- package/src/components/Operations.tsx +133 -0
- package/src/components/Schema.tsx +171 -0
- package/src/components/__snapshots__/operations.ts +50 -0
- package/src/components/index.ts +3 -0
- package/src/index.ts +15 -0
- package/src/parser/index.ts +345 -0
- package/src/plugin.ts +167 -0
- package/src/types.ts +151 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Oas } from '@kubb/plugin-oas/components'
|
|
2
|
+
import { Const, File, Type, useApp, useFile } from '@kubb/react'
|
|
3
|
+
import { pluginTsName } from '@kubb/plugin-ts'
|
|
4
|
+
|
|
5
|
+
import transformers from '@kubb/core/transformers'
|
|
6
|
+
import { isKeyword, schemaKeywords } from '@kubb/plugin-oas'
|
|
7
|
+
import { useSchema } from '@kubb/plugin-oas/hooks'
|
|
8
|
+
import type { ReactNode } from 'react'
|
|
9
|
+
import * as parserZod from '../parser/index.ts'
|
|
10
|
+
import { pluginZodName } from '../plugin.ts'
|
|
11
|
+
import type { PluginZod } from '../types.ts'
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
description?: string
|
|
15
|
+
withTypeAnnotation?: boolean
|
|
16
|
+
keysToOmit?: string[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function Schema(props: Props): ReactNode {
|
|
20
|
+
const { keysToOmit, withTypeAnnotation, description } = props
|
|
21
|
+
const { tree, name } = useSchema()
|
|
22
|
+
const {
|
|
23
|
+
pluginManager,
|
|
24
|
+
plugin: {
|
|
25
|
+
options: { mapper, typedSchema, coercion },
|
|
26
|
+
},
|
|
27
|
+
} = useApp<PluginZod>()
|
|
28
|
+
|
|
29
|
+
// all checks are also inside this.schema(React)
|
|
30
|
+
const resolvedName = pluginManager.resolveName({
|
|
31
|
+
name,
|
|
32
|
+
pluginKey: [pluginZodName],
|
|
33
|
+
type: 'function',
|
|
34
|
+
})
|
|
35
|
+
const resolvedTypeName = pluginManager.resolveName({
|
|
36
|
+
name,
|
|
37
|
+
pluginKey: [pluginZodName],
|
|
38
|
+
type: 'type',
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const typeName = pluginManager.resolveName({
|
|
42
|
+
name,
|
|
43
|
+
pluginKey: [pluginTsName],
|
|
44
|
+
type: 'type',
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
if (!tree.length) {
|
|
48
|
+
return (
|
|
49
|
+
<Const
|
|
50
|
+
name={resolvedName}
|
|
51
|
+
export
|
|
52
|
+
JSDoc={{
|
|
53
|
+
comments: [description ? `@description ${transformers.jsStringEscape(description)}` : undefined].filter(Boolean),
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
undefined
|
|
57
|
+
</Const>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const hasTuple = tree.some((item) => isKeyword(item, schemaKeywords.tuple))
|
|
62
|
+
|
|
63
|
+
const output = parserZod
|
|
64
|
+
.sort(tree)
|
|
65
|
+
.filter((item) => {
|
|
66
|
+
if (hasTuple && (isKeyword(item, schemaKeywords.min) || isKeyword(item, schemaKeywords.max))) {
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return true
|
|
71
|
+
})
|
|
72
|
+
.map((item) => parserZod.parse(undefined, item, { name, typeName, description, mapper, coercion, keysToOmit }))
|
|
73
|
+
.filter(Boolean)
|
|
74
|
+
.join('')
|
|
75
|
+
|
|
76
|
+
const suffix = output.endsWith('.nullable()') ? '.unwrap().and' : '.and'
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<>
|
|
80
|
+
<Const
|
|
81
|
+
export
|
|
82
|
+
name={resolvedName}
|
|
83
|
+
JSDoc={{
|
|
84
|
+
comments: [description ? `@description ${transformers.jsStringEscape(description)}` : undefined].filter(Boolean),
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
{[
|
|
88
|
+
output,
|
|
89
|
+
keysToOmit?.length ? `${suffix}(z.object({ ${keysToOmit.map((key) => `${key}: z.never()`).join(',')} }))` : undefined,
|
|
90
|
+
withTypeAnnotation && typeName ? ` as z.ZodType<${typeName}>` : '',
|
|
91
|
+
]
|
|
92
|
+
.filter(Boolean)
|
|
93
|
+
.join('') || ''}
|
|
94
|
+
</Const>
|
|
95
|
+
{typedSchema && (
|
|
96
|
+
<Type export name={resolvedTypeName}>
|
|
97
|
+
{`z.infer<typeof ${resolvedName}>`}
|
|
98
|
+
</Type>
|
|
99
|
+
)}
|
|
100
|
+
</>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
type FileProps = {}
|
|
105
|
+
|
|
106
|
+
Schema.File = function ({}: FileProps): ReactNode {
|
|
107
|
+
const {
|
|
108
|
+
pluginManager,
|
|
109
|
+
plugin: {
|
|
110
|
+
options: { typed },
|
|
111
|
+
},
|
|
112
|
+
} = useApp<PluginZod>()
|
|
113
|
+
const { tree, schema } = useSchema()
|
|
114
|
+
|
|
115
|
+
const withData = tree.some(
|
|
116
|
+
(schema) =>
|
|
117
|
+
schema.keyword === schemaKeywords.array ||
|
|
118
|
+
schema.keyword === schemaKeywords.and ||
|
|
119
|
+
schema.keyword === schemaKeywords.object ||
|
|
120
|
+
schema.keyword === schemaKeywords.union ||
|
|
121
|
+
schema.keyword === schemaKeywords.tuple,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
const withTypeAnnotation = !!typed
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<Oas.Schema.File output={pluginManager.config.output.path}>
|
|
128
|
+
<Schema.Imports />
|
|
129
|
+
<File.Source>
|
|
130
|
+
<Schema withTypeAnnotation={withTypeAnnotation} description={schema?.description} />
|
|
131
|
+
</File.Source>
|
|
132
|
+
</Oas.Schema.File>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
Schema.Imports = (): ReactNode => {
|
|
136
|
+
const {
|
|
137
|
+
pluginManager,
|
|
138
|
+
plugin: {
|
|
139
|
+
options: { typed, importPath },
|
|
140
|
+
},
|
|
141
|
+
} = useApp<PluginZod>()
|
|
142
|
+
const { path: root } = useFile()
|
|
143
|
+
const { name, tree, schema } = useSchema()
|
|
144
|
+
|
|
145
|
+
// used for this.options.typed
|
|
146
|
+
const typeName = pluginManager.resolveName({
|
|
147
|
+
name,
|
|
148
|
+
pluginKey: [pluginTsName],
|
|
149
|
+
type: 'type',
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
const typeFileName = pluginManager.resolveName({
|
|
153
|
+
name: name,
|
|
154
|
+
pluginKey: [pluginTsName],
|
|
155
|
+
type: 'file',
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
const typePath = pluginManager.resolvePath({
|
|
159
|
+
baseName: typeFileName,
|
|
160
|
+
pluginKey: [pluginTsName],
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const withTypeAnnotation = !!typed
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<>
|
|
167
|
+
<File.Import name={['z']} path={importPath} />
|
|
168
|
+
{withTypeAnnotation && typeName && typePath && <File.Import isTypeOnly root={root} path={typePath} name={[typeName]} />}
|
|
169
|
+
</>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const operations = {
|
|
2
|
+
'get_pets-pet-id': {
|
|
3
|
+
request: undefined,
|
|
4
|
+
parameters: {
|
|
5
|
+
path: undefined,
|
|
6
|
+
query: undefined,
|
|
7
|
+
header: undefined,
|
|
8
|
+
},
|
|
9
|
+
responses: {
|
|
10
|
+
200: GetPetsPetIdQueryResponse,
|
|
11
|
+
default: GetPetsPetIdQueryResponse,
|
|
12
|
+
},
|
|
13
|
+
errors: {},
|
|
14
|
+
},
|
|
15
|
+
listPets: {
|
|
16
|
+
request: undefined,
|
|
17
|
+
parameters: {
|
|
18
|
+
path: undefined,
|
|
19
|
+
query: ListPetsQueryParams,
|
|
20
|
+
header: undefined,
|
|
21
|
+
},
|
|
22
|
+
responses: {
|
|
23
|
+
200: ListPetsQueryResponse,
|
|
24
|
+
default: ListPetsQueryResponse,
|
|
25
|
+
},
|
|
26
|
+
errors: {},
|
|
27
|
+
},
|
|
28
|
+
createPets: {
|
|
29
|
+
request: CreatePetsMutationRequest,
|
|
30
|
+
parameters: {
|
|
31
|
+
path: undefined,
|
|
32
|
+
query: undefined,
|
|
33
|
+
header: undefined,
|
|
34
|
+
},
|
|
35
|
+
responses: {
|
|
36
|
+
201: CreatePetsMutationResponse,
|
|
37
|
+
default: CreatePetsMutationResponse,
|
|
38
|
+
},
|
|
39
|
+
errors: {},
|
|
40
|
+
},
|
|
41
|
+
} as const
|
|
42
|
+
export const paths = {
|
|
43
|
+
'/pets/{pet_id}': {
|
|
44
|
+
get: operations['get_pets-pet-id'],
|
|
45
|
+
},
|
|
46
|
+
'/pets': {
|
|
47
|
+
get: operations['listPets'],
|
|
48
|
+
post: operations['createPets'],
|
|
49
|
+
},
|
|
50
|
+
} as const
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { pluginZod } from './plugin.ts'
|
|
2
|
+
|
|
3
|
+
export { pluginZod, pluginZodName } from './plugin.ts'
|
|
4
|
+
export type { PluginZod } from './types.ts'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated Use `import { pluginZod } from '@kubb/plugin-zod'` instead
|
|
8
|
+
*/
|
|
9
|
+
const definePluginDefault = pluginZod
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated Use `import { pluginZod } from '@kubb/plugin-zod'` instead
|
|
12
|
+
*/
|
|
13
|
+
export const definePlugin = pluginZod
|
|
14
|
+
|
|
15
|
+
export default definePluginDefault
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import transformers, { createJSDocBlockText } from '@kubb/core/transformers'
|
|
2
|
+
import { type SchemaKeywordMapper, isKeyword, schemaKeywords } from '@kubb/plugin-oas'
|
|
3
|
+
|
|
4
|
+
import type { Schema, SchemaKeywordBase, SchemaMapper } from '@kubb/plugin-oas'
|
|
5
|
+
|
|
6
|
+
export const zodKeywordMapper = {
|
|
7
|
+
any: () => 'z.any()',
|
|
8
|
+
unknown: () => 'z.unknown()',
|
|
9
|
+
number: (coercion?: boolean, min?: number, max?: number) => {
|
|
10
|
+
return [coercion ? 'z.coerce.number()' : 'z.number()', min !== undefined ? `.min(${min})` : undefined, max !== undefined ? `.max(${max})` : undefined]
|
|
11
|
+
.filter(Boolean)
|
|
12
|
+
.join('')
|
|
13
|
+
},
|
|
14
|
+
integer: (coercion?: boolean, min?: number, max?: number) => {
|
|
15
|
+
return [coercion ? 'z.coerce.number()' : 'z.number()', min !== undefined ? `.min(${min})` : undefined, max !== undefined ? `.max(${max})` : undefined]
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.join('')
|
|
18
|
+
},
|
|
19
|
+
object: (value?: string) => `z.object({${value}})`,
|
|
20
|
+
string: (coercion?: boolean, min?: number, max?: number) => {
|
|
21
|
+
return [coercion ? 'z.coerce.string()' : 'z.string()', min !== undefined ? `.min(${min})` : undefined, max !== undefined ? `.max(${max})` : undefined]
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.join('')
|
|
24
|
+
},
|
|
25
|
+
boolean: () => 'z.boolean()',
|
|
26
|
+
undefined: () => 'z.undefined()',
|
|
27
|
+
nullable: () => '.nullable()',
|
|
28
|
+
null: () => 'z.null()',
|
|
29
|
+
nullish: () => '.nullish()',
|
|
30
|
+
array: (items: string[] = [], min?: number, max?: number) => {
|
|
31
|
+
return [`z.array(${items?.join('')})`, min !== undefined ? `.min(${min})` : undefined, max !== undefined ? `.max(${max})` : undefined]
|
|
32
|
+
.filter(Boolean)
|
|
33
|
+
.join('')
|
|
34
|
+
},
|
|
35
|
+
tuple: (items: string[] = []) => `z.tuple([${items?.join(', ')}])`,
|
|
36
|
+
enum: (items: string[] = []) => `z.enum([${items?.join(', ')}])`,
|
|
37
|
+
union: (items: string[] = []) => `z.union([${items?.join(', ')}])`,
|
|
38
|
+
const: (value?: string | number) => `z.literal(${value ?? ''})`,
|
|
39
|
+
/**
|
|
40
|
+
* ISO 8601
|
|
41
|
+
*/
|
|
42
|
+
datetime: (offset = false, local = false) => {
|
|
43
|
+
if (offset) {
|
|
44
|
+
return `z.string().datetime({ offset: ${offset} })`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (local) {
|
|
48
|
+
return `z.string().datetime({ local: ${local} })`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return 'z.string().datetime()'
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Type `'date'` Date
|
|
55
|
+
* Type `'string'` ISO date format (YYYY-MM-DD)
|
|
56
|
+
* @default ISO date format (YYYY-MM-DD)
|
|
57
|
+
*/
|
|
58
|
+
date: (type: 'date' | 'string' = 'string', coercion?: boolean) => {
|
|
59
|
+
if (type === 'string') {
|
|
60
|
+
return 'z.string().date()'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (coercion) {
|
|
64
|
+
return 'z.coerce.date()'
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return 'z.date()'
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* Type `'date'` Date
|
|
71
|
+
* Type `'string'` ISO time format (HH:mm:ss[.SSSSSS])
|
|
72
|
+
* @default ISO time format (HH:mm:ss[.SSSSSS])
|
|
73
|
+
*/
|
|
74
|
+
time: (type: 'date' | 'string' = 'string', coercion?: boolean) => {
|
|
75
|
+
if (type === 'string') {
|
|
76
|
+
return 'z.string().time()'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (coercion) {
|
|
80
|
+
return 'z.coerce.date()'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return 'z.date()'
|
|
84
|
+
},
|
|
85
|
+
uuid: () => '.uuid()',
|
|
86
|
+
url: () => '.url()',
|
|
87
|
+
strict: () => '.strict()',
|
|
88
|
+
default: (value?: string | number | true) => `.default(${value ?? ''})`,
|
|
89
|
+
and: (items: string[] = []) => items?.map((item) => `.and(${item})`).join(''),
|
|
90
|
+
describe: (value = '') => `.describe(${value})`,
|
|
91
|
+
min: (value?: number) => `.min(${value ?? ''})`,
|
|
92
|
+
max: (value?: number) => `.max(${value ?? ''})`,
|
|
93
|
+
optional: () => '.optional()',
|
|
94
|
+
matches: (value = '') => `.regex(${value})`,
|
|
95
|
+
email: () => '.email()',
|
|
96
|
+
firstName: undefined,
|
|
97
|
+
lastName: undefined,
|
|
98
|
+
password: undefined,
|
|
99
|
+
phone: undefined,
|
|
100
|
+
readOnly: undefined,
|
|
101
|
+
ref: (value?: string) => (value ? `z.lazy(() => ${value})` : undefined),
|
|
102
|
+
blob: () => 'z.string()',
|
|
103
|
+
deprecated: undefined,
|
|
104
|
+
example: undefined,
|
|
105
|
+
schema: undefined,
|
|
106
|
+
catchall: (value?: string) => (value ? `.catchall(${value})` : undefined),
|
|
107
|
+
name: undefined,
|
|
108
|
+
} satisfies SchemaMapper<string | null | undefined>
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @link based on https://github.com/cellular/oazapfts/blob/7ba226ebb15374e8483cc53e7532f1663179a22c/src/codegen/generate.ts#L398
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
export function sort(items?: Schema[]): Schema[] {
|
|
115
|
+
const order: string[] = [
|
|
116
|
+
schemaKeywords.string,
|
|
117
|
+
schemaKeywords.datetime,
|
|
118
|
+
schemaKeywords.date,
|
|
119
|
+
schemaKeywords.time,
|
|
120
|
+
schemaKeywords.tuple,
|
|
121
|
+
schemaKeywords.number,
|
|
122
|
+
schemaKeywords.object,
|
|
123
|
+
schemaKeywords.enum,
|
|
124
|
+
schemaKeywords.url,
|
|
125
|
+
schemaKeywords.email,
|
|
126
|
+
schemaKeywords.firstName,
|
|
127
|
+
schemaKeywords.lastName,
|
|
128
|
+
schemaKeywords.password,
|
|
129
|
+
schemaKeywords.matches,
|
|
130
|
+
schemaKeywords.uuid,
|
|
131
|
+
schemaKeywords.min,
|
|
132
|
+
schemaKeywords.max,
|
|
133
|
+
schemaKeywords.default,
|
|
134
|
+
schemaKeywords.describe,
|
|
135
|
+
schemaKeywords.optional,
|
|
136
|
+
schemaKeywords.nullable,
|
|
137
|
+
schemaKeywords.nullish,
|
|
138
|
+
schemaKeywords.null,
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
if (!items) {
|
|
142
|
+
return []
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return transformers.orderBy(items, [(v) => order.indexOf(v.keyword)], ['asc'])
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
type ParserOptions = {
|
|
149
|
+
name: string
|
|
150
|
+
typeName?: string
|
|
151
|
+
description?: string
|
|
152
|
+
|
|
153
|
+
keysToOmit?: string[]
|
|
154
|
+
mapper?: Record<string, string>
|
|
155
|
+
coercion?: boolean
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function parse(parent: Schema | undefined, current: Schema, options: ParserOptions): string | undefined {
|
|
159
|
+
const value = zodKeywordMapper[current.keyword as keyof typeof zodKeywordMapper]
|
|
160
|
+
|
|
161
|
+
if (!value) {
|
|
162
|
+
return undefined
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (isKeyword(current, schemaKeywords.union)) {
|
|
166
|
+
// zod union type needs at least 2 items
|
|
167
|
+
if (Array.isArray(current.args) && current.args.length === 1) {
|
|
168
|
+
return parse(parent, current.args[0] as Schema, options)
|
|
169
|
+
}
|
|
170
|
+
if (Array.isArray(current.args) && !current.args.length) {
|
|
171
|
+
return ''
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return zodKeywordMapper.union(
|
|
175
|
+
sort(current.args)
|
|
176
|
+
.map((schema) => parse(current, schema, options))
|
|
177
|
+
.filter(Boolean),
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (isKeyword(current, schemaKeywords.and)) {
|
|
182
|
+
const items = sort(current.args)
|
|
183
|
+
.filter((schema: Schema) => {
|
|
184
|
+
return ![schemaKeywords.optional, schemaKeywords.describe].includes(schema.keyword as typeof schemaKeywords.describe)
|
|
185
|
+
})
|
|
186
|
+
.map((schema: Schema) => parse(current, schema, options))
|
|
187
|
+
.filter(Boolean)
|
|
188
|
+
|
|
189
|
+
return `${items.slice(0, 1)}${zodKeywordMapper.and(items.slice(1))}`
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (isKeyword(current, schemaKeywords.array)) {
|
|
193
|
+
return zodKeywordMapper.array(
|
|
194
|
+
sort(current.args.items)
|
|
195
|
+
.map((schemas) => parse(current, schemas, options))
|
|
196
|
+
.filter(Boolean),
|
|
197
|
+
current.args.min,
|
|
198
|
+
current.args.max,
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (isKeyword(current, schemaKeywords.enum)) {
|
|
203
|
+
if (current.args.asConst) {
|
|
204
|
+
return zodKeywordMapper.union(
|
|
205
|
+
current.args.items
|
|
206
|
+
.map((schema) => {
|
|
207
|
+
return parse(
|
|
208
|
+
current,
|
|
209
|
+
{
|
|
210
|
+
keyword: schemaKeywords.const,
|
|
211
|
+
args: schema,
|
|
212
|
+
},
|
|
213
|
+
options,
|
|
214
|
+
)
|
|
215
|
+
})
|
|
216
|
+
.filter(Boolean),
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return zodKeywordMapper.enum(
|
|
221
|
+
current.args.items.map((schema) => {
|
|
222
|
+
if (schema.format === 'number') {
|
|
223
|
+
return transformers.stringify(schema.value)
|
|
224
|
+
}
|
|
225
|
+
return transformers.stringify(schema.value)
|
|
226
|
+
}),
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (isKeyword(current, schemaKeywords.ref)) {
|
|
231
|
+
return zodKeywordMapper.ref(current.args?.name)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (isKeyword(current, schemaKeywords.object)) {
|
|
235
|
+
const properties = Object.entries(current.args?.properties || {})
|
|
236
|
+
.filter((item) => {
|
|
237
|
+
const schema = item[1]
|
|
238
|
+
return schema && typeof schema.map === 'function'
|
|
239
|
+
})
|
|
240
|
+
.map(([name, schemas]) => {
|
|
241
|
+
const nameSchema = schemas.find((schema) => schema.keyword === schemaKeywords.name) as SchemaKeywordMapper['name']
|
|
242
|
+
const mappedName = nameSchema?.args || name
|
|
243
|
+
|
|
244
|
+
// custom mapper(pluginOptions)
|
|
245
|
+
if (options.mapper?.[mappedName]) {
|
|
246
|
+
return `"${name}": ${options.mapper?.[mappedName]}`
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return `"${name}": ${sort(schemas)
|
|
250
|
+
.map((schema, array) => {
|
|
251
|
+
return parse(current, schema, options)
|
|
252
|
+
})
|
|
253
|
+
.filter(Boolean)
|
|
254
|
+
.join('')}`
|
|
255
|
+
})
|
|
256
|
+
.join(',')
|
|
257
|
+
|
|
258
|
+
const additionalProperties = current.args?.additionalProperties?.length
|
|
259
|
+
? current.args.additionalProperties
|
|
260
|
+
.map((schema) => parse(current, schema, options))
|
|
261
|
+
.filter(Boolean)
|
|
262
|
+
.at(0)
|
|
263
|
+
: undefined
|
|
264
|
+
|
|
265
|
+
const text = [
|
|
266
|
+
zodKeywordMapper.object(properties),
|
|
267
|
+
current.args?.strict ? zodKeywordMapper.strict() : undefined,
|
|
268
|
+
additionalProperties ? zodKeywordMapper.catchall(additionalProperties) : undefined,
|
|
269
|
+
].filter(Boolean)
|
|
270
|
+
|
|
271
|
+
return text.join('')
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (isKeyword(current, schemaKeywords.tuple)) {
|
|
275
|
+
return zodKeywordMapper.tuple(
|
|
276
|
+
sort(current.args.items)
|
|
277
|
+
.map((schema) => parse(current, schema, options))
|
|
278
|
+
.filter(Boolean),
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (isKeyword(current, schemaKeywords.const)) {
|
|
283
|
+
if (current.args.format === 'number' && current.args.value !== undefined) {
|
|
284
|
+
return zodKeywordMapper.const(Number.parseInt(current.args.value?.toString()))
|
|
285
|
+
}
|
|
286
|
+
return zodKeywordMapper.const(transformers.stringify(current.args.value))
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (isKeyword(current, schemaKeywords.matches)) {
|
|
290
|
+
if (current.args) {
|
|
291
|
+
return zodKeywordMapper.matches(transformers.toRegExpString(current.args))
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (isKeyword(current, schemaKeywords.default)) {
|
|
296
|
+
if (current.args) {
|
|
297
|
+
return zodKeywordMapper.default(current.args)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (isKeyword(current, schemaKeywords.describe)) {
|
|
302
|
+
if (current.args) {
|
|
303
|
+
return zodKeywordMapper.describe(transformers.stringify(current.args.toString()))
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (isKeyword(current, schemaKeywords.string)) {
|
|
308
|
+
return zodKeywordMapper.string(options.coercion)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (isKeyword(current, schemaKeywords.number) || isKeyword(current, schemaKeywords.integer)) {
|
|
312
|
+
return zodKeywordMapper.number(options.coercion)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (isKeyword(current, schemaKeywords.min)) {
|
|
316
|
+
return zodKeywordMapper.min(current.args)
|
|
317
|
+
}
|
|
318
|
+
if (isKeyword(current, schemaKeywords.max)) {
|
|
319
|
+
return zodKeywordMapper.max(current.args)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (isKeyword(current, schemaKeywords.datetime)) {
|
|
323
|
+
return zodKeywordMapper.datetime(current.args.offset, current.args.local)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (isKeyword(current, schemaKeywords.date)) {
|
|
327
|
+
return zodKeywordMapper.date(current.args.type, options.coercion)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (isKeyword(current, schemaKeywords.time)) {
|
|
331
|
+
return zodKeywordMapper.time(current.args.type, options.coercion)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (current.keyword in zodKeywordMapper && 'args' in current) {
|
|
335
|
+
const value = zodKeywordMapper[current.keyword as keyof typeof zodKeywordMapper] as (typeof zodKeywordMapper)['const']
|
|
336
|
+
|
|
337
|
+
return value((current as SchemaKeywordBase<unknown>).args as any)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (current.keyword in zodKeywordMapper) {
|
|
341
|
+
return value()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return undefined
|
|
345
|
+
}
|