diff --git a/.changeset/stale-sloths-jog.md b/.changeset/stale-sloths-jog.md new file mode 100644 index 0000000000..15b68966b3 --- /dev/null +++ b/.changeset/stale-sloths-jog.md @@ -0,0 +1,5 @@ +--- +'@hey-api/openapi-ts': patch +--- + +fix(zod): add `dates.local` option to allow unqualified (timezone-less) datetimes diff --git a/examples/openapi-ts-angular-common/angular.json b/examples/openapi-ts-angular-common/angular.json index 37516af293..6a2d352df6 100644 --- a/examples/openapi-ts-angular-common/angular.json +++ b/examples/openapi-ts-angular-common/angular.json @@ -88,5 +88,8 @@ } } } + }, + "cli": { + "analytics": false } } diff --git a/examples/openapi-ts-angular/angular.json b/examples/openapi-ts-angular/angular.json index 37516af293..6a2d352df6 100644 --- a/examples/openapi-ts-angular/angular.json +++ b/examples/openapi-ts-angular/angular.json @@ -88,5 +88,8 @@ } } } + }, + "cli": { + "analytics": false } } diff --git a/packages/openapi-ts/src/plugins/zod/config.ts b/packages/openapi-ts/src/plugins/zod/config.ts index 7fab2bb5fb..42a7f8b4e6 100644 --- a/packages/openapi-ts/src/plugins/zod/config.ts +++ b/packages/openapi-ts/src/plugins/zod/config.ts @@ -67,6 +67,7 @@ export const defaultConfig: ZodPlugin['Config'] = { plugin.config.dates = context.valueToObject({ defaultValue: { + local: false, offset: false, }, value: plugin.config.dates, diff --git a/packages/openapi-ts/src/plugins/zod/mini/plugin.ts b/packages/openapi-ts/src/plugins/zod/mini/plugin.ts index bc6549ddea..09b009671b 100644 --- a/packages/openapi-ts/src/plugins/zod/mini/plugin.ts +++ b/packages/openapi-ts/src/plugins/zod/mini/plugin.ts @@ -536,6 +536,15 @@ const stringTypeToZodSchema = ({ }), }); + const dateTimeOptions: { key: string; value: boolean }[] = []; + + if (plugin.config.dates.offset) { + dateTimeOptions.push({ key: 'offset', value: true }); + } + if (plugin.config.dates.local) { + dateTimeOptions.push({ key: 'local', value: true }); + } + if (schema.format) { switch (schema.format) { case 'date': @@ -558,18 +567,14 @@ const stringTypeToZodSchema = ({ }), name: identifiers.datetime, }), - parameters: plugin.config.dates.offset - ? [ - tsc.objectExpression({ - obj: [ - { - key: 'offset', - value: true, - }, - ], - }), - ] - : [], + parameters: + dateTimeOptions.length > 0 + ? [ + tsc.objectExpression({ + obj: dateTimeOptions, + }), + ] + : [], }); break; case 'email': diff --git a/packages/openapi-ts/src/plugins/zod/types.d.ts b/packages/openapi-ts/src/plugins/zod/types.d.ts index d293d71147..d1a9534ac2 100644 --- a/packages/openapi-ts/src/plugins/zod/types.d.ts +++ b/packages/openapi-ts/src/plugins/zod/types.d.ts @@ -33,6 +33,15 @@ export type UserConfig = Plugin.Name<'zod'> & { * date validation features. */ dates?: { + /** + * Whether to allow unqualified (timezone-less) datetimes: + * + * When enabled, Zod will accept datetime strings without timezone information. + * When disabled, Zod will require timezone information in datetime strings. + * + * @default false + */ + local?: boolean; /** * Whether to include timezone offset information when handling dates. * @@ -365,6 +374,15 @@ export type Config = Plugin.Name<'zod'> & { * date validation features. */ dates: { + /** + * Whether to allow unqualified (timezone-less) datetimes: + * + * When enabled, Zod will accept datetime strings without timezone information. + * When disabled, Zod will require timezone information in datetime strings. + * + * @default false + */ + local: boolean; /** * Whether to include timezone offset information when handling dates. * diff --git a/packages/openapi-ts/src/plugins/zod/v3/plugin.ts b/packages/openapi-ts/src/plugins/zod/v3/plugin.ts index fcd2412d3c..5172c6f429 100644 --- a/packages/openapi-ts/src/plugins/zod/v3/plugin.ts +++ b/packages/openapi-ts/src/plugins/zod/v3/plugin.ts @@ -449,6 +449,15 @@ const stringTypeToZodSchema = ({ }), }); + const dateTimeOptions: { key: string; value: boolean }[] = []; + + if (plugin.config.dates.offset) { + dateTimeOptions.push({ key: 'offset', value: true }); + } + if (plugin.config.dates.local) { + dateTimeOptions.push({ key: 'local', value: true }); + } + if (schema.format) { switch (schema.format) { case 'date': @@ -465,18 +474,14 @@ const stringTypeToZodSchema = ({ expression: stringExpression, name: identifiers.datetime, }), - parameters: plugin.config.dates.offset - ? [ - tsc.objectExpression({ - obj: [ - { - key: 'offset', - value: true, - }, - ], - }), - ] - : [], + parameters: + dateTimeOptions.length > 0 + ? [ + tsc.objectExpression({ + obj: dateTimeOptions, + }), + ] + : [], }); break; case 'email': diff --git a/packages/openapi-ts/src/plugins/zod/v4/plugin.ts b/packages/openapi-ts/src/plugins/zod/v4/plugin.ts index 4114a24801..3a33cb3025 100644 --- a/packages/openapi-ts/src/plugins/zod/v4/plugin.ts +++ b/packages/openapi-ts/src/plugins/zod/v4/plugin.ts @@ -515,6 +515,15 @@ const stringTypeToZodSchema = ({ }), }); + const dateTimeOptions: { key: string; value: boolean }[] = []; + + if (plugin.config.dates.offset) { + dateTimeOptions.push({ key: 'offset', value: true }); + } + if (plugin.config.dates.local) { + dateTimeOptions.push({ key: 'local', value: true }); + } + if (schema.format) { switch (schema.format) { case 'date': @@ -537,18 +546,14 @@ const stringTypeToZodSchema = ({ }), name: identifiers.datetime, }), - parameters: plugin.config.dates.offset - ? [ - tsc.objectExpression({ - obj: [ - { - key: 'offset', - value: true, - }, - ], - }), - ] - : [], + parameters: + dateTimeOptions.length > 0 + ? [ + tsc.objectExpression({ + obj: dateTimeOptions, + }), + ] + : [], }); break; case 'email':