| 1 | import * as Schema from "effect/Schema" |
| 2 | import { enable } from "effect/schema/SchemaJITCompiler" |
| 3 | import * as SchemaParser from "effect/SchemaParser" |
| 4 | import * as SchemaTransformation from "effect/SchemaTransformation" |
| 5 | import assert from "node:assert/strict" |
| 6 | |
| 7 | type Kind = "digits" | "checked" | "unchecked" | "two-passes" | "checked-template" | "unchecked-template" |
| 8 | |
| 9 | const 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 | |
| 58 | export const digits = () => fixture("digits") |
| 59 | export const checkedSource = () => fixture("checked") |
| 60 | export const uncheckedSource = () => fixture("unchecked") |
| 61 | export const twoPasses = () => fixture("two-passes") |
| 62 | export const checkedTemplateTarget = () => fixture("checked-template") |
| 63 | export const uncheckedTemplateTarget = () => fixture("unchecked-template") |