Skip to content

Commit ccbb1cd

Browse files
committed
Add options for datetime into zod plugin
1 parent 93dad69 commit ccbb1cd

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

packages/openapi-ts/src/plugins/zod/plugin.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ const zIdentifier = compiler.identifier({ text: 'z' });
4040
const nameTransformer = (name: string) => `z-${name}`;
4141

4242
const arrayTypeToZodSchema = ({
43+
config,
4344
context,
4445
result,
4546
schema,
4647
}: {
48+
config: Omit<Config, 'name'>;
4749
context: IR.Context;
4850
result: Result;
4951
schema: SchemaWithType<'array'>;
@@ -73,6 +75,7 @@ const arrayTypeToZodSchema = ({
7375
// at least one item is guaranteed
7476
const itemExpressions = schema.items!.map((item) =>
7577
schemaToZodSchema({
78+
config,
7679
context,
7780
result,
7881
schema: item,
@@ -331,10 +334,12 @@ const numberTypeToZodSchema = ({
331334
};
332335

333336
const objectTypeToZodSchema = ({
337+
config,
334338
context,
335339
result,
336340
schema,
337341
}: {
342+
config: Omit<Config, 'name'>;
338343
context: IR.Context;
339344
result: Result;
340345
schema: SchemaWithType<'object'>;
@@ -353,6 +358,7 @@ const objectTypeToZodSchema = ({
353358
const isRequired = required.includes(name);
354359

355360
const propertyExpression = schemaToZodSchema({
361+
config,
356362
context,
357363
optional: !isRequired,
358364
result,
@@ -432,8 +438,10 @@ const objectTypeToZodSchema = ({
432438
};
433439

434440
const stringTypeToZodSchema = ({
441+
config,
435442
schema,
436443
}: {
444+
config: Omit<Config, 'name'>;
437445
context: IR.Context;
438446
schema: SchemaWithType<'string'>;
439447
}) => {
@@ -463,6 +471,11 @@ const stringTypeToZodSchema = ({
463471
expression: stringExpression,
464472
name: compiler.identifier({ text: 'datetime' }),
465473
}),
474+
parameters: [
475+
config.dateTimeOptions
476+
? JSON.stringify(config.dateTimeOptions)
477+
: undefined,
478+
],
466479
});
467480
break;
468481
case 'ipv4':
@@ -642,17 +655,20 @@ const voidTypeToZodSchema = ({
642655
};
643656

644657
const schemaTypeToZodSchema = ({
658+
config,
645659
context,
646660
result,
647661
schema,
648662
}: {
663+
config: Omit<Config, 'name'>;
649664
context: IR.Context;
650665
result: Result;
651666
schema: IR.SchemaObject;
652667
}): ts.Expression => {
653668
switch (schema.type as Required<IR.SchemaObject>['type']) {
654669
case 'array':
655670
return arrayTypeToZodSchema({
671+
config,
656672
context,
657673
result,
658674
schema: schema as SchemaWithType<'array'>,
@@ -685,12 +701,14 @@ const schemaTypeToZodSchema = ({
685701
});
686702
case 'object':
687703
return objectTypeToZodSchema({
704+
config,
688705
context,
689706
result,
690707
schema: schema as SchemaWithType<'object'>,
691708
});
692709
case 'string':
693710
return stringTypeToZodSchema({
711+
config,
694712
context,
695713
schema: schema as SchemaWithType<'string'>,
696714
});
@@ -718,10 +736,12 @@ const schemaTypeToZodSchema = ({
718736
};
719737

720738
const operationToZodSchema = ({
739+
config,
721740
context,
722741
operation,
723742
result,
724743
}: {
744+
config: Omit<Config, 'name'>;
725745
context: IR.Context;
726746
operation: IR.OperationObject;
727747
result: Result;
@@ -736,6 +756,7 @@ const operationToZodSchema = ({
736756
id: operation.id,
737757
type: 'response',
738758
}),
759+
config,
739760
context,
740761
result,
741762
schema: response,
@@ -746,6 +767,7 @@ const operationToZodSchema = ({
746767

747768
const schemaToZodSchema = ({
748769
$ref,
770+
config,
749771
context,
750772
optional,
751773
result,
@@ -755,6 +777,7 @@ const schemaToZodSchema = ({
755777
* When $ref is supplied, a node will be emitted to the file.
756778
*/
757779
$ref?: string;
780+
config: Omit<Config, 'name'>;
758781
context: IR.Context;
759782
/**
760783
* Accept `optional` to handle optional object properties. We can't handle
@@ -798,6 +821,7 @@ const schemaToZodSchema = ({
798821
if (!identifierRef.name) {
799822
const ref = context.resolveIrRef<IR.SchemaObject>(schema.$ref);
800823
expression = schemaToZodSchema({
824+
config,
801825
context,
802826
result,
803827
schema: ref,
@@ -836,6 +860,7 @@ const schemaToZodSchema = ({
836860
}
837861
} else if (schema.type) {
838862
expression = schemaTypeToZodSchema({
863+
config,
839864
context,
840865
result,
841866
schema,
@@ -846,6 +871,7 @@ const schemaToZodSchema = ({
846871
if (schema.items) {
847872
const itemTypes = schema.items.map((item) =>
848873
schemaToZodSchema({
874+
config,
849875
context,
850876
result,
851877
schema: item,
@@ -895,6 +921,7 @@ const schemaToZodSchema = ({
895921
}
896922
} else {
897923
expression = schemaToZodSchema({
924+
config,
898925
context,
899926
result,
900927
schema,
@@ -903,6 +930,7 @@ const schemaToZodSchema = ({
903930
} else {
904931
// catch-all fallback for failed schemas
905932
expression = schemaTypeToZodSchema({
933+
config,
906934
context,
907935
result,
908936
schema: {
@@ -982,13 +1010,18 @@ export const handler: Plugin.Handler<Config> = ({ context, plugin }) => {
9821010
name: 'z',
9831011
});
9841012

1013+
const config: Omit<Config, 'name'> = {
1014+
dateTimeOptions: plugin.dateTimeOptions,
1015+
};
1016+
9851017
context.subscribe('operation', ({ operation }) => {
9861018
const result: Result = {
9871019
circularReferenceTracker: new Set(),
9881020
hasCircularReference: false,
9891021
};
9901022

9911023
operationToZodSchema({
1024+
config,
9921025
context,
9931026
operation,
9941027
result,
@@ -1003,6 +1036,7 @@ export const handler: Plugin.Handler<Config> = ({ context, plugin }) => {
10031036

10041037
schemaToZodSchema({
10051038
$ref,
1039+
config,
10061040
context,
10071041
result,
10081042
schema,

packages/openapi-ts/src/plugins/zod/types.d.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
import type { Plugin } from '../types';
33

44
export interface Config extends Plugin.Name<'zod'> {
5+
/**
6+
* Zod options for the generated schema about datetimes.
7+
* https://zod.dev/?id=datetimes
8+
*/
9+
dateTimeOptions?: {
10+
local?: boolean;
11+
offset?: boolean;
12+
precision?: number;
13+
};
514
/**
615
* Should the exports from the generated files be re-exported in the index
716
* barrel file?
@@ -13,8 +22,8 @@ export interface Config extends Plugin.Name<'zod'> {
1322
* Customise the Zod schema name. By default, `z{{name}}` is used,
1423
* where `name` is a definition name or an operation name.
1524
*/
16-
// nameBuilder?: (model: IR.OperationObject | IR.SchemaObject) => string;
17-
/**
25+
// nameBuilder?: (model: IR.OperationObject | IR.SchemaObject) => string;
26+
/**
1827
* Name of the generated file.
1928
*
2029
* @default 'zod'

0 commit comments

Comments
 (0)