@hoangvu12/yomi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -0
- package/dist/coerce.d.ts +8 -0
- package/dist/coerce.d.ts.map +1 -0
- package/dist/coerce.js +207 -0
- package/dist/coerce.js.map +1 -0
- package/dist/coercers/array.d.ts +20 -0
- package/dist/coercers/array.d.ts.map +1 -0
- package/dist/coercers/array.js +77 -0
- package/dist/coercers/array.js.map +1 -0
- package/dist/coercers/enum.d.ts +12 -0
- package/dist/coercers/enum.d.ts.map +1 -0
- package/dist/coercers/enum.js +62 -0
- package/dist/coercers/enum.js.map +1 -0
- package/dist/coercers/object.d.ts +23 -0
- package/dist/coercers/object.d.ts.map +1 -0
- package/dist/coercers/object.js +75 -0
- package/dist/coercers/object.js.map +1 -0
- package/dist/coercers/primitive.d.ts +33 -0
- package/dist/coercers/primitive.d.ts.map +1 -0
- package/dist/coercers/primitive.js +160 -0
- package/dist/coercers/primitive.js.map +1 -0
- package/dist/coercers/union.d.ts +35 -0
- package/dist/coercers/union.d.ts.map +1 -0
- package/dist/coercers/union.js +82 -0
- package/dist/coercers/union.js.map +1 -0
- package/dist/flags.d.ts +44 -0
- package/dist/flags.d.ts.map +1 -0
- package/dist/flags.js +42 -0
- package/dist/flags.js.map +1 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +17 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +157 -0
- package/dist/parse.js.map +1 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +48 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Yomi (読み)
|
|
2
|
+
|
|
3
|
+
**Yomi** (pronounced "yoh-mee", 読み) means "reading" or "interpretation" in Japanese. This library interprets messy LLM output and coerces it to match your Zod schemas.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
LLMs don't return perfect JSON. They return:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{name: "John", age: "25",} // unquoted keys, trailing comma
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Here's the user data: {"name": "John", "age": 25} // wrapped in text
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{"name": "John", "age": "25", "active": "yes"} // wrong types everywhere
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`JSON.parse()` fails. Even if it succeeds, your types are wrong.
|
|
22
|
+
|
|
23
|
+
## The Solution
|
|
24
|
+
|
|
25
|
+
Yomi uses a two-phase approach inspired by [BAML](https://docs.boundaryml.com/)'s schema-aligned parsing:
|
|
26
|
+
|
|
27
|
+
1. **Flexible JSON parsing** - Fix malformed JSON, extract from markdown/text
|
|
28
|
+
2. **Schema-aligned coercion** - Walk your Zod schema and coerce values to match
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { z } from "zod";
|
|
32
|
+
import { parse } from "@hoangvu12/yomi";
|
|
33
|
+
|
|
34
|
+
const User = z.object({
|
|
35
|
+
name: z.string(),
|
|
36
|
+
age: z.number(),
|
|
37
|
+
active: z.boolean(),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const result = parse(User, `{name: "John", age: "25", active: "yes"}`);
|
|
41
|
+
|
|
42
|
+
// result.success === true
|
|
43
|
+
// result.data.value === { name: "John", age: 25, active: true }
|
|
44
|
+
// result.data.flags === ["json_repaired", "string_to_number", "string_to_bool"]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install @hoangvu12/yomi zod
|
|
51
|
+
# or
|
|
52
|
+
bun add @hoangvu12/yomi zod
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
### `parse(schema, input)`
|
|
58
|
+
|
|
59
|
+
Parse and coerce input to match schema. Returns a result object.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const result = parse(UserSchema, rawInput);
|
|
63
|
+
|
|
64
|
+
if (result.success) {
|
|
65
|
+
console.log(result.data.value); // typed as z.infer<typeof UserSchema>
|
|
66
|
+
console.log(result.data.flags); // what transformations happened
|
|
67
|
+
} else {
|
|
68
|
+
console.log(result.error); // what went wrong
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### `parseOrThrow(schema, input)`
|
|
73
|
+
|
|
74
|
+
Same as `parse`, but throws on failure. Returns the coerced value directly.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const user = parseOrThrow(UserSchema, rawInput);
|
|
78
|
+
// user is typed as z.infer<typeof UserSchema>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### `coerce(schema, value)` / `coerceOrThrow(schema, value)`
|
|
82
|
+
|
|
83
|
+
Skip JSON parsing, just do schema coercion on an already-parsed value.
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
const result = coerce(UserSchema, { name: "John", age: "25" });
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## What It Fixes
|
|
90
|
+
|
|
91
|
+
### JSON Parsing
|
|
92
|
+
|
|
93
|
+
| Input | Fixed |
|
|
94
|
+
|-------|-------|
|
|
95
|
+
| `{name: "John"}` | Unquoted keys |
|
|
96
|
+
| `{"name": "John",}` | Trailing commas |
|
|
97
|
+
| `// comment` | Comments |
|
|
98
|
+
| `'single quotes'` | Single quotes |
|
|
99
|
+
| `` ```json {...}``` `` | Markdown code blocks |
|
|
100
|
+
| `Here's the data: {...}` | Surrounding text |
|
|
101
|
+
|
|
102
|
+
### Type Coercion
|
|
103
|
+
|
|
104
|
+
| From | To | Example |
|
|
105
|
+
|------|----|---------|
|
|
106
|
+
| `"123"` | `number` | `"25"` → `25` |
|
|
107
|
+
| `"12.5"` | `int` | `"12.5"` → `13` (rounded) |
|
|
108
|
+
| `123` | `string` | `123` → `"123"` |
|
|
109
|
+
| `"true"`, `"yes"`, `"1"` | `boolean` | → `true` |
|
|
110
|
+
| `"false"`, `"no"`, `"0"` | `boolean` | → `false` |
|
|
111
|
+
| `value` | `array` | `"x"` → `["x"]` |
|
|
112
|
+
| `[value]` | `single` | `["x"]` → `"x"` |
|
|
113
|
+
| `"PENDING"` | `enum` | Case-insensitive match |
|
|
114
|
+
| `null` | `undefined` | For optional fields |
|
|
115
|
+
| `{extra: ...}` | `object` | Extra keys ignored |
|
|
116
|
+
|
|
117
|
+
## Flags
|
|
118
|
+
|
|
119
|
+
Every transformation is tracked. Use flags to:
|
|
120
|
+
- Log when coercion happens in production
|
|
121
|
+
- Detect if defaults were used vs explicit values
|
|
122
|
+
- Debug why parsing succeeded unexpectedly
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const result = parse(Schema, input);
|
|
126
|
+
if (result.success) {
|
|
127
|
+
for (const flag of result.data.flags) {
|
|
128
|
+
console.log(flag);
|
|
129
|
+
// { flag: "string_to_number" }
|
|
130
|
+
// { flag: "extra_keys_ignored", keys: ["confidence"] }
|
|
131
|
+
// { flag: "float_to_int", original: 12.5, rounded: 13 }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Available Flags
|
|
137
|
+
|
|
138
|
+
| Flag | Meaning |
|
|
139
|
+
|------|---------|
|
|
140
|
+
| `json_repaired` | jsonrepair fixed the JSON |
|
|
141
|
+
| `extracted_from_markdown` | Extracted from `` ```json ``` `` block |
|
|
142
|
+
| `extracted_from_text` | Extracted JSON from surrounding text |
|
|
143
|
+
| `string_to_number` | `"123"` → `123` |
|
|
144
|
+
| `string_to_bool` | `"true"` → `true` |
|
|
145
|
+
| `number_to_string` | `123` → `"123"` |
|
|
146
|
+
| `bool_to_string` | `true` → `"true"` |
|
|
147
|
+
| `float_to_int` | `12.5` → `13` |
|
|
148
|
+
| `single_to_array` | `x` → `[x]` |
|
|
149
|
+
| `array_to_single` | `[x]` → `x` |
|
|
150
|
+
| `null_to_undefined` | `null` → `undefined` |
|
|
151
|
+
| `extra_keys_ignored` | Object had extra properties |
|
|
152
|
+
| `missing_optional_key` | Optional field was missing |
|
|
153
|
+
| `default_used` | Used schema's default value |
|
|
154
|
+
| `enum_case_insensitive` | `"PENDING"` matched `"pending"` |
|
|
155
|
+
|
|
156
|
+
## Supported Zod Types
|
|
157
|
+
|
|
158
|
+
- Primitives: `string`, `number`, `boolean`, `null`, `undefined`, `literal`
|
|
159
|
+
- Objects: `object`, `record`
|
|
160
|
+
- Arrays: `array`, `tuple`
|
|
161
|
+
- Unions: `union`, `discriminatedUnion`, `optional`, `nullable`
|
|
162
|
+
- Enums: `enum`, `nativeEnum`
|
|
163
|
+
- Modifiers: `default`, `catch`
|
|
164
|
+
- Passthrough: `any`, `unknown`
|
|
165
|
+
|
|
166
|
+
## How It Works
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
LLM Output (string)
|
|
170
|
+
│
|
|
171
|
+
▼
|
|
172
|
+
┌─────────────────┐
|
|
173
|
+
│ Flexible JSON │ ← jsonrepair + markdown extraction
|
|
174
|
+
│ Parser │
|
|
175
|
+
└────────┬────────┘
|
|
176
|
+
│ unknown
|
|
177
|
+
▼
|
|
178
|
+
┌─────────────────┐
|
|
179
|
+
│ Schema-Aligned │ ← walks Zod schema tree
|
|
180
|
+
│ Coercer │
|
|
181
|
+
└────────┬────────┘
|
|
182
|
+
│ { value: T, flags: Flag[] }
|
|
183
|
+
▼
|
|
184
|
+
Result<T>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The coercer recursively walks your Zod schema using `schema._def`, dispatching to type-specific coercion functions. Each coercer tries to interpret the input value as the expected type, recording flags when transformations occur.
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT
|
package/dist/coerce.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type CoerceContext, type CoerceResult } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Coerce a value to match a Zod schema.
|
|
5
|
+
* This is the main entry point for schema-aligned coercion.
|
|
6
|
+
*/
|
|
7
|
+
export declare function coerceToSchema<T extends z.ZodTypeAny>(schema: T, value: unknown, ctx?: CoerceContext): CoerceResult<z.infer<T>>;
|
|
8
|
+
//# sourceMappingURL=coerce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coerce.d.ts","sourceRoot":"","sources":["../src/coerce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EAIlB,MAAM,YAAY,CAAC;AAcpB;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EACnD,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,OAAO,EACd,GAAG,CAAC,EAAE,aAAa,GAClB,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAG1B"}
|
package/dist/coerce.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createContext, failure, describeType, } from "./types.js";
|
|
3
|
+
import { coerceString, coerceNumber, coerceInt, coerceBoolean, coerceNull, coerceLiteral, } from "./coercers/primitive.js";
|
|
4
|
+
import { coerceArray, coerceTuple } from "./coercers/array.js";
|
|
5
|
+
import { coerceObject, coerceRecord } from "./coercers/object.js";
|
|
6
|
+
import { coerceUnion, coerceOptional, coerceNullable, coerceDefault } from "./coercers/union.js";
|
|
7
|
+
import { coerceEnum, coerceNativeEnum } from "./coercers/enum.js";
|
|
8
|
+
/**
|
|
9
|
+
* Coerce a value to match a Zod schema.
|
|
10
|
+
* This is the main entry point for schema-aligned coercion.
|
|
11
|
+
*/
|
|
12
|
+
export function coerceToSchema(schema, value, ctx) {
|
|
13
|
+
const context = ctx ?? createContext();
|
|
14
|
+
return coerceZodType(schema, value, context);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Internal dispatcher for Zod types.
|
|
18
|
+
*/
|
|
19
|
+
function coerceZodType(schema, value, ctx) {
|
|
20
|
+
const def = schema._def;
|
|
21
|
+
const typeName = def.typeName;
|
|
22
|
+
switch (typeName) {
|
|
23
|
+
// Primitives
|
|
24
|
+
case z.ZodFirstPartyTypeKind.ZodString:
|
|
25
|
+
return coerceString(value, ctx);
|
|
26
|
+
case z.ZodFirstPartyTypeKind.ZodNumber:
|
|
27
|
+
return coerceNumber(value, ctx);
|
|
28
|
+
case z.ZodFirstPartyTypeKind.ZodBigInt:
|
|
29
|
+
return coerceInt(value, ctx); // Use int coercion for bigint
|
|
30
|
+
case z.ZodFirstPartyTypeKind.ZodBoolean:
|
|
31
|
+
return coerceBoolean(value, ctx);
|
|
32
|
+
case z.ZodFirstPartyTypeKind.ZodNull:
|
|
33
|
+
return coerceNull(value, ctx);
|
|
34
|
+
case z.ZodFirstPartyTypeKind.ZodUndefined:
|
|
35
|
+
if (value === undefined || value === null) {
|
|
36
|
+
return { success: true, value: undefined, flags: ctx.flags };
|
|
37
|
+
}
|
|
38
|
+
return failure("Expected undefined", ctx, "undefined", describeType(value));
|
|
39
|
+
case z.ZodFirstPartyTypeKind.ZodVoid:
|
|
40
|
+
return { success: true, value: undefined, flags: ctx.flags };
|
|
41
|
+
case z.ZodFirstPartyTypeKind.ZodAny:
|
|
42
|
+
case z.ZodFirstPartyTypeKind.ZodUnknown:
|
|
43
|
+
return { success: true, value, flags: ctx.flags };
|
|
44
|
+
case z.ZodFirstPartyTypeKind.ZodNever:
|
|
45
|
+
return failure("ZodNever cannot match any value", ctx, "never", describeType(value));
|
|
46
|
+
// Literals
|
|
47
|
+
case z.ZodFirstPartyTypeKind.ZodLiteral:
|
|
48
|
+
return coerceLiteral(value, def.value, ctx);
|
|
49
|
+
// Arrays
|
|
50
|
+
case z.ZodFirstPartyTypeKind.ZodArray:
|
|
51
|
+
return coerceArray(value, (v, c) => coerceZodType(def.type, v, c), ctx);
|
|
52
|
+
// Tuples
|
|
53
|
+
case z.ZodFirstPartyTypeKind.ZodTuple: {
|
|
54
|
+
const items = def.items;
|
|
55
|
+
const coercers = items.map((item) => (v, c) => coerceZodType(item, v, c));
|
|
56
|
+
return coerceTuple(value, coercers, ctx);
|
|
57
|
+
}
|
|
58
|
+
// Objects
|
|
59
|
+
case z.ZodFirstPartyTypeKind.ZodObject: {
|
|
60
|
+
const shape = def.shape();
|
|
61
|
+
const objectSchema = {};
|
|
62
|
+
for (const [key, propSchema] of Object.entries(shape)) {
|
|
63
|
+
const isOptional = propSchema.isOptional();
|
|
64
|
+
const hasDefault = propSchema._def.typeName === z.ZodFirstPartyTypeKind.ZodDefault;
|
|
65
|
+
objectSchema[key] = {
|
|
66
|
+
coercer: (v, c) => coerceZodType(propSchema, v, c),
|
|
67
|
+
optional: isOptional,
|
|
68
|
+
...(hasDefault ? { default: propSchema._def.defaultValue() } : {}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return coerceObject(value, objectSchema, ctx);
|
|
72
|
+
}
|
|
73
|
+
// Records
|
|
74
|
+
case z.ZodFirstPartyTypeKind.ZodRecord:
|
|
75
|
+
return coerceRecord(value, (v, c) => coerceZodType(def.valueType, v, c), ctx);
|
|
76
|
+
// Maps
|
|
77
|
+
case z.ZodFirstPartyTypeKind.ZodMap:
|
|
78
|
+
// Treat as record for now
|
|
79
|
+
return coerceRecord(value, (v, c) => coerceZodType(def.valueType, v, c), ctx);
|
|
80
|
+
// Unions
|
|
81
|
+
case z.ZodFirstPartyTypeKind.ZodUnion: {
|
|
82
|
+
const options = def.options;
|
|
83
|
+
const coercers = options.map((opt) => (v, c) => coerceZodType(opt, v, c));
|
|
84
|
+
return coerceUnion(value, coercers, ctx);
|
|
85
|
+
}
|
|
86
|
+
case z.ZodFirstPartyTypeKind.ZodDiscriminatedUnion: {
|
|
87
|
+
const options = def.options;
|
|
88
|
+
const coercers = options.map((opt) => (v, c) => coerceZodType(opt, v, c));
|
|
89
|
+
return coerceUnion(value, coercers, ctx);
|
|
90
|
+
}
|
|
91
|
+
// Optionals and Nullables
|
|
92
|
+
case z.ZodFirstPartyTypeKind.ZodOptional:
|
|
93
|
+
return coerceOptional(value, (v, c) => coerceZodType(def.innerType, v, c), ctx);
|
|
94
|
+
case z.ZodFirstPartyTypeKind.ZodNullable:
|
|
95
|
+
return coerceNullable(value, (v, c) => coerceZodType(def.innerType, v, c), ctx);
|
|
96
|
+
// Defaults
|
|
97
|
+
case z.ZodFirstPartyTypeKind.ZodDefault:
|
|
98
|
+
return coerceDefault(value, (v, c) => coerceZodType(def.innerType, v, c), def.defaultValue(), ctx);
|
|
99
|
+
// Catch
|
|
100
|
+
case z.ZodFirstPartyTypeKind.ZodCatch: {
|
|
101
|
+
const result = coerceZodType(def.innerType, value, ctx);
|
|
102
|
+
if (result.success)
|
|
103
|
+
return result;
|
|
104
|
+
return { success: true, value: def.catchValue({ error: result.error, input: value }), flags: ctx.flags };
|
|
105
|
+
}
|
|
106
|
+
// Enums
|
|
107
|
+
case z.ZodFirstPartyTypeKind.ZodEnum:
|
|
108
|
+
return coerceEnum(value, def.values, ctx);
|
|
109
|
+
case z.ZodFirstPartyTypeKind.ZodNativeEnum:
|
|
110
|
+
return coerceNativeEnum(value, def.values, ctx);
|
|
111
|
+
// Effects/Transforms
|
|
112
|
+
case z.ZodFirstPartyTypeKind.ZodEffects: {
|
|
113
|
+
// First coerce the inner type
|
|
114
|
+
const innerResult = coerceZodType(def.schema, value, ctx);
|
|
115
|
+
if (!innerResult.success)
|
|
116
|
+
return innerResult;
|
|
117
|
+
// Then apply the effect
|
|
118
|
+
// Note: We only handle refinements here, not transforms
|
|
119
|
+
// Transforms would need async support
|
|
120
|
+
if (def.effect.type === "refinement") {
|
|
121
|
+
const refinement = def.effect.refinement;
|
|
122
|
+
try {
|
|
123
|
+
const isValid = refinement(innerResult.value);
|
|
124
|
+
if (!isValid) {
|
|
125
|
+
return failure("Refinement failed", ctx, "refined value", describeType(innerResult.value));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
return failure(`Refinement error: ${e instanceof Error ? e.message : String(e)}`, ctx, "refined value", describeType(innerResult.value));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return innerResult;
|
|
133
|
+
}
|
|
134
|
+
// Lazy
|
|
135
|
+
case z.ZodFirstPartyTypeKind.ZodLazy:
|
|
136
|
+
return coerceZodType(def.getter(), value, ctx);
|
|
137
|
+
// Branded
|
|
138
|
+
case z.ZodFirstPartyTypeKind.ZodBranded:
|
|
139
|
+
return coerceZodType(def.type, value, ctx);
|
|
140
|
+
// Pipeline
|
|
141
|
+
case z.ZodFirstPartyTypeKind.ZodPipeline: {
|
|
142
|
+
const inResult = coerceZodType(def.in, value, ctx);
|
|
143
|
+
if (!inResult.success)
|
|
144
|
+
return inResult;
|
|
145
|
+
return coerceZodType(def.out, inResult.value, ctx);
|
|
146
|
+
}
|
|
147
|
+
// Readonly
|
|
148
|
+
case z.ZodFirstPartyTypeKind.ZodReadonly:
|
|
149
|
+
return coerceZodType(def.innerType, value, ctx);
|
|
150
|
+
// Date - special handling
|
|
151
|
+
case z.ZodFirstPartyTypeKind.ZodDate: {
|
|
152
|
+
if (value instanceof Date) {
|
|
153
|
+
if (isNaN(value.getTime())) {
|
|
154
|
+
return failure("Invalid Date", ctx, "Date", "Invalid Date");
|
|
155
|
+
}
|
|
156
|
+
return { success: true, value, flags: ctx.flags };
|
|
157
|
+
}
|
|
158
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
159
|
+
const date = new Date(value);
|
|
160
|
+
if (isNaN(date.getTime())) {
|
|
161
|
+
return failure(`Cannot parse "${value}" as Date`, ctx, "Date", describeType(value));
|
|
162
|
+
}
|
|
163
|
+
return { success: true, value: date, flags: ctx.flags };
|
|
164
|
+
}
|
|
165
|
+
return failure("Expected Date", ctx, "Date", describeType(value));
|
|
166
|
+
}
|
|
167
|
+
// Intersection - coerce to both types
|
|
168
|
+
case z.ZodFirstPartyTypeKind.ZodIntersection: {
|
|
169
|
+
const leftResult = coerceZodType(def.left, value, ctx);
|
|
170
|
+
if (!leftResult.success)
|
|
171
|
+
return leftResult;
|
|
172
|
+
const rightResult = coerceZodType(def.right, leftResult.value, ctx);
|
|
173
|
+
if (!rightResult.success)
|
|
174
|
+
return rightResult;
|
|
175
|
+
// Merge results for objects
|
|
176
|
+
if (typeof leftResult.value === "object" && typeof rightResult.value === "object") {
|
|
177
|
+
return { success: true, value: { ...leftResult.value, ...rightResult.value }, flags: ctx.flags };
|
|
178
|
+
}
|
|
179
|
+
return rightResult;
|
|
180
|
+
}
|
|
181
|
+
// Set
|
|
182
|
+
case z.ZodFirstPartyTypeKind.ZodSet: {
|
|
183
|
+
const arrayResult = coerceArray(value, (v, c) => coerceZodType(def.valueType, v, c), ctx);
|
|
184
|
+
if (!arrayResult.success)
|
|
185
|
+
return arrayResult;
|
|
186
|
+
return { success: true, value: new Set(arrayResult.value), flags: ctx.flags };
|
|
187
|
+
}
|
|
188
|
+
// Promise - just pass through
|
|
189
|
+
case z.ZodFirstPartyTypeKind.ZodPromise:
|
|
190
|
+
return { success: true, value, flags: ctx.flags };
|
|
191
|
+
// Function - just pass through
|
|
192
|
+
case z.ZodFirstPartyTypeKind.ZodFunction:
|
|
193
|
+
if (typeof value === "function") {
|
|
194
|
+
return { success: true, value, flags: ctx.flags };
|
|
195
|
+
}
|
|
196
|
+
return failure("Expected function", ctx, "function", describeType(value));
|
|
197
|
+
// Symbol
|
|
198
|
+
case z.ZodFirstPartyTypeKind.ZodSymbol:
|
|
199
|
+
if (typeof value === "symbol") {
|
|
200
|
+
return { success: true, value, flags: ctx.flags };
|
|
201
|
+
}
|
|
202
|
+
return failure("Expected symbol", ctx, "symbol", describeType(value));
|
|
203
|
+
default:
|
|
204
|
+
return failure(`Unsupported Zod type: ${typeName}`, ctx, typeName, describeType(value));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=coerce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coerce.js","sourceRoot":"","sources":["../src/coerce.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CoerceContext, type CoerceResult } from "../types.js";
|
|
2
|
+
export type ElementCoercer<T> = (value: unknown, ctx: CoerceContext) => CoerceResult<T>;
|
|
3
|
+
/**
|
|
4
|
+
* LLMs often return a single item when we expect an array (especially when
|
|
5
|
+
* there's only one result). Rather than failing, we wrap it in an array.
|
|
6
|
+
*/
|
|
7
|
+
export declare function coerceArray<T>(value: unknown, elementCoercer: ElementCoercer<T>, ctx: CoerceContext): CoerceResult<T[]>;
|
|
8
|
+
/**
|
|
9
|
+
* The reverse case: schema expects single value but LLM returned [value].
|
|
10
|
+
* If the array has exactly one element, unwrap it.
|
|
11
|
+
*/
|
|
12
|
+
export declare function coerceArrayToSingle<T>(value: unknown, elementCoercer: ElementCoercer<T>, ctx: CoerceContext): CoerceResult<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Tuples are fixed-length arrays where each position has a specific type.
|
|
15
|
+
* We validate length matches and coerce each element to its expected type.
|
|
16
|
+
*/
|
|
17
|
+
export declare function coerceTuple<T extends unknown[]>(value: unknown, elementCoercers: {
|
|
18
|
+
[K in keyof T]: ElementCoercer<T[K]>;
|
|
19
|
+
}, ctx: CoerceContext): CoerceResult<T>;
|
|
20
|
+
//# sourceMappingURL=array.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/coercers/array.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EAKlB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC;AAExF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,KAAK,EAAE,OAAO,EACd,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,EACjC,GAAG,EAAE,aAAa,GACjB,YAAY,CAAC,CAAC,EAAE,CAAC,CAiCnB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,KAAK,EAAE,OAAO,EACd,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,EACjC,GAAG,EAAE,aAAa,GACjB,YAAY,CAAC,CAAC,CAAC,CAqBjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,EAC7C,KAAK,EAAE,OAAO,EACd,eAAe,EAAE;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,EACzD,GAAG,EAAE,aAAa,GACjB,YAAY,CAAC,CAAC,CAAC,CAgCjB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Flag } from "../flags.js";
|
|
2
|
+
import { childContext, success, failure, describeType, } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* LLMs often return a single item when we expect an array (especially when
|
|
5
|
+
* there's only one result). Rather than failing, we wrap it in an array.
|
|
6
|
+
*/
|
|
7
|
+
export function coerceArray(value, elementCoercer, ctx) {
|
|
8
|
+
if (value === null || value === undefined) {
|
|
9
|
+
return failure("Expected array, got null/undefined", ctx, "array", describeType(value));
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(value)) {
|
|
12
|
+
const results = [];
|
|
13
|
+
for (let i = 0; i < value.length; i++) {
|
|
14
|
+
// Each element gets its own path context for error reporting
|
|
15
|
+
const elementCtx = childContext(ctx, i);
|
|
16
|
+
const result = elementCoercer(value[i], elementCtx);
|
|
17
|
+
if (!result.success) {
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
results.push(result.value);
|
|
21
|
+
}
|
|
22
|
+
return success(results, ctx);
|
|
23
|
+
}
|
|
24
|
+
// Single value → wrap in array (common LLM behavior)
|
|
25
|
+
ctx.flags.push({ flag: Flag.SingleToArray });
|
|
26
|
+
const elementCtx = childContext(ctx, 0);
|
|
27
|
+
const result = elementCoercer(value, elementCtx);
|
|
28
|
+
if (!result.success) {
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
return success([result.value], ctx);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The reverse case: schema expects single value but LLM returned [value].
|
|
35
|
+
* If the array has exactly one element, unwrap it.
|
|
36
|
+
*/
|
|
37
|
+
export function coerceArrayToSingle(value, elementCoercer, ctx) {
|
|
38
|
+
if (!Array.isArray(value)) {
|
|
39
|
+
return elementCoercer(value, ctx);
|
|
40
|
+
}
|
|
41
|
+
if (value.length === 0) {
|
|
42
|
+
return failure("Expected single value, got empty array", ctx, "single value", "empty array");
|
|
43
|
+
}
|
|
44
|
+
if (value.length > 1) {
|
|
45
|
+
return failure(`Expected single value, got array with ${value.length} elements`, ctx, "single value", `array[${value.length}]`);
|
|
46
|
+
}
|
|
47
|
+
ctx.flags.push({ flag: Flag.ArrayToSingle });
|
|
48
|
+
const elementCtx = childContext(ctx, 0);
|
|
49
|
+
return elementCoercer(value[0], elementCtx);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Tuples are fixed-length arrays where each position has a specific type.
|
|
53
|
+
* We validate length matches and coerce each element to its expected type.
|
|
54
|
+
*/
|
|
55
|
+
export function coerceTuple(value, elementCoercers, ctx) {
|
|
56
|
+
if (!Array.isArray(value)) {
|
|
57
|
+
return failure("Expected tuple (array), got " + describeType(value), ctx, "tuple", describeType(value));
|
|
58
|
+
}
|
|
59
|
+
if (value.length !== elementCoercers.length) {
|
|
60
|
+
return failure(`Expected tuple of length ${elementCoercers.length}, got length ${value.length}`, ctx, `tuple[${elementCoercers.length}]`, `array[${value.length}]`);
|
|
61
|
+
}
|
|
62
|
+
const results = [];
|
|
63
|
+
for (let i = 0; i < elementCoercers.length; i++) {
|
|
64
|
+
const elementCtx = childContext(ctx, i);
|
|
65
|
+
const coercer = elementCoercers[i];
|
|
66
|
+
if (!coercer) {
|
|
67
|
+
return failure(`Missing coercer for index ${i}`, ctx, "coercer", "undefined");
|
|
68
|
+
}
|
|
69
|
+
const result = coercer(value[i], elementCtx);
|
|
70
|
+
if (!result.success) {
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
results.push(result.value);
|
|
74
|
+
}
|
|
75
|
+
return success(results, ctx);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=array.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array.js","sourceRoot":"","sources":["../../src/coercers/array.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type CoerceContext, type CoerceResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* LLMs often return enum values with wrong casing - "PENDING" instead of "pending".
|
|
4
|
+
* Rather than failing, we do case-insensitive matching and track when it happens.
|
|
5
|
+
*/
|
|
6
|
+
export declare function coerceEnum<T extends string>(value: unknown, allowedValues: readonly T[], ctx: CoerceContext): CoerceResult<T>;
|
|
7
|
+
/**
|
|
8
|
+
* TypeScript enums have reverse mappings for numeric values.
|
|
9
|
+
* We filter those out and match against both keys and values.
|
|
10
|
+
*/
|
|
11
|
+
export declare function coerceNativeEnum<T extends Record<string, string | number>>(value: unknown, enumObject: T, ctx: CoerceContext): CoerceResult<T[keyof T]>;
|
|
12
|
+
//# sourceMappingURL=enum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum.d.ts","sourceRoot":"","sources":["../../src/coercers/enum.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,SAAS,CAAC,EAAE,EAC3B,GAAG,EAAE,aAAa,GACjB,YAAY,CAAC,CAAC,CAAC,CA8BjB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EACxE,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,CAAC,EACb,GAAG,EAAE,aAAa,GACjB,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CA4C1B"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Flag } from "../flags.js";
|
|
2
|
+
import { success, failure, describeType, } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* LLMs often return enum values with wrong casing - "PENDING" instead of "pending".
|
|
5
|
+
* Rather than failing, we do case-insensitive matching and track when it happens.
|
|
6
|
+
*/
|
|
7
|
+
export function coerceEnum(value, allowedValues, ctx) {
|
|
8
|
+
if (typeof value !== "string") {
|
|
9
|
+
return failure(`Expected enum value, got ${describeType(value)}`, ctx, allowedValues.join(" | "), describeType(value));
|
|
10
|
+
}
|
|
11
|
+
// Fast path: exact match
|
|
12
|
+
if (allowedValues.includes(value)) {
|
|
13
|
+
return success(value, ctx);
|
|
14
|
+
}
|
|
15
|
+
// Fallback: case-insensitive match
|
|
16
|
+
const lowerValue = value.toLowerCase();
|
|
17
|
+
const match = allowedValues.find((v) => v.toLowerCase() === lowerValue);
|
|
18
|
+
if (match) {
|
|
19
|
+
ctx.flags.push({ flag: Flag.EnumCaseInsensitive, input: value, matched: match });
|
|
20
|
+
return success(match, ctx);
|
|
21
|
+
}
|
|
22
|
+
return failure(`Value "${value}" is not a valid enum value`, ctx, allowedValues.join(" | "), `"${value}"`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* TypeScript enums have reverse mappings for numeric values.
|
|
26
|
+
* We filter those out and match against both keys and values.
|
|
27
|
+
*/
|
|
28
|
+
export function coerceNativeEnum(value, enumObject, ctx) {
|
|
29
|
+
// Filter out numeric keys (reverse mappings from numeric enums)
|
|
30
|
+
const enumValues = Object.entries(enumObject)
|
|
31
|
+
.filter(([key]) => isNaN(Number(key)))
|
|
32
|
+
.map(([_, val]) => val);
|
|
33
|
+
if (enumValues.includes(value)) {
|
|
34
|
+
return success(value, ctx);
|
|
35
|
+
}
|
|
36
|
+
// Try matching by key or value name, case-insensitive
|
|
37
|
+
if (typeof value === "string") {
|
|
38
|
+
const lowerValue = value.toLowerCase();
|
|
39
|
+
for (const [key, enumValue] of Object.entries(enumObject)) {
|
|
40
|
+
if (isNaN(Number(key))) {
|
|
41
|
+
// Match against enum key name
|
|
42
|
+
if (key.toLowerCase() === lowerValue) {
|
|
43
|
+
ctx.flags.push({ flag: Flag.EnumCaseInsensitive, input: value, matched: key });
|
|
44
|
+
return success(enumValue, ctx);
|
|
45
|
+
}
|
|
46
|
+
// Match against string enum value
|
|
47
|
+
if (typeof enumValue === "string" && enumValue.toLowerCase() === lowerValue) {
|
|
48
|
+
ctx.flags.push({ flag: Flag.EnumCaseInsensitive, input: value, matched: enumValue });
|
|
49
|
+
return success(enumValue, ctx);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// For numeric enums, also accept the number directly
|
|
55
|
+
if (typeof value === "number") {
|
|
56
|
+
if (enumValues.includes(value)) {
|
|
57
|
+
return success(value, ctx);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return failure(`Value "${String(value)}" is not a valid enum value`, ctx, enumValues.map((v) => String(v)).join(" | "), describeType(value));
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=enum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum.js","sourceRoot":"","sources":["../../src/coercers/enum.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CoerceContext, type CoerceResult } from "../types.js";
|
|
2
|
+
export type PropertyCoercer<T> = (value: unknown, ctx: CoerceContext) => CoerceResult<T>;
|
|
3
|
+
export interface ObjectSchema {
|
|
4
|
+
[key: string]: {
|
|
5
|
+
coercer: PropertyCoercer<unknown>;
|
|
6
|
+
optional: boolean;
|
|
7
|
+
default?: unknown;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* LLMs often add extra fields we didn't ask for (explanations, confidence scores,
|
|
12
|
+
* reasoning). We ignore these rather than failing, but track them in flags.
|
|
13
|
+
*
|
|
14
|
+
* Missing optional fields are also tracked - callers can detect when defaults
|
|
15
|
+
* were used vs when the LLM explicitly provided values.
|
|
16
|
+
*/
|
|
17
|
+
export declare function coerceObject<T extends Record<string, unknown>>(value: unknown, schema: ObjectSchema, ctx: CoerceContext): CoerceResult<T>;
|
|
18
|
+
/**
|
|
19
|
+
* For z.record() - a map with string keys and uniform value types.
|
|
20
|
+
* Unlike objects, we don't have a fixed schema - just coerce each value.
|
|
21
|
+
*/
|
|
22
|
+
export declare function coerceRecord<T>(value: unknown, valueCoercer: PropertyCoercer<T>, ctx: CoerceContext): CoerceResult<Record<string, T>>;
|
|
23
|
+
//# sourceMappingURL=object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../src/coercers/object.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EAKlB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC;AAEzF,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;QAClC,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH;AAMD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5D,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,aAAa,GACjB,YAAY,CAAC,CAAC,CAAC,CAoDjB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,EAChC,GAAG,EAAE,aAAa,GACjB,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAwBjC"}
|