1import * as Schema from "effect/Schema"
2import * as SchemaAST from "effect/SchemaAST"
3import * as SchemaParser from "effect/SchemaParser"
4import assert from "node:assert/strict"
5import { invalidData, validData, validDataWithExtras } from "./data.ts"
6
7export const schema = Schema.Struct({
8 number: Schema.Number,
9 negNumber: Schema.Number,
10 maxNumber: Schema.Number,
11 string: Schema.String,
12 longString: Schema.String,
13 boolean: Schema.Boolean,
14 deeplyNested: Schema.Struct({
15 foo: Schema.String,
16 num: Schema.Number,
17 bool: Schema.Boolean
18 })
19})
20
21export const targets = [
22 { ast: schema.ast, operations: ["decode"] },
23 { ast: SchemaAST.toType(schema.ast), operations: ["is"] },
24 { ast: SchemaAST.flip(schema.ast), operations: ["decode"] }
25] as const
26export const roots = targets.map((target) => target.ast)
27
28const parseCase = (input: unknown, invalid = false) => () => {
29 const parse = SchemaParser.decodeUnknownSync(schema)
30 return {
31 run: invalid
32 ? () => {
33 try {
34 parse(input)
35 return false
36 } catch {
37 return true
38 }
39 }
40 : () => parse(input),
41 validate: invalid
42 ? (result: unknown) => assert.equal(result, true)
43 : (result: unknown) => assert.deepEqual(result, validData)
44 }
45}
46
47const guardCase = (input: unknown, expected: boolean) => () => {
48 const guard = SchemaParser.is(schema)
49 return {
50 run: expected
51 ? () => {
52 if (!guard(input)) throw new Error("Invalid")
53 return true
54 }
55 : () => guard(input),
56 validate: (result: unknown) => assert.equal(result, expected)
57 }
58}
59
60export const parseValid = parseCase(validData)
61export const parseExtraValid = parseCase(validDataWithExtras)
62export const parseInvalid = parseCase(invalidData, true)
63export const isValid = guardCase(validData, true)
64export const isExtraValid = guardCase(validDataWithExtras, true)
65export const isInvalid = guardCase(invalidData, false)