Skip to content

Commit

Permalink
feat: Add support intersect (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
chimame authored Feb 10, 2024
1 parent 6d259df commit 806a54e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
18 changes: 17 additions & 1 deletion coercion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { WrapSchema, AllSchema, ObjectSchema } from "./types/schema";
import {
type VariantOptions,
type TupleItems,
type BaseSchema,
type IntersectOptions,
coerce,
} from "valibot";

Expand Down Expand Up @@ -278,6 +278,22 @@ export function enableTypeCoercion<Type extends AllSchema,>(
: schema,
(output) => coerceString(output),
);
} else if (type.type === "intersect") {
schema = {
...type,
options: type.options.map((item) =>
enableTypeCoercion(item),
) as IntersectOptions,
};
schema = coerce(
options?.wrap
? {
...options.wrap,
wrapped: schema,
}
: schema,
(output) => coerceString(output),
);
} else if (type.type === "object") {
const shape = {
...type,
Expand Down
6 changes: 5 additions & 1 deletion parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import {
type BaseSchema,
type Output,
type ParseInfo,
SafeParseResult,
safeParse,
} from "valibot";
Expand All @@ -16,18 +17,21 @@ export function parseWithValibot<Schema extends BaseSchema & { type: string }>(
payload: FormData | URLSearchParams,
config: {
schema: Schema | ((intent: string) => Schema);
info?: Pick<ParseInfo, "abortEarly" | "abortPipeEarly" | "skipPipe">;
},
): Submission<Output<Schema>>;
export function parseWithValibot<Schema extends BaseSchema & { type: string }>(
payload: FormData | URLSearchParams,
config: {
schema: Schema | ((intent: string) => Schema);
info?: Pick<ParseInfo, "abortEarly" | "abortPipeEarly" | "skipPipe">;
},
): Promise<Submission<Output<Schema>>>;
export function parseWithValibot<Schema extends BaseSchema & { type: string }>(
payload: FormData | URLSearchParams,
config: {
schema: Schema | ((intent: Intent | null) => Schema);
info?: Pick<ParseInfo, "abortEarly" | "abortPipeEarly" | "skipPipe">;
},
): Submission<Output<Schema>> | Promise<Submission<Output<Schema>>> {
return baseParse<Output<Schema>, string[]>(payload, {
Expand Down Expand Up @@ -60,7 +64,7 @@ export function parseWithValibot<Schema extends BaseSchema & { type: string }>(
};
};

return resolveResult(safeParse(schema, payload));
return resolveResult(safeParse(schema, payload, config.info));
},
});
}
63 changes: 63 additions & 0 deletions tests/coercion/schema/intersect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { describe, expect, test } from "vitest";
import { literal, object, string, intersect } from "valibot";
import { parseWithValibot } from "../../../parse";
import { createFormData } from "../../helpers/FormData";

describe("intersect", () => {
test("should pass only intersect values", () => {
const schema1 = object({
intersect: intersect([string(), literal("test")]),
});
const input1 = createFormData("intersect", "test");
const output1 = parseWithValibot(input1, { schema: schema1 });
expect(output1).toMatchObject({
status: "success",
value: { intersect: "test" },
});

const errorInput1 = createFormData("intersect", "foo");
const errorOutput1 = parseWithValibot(errorInput1, { schema: schema1 });
expect(errorOutput1).toMatchObject({
error: { intersect: ["Invalid type"] },
});
const errorInput2 = createFormData("intersect", "");
const errorOutput2 = parseWithValibot(errorInput2, { schema: schema1 });
expect(errorOutput2).toMatchObject({
error: { intersect: ["Invalid type", "Invalid type"] },
});

const schema2 = intersect([
object({ foo: string() }),
object({ bar: string() }),
]);
const input2 = createFormData("foo", "test");
input2.append("bar", "test");
const output2 = parseWithValibot(input2, { schema: schema2 });
expect(output2).toMatchObject({
status: "success",
value: { foo: "test", bar: "test" },
});
const errorInput3 = createFormData("foo", "test");
const errorOutput3 = parseWithValibot(errorInput3, { schema: schema2 });
expect(errorOutput3).toMatchObject({
error: { bar: ["Invalid type"] },
});
const errorInput4 = createFormData("bar", "test");
const errorOutput4 = parseWithValibot(errorInput4, { schema: schema2 });
expect(errorOutput4).toMatchObject({
error: { foo: ["Invalid type"] },
});
});

test("should throw only first issue", () => {
const schema = object({
intersect: intersect([string(), literal("test")]),
});
const errorInput = createFormData("intersect", "");
const info = { abortEarly: true };
const errorOutput = parseWithValibot(errorInput, { schema, info });
expect(errorOutput).toMatchObject({
error: { intersect: ["Invalid type"] },
});
});
});

0 comments on commit 806a54e

Please sign in to comment.