Skip to content

Commit 02e5991

Browse files
authored
Merge pull request #3509 from hey-api/refactor/valibot-union-intersection
refactor: extract valibot union and intersection handler
2 parents e96c2e2 + 104b18d commit 02e5991

3 files changed

Lines changed: 107 additions & 29 deletions

File tree

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { IR } from '@hey-api/shared';
2+
3+
import { $ } from '../../../../ts-dsl';
4+
import type { Pipes } from '../../shared/pipes';
5+
import { pipesToNode } from '../../shared/pipes';
6+
import type { CompositeHandlerResult, ValibotFinal, ValibotResult } from '../../shared/types';
7+
import type { ValibotPlugin } from '../../types';
8+
import { identifiers } from '../constants';
9+
10+
interface IntersectionToPipesContext {
11+
applyModifiers: (result: ValibotResult, options?: { optional?: boolean }) => ValibotFinal;
12+
childResults: Array<ValibotResult>;
13+
parentSchema: IR.SchemaObject;
14+
plugin: ValibotPlugin['Instance'];
15+
}
16+
17+
export function intersectionToPipes(ctx: IntersectionToPipesContext): CompositeHandlerResult {
18+
const { applyModifiers, childResults, plugin } = ctx;
19+
20+
const v = plugin.external('valibot.v');
21+
let pipes: Pipes;
22+
23+
if (childResults.length === 0) {
24+
pipes = [$(v).attr(identifiers.schemas.any).call()];
25+
} else if (childResults.length === 1) {
26+
const finalResult = applyModifiers(childResults[0]!);
27+
pipes = finalResult.pipes;
28+
} else {
29+
const itemNodes = childResults.map((item) => pipesToNode(item.pipes, plugin));
30+
pipes = [
31+
$(v)
32+
.attr(identifiers.schemas.intersect)
33+
.call($.array(...itemNodes)),
34+
];
35+
}
36+
37+
return { childResults, pipes };
38+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import type { IR } from '@hey-api/shared';
2+
3+
import { $ } from '../../../../ts-dsl';
4+
import type { Pipes } from '../../shared/pipes';
5+
import { pipesToNode } from '../../shared/pipes';
6+
import type { CompositeHandlerResult, ValibotFinal, ValibotResult } from '../../shared/types';
7+
import type { ValibotPlugin } from '../../types';
8+
import { identifiers } from '../constants';
9+
10+
interface UnionToPipesContext {
11+
applyModifiers: (result: ValibotResult, options?: { optional?: boolean }) => ValibotFinal;
12+
childResults: Array<ValibotResult>;
13+
parentSchema: IR.SchemaObject;
14+
plugin: ValibotPlugin['Instance'];
15+
schemas: ReadonlyArray<IR.SchemaObject>;
16+
}
17+
18+
export function unionToPipes(ctx: UnionToPipesContext): CompositeHandlerResult {
19+
const { childResults, plugin, schemas } = ctx;
20+
21+
const nonNullItems: Array<ValibotResult> = [];
22+
childResults.forEach((item, index) => {
23+
const schema = schemas[index]!;
24+
if (schema.type !== 'null') {
25+
nonNullItems.push(item);
26+
}
27+
});
28+
29+
const v = plugin.external('valibot.v');
30+
let pipes: Pipes;
31+
32+
if (nonNullItems.length === 0) {
33+
pipes = [$(v).attr(identifiers.schemas.null).call()];
34+
} else if (nonNullItems.length === 1) {
35+
pipes = nonNullItems[0]!.pipes;
36+
} else {
37+
const itemNodes = nonNullItems.map((i) => pipesToNode(i.pipes, plugin));
38+
pipes = [
39+
$(v)
40+
.attr(identifiers.schemas.union)
41+
.call($.array(...itemNodes)),
42+
];
43+
}
44+
45+
return {
46+
childResults,
47+
pipes,
48+
};
49+
}

packages/openapi-ts/src/plugins/valibot/v1/walker.ts

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import { identifiers } from './constants';
1515
import { arrayToPipes } from './toAst/array';
1616
import { booleanToPipes } from './toAst/boolean';
1717
import { enumToPipes } from './toAst/enum';
18+
import { intersectionToPipes } from './toAst/intersection';
1819
import { neverToPipes } from './toAst/never';
1920
import { nullToPipes } from './toAst/null';
2021
import { numberToPipes } from './toAst/number';
2122
import { objectToPipes } from './toAst/object';
2223
import { stringToPipes } from './toAst/string';
2324
import { tupleToPipes } from './toAst/tuple';
2425
import { undefinedToPipes } from './toAst/undefined';
26+
import { unionToPipes } from './toAst/union';
2527
import { unknownToPipes } from './toAst/unknown';
2628
import { voidToPipes } from './toAst/void';
2729

@@ -143,16 +145,19 @@ export function createVisitor(
143145
}
144146
},
145147
intersection(items, schemas, parentSchema, ctx) {
146-
const v = ctx.plugin.external('valibot.v');
147-
const itemNodes = items.map((item) => pipesToNode(item.pipes, ctx.plugin));
148+
const applyModifiers = (result: ValibotResult, opts?: { optional?: boolean }) =>
149+
this.applyModifiers(result, ctx, opts) as ValibotFinal;
150+
151+
const { pipes } = intersectionToPipes({
152+
applyModifiers,
153+
childResults: items,
154+
parentSchema,
155+
plugin: ctx.plugin,
156+
});
148157

149158
return {
150159
meta: composeMeta(items, { default: parentSchema.default }),
151-
pipes: [
152-
$(v)
153-
.attr(identifiers.schemas.intersect)
154-
.call($.array(...itemNodes)),
155-
],
160+
pipes,
156161
};
157162
},
158163
never(schema, ctx) {
@@ -290,33 +295,19 @@ export function createVisitor(
290295
};
291296
},
292297
union(items, schemas, parentSchema, ctx) {
293-
const v = ctx.plugin.external('valibot.v');
298+
const applyModifiers = (result: ValibotResult, opts?: { optional?: boolean }) =>
299+
this.applyModifiers(result, ctx, opts) as ValibotFinal;
294300

295301
const hasNull = schemas.some((s) => s.type === 'null') || items.some((i) => i.meta.nullable);
296302

297-
const nonNullItems: Array<ValibotResult> = [];
298-
items.forEach((item, index) => {
299-
const schema = schemas[index]!;
300-
if (schema.type !== 'null') {
301-
nonNullItems.push(item);
302-
}
303+
const { pipes } = unionToPipes({
304+
applyModifiers,
305+
childResults: items,
306+
parentSchema,
307+
plugin: ctx.plugin,
308+
schemas,
303309
});
304310

305-
let pipes: Pipes;
306-
307-
if (nonNullItems.length === 0) {
308-
pipes = [$(v).attr(identifiers.schemas.null).call()];
309-
} else if (nonNullItems.length === 1) {
310-
pipes = nonNullItems[0]!.pipes;
311-
} else {
312-
const itemNodes = nonNullItems.map((i) => pipesToNode(i.pipes, ctx.plugin));
313-
pipes = [
314-
$(v)
315-
.attr(identifiers.schemas.union)
316-
.call($.array(...itemNodes)),
317-
];
318-
}
319-
320311
return {
321312
meta: composeMeta(items, {
322313
default: parentSchema.default,

0 commit comments

Comments
 (0)