Skip to content

Commit b7bdcae

Browse files
committed
feat: adds buildApiForValibot()
1 parent 022f468 commit b7bdcae

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

src/directive.ts

+33
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,39 @@ export function buildApi(config: FormattedDirectiveConfig, directives: ReadonlyA
120120
.join('')
121121
}
122122

123+
// This function generates `[v.minLength(100), v.email()]`
124+
// NOTE: valibot's API is not a method chain, so it is prepared separately from buildApi.
125+
//
126+
// config
127+
// {
128+
// 'constraint': {
129+
// 'minLength': ['minLength', '$1'],
130+
// 'format': {
131+
// 'uri': ['url', '$2'],
132+
// 'email': ['email', '$2'],
133+
// }
134+
// }
135+
// }
136+
//
137+
// GraphQL schema
138+
// ```graphql
139+
// input ExampleInput {
140+
// email: String! @required(msg: "message") @constraint(minLength: 100, format: "email")
141+
// }
142+
// ```
143+
//
144+
// FIXME: v.required() is not supported yet. v.required() is classified as `Methods` and must wrap the schema. ex) `v.required(v.object({...}))`
145+
export function buildApiForValibot(config: FormattedDirectiveConfig, directives: ReadonlyArray<ConstDirectiveNode>): string[] {
146+
return directives
147+
.filter(directive => config[directive.name.value] !== undefined)
148+
.map((directive) => {
149+
const directiveName = directive.name.value;
150+
const argsConfig = config[directiveName];
151+
const apis = buildApiFromDirectiveArguments(argsConfig, directive.arguments ?? []);
152+
return apis.map((api) => `v${api}`);
153+
}).flat()
154+
}
155+
123156
function buildApiSchema(validationSchema: string[] | undefined, argValue: ConstValueNode): string {
124157
if (!validationSchema)
125158
return '';

tests/directive.spec.ts

+61
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
} from '../src/directive';
1010
import {
1111
buildApi,
12+
buildApiForValibot,
1213
exportedForTesting,
1314
formatDirectiveConfig,
1415
formatDirectiveObjectArguments,
@@ -603,4 +604,64 @@ describe('format directive config', () => {
603604
});
604605
}
605606
});
607+
608+
describe('buildApiForValibot', () => {
609+
const cases: {
610+
name: string
611+
args: {
612+
config: FormattedDirectiveConfig
613+
args: ReadonlyArray<ConstDirectiveNode>
614+
}
615+
want: string[]
616+
}[] = [
617+
{
618+
name: 'valid',
619+
args: {
620+
config: {
621+
constraint: {
622+
minLength: ['minLength', '$1'],
623+
format: {
624+
uri: ['url'],
625+
email: ['email'],
626+
},
627+
},
628+
},
629+
args: [
630+
// @constraint(minLength: 100, format: "email")
631+
buildConstDirectiveNodes('constraint', {
632+
minLength: `100`,
633+
format: `"email"`,
634+
}),
635+
],
636+
},
637+
want: [`v.minLength(100)`, `v.email()`],
638+
},
639+
{
640+
name: 'enum',
641+
args: {
642+
config: {
643+
constraint: {
644+
format: {
645+
URI: ['uri'],
646+
},
647+
},
648+
},
649+
args: [
650+
// @constraint(format: EMAIL)
651+
buildConstDirectiveNodes('constraint', {
652+
format: 'URI',
653+
}),
654+
],
655+
},
656+
want: [`v.uri()`],
657+
},
658+
];
659+
for (const tc of cases) {
660+
it(tc.name, () => {
661+
const { config, args } = tc.args;
662+
const got = buildApiForValibot(config, args);
663+
expect(got).toStrictEqual(tc.want);
664+
});
665+
}
666+
});
606667
});

0 commit comments

Comments
 (0)