Skip to content

Commit 7aa54a9

Browse files
committed
feat: support object type and union type
1 parent 48b2aa7 commit 7aa54a9

File tree

2 files changed

+447
-0
lines changed

2 files changed

+447
-0
lines changed

src/valibot/index.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ import type {
66
InputObjectTypeDefinitionNode,
77
InputValueDefinitionNode,
88
NameNode,
9+
ObjectTypeDefinitionNode,
910
TypeNode,
11+
UnionTypeDefinitionNode,
1012
} from 'graphql';
1113

1214
import type { ValidationSchemaPluginConfig } from '../config';
1315
import { BaseSchemaVisitor } from '../schema_visitor';
1416
import type { Visitor } from '../visitor';
1517
import { buildApiForValibot, formatDirectiveConfig } from '../directive';
1618
import {
19+
ObjectTypeDefinitionBuilder,
1720
isInput,
1821
isListType,
1922
isNamedType,
@@ -48,6 +51,41 @@ export class ValibotSchemaVisitor extends BaseSchemaVisitor {
4851
};
4952
}
5053

54+
get ObjectTypeDefinition() {
55+
return {
56+
leave: ObjectTypeDefinitionBuilder(this.config.withObjectType, (node: ObjectTypeDefinitionNode) => {
57+
const visitor = this.createVisitor('output');
58+
const name = visitor.convertName(node.name.value);
59+
this.importTypes.push(name);
60+
61+
// Building schema for field arguments.
62+
const argumentBlocks = this.buildTypeDefinitionArguments(node, visitor);
63+
const appendArguments = argumentBlocks ? `\n${argumentBlocks}` : '';
64+
65+
// Building schema for fields.
66+
const shape = node.fields?.map(field => generateFieldValibotSchema(this.config, visitor, field, 2)).join(',\n');
67+
68+
switch (this.config.validationSchemaExportType) {
69+
default:
70+
return (
71+
new DeclarationBlock({})
72+
.export()
73+
.asKind('function')
74+
.withName(`${name}Schema(): v.GenericSchema<${name}>`)
75+
.withBlock(
76+
[
77+
indent(`return v.object({`),
78+
indent(`__typename: v.optional(v.literal('${node.name.value}')),`, 2),
79+
shape,
80+
indent('})'),
81+
].join('\n'),
82+
).string + appendArguments
83+
);
84+
}
85+
}),
86+
};
87+
}
88+
5189
get EnumTypeDefinition() {
5290
return {
5391
leave: (node: EnumTypeDefinitionNode) => {
@@ -74,6 +112,42 @@ export class ValibotSchemaVisitor extends BaseSchemaVisitor {
74112
};
75113
}
76114

115+
get UnionTypeDefinition() {
116+
return {
117+
leave: (node: UnionTypeDefinitionNode) => {
118+
if (!node.types || !this.config.withObjectType)
119+
return;
120+
const visitor = this.createVisitor('output');
121+
const unionName = visitor.convertName(node.name.value);
122+
const unionElements = node.types
123+
.map((t) => {
124+
const element = visitor.convertName(t.name.value);
125+
const typ = visitor.getType(t.name.value);
126+
if (typ?.astNode?.kind === 'EnumTypeDefinition')
127+
return `${element}Schema`;
128+
129+
switch (this.config.validationSchemaExportType) {
130+
default:
131+
return `${element}Schema()`;
132+
}
133+
})
134+
.join(', ');
135+
const unionElementsCount = node.types.length ?? 0;
136+
137+
const union = unionElementsCount > 1 ? `v.union([${unionElements}])` : unionElements;
138+
139+
switch (this.config.validationSchemaExportType) {
140+
default:
141+
return new DeclarationBlock({})
142+
.export()
143+
.asKind('function')
144+
.withName(`${unionName}Schema()`)
145+
.withBlock(indent(`return ${union}`)).string;
146+
}
147+
},
148+
};
149+
}
150+
77151
protected buildInputFields(
78152
fields: readonly (FieldDefinitionNode | InputValueDefinitionNode)[],
79153
visitor: Visitor,
@@ -147,13 +221,17 @@ function generateNameNodeValibotSchema(config: ValidationSchemaPluginConfig, vis
147221

148222
switch (converter?.targetKind) {
149223
case 'InputObjectTypeDefinition':
224+
case 'ObjectTypeDefinition':
225+
case 'UnionTypeDefinition':
150226
// using switch-case rather than if-else to allow for future expansion
151227
switch (config.validationSchemaExportType) {
152228
default:
153229
return `${converter.convertName()}Schema()`;
154230
}
155231
case 'EnumTypeDefinition':
156232
return `${converter.convertName()}Schema`;
233+
case 'ScalarTypeDefinition':
234+
return valibot4Scalar(config, visitor, node.value);
157235
default:
158236
if (converter?.targetKind)
159237
console.warn('Unknown targetKind', converter?.targetKind);

0 commit comments

Comments
 (0)