1import * as Schema from "effect/Schema"
2import { enable } from "effect/schema/SchemaJITCompiler"
3import * as SchemaParser from "effect/SchemaParser"
4import * as SchemaTransformation from "effect/SchemaTransformation"
5import assert from "node:assert/strict"
6
7type Kind = "digits" | "checked" | "unchecked" | "two-passes" | "checked-template" | "unchecked-template"
8
9const fixture = (kind: Kind) => {
10 const text = Schema.String.check(Schema.isPattern(/^[a-z][a-z0-9]{1,15}$/))
11 const digits = Schema.String.check(Schema.isPattern(/^[0-9]{1,6}$/))
12 const toNumber = SchemaTransformation.transform({ decode: Number, encode: String })
13 const toTemplate = SchemaTransformation.transform({
14 decode: (s: string): `x-${string}` => `x-${s}`,
15 encode: (s: `x-${string}`) => s.slice(2)
16 })
17 const template = Schema.TemplateLiteral(["x-", Schema.String])
18 const names = Array.from({ length: 11 }, (_, index) => `s${index}`)
19 const checkedFields = Object.fromEntries(names.map((name) => [name, text]))
20 const uncheckedFields = Object.fromEntries(names.map((name) => [name, Schema.String]))
21 const source = kind === "unchecked" || kind === "unchecked-template" ? Schema.String : digits
22 const field = kind === "digits" || kind === "two-passes"
23 ? digits
24 : kind === "checked-template" || kind === "unchecked-template"
25 ? source.pipe(Schema.decodeTo(template, toTemplate))
26 : source.pipe(Schema.decodeTo(Schema.Number, toNumber))
27 const schema = Schema.Array(Schema.Struct({ ...checkedFields, n: field }))
28 enable(schema.ast)
29 const decode = SchemaParser.decodeUnknownSync(schema)
30 const input = Array.from({ length: 1000 }, (_, index) => ({
31 ...Object.fromEntries(names.map((name) => [name, `value${index}`])),
32 n: String(index + 1)
33 }))
34 const expected = input.map((row) => ({
35 ...row,
36 n: kind === "digits"
37 ? row.n
38 : kind === "checked-template" || kind === "unchecked-template"
39 ? `x-${row.n}`
40 : Number(row.n)
41 }))
42 let run = () => decode(input)
43 if (kind === "two-passes") {
44 const transformations = Schema.Array(Schema.Struct({
45 ...uncheckedFields,
46 n: Schema.String.pipe(Schema.decodeTo(Schema.Number, toNumber))
47 }))
48 enable(transformations.ast)
49 const transform = SchemaParser.decodeUnknownSync(transformations)
50 run = () => transform(decode(input))
51 }
52 return {
53 run,
54 validate: (result: unknown) => assert.deepEqual(result, expected)
55 }
56}
57
58export const digits = () => fixture("digits")
59export const checkedSource = () => fixture("checked")
60export const uncheckedSource = () => fixture("unchecked")
61export const twoPasses = () => fixture("two-passes")
62export const checkedTemplateTarget = () => fixture("checked-template")
63export const uncheckedTemplateTarget = () => fixture("unchecked-template")