@agimon-ai/foundation-validator 0.2.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/LICENSE +52 -0
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +181 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +181 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: AgiFlow
|
|
6
|
+
Licensed Work: @agimon-ai/public-packages
|
|
7
|
+
The Licensed Work is (c) 2026 AgiFlow.
|
|
8
|
+
Additional Use Grant: None
|
|
9
|
+
Change Date: 2030-03-06
|
|
10
|
+
Change License: Apache License, Version 2.0
|
|
11
|
+
|
|
12
|
+
Terms
|
|
13
|
+
|
|
14
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
15
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
16
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
17
|
+
production use.
|
|
18
|
+
|
|
19
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
20
|
+
available distribution of a specific version of the Licensed Work under this
|
|
21
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
22
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
23
|
+
above terminate.
|
|
24
|
+
|
|
25
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
26
|
+
currently in effect as described in this License, you must purchase a
|
|
27
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
28
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
29
|
+
|
|
30
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
31
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
32
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
33
|
+
for each version of the Licensed Work released by Licensor.
|
|
34
|
+
|
|
35
|
+
You must conspicuously display this License on each original or modified copy
|
|
36
|
+
of the Licensed Work. If you receive the Licensed Work in original or
|
|
37
|
+
modified form from a third party, the terms and conditions set forth in this
|
|
38
|
+
License apply to your use of that work.
|
|
39
|
+
|
|
40
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
41
|
+
terminate your rights under this License for the current and all other
|
|
42
|
+
versions of the Licensed Work.
|
|
43
|
+
|
|
44
|
+
This License does not grant you any right in any trademark or logo of
|
|
45
|
+
Licensor or its affiliates (provided that you may use a trademark or logo of
|
|
46
|
+
Licensor as expressly required by this License).
|
|
47
|
+
|
|
48
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
49
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
|
52
|
+
TITLE.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
let e=require(`zod`);function t(e){return e._def.type??``}function n(e){let r=t(e);if(r===`optional`||r===`nullable`||r===`default`){let t=e._def.innerType;return t?n(t):e}return e}function r(e){let i=n(e),a=t(i);return a===`object`||a===`array`||a===`record`?!0:a===`union`?(i._def.options??[]).some(r):!1}function i(e,t){let n={...e};for(let[e,i]of Object.entries(t.shape)){let t=n[e];if(typeof t==`string`&&r(i))try{n[e]=JSON.parse(t)}catch{}}return n}function a(e){return e._def.type??``}function o(e){return e._def.innerType}function s(e){let t=a(e);return t!==`optional`&&t!==`default`}function c(e){switch(a(e)){case`string`:return`string`;case`number`:return`number`;case`boolean`:return`boolean`;case`bigint`:return`bigint`;case`null`:return`null`;case`undefined`:return`undefined`;case`any`:return`any`;case`unknown`:return`unknown`;case`literal`:return JSON.stringify(e._def.value);case`enum`:return`enum [${(e.options??[]).join(`, `)}]`;case`array`:{let t=e._def.element;return t?`${c(t)}[]`:`unknown[]`}case`record`:{let t=e._def.valueType;return t?`Record<string, ${c(t)}>`:`Record<string, unknown>`}case`object`:return`object`;case`optional`:case`nullable`:case`default`:{let t=o(e);return t?c(t):`unknown`}case`union`:return(e._def.options??[]).map(c).join(` | `);default:return`unknown`}}function l(e){return e.match(/received (\w+)(?:\s|$)/)?.[1]}function u(e){switch(e.code){case`invalid_type`:{let t=e;return l(t.message)===`undefined`?`Required field is missing`:t.message}case`invalid_value`:return`Invalid value — must be one of: ${e.values.join(`, `)}`;case`too_small`:{let t=e;return`Value too small — minimum is ${String(t.minimum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`too_big`:{let t=e;return`Value too large — maximum is ${String(t.maximum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`unrecognized_keys`:return`Unrecognized keys: ${e.keys.join(`, `)}`;default:return e.message}}function d(e,t,n){let r=`--${t}`;switch(e.code){case`invalid_type`:{let t=e,i=l(t.message);return i===`undefined`?`Provide: ${r} <${n?c(n):`value`}>`:i===`string`&&(t.expected===`record`||t.expected===`array`||t.expected===`object`)?`Received a JSON string instead of ${t.expected}.\n → The coercion layer should handle this automatically.\n → CLI usage: ${r} '<json ${t.expected}>'`:void 0}case`invalid_value`:{let t=e.values[0];return`Use: ${r} ${String(t)}`}default:return}}function f(e,t){if(e.length!==0)return t.shape[e[0]]}function p(e,t){let{schemaName:n,schema:r}=t??{},i=new Map;for(let t of e.issues){let e=t.path.length>0?t.path.map(String).join(`.`):`(root)`,n=i.get(e)??[];n.push(t),i.set(e,n)}let a=[n?`Validation failed for "${n}":`:`Validation failed:`];for(let[e,t]of i){a.push(``);let n=r?f(e.split(`.`),r):void 0,i=n?s(n):t.some(e=>{if(e.code!==`invalid_type`)return!1;let t=e.message;return l(t)===`undefined`}),o=n?c(n):``,p=`(${i?`required`:`optional`})${o?` — ${o}`:``}`;a.push(` • ${e} ${p}`);for(let r of t){a.push(` ✗ ${u(r)}`);let t=d(r,e,n);t&&a.push(` → ${t}`)}}return a.join(`
|
|
2
|
+
`)}function m(e){return e._def.type??``}function h(e){return e._def.innerType}function g(e){let t=m(e);if(t===`optional`||t===`nullable`||t===`default`){let t=h(e);return t?g(t):e}return e}function _(e){let t=m(e);return t!==`optional`&&t!==`default`}function v(e){if(m(e)===`default`)return e._def.defaultValue}function y(e){return e.description??``}function b(e){let t=g(e);switch(m(t)){case`boolean`:return`boolean`;case`number`:return`number`;case`object`:case`record`:case`array`:return`json`;case`union`:return(t._def.options??[]).some(e=>{let t=m(g(e));return t===`object`||t===`array`||t===`record`})?`json`:`string`;default:return`string`}}function x(e){let t=g(e);if(m(t)===`enum`)return t.options}function S(e,t){if(t&&t.length>0)return`<${t.join(`|`)}>`;switch(e){case`boolean`:return``;case`number`:return`<number>`;case`json`:return`<json>`;default:return`<string>`}}function C(e,t){let n=b(t),r=x(t),i=v(t),a=y(t);return{flag:`--${e}`,type:n,required:_(t),description:a,default:i,choices:r,typeLabel:c(t)}}const w=36;function T(e,t){return e.length>=t?`${e} `:e.padEnd(t)}function E(e){let t=S(e.type,e.choices),n=t?`${e.flag} ${t}`:e.flag,r=e.type===`json`?` — ${e.typeLabel}`:``,i=e.default===void 0?``:` [default: ${JSON.stringify(e.default)}]`,a=`${e.description}${r}${i}`.trim();return` ${T(n,36)}${a}`}function D(e,t){let n=[],r=t.command??`<tool>`;n.push(`Usage: ${r} [options]`),t.description&&(n.push(``),n.push(t.description));let i=e.filter(e=>e.required),a=e.filter(e=>!e.required);if(i.length>0){n.push(``),n.push(`Required:`);for(let e of i)n.push(E(e))}if(a.length>0){n.push(``),n.push(`Optional:`);for(let e of a)n.push(E(e))}return n.join(`
|
|
3
|
+
`)}function O(e,t){let n=Object.entries(e.shape).map(([e,t])=>C(e,t));return{args:n,help:D(n,t??{})}}function k(e){return(e.startsWith(`--`)?e.slice(2):e).replace(/-([a-z])/gi,(e,t)=>t.toUpperCase())}function A(e,t){let{args:n}=O(t),r=new Map(n.map(e=>[k(e.flag),e])),i=new Map(n.map(e=>[e.flag,e])),a={},o=0;for(;o<e.length;){let t=e[o];if(!t.startsWith(`--`)){o++;continue}if(t.startsWith(`--no-`)){let e=k(t.slice(5));a[e]=!1,o++;continue}let n=t.indexOf(`=`),s,c;n===-1?(s=t,c=void 0):(s=t.slice(0,n),c=t.slice(n+1));let l=k(s),u=r.get(l)??i.get(s);if(u?.type===`boolean`){a[l]=!0,o++;continue}let d;if(c!==void 0)d=c,o++;else if(o+1<e.length&&!e[o+1].startsWith(`--`))d=e[o+1],o+=2;else{a[l]=!0,o++;continue}if(u?.type===`json`)try{a[l]=JSON.parse(d)}catch{a[l]=d}else if(u?.type===`number`){let e=Number.parseFloat(d);a[l]=Number.isNaN(e)?d:e}else a[l]=d}return a}function j(t){if(!t||typeof t!=`object`||Array.isArray(t))return e.z.unknown();let n=t,r=n.anyOf??n.oneOf;if(Array.isArray(r)&&r.length>0){let t=r.map(j);return t.length===1?t[0]:e.z.union([t[0],t[1],...t.slice(2)])}if(Array.isArray(n.enum)&&n.enum.every(e=>typeof e==`string`)){let[t,r,...i]=n.enum;return t===void 0?e.z.unknown():r===void 0?e.z.literal(t):e.z.enum([t,r,...i])}let i=n.type;if(Array.isArray(i)){let t=i.filter(e=>e!==`null`),r=i.includes(`null`);if(t.length===0)return r?e.z.null():e.z.unknown();let a=t.length===1?j({...n,type:t[0]}):e.z.union(t.map(e=>j({...n,type:e})));return r?e.z.union([a,e.z.null()]):a}if(i===`string`)return e.z.string();if(i===`number`||i===`integer`)return e.z.number();if(i===`boolean`)return e.z.boolean();if(i===`null`)return e.z.null();if(i===`array`){let t=n.items?j(n.items):e.z.unknown();return e.z.array(t)}return i===`object`?n.properties&&typeof n.properties==`object`&&!Array.isArray(n.properties)?M(n):e.z.record(e.z.string(),e.z.unknown()):e.z.unknown()}function M(t){let n=t.properties,r=new Set(Array.isArray(t.required)?t.required:[]);if(!n)return e.z.object({});let i={};for(let[e,t]of Object.entries(n)){let n=j(t);i[e]=r.has(e)?n:n.optional()}return e.z.object(i)}exports.cliArgsToObject=A,exports.coerceArgs=i,exports.describeType=c,exports.formatZodError=p,exports.jsonSchemaToZod=M,exports.zodToCliArgs=O;
|
|
4
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["defType","defType","defInnerType","isRequired","lines: string[]","lines: string[]","result: Record<string, unknown>","key","flagToken: string","inlineValue: string | undefined","rawValue: string | undefined","z","shape: Record<string, z.ZodTypeAny>"],"sources":["../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":["import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Zod v4 schema shapes expose $ZodType internally; use a structural interface\n// to avoid the public ZodType vs $ZodType mismatch.\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; options?: ZodLike[] };\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction unwrapZodLike(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = schema._def.innerType;\n return inner ? unwrapZodLike(inner) : schema;\n }\n return schema;\n}\n\nfunction isNonPrimitive(schema: ZodLike): boolean {\n const core = unwrapZodLike(schema);\n const t = defType(core);\n if (t === 'object' || t === 'array' || t === 'record') return true;\n if (t === 'union') {\n return (core._def.options ?? []).some(isNonPrimitive);\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Walks a ZodObject's shape and, for any field that expects a non-primitive\n * type (object, array, record, or union containing one), attempts to\n * JSON.parse string values. Leaves the value unchanged if:\n * - it is not a string\n * - the schema expects a primitive\n * - the string is not valid JSON\n *\n * This handles the common Claude Code behaviour of stringifying nested args\n * (e.g. env: '{\"KEY\":\"val\"}' instead of env: { KEY: 'val' }).\n */\nexport function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const result = { ...args };\n\n for (const [key, rawSchema] of Object.entries(schema.shape)) {\n const value = result[key];\n if (typeof value !== 'string') continue;\n if (!isNonPrimitive(rawSchema as unknown as ZodLike)) continue;\n\n try {\n result[key] = JSON.parse(value);\n } catch {\n // keep as string — not valid JSON\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal schema introspection — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: {\n type?: string;\n innerType?: ZodLike;\n element?: ZodLike;\n valueType?: ZodLike;\n options?: readonly ZodLike[];\n value?: unknown;\n };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\n/**\n * Produces a concise human-readable type label for a Zod schema.\n * Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'\n */\nexport function describeType(schema: ZodLike): string {\n const t = defType(schema);\n switch (t) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'bigint':\n return 'bigint';\n case 'null':\n return 'null';\n case 'undefined':\n return 'undefined';\n case 'any':\n return 'any';\n case 'unknown':\n return 'unknown';\n case 'literal':\n return JSON.stringify(schema._def.value);\n case 'enum': {\n // ZodEnum in v4 exposes .options as a getter\n const opts = (schema as unknown as { options: string[] }).options ?? [];\n return `enum [${opts.join(', ')}]`;\n }\n case 'array': {\n const el = schema._def.element;\n return el ? `${describeType(el)}[]` : 'unknown[]';\n }\n case 'record': {\n const valType = schema._def.valueType;\n return valType ? `Record<string, ${describeType(valType)}>` : 'Record<string, unknown>';\n }\n case 'object':\n return 'object';\n case 'optional':\n case 'nullable':\n case 'default': {\n const inner = defInnerType(schema);\n return inner ? describeType(inner) : 'unknown';\n }\n case 'union': {\n const opts = schema._def.options ?? [];\n return opts.map(describeType).join(' | ');\n }\n default:\n return 'unknown';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Issue formatting — Zod v4 issue shapes\n// ---------------------------------------------------------------------------\n\n// Zod v4 uses 'invalid_value' (not 'invalid_enum_value') for enum violations.\n// Use string cast on issue.code to avoid ZodIssueCode constraint errors.\n\ninterface InvalidTypeIssueV4 {\n code: string;\n expected: string;\n message: string;\n path: (string | number)[];\n}\n\ninterface InvalidValueIssueV4 {\n code: string;\n values: (string | number)[];\n message: string;\n path: (string | number)[];\n}\n\ninterface TooSmallIssueV4 {\n code: string;\n minimum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface TooBigIssueV4 {\n code: string;\n maximum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface UnrecognizedKeysIssueV4 {\n code: string;\n keys: string[];\n message: string;\n path: (string | number)[];\n}\n\nfunction extractReceived(message: string): string | undefined {\n return message.match(/received (\\w+)(?:\\s|$)/)?.[1];\n}\n\nfunction formatIssueMessage(issue: z.ZodIssue): string {\n const code = issue.code as string;\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n if (received === 'undefined') return 'Required field is missing';\n return i.message;\n }\n // Zod v4 uses 'invalid_value' for enum violations\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n return `Invalid value — must be one of: ${i.values.join(', ')}`;\n }\n case 'too_small': {\n const i = issue as unknown as TooSmallIssueV4;\n return `Value too small — minimum is ${String(i.minimum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'too_big': {\n const i = issue as unknown as TooBigIssueV4;\n return `Value too large — maximum is ${String(i.maximum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'unrecognized_keys': {\n const i = issue as unknown as UnrecognizedKeysIssueV4;\n return `Unrecognized keys: ${i.keys.join(', ')}`;\n }\n default:\n return issue.message;\n }\n}\n\nfunction getActionableHint(issue: z.ZodIssue, fieldPath: string, fieldSchema: ZodLike | undefined): string | undefined {\n const flag = `--${fieldPath}`;\n const code = issue.code as string;\n\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n\n if (received === 'undefined') {\n const typeLabel = fieldSchema ? describeType(fieldSchema) : 'value';\n return `Provide: ${flag} <${typeLabel}>`;\n }\n\n if (received === 'string' && (i.expected === 'record' || i.expected === 'array' || i.expected === 'object')) {\n return `Received a JSON string instead of ${i.expected}.\\n → The coercion layer should handle this automatically.\\n → CLI usage: ${flag} '<json ${i.expected}>'`;\n }\n\n return undefined;\n }\n\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n const example = i.values[0];\n return `Use: ${flag} ${String(example)}`;\n }\n\n default:\n return undefined;\n }\n}\n\nfunction getFieldSchema(pathSegments: string[], schema: z.ZodObject<z.ZodRawShape>): ZodLike | undefined {\n if (pathSegments.length === 0) return undefined;\n return schema.shape[pathSegments[0]] as unknown as ZodLike | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodError into a multi-line string optimized for AI agents.\n *\n * Each field with errors shows:\n * - field name, whether it is required/optional, and its expected type\n * - a concise description of what went wrong\n * - a concrete actionable hint (e.g. CLI flag usage)\n *\n * Detecting stringified objects: when the error says \"expected record/array,\n * received string\", it calls out the common Claude Code serialisation issue\n * and explains that the coercion layer should handle it automatically.\n *\n * @example\n * try {\n * schema.parse(args);\n * } catch (err) {\n * if (err instanceof z.ZodError) {\n * console.error(formatZodError(err, { schemaName: 'run_spec', schema }));\n * }\n * }\n */\nexport function formatZodError(\n error: z.ZodError,\n options?: { schemaName?: string; schema?: z.ZodObject<z.ZodRawShape> },\n): string {\n const { schemaName, schema } = options ?? {};\n\n // Group issues by dotted path\n const byPath = new Map<string, z.ZodIssue[]>();\n for (const issue of error.issues) {\n const path = issue.path.length > 0 ? issue.path.map(String).join('.') : '(root)';\n const existing = byPath.get(path) ?? [];\n existing.push(issue);\n byPath.set(path, existing);\n }\n\n const header = schemaName ? `Validation failed for \"${schemaName}\":` : 'Validation failed:';\n const lines: string[] = [header];\n\n for (const [path, issues] of byPath) {\n lines.push('');\n\n const fieldSchema = schema ? getFieldSchema(path.split('.'), schema) : undefined;\n const required = fieldSchema\n ? isRequired(fieldSchema)\n : issues.some((i) => {\n if ((i.code as string) !== 'invalid_type') return false;\n const msg = (i as unknown as { message: string }).message;\n return extractReceived(msg) === 'undefined';\n });\n\n const typeDesc = fieldSchema ? describeType(fieldSchema) : '';\n const meta = `(${required ? 'required' : 'optional'})${typeDesc ? ` — ${typeDesc}` : ''}`;\n\n lines.push(` • ${path} ${meta}`);\n\n for (const issue of issues) {\n lines.push(` ✗ ${formatIssueMessage(issue)}`);\n const hint = getActionableHint(issue, path, fieldSchema);\n if (hint) {\n lines.push(` → ${hint}`);\n }\n }\n }\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\nimport type { CliArgDefinition, CliArgType, CliArgsResult } from '../types/index.js';\nimport { describeType } from './formatZodError.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; defaultValue?: unknown; options?: readonly ZodLike[] };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction unwrapSchema(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = defInnerType(schema);\n return inner ? unwrapSchema(inner) : schema;\n }\n return schema;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\nfunction getDefault(schema: ZodLike): unknown {\n if (defType(schema) === 'default') {\n return schema._def.defaultValue;\n }\n return undefined;\n}\n\nfunction getDescription(schema: ZodLike): string {\n return schema.description ?? '';\n}\n\n/**\n * Maps a Zod schema field to a CliArgType used for help text and parsing.\n */\nfunction resolveCliType(schema: ZodLike): CliArgType {\n const core = unwrapSchema(schema);\n const t = defType(core);\n\n switch (t) {\n case 'boolean':\n return 'boolean';\n case 'number':\n return 'number';\n case 'object':\n case 'record':\n case 'array':\n return 'json';\n case 'union': {\n const opts: readonly ZodLike[] = core._def.options ?? [];\n const hasNonPrimitive = opts.some((o) => {\n const ot = defType(unwrapSchema(o));\n return ot === 'object' || ot === 'array' || ot === 'record';\n });\n return hasNonPrimitive ? 'json' : 'string';\n }\n default:\n return 'string';\n }\n}\n\n/**\n * Returns enum choices if the (unwrapped) schema is a ZodEnum.\n */\nfunction getChoices(schema: ZodLike): string[] | undefined {\n const core = unwrapSchema(schema);\n if (defType(core) === 'enum') {\n return (core as unknown as { options: string[] }).options;\n }\n return undefined;\n}\n\n/**\n * Builds the value placeholder shown in help text, e.g. '<string>', '<json>',\n * '<playwright|extension>'.\n */\nfunction buildValuePlaceholder(argType: CliArgType, choices?: string[]): string {\n if (choices && choices.length > 0) return `<${choices.join('|')}>`;\n switch (argType) {\n case 'boolean':\n return '';\n case 'number':\n return '<number>';\n case 'json':\n return '<json>';\n default:\n return '<string>';\n }\n}\n\n/**\n * Converts a single schema field to a CliArgDefinition.\n */\nfunction fieldToCliArg(key: string, schema: ZodLike): CliArgDefinition {\n const argType = resolveCliType(schema);\n const choices = getChoices(schema);\n const defaultVal = getDefault(schema);\n const desc = getDescription(schema);\n\n return {\n flag: `--${key}`,\n type: argType,\n required: isRequired(schema),\n description: desc,\n default: defaultVal,\n choices,\n typeLabel: describeType(schema),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Help text formatting\n// ---------------------------------------------------------------------------\n\nconst COL_WIDTH = 36;\n\nfunction padEnd(str: string, width: number): string {\n return str.length >= width ? `${str} ` : str.padEnd(width);\n}\n\nfunction renderArg(arg: CliArgDefinition): string {\n const placeholder = buildValuePlaceholder(arg.type, arg.choices);\n const flagPart = placeholder ? `${arg.flag} ${placeholder}` : arg.flag;\n\n const typeAnnotation = arg.type === 'json' ? ` — ${arg.typeLabel}` : '';\n const defaultAnnotation = arg.default !== undefined ? ` [default: ${JSON.stringify(arg.default)}]` : '';\n const description = `${arg.description}${typeAnnotation}${defaultAnnotation}`.trim();\n\n return ` ${padEnd(flagPart, COL_WIDTH)}${description}`;\n}\n\nfunction formatHelp(args: CliArgDefinition[], options: { command?: string; description?: string }): string {\n const lines: string[] = [];\n\n const commandName = options.command ?? '<tool>';\n lines.push(`Usage: ${commandName} [options]`);\n\n if (options.description) {\n lines.push('');\n lines.push(options.description);\n }\n\n const required = args.filter((a) => a.required);\n const optional = args.filter((a) => !a.required);\n\n if (required.length > 0) {\n lines.push('');\n lines.push('Required:');\n for (const arg of required) {\n lines.push(renderArg(arg));\n }\n }\n\n if (optional.length > 0) {\n lines.push('');\n lines.push('Optional:');\n for (const arg of optional) {\n lines.push(renderArg(arg));\n }\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodObject schema to:\n * - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)\n * - `help`: formatted help string equivalent to `--help` output\n *\n * Enables AI agents to inspect a tool's expected arguments as CLI flags,\n * then reconstruct a valid call using {@link cliArgsToObject}.\n *\n * @example\n * const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });\n * console.log(help);\n * // Usage: run_spec [options]\n * //\n * // Required:\n * // --specPath <string> Absolute path to the spec file\n * //\n * // Optional:\n * // --headless Run in headless mode [default: true]\n * // --env <json> Environment variables — Record<string, string>\n */\nexport function zodToCliArgs(\n schema: z.ZodObject<z.ZodRawShape>,\n options?: { command?: string; description?: string },\n): CliArgsResult {\n const args = Object.entries(schema.shape).map(([key, fieldSchema]) =>\n fieldToCliArg(key, fieldSchema as unknown as ZodLike),\n );\n\n const help = formatHelp(args, options ?? {});\n\n return { args, help };\n}\n","import { z } from 'zod';\nimport { zodToCliArgs } from './zodToCliArgs.js';\n\n// ---------------------------------------------------------------------------\n// Key normalisation\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a CLI flag name (without --) to a camelCase object key.\n * Supports both kebab-case and camelCase input:\n * 'spec-path' → 'specPath'\n * 'specPath' → 'specPath'\n * 'base-url' → 'baseURL' (only uppercases the first letter after -)\n */\nfunction flagToKey(flag: string): string {\n // strip leading -- if present\n const raw = flag.startsWith('--') ? flag.slice(2) : flag;\n // kebab-case → camelCase\n return raw.replace(/-([a-z])/gi, (_, c: string) => c.toUpperCase());\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parses a CLI argv array (e.g. process.argv.slice(2)) into a\n * Record<string, unknown> that can be validated by a Zod schema.\n *\n * Uses the schema to determine which flags are booleans (no value expected)\n * and which expect a JSON value (auto-parsed). The result can be passed\n * directly to {@link coerceArgs} or schema.parse().\n *\n * Parsing rules:\n * --flag (boolean in schema) → { flag: true }\n * --no-flag → { flag: false }\n * --key value (json in schema) → { key: JSON.parse(value) }\n * --key value (number in schema) → { key: parseFloat(value) }\n * --key value (string/default) → { key: value }\n * Kebab-case flags are converted to camelCase automatically.\n *\n * @example\n * const obj = cliArgsToObject(\n * ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{\"KEY\":\"val\"}'],\n * RunSpecToolInputSchema,\n * );\n * // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }\n */\nexport function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const { args: argDefs } = zodToCliArgs(schema);\n\n // Build lookup maps: both camelCase and kebab forms → CliArgDefinition\n const byKey = new Map(argDefs.map((d) => [flagToKey(d.flag), d]));\n // Also support kebab-case lookups (the flag already starts with --)\n const byFlag = new Map(argDefs.map((d) => [d.flag, d]));\n\n const result: Record<string, unknown> = {};\n\n let i = 0;\n while (i < argv.length) {\n const token = argv[i];\n\n if (!token.startsWith('--')) {\n i++;\n continue;\n }\n\n // Handle --no-<flag> negation\n if (token.startsWith('--no-')) {\n const key = flagToKey(token.slice(5)); // strip --no-\n result[key] = false;\n i++;\n continue;\n }\n\n // Support --key=value syntax\n const eqIdx = token.indexOf('=');\n let flagToken: string;\n let inlineValue: string | undefined;\n\n if (eqIdx !== -1) {\n flagToken = token.slice(0, eqIdx);\n inlineValue = token.slice(eqIdx + 1);\n } else {\n flagToken = token;\n inlineValue = undefined;\n }\n\n const key = flagToKey(flagToken);\n const argDef = byKey.get(key) ?? byFlag.get(flagToken);\n\n // Boolean flags: presence alone means true\n if (argDef?.type === 'boolean') {\n result[key] = true;\n i++;\n continue;\n }\n\n // Determine the value: inline (--key=val) or next token\n let rawValue: string | undefined;\n if (inlineValue !== undefined) {\n rawValue = inlineValue;\n i++;\n } else if (i + 1 < argv.length && !argv[i + 1].startsWith('--')) {\n rawValue = argv[i + 1];\n i += 2;\n } else {\n // No value token following — treat as boolean true\n result[key] = true;\n i++;\n continue;\n }\n\n // Parse value based on schema type\n if (argDef?.type === 'json') {\n try {\n result[key] = JSON.parse(rawValue);\n } catch {\n result[key] = rawValue;\n }\n } else if (argDef?.type === 'number') {\n const parsed = Number.parseFloat(rawValue);\n result[key] = Number.isNaN(parsed) ? rawValue : parsed;\n } else {\n result[key] = rawValue;\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype JsonSchemaNode = Record<string, unknown>;\n\n/**\n * Convert a single JSON Schema property node to a Zod type.\n * Handles: string, number, integer, boolean, null, array, object,\n * anyOf/oneOf, enum, and array-of-types (e.g. [\"string\",\"null\"]).\n */\nfunction propertyToZod(node: unknown): z.ZodTypeAny {\n if (!node || typeof node !== 'object' || Array.isArray(node)) return z.unknown();\n const n = node as JsonSchemaNode;\n\n // anyOf / oneOf → union\n const variants = (n.anyOf ?? n.oneOf) as unknown[] | undefined;\n if (Array.isArray(variants) && variants.length > 0) {\n const members = variants.map(propertyToZod);\n if (members.length === 1) return members[0];\n return z.union([members[0], members[1], ...members.slice(2)] as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]);\n }\n\n // enum\n if (Array.isArray(n.enum) && n.enum.every((v) => typeof v === 'string')) {\n const [first, second, ...rest] = n.enum as string[];\n if (first === undefined) return z.unknown();\n if (second === undefined) return z.literal(first);\n return z.enum([first, second, ...rest]);\n }\n\n const type = n.type;\n\n // Array-of-types: [\"string\", \"null\"] → optional string\n if (Array.isArray(type)) {\n const nonNull = type.filter((t) => t !== 'null') as string[];\n const nullable = type.includes('null');\n if (nonNull.length === 0) return nullable ? z.null() : z.unknown();\n const inner =\n nonNull.length === 1\n ? propertyToZod({ ...n, type: nonNull[0] })\n : z.union(\n nonNull.map((t) => propertyToZod({ ...n, type: t })) as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]],\n );\n return nullable ? z.union([inner, z.null()]) : inner;\n }\n\n if (type === 'string') return z.string();\n if (type === 'number' || type === 'integer') return z.number();\n if (type === 'boolean') return z.boolean();\n if (type === 'null') return z.null();\n\n if (type === 'array') {\n const items = n.items ? propertyToZod(n.items) : z.unknown();\n return z.array(items);\n }\n\n if (type === 'object') {\n if (n.properties && typeof n.properties === 'object' && !Array.isArray(n.properties)) {\n return jsonSchemaToZod(n);\n }\n return z.record(z.string(), z.unknown());\n }\n\n return z.unknown();\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a JSON Schema object definition to a Zod object schema.\n *\n * Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the\n * common scalar types. Fields not listed in `required` are made optional.\n * Unknown/unsupported nodes map to `z.unknown()`.\n *\n * This is intentionally non-exhaustive: the goal is accurate type\n * classification for coercion (primitive vs non-primitive), not strict\n * schema validation.\n *\n * @example\n * const schema = jsonSchemaToZod({\n * type: 'object',\n * properties: {\n * env: { type: 'object' },\n * headless: { type: 'boolean' },\n * },\n * required: ['env'],\n * });\n * // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)\n * // schema.shape.headless → ZodOptional<ZodBoolean>\n */\nexport function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape> {\n const properties = schema.properties as Record<string, unknown> | undefined;\n const required = new Set<string>(Array.isArray(schema.required) ? (schema.required as string[]) : []);\n\n if (!properties) return z.object({});\n\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(properties)) {\n const zodType = propertyToZod(prop);\n shape[key] = required.has(key) ? zodType : zodType.optional();\n }\n\n return z.object(shape);\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types/index.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Types for foundation-validator utilities
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The CLI type to use when parsing and displaying an argument.
|
|
10
|
+
* - 'string': plain string value
|
|
11
|
+
* - 'number': numeric value (parsed via parseFloat)
|
|
12
|
+
* - 'boolean': flag with no value (presence = true, --no-flag = false)
|
|
13
|
+
* - 'json': JSON-encoded object or array
|
|
14
|
+
*/
|
|
15
|
+
type CliArgType = 'string' | 'number' | 'boolean' | 'json';
|
|
16
|
+
/**
|
|
17
|
+
* A single CLI argument definition derived from a Zod schema field.
|
|
18
|
+
*/
|
|
19
|
+
interface CliArgDefinition {
|
|
20
|
+
/** CLI flag including -- prefix, e.g. '--specPath' */
|
|
21
|
+
flag: string;
|
|
22
|
+
/** Argument value type for parsing */
|
|
23
|
+
type: CliArgType;
|
|
24
|
+
/** Whether this argument is required */
|
|
25
|
+
required: boolean;
|
|
26
|
+
/** Human-readable description */
|
|
27
|
+
description: string;
|
|
28
|
+
/** Default value if any */
|
|
29
|
+
default?: unknown;
|
|
30
|
+
/** Valid choices for enum fields */
|
|
31
|
+
choices?: string[];
|
|
32
|
+
/** Human-readable type label for help text, e.g. 'Record<string, string>' */
|
|
33
|
+
typeLabel: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Result of converting a Zod schema to CLI arg definitions.
|
|
37
|
+
*/
|
|
38
|
+
interface CliArgsResult {
|
|
39
|
+
/** Structured arg definitions for programmatic use */
|
|
40
|
+
args: CliArgDefinition[];
|
|
41
|
+
/** Formatted help string for display (equivalent of --help output) */
|
|
42
|
+
help: string;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/utils/coerceArgs.d.ts
|
|
46
|
+
/**
|
|
47
|
+
* Walks a ZodObject's shape and, for any field that expects a non-primitive
|
|
48
|
+
* type (object, array, record, or union containing one), attempts to
|
|
49
|
+
* JSON.parse string values. Leaves the value unchanged if:
|
|
50
|
+
* - it is not a string
|
|
51
|
+
* - the schema expects a primitive
|
|
52
|
+
* - the string is not valid JSON
|
|
53
|
+
*
|
|
54
|
+
* This handles the common Claude Code behaviour of stringifying nested args
|
|
55
|
+
* (e.g. env: '{"KEY":"val"}' instead of env: { KEY: 'val' }).
|
|
56
|
+
*/
|
|
57
|
+
declare function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/utils/formatZodError.d.ts
|
|
60
|
+
interface ZodLike {
|
|
61
|
+
_def: {
|
|
62
|
+
type?: string;
|
|
63
|
+
innerType?: ZodLike;
|
|
64
|
+
element?: ZodLike;
|
|
65
|
+
valueType?: ZodLike;
|
|
66
|
+
options?: readonly ZodLike[];
|
|
67
|
+
value?: unknown;
|
|
68
|
+
};
|
|
69
|
+
description?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Produces a concise human-readable type label for a Zod schema.
|
|
73
|
+
* Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'
|
|
74
|
+
*/
|
|
75
|
+
declare function describeType(schema: ZodLike): string;
|
|
76
|
+
/**
|
|
77
|
+
* Converts a ZodError into a multi-line string optimized for AI agents.
|
|
78
|
+
*
|
|
79
|
+
* Each field with errors shows:
|
|
80
|
+
* - field name, whether it is required/optional, and its expected type
|
|
81
|
+
* - a concise description of what went wrong
|
|
82
|
+
* - a concrete actionable hint (e.g. CLI flag usage)
|
|
83
|
+
*
|
|
84
|
+
* Detecting stringified objects: when the error says "expected record/array,
|
|
85
|
+
* received string", it calls out the common Claude Code serialisation issue
|
|
86
|
+
* and explains that the coercion layer should handle it automatically.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* try {
|
|
90
|
+
* schema.parse(args);
|
|
91
|
+
* } catch (err) {
|
|
92
|
+
* if (err instanceof z.ZodError) {
|
|
93
|
+
* console.error(formatZodError(err, { schemaName: 'run_spec', schema }));
|
|
94
|
+
* }
|
|
95
|
+
* }
|
|
96
|
+
*/
|
|
97
|
+
declare function formatZodError(error: z.ZodError, options?: {
|
|
98
|
+
schemaName?: string;
|
|
99
|
+
schema?: z.ZodObject<z.ZodRawShape>;
|
|
100
|
+
}): string;
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/utils/zodToCliArgs.d.ts
|
|
103
|
+
/**
|
|
104
|
+
* Converts a ZodObject schema to:
|
|
105
|
+
* - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)
|
|
106
|
+
* - `help`: formatted help string equivalent to `--help` output
|
|
107
|
+
*
|
|
108
|
+
* Enables AI agents to inspect a tool's expected arguments as CLI flags,
|
|
109
|
+
* then reconstruct a valid call using {@link cliArgsToObject}.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });
|
|
113
|
+
* console.log(help);
|
|
114
|
+
* // Usage: run_spec [options]
|
|
115
|
+
* //
|
|
116
|
+
* // Required:
|
|
117
|
+
* // --specPath <string> Absolute path to the spec file
|
|
118
|
+
* //
|
|
119
|
+
* // Optional:
|
|
120
|
+
* // --headless Run in headless mode [default: true]
|
|
121
|
+
* // --env <json> Environment variables — Record<string, string>
|
|
122
|
+
*/
|
|
123
|
+
declare function zodToCliArgs(schema: z.ZodObject<z.ZodRawShape>, options?: {
|
|
124
|
+
command?: string;
|
|
125
|
+
description?: string;
|
|
126
|
+
}): CliArgsResult;
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/utils/cliArgsToObject.d.ts
|
|
129
|
+
/**
|
|
130
|
+
* Parses a CLI argv array (e.g. process.argv.slice(2)) into a
|
|
131
|
+
* Record<string, unknown> that can be validated by a Zod schema.
|
|
132
|
+
*
|
|
133
|
+
* Uses the schema to determine which flags are booleans (no value expected)
|
|
134
|
+
* and which expect a JSON value (auto-parsed). The result can be passed
|
|
135
|
+
* directly to {@link coerceArgs} or schema.parse().
|
|
136
|
+
*
|
|
137
|
+
* Parsing rules:
|
|
138
|
+
* --flag (boolean in schema) → { flag: true }
|
|
139
|
+
* --no-flag → { flag: false }
|
|
140
|
+
* --key value (json in schema) → { key: JSON.parse(value) }
|
|
141
|
+
* --key value (number in schema) → { key: parseFloat(value) }
|
|
142
|
+
* --key value (string/default) → { key: value }
|
|
143
|
+
* Kebab-case flags are converted to camelCase automatically.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const obj = cliArgsToObject(
|
|
147
|
+
* ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{"KEY":"val"}'],
|
|
148
|
+
* RunSpecToolInputSchema,
|
|
149
|
+
* );
|
|
150
|
+
* // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }
|
|
151
|
+
*/
|
|
152
|
+
declare function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/utils/jsonSchemaToZod.d.ts
|
|
155
|
+
/**
|
|
156
|
+
* Convert a JSON Schema object definition to a Zod object schema.
|
|
157
|
+
*
|
|
158
|
+
* Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the
|
|
159
|
+
* common scalar types. Fields not listed in `required` are made optional.
|
|
160
|
+
* Unknown/unsupported nodes map to `z.unknown()`.
|
|
161
|
+
*
|
|
162
|
+
* This is intentionally non-exhaustive: the goal is accurate type
|
|
163
|
+
* classification for coercion (primitive vs non-primitive), not strict
|
|
164
|
+
* schema validation.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* const schema = jsonSchemaToZod({
|
|
168
|
+
* type: 'object',
|
|
169
|
+
* properties: {
|
|
170
|
+
* env: { type: 'object' },
|
|
171
|
+
* headless: { type: 'boolean' },
|
|
172
|
+
* },
|
|
173
|
+
* required: ['env'],
|
|
174
|
+
* });
|
|
175
|
+
* // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)
|
|
176
|
+
* // schema.shape.headless → ZodOptional<ZodBoolean>
|
|
177
|
+
*/
|
|
178
|
+
declare function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape>;
|
|
179
|
+
//#endregion
|
|
180
|
+
export { CliArgDefinition, CliArgType, CliArgsResult, cliArgsToObject, coerceArgs, describeType, formatZodError, jsonSchemaToZod, zodToCliArgs };
|
|
181
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types/index.ts","../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAKA;AAoBA;;;;ACcA;AAAiC,KDvCrB,UAAA,GCuCqB,QAAA,GAAA,QAAA,GAAA,SAAA,GAAA,MAAA;;;;AAAoE,UDlCpF,gBAAA,CCkCoF;;;;EC3C3F,IAAA,EFaF,UEbS;EAGD;EACF,QAAA,EAAA,OAAA;EACE;EACO,WAAA,EAAA,MAAA;EAAO;EAuBd,OAAA,CAAA,EAAA,OAAY;EAgMZ;EACL,OAAA,CAAA,EAAA,MAAA,EAAA;EAC+C;EAAZ,SAAA,EAAA,MAAA;;;;;AC3B9B,UHvKC,aAAA,CGuKW;EACJ;EAAZ,IAAA,EHtKJ,gBGsKI,EAAA;EAET;EAAa,IAAA,EAAA,MAAA;;;;;;AHnMhB;AAKA;AAoBA;;;;ACcA;;;AAAoE,iBAApD,UAAA,CAAoD,IAAA,EAAnC,MAAmC,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,MAAA,EAAF,CAAA,CAAE,SAAA,CAAU,CAAA,CAAE,WAAZ,CAAA,CAAA,EAA2B,MAA3B,CAAA,MAAA,EAAA,OAAA,CAAA;;;UC3C1D,OAAA;;IFIE,IAAA,CAAA,EAAA,MAAU;IAKL,SAAA,CAAA,EEND,OFMiB;IAoBhB,OAAA,CAAA,EEzBH,OFyBgB;gBExBd;uBACO;;EDqCP,CAAA;EAAiB,WAAA,CAAA,EAAA,MAAA;;;;;;iBCdjB,YAAA,SAAqB;;AApCb;;;;;;AAoCxB;AAgMA;;;;;;;;ACzBA;;;;;iBDyBgB,cAAA,QACP,CAAA,CAAE,iBErLX;;WFsL4C,CAAA,CAAE,UAAU,CAAA,CAAE;AEtL1D,CAAA,CAAA,EAAgB,MAAA;;;;AJrChB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;AAaD,iBC8LP,YAAA,CD9LO,MAAA,EC+Lb,CAAA,CAAE,SD/LW,CC+LD,CAAA,CAAE,WD/LD,CAAA,EAAA,OAuNvB,CAvNuB,EAAA;EAAO,OAAA,CAAA,EAAA,MAAA;EAuBd,WAAA,CAAA,EAAA,MAAY;AAgM5B,CAAA,CAAA,ECtBG,aDsBa;;;;;AFzNhB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBEYA,eAAA,CFZ4B,IAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EEYY,CAAA,CAAE,SFZd,CEYwB,CAAA,CAAE,WFZ1B,CAAA,CAAA,EEYyC,MFZzC,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;AFzB5C;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBG4DA,eAAA,CH5D4B,MAAA,EG4DJ,MH5DI,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,EG4DsB,CAAA,CAAE,SH5DxB,CG4DkC,CAAA,CAAE,WH5DpC,CAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/types/index.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Types for foundation-validator utilities
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The CLI type to use when parsing and displaying an argument.
|
|
10
|
+
* - 'string': plain string value
|
|
11
|
+
* - 'number': numeric value (parsed via parseFloat)
|
|
12
|
+
* - 'boolean': flag with no value (presence = true, --no-flag = false)
|
|
13
|
+
* - 'json': JSON-encoded object or array
|
|
14
|
+
*/
|
|
15
|
+
type CliArgType = 'string' | 'number' | 'boolean' | 'json';
|
|
16
|
+
/**
|
|
17
|
+
* A single CLI argument definition derived from a Zod schema field.
|
|
18
|
+
*/
|
|
19
|
+
interface CliArgDefinition {
|
|
20
|
+
/** CLI flag including -- prefix, e.g. '--specPath' */
|
|
21
|
+
flag: string;
|
|
22
|
+
/** Argument value type for parsing */
|
|
23
|
+
type: CliArgType;
|
|
24
|
+
/** Whether this argument is required */
|
|
25
|
+
required: boolean;
|
|
26
|
+
/** Human-readable description */
|
|
27
|
+
description: string;
|
|
28
|
+
/** Default value if any */
|
|
29
|
+
default?: unknown;
|
|
30
|
+
/** Valid choices for enum fields */
|
|
31
|
+
choices?: string[];
|
|
32
|
+
/** Human-readable type label for help text, e.g. 'Record<string, string>' */
|
|
33
|
+
typeLabel: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Result of converting a Zod schema to CLI arg definitions.
|
|
37
|
+
*/
|
|
38
|
+
interface CliArgsResult {
|
|
39
|
+
/** Structured arg definitions for programmatic use */
|
|
40
|
+
args: CliArgDefinition[];
|
|
41
|
+
/** Formatted help string for display (equivalent of --help output) */
|
|
42
|
+
help: string;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/utils/coerceArgs.d.ts
|
|
46
|
+
/**
|
|
47
|
+
* Walks a ZodObject's shape and, for any field that expects a non-primitive
|
|
48
|
+
* type (object, array, record, or union containing one), attempts to
|
|
49
|
+
* JSON.parse string values. Leaves the value unchanged if:
|
|
50
|
+
* - it is not a string
|
|
51
|
+
* - the schema expects a primitive
|
|
52
|
+
* - the string is not valid JSON
|
|
53
|
+
*
|
|
54
|
+
* This handles the common Claude Code behaviour of stringifying nested args
|
|
55
|
+
* (e.g. env: '{"KEY":"val"}' instead of env: { KEY: 'val' }).
|
|
56
|
+
*/
|
|
57
|
+
declare function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/utils/formatZodError.d.ts
|
|
60
|
+
interface ZodLike {
|
|
61
|
+
_def: {
|
|
62
|
+
type?: string;
|
|
63
|
+
innerType?: ZodLike;
|
|
64
|
+
element?: ZodLike;
|
|
65
|
+
valueType?: ZodLike;
|
|
66
|
+
options?: readonly ZodLike[];
|
|
67
|
+
value?: unknown;
|
|
68
|
+
};
|
|
69
|
+
description?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Produces a concise human-readable type label for a Zod schema.
|
|
73
|
+
* Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'
|
|
74
|
+
*/
|
|
75
|
+
declare function describeType(schema: ZodLike): string;
|
|
76
|
+
/**
|
|
77
|
+
* Converts a ZodError into a multi-line string optimized for AI agents.
|
|
78
|
+
*
|
|
79
|
+
* Each field with errors shows:
|
|
80
|
+
* - field name, whether it is required/optional, and its expected type
|
|
81
|
+
* - a concise description of what went wrong
|
|
82
|
+
* - a concrete actionable hint (e.g. CLI flag usage)
|
|
83
|
+
*
|
|
84
|
+
* Detecting stringified objects: when the error says "expected record/array,
|
|
85
|
+
* received string", it calls out the common Claude Code serialisation issue
|
|
86
|
+
* and explains that the coercion layer should handle it automatically.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* try {
|
|
90
|
+
* schema.parse(args);
|
|
91
|
+
* } catch (err) {
|
|
92
|
+
* if (err instanceof z.ZodError) {
|
|
93
|
+
* console.error(formatZodError(err, { schemaName: 'run_spec', schema }));
|
|
94
|
+
* }
|
|
95
|
+
* }
|
|
96
|
+
*/
|
|
97
|
+
declare function formatZodError(error: z.ZodError, options?: {
|
|
98
|
+
schemaName?: string;
|
|
99
|
+
schema?: z.ZodObject<z.ZodRawShape>;
|
|
100
|
+
}): string;
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/utils/zodToCliArgs.d.ts
|
|
103
|
+
/**
|
|
104
|
+
* Converts a ZodObject schema to:
|
|
105
|
+
* - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)
|
|
106
|
+
* - `help`: formatted help string equivalent to `--help` output
|
|
107
|
+
*
|
|
108
|
+
* Enables AI agents to inspect a tool's expected arguments as CLI flags,
|
|
109
|
+
* then reconstruct a valid call using {@link cliArgsToObject}.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });
|
|
113
|
+
* console.log(help);
|
|
114
|
+
* // Usage: run_spec [options]
|
|
115
|
+
* //
|
|
116
|
+
* // Required:
|
|
117
|
+
* // --specPath <string> Absolute path to the spec file
|
|
118
|
+
* //
|
|
119
|
+
* // Optional:
|
|
120
|
+
* // --headless Run in headless mode [default: true]
|
|
121
|
+
* // --env <json> Environment variables — Record<string, string>
|
|
122
|
+
*/
|
|
123
|
+
declare function zodToCliArgs(schema: z.ZodObject<z.ZodRawShape>, options?: {
|
|
124
|
+
command?: string;
|
|
125
|
+
description?: string;
|
|
126
|
+
}): CliArgsResult;
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/utils/cliArgsToObject.d.ts
|
|
129
|
+
/**
|
|
130
|
+
* Parses a CLI argv array (e.g. process.argv.slice(2)) into a
|
|
131
|
+
* Record<string, unknown> that can be validated by a Zod schema.
|
|
132
|
+
*
|
|
133
|
+
* Uses the schema to determine which flags are booleans (no value expected)
|
|
134
|
+
* and which expect a JSON value (auto-parsed). The result can be passed
|
|
135
|
+
* directly to {@link coerceArgs} or schema.parse().
|
|
136
|
+
*
|
|
137
|
+
* Parsing rules:
|
|
138
|
+
* --flag (boolean in schema) → { flag: true }
|
|
139
|
+
* --no-flag → { flag: false }
|
|
140
|
+
* --key value (json in schema) → { key: JSON.parse(value) }
|
|
141
|
+
* --key value (number in schema) → { key: parseFloat(value) }
|
|
142
|
+
* --key value (string/default) → { key: value }
|
|
143
|
+
* Kebab-case flags are converted to camelCase automatically.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const obj = cliArgsToObject(
|
|
147
|
+
* ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{"KEY":"val"}'],
|
|
148
|
+
* RunSpecToolInputSchema,
|
|
149
|
+
* );
|
|
150
|
+
* // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }
|
|
151
|
+
*/
|
|
152
|
+
declare function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown>;
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/utils/jsonSchemaToZod.d.ts
|
|
155
|
+
/**
|
|
156
|
+
* Convert a JSON Schema object definition to a Zod object schema.
|
|
157
|
+
*
|
|
158
|
+
* Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the
|
|
159
|
+
* common scalar types. Fields not listed in `required` are made optional.
|
|
160
|
+
* Unknown/unsupported nodes map to `z.unknown()`.
|
|
161
|
+
*
|
|
162
|
+
* This is intentionally non-exhaustive: the goal is accurate type
|
|
163
|
+
* classification for coercion (primitive vs non-primitive), not strict
|
|
164
|
+
* schema validation.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* const schema = jsonSchemaToZod({
|
|
168
|
+
* type: 'object',
|
|
169
|
+
* properties: {
|
|
170
|
+
* env: { type: 'object' },
|
|
171
|
+
* headless: { type: 'boolean' },
|
|
172
|
+
* },
|
|
173
|
+
* required: ['env'],
|
|
174
|
+
* });
|
|
175
|
+
* // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)
|
|
176
|
+
* // schema.shape.headless → ZodOptional<ZodBoolean>
|
|
177
|
+
*/
|
|
178
|
+
declare function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape>;
|
|
179
|
+
//#endregion
|
|
180
|
+
export { CliArgDefinition, CliArgType, CliArgsResult, cliArgsToObject, coerceArgs, describeType, formatZodError, jsonSchemaToZod, zodToCliArgs };
|
|
181
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/index.ts","../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAKA;AAoBA;;;;ACcA;AAAiC,KDvCrB,UAAA,GCuCqB,QAAA,GAAA,QAAA,GAAA,SAAA,GAAA,MAAA;;;;AAAoE,UDlCpF,gBAAA,CCkCoF;;;;EC3C3F,IAAA,EFaF,UEbS;EAGD;EACF,QAAA,EAAA,OAAA;EACE;EACO,WAAA,EAAA,MAAA;EAAO;EAuBd,OAAA,CAAA,EAAA,OAAY;EAgMZ;EACL,OAAA,CAAA,EAAA,MAAA,EAAA;EAC+C;EAAZ,SAAA,EAAA,MAAA;;;;;AC3B9B,UHvKC,aAAA,CGuKW;EACJ;EAAZ,IAAA,EHtKJ,gBGsKI,EAAA;EAET;EAAa,IAAA,EAAA,MAAA;;;;;;AHnMhB;AAKA;AAoBA;;;;ACcA;;;AAAoE,iBAApD,UAAA,CAAoD,IAAA,EAAnC,MAAmC,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,MAAA,EAAF,CAAA,CAAE,SAAA,CAAU,CAAA,CAAE,WAAZ,CAAA,CAAA,EAA2B,MAA3B,CAAA,MAAA,EAAA,OAAA,CAAA;;;UC3C1D,OAAA;;IFIE,IAAA,CAAA,EAAA,MAAU;IAKL,SAAA,CAAA,EEND,OFMiB;IAoBhB,OAAA,CAAA,EEzBH,OFyBgB;gBExBd;uBACO;;EDqCP,CAAA;EAAiB,WAAA,CAAA,EAAA,MAAA;;;;;;iBCdjB,YAAA,SAAqB;;AApCb;;;;;;AAoCxB;AAgMA;;;;;;;;ACzBA;;;;;iBDyBgB,cAAA,QACP,CAAA,CAAE,iBErLX;;WFsL4C,CAAA,CAAE,UAAU,CAAA,CAAE;AEtL1D,CAAA,CAAA,EAAgB,MAAA;;;;AJrChB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;AAaD,iBC8LP,YAAA,CD9LO,MAAA,EC+Lb,CAAA,CAAE,SD/LW,CC+LD,CAAA,CAAE,WD/LD,CAAA,EAAA,OAuNvB,CAvNuB,EAAA;EAAO,OAAA,CAAA,EAAA,MAAA;EAuBd,WAAA,CAAA,EAAA,MAAY;AAgM5B,CAAA,CAAA,ECtBG,aDsBa;;;;;AFzNhB;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBEYA,eAAA,CFZ4B,IAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EEYY,CAAA,CAAE,SFZd,CEYwB,CAAA,CAAE,WFZ1B,CAAA,CAAA,EEYyC,MFZzC,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;AFzB5C;AAKA;AAoBA;;;;ACcA;;;;;;;;;AClDwB;;;;;;AAoCR,iBG4DA,eAAA,CH5D4B,MAAA,EG4DJ,MH5DI,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,EG4DsB,CAAA,CAAE,SH5DxB,CG4DkC,CAAA,CAAE,WH5DpC,CAAA"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{z as e}from"zod";function t(e){return e._def.type??``}function n(e){let r=t(e);if(r===`optional`||r===`nullable`||r===`default`){let t=e._def.innerType;return t?n(t):e}return e}function r(e){let i=n(e),a=t(i);return a===`object`||a===`array`||a===`record`?!0:a===`union`?(i._def.options??[]).some(r):!1}function i(e,t){let n={...e};for(let[e,i]of Object.entries(t.shape)){let t=n[e];if(typeof t==`string`&&r(i))try{n[e]=JSON.parse(t)}catch{}}return n}function a(e){return e._def.type??``}function o(e){return e._def.innerType}function s(e){let t=a(e);return t!==`optional`&&t!==`default`}function c(e){switch(a(e)){case`string`:return`string`;case`number`:return`number`;case`boolean`:return`boolean`;case`bigint`:return`bigint`;case`null`:return`null`;case`undefined`:return`undefined`;case`any`:return`any`;case`unknown`:return`unknown`;case`literal`:return JSON.stringify(e._def.value);case`enum`:return`enum [${(e.options??[]).join(`, `)}]`;case`array`:{let t=e._def.element;return t?`${c(t)}[]`:`unknown[]`}case`record`:{let t=e._def.valueType;return t?`Record<string, ${c(t)}>`:`Record<string, unknown>`}case`object`:return`object`;case`optional`:case`nullable`:case`default`:{let t=o(e);return t?c(t):`unknown`}case`union`:return(e._def.options??[]).map(c).join(` | `);default:return`unknown`}}function l(e){return e.match(/received (\w+)(?:\s|$)/)?.[1]}function u(e){switch(e.code){case`invalid_type`:{let t=e;return l(t.message)===`undefined`?`Required field is missing`:t.message}case`invalid_value`:return`Invalid value — must be one of: ${e.values.join(`, `)}`;case`too_small`:{let t=e;return`Value too small — minimum is ${String(t.minimum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`too_big`:{let t=e;return`Value too large — maximum is ${String(t.maximum)}${t.inclusive?` (inclusive)`:` (exclusive)`}`}case`unrecognized_keys`:return`Unrecognized keys: ${e.keys.join(`, `)}`;default:return e.message}}function d(e,t,n){let r=`--${t}`;switch(e.code){case`invalid_type`:{let t=e,i=l(t.message);return i===`undefined`?`Provide: ${r} <${n?c(n):`value`}>`:i===`string`&&(t.expected===`record`||t.expected===`array`||t.expected===`object`)?`Received a JSON string instead of ${t.expected}.\n → The coercion layer should handle this automatically.\n → CLI usage: ${r} '<json ${t.expected}>'`:void 0}case`invalid_value`:{let t=e.values[0];return`Use: ${r} ${String(t)}`}default:return}}function f(e,t){if(e.length!==0)return t.shape[e[0]]}function p(e,t){let{schemaName:n,schema:r}=t??{},i=new Map;for(let t of e.issues){let e=t.path.length>0?t.path.map(String).join(`.`):`(root)`,n=i.get(e)??[];n.push(t),i.set(e,n)}let a=[n?`Validation failed for "${n}":`:`Validation failed:`];for(let[e,t]of i){a.push(``);let n=r?f(e.split(`.`),r):void 0,i=n?s(n):t.some(e=>{if(e.code!==`invalid_type`)return!1;let t=e.message;return l(t)===`undefined`}),o=n?c(n):``,p=`(${i?`required`:`optional`})${o?` — ${o}`:``}`;a.push(` • ${e} ${p}`);for(let r of t){a.push(` ✗ ${u(r)}`);let t=d(r,e,n);t&&a.push(` → ${t}`)}}return a.join(`
|
|
2
|
+
`)}function m(e){return e._def.type??``}function h(e){return e._def.innerType}function g(e){let t=m(e);if(t===`optional`||t===`nullable`||t===`default`){let t=h(e);return t?g(t):e}return e}function _(e){let t=m(e);return t!==`optional`&&t!==`default`}function v(e){if(m(e)===`default`)return e._def.defaultValue}function y(e){return e.description??``}function b(e){let t=g(e);switch(m(t)){case`boolean`:return`boolean`;case`number`:return`number`;case`object`:case`record`:case`array`:return`json`;case`union`:return(t._def.options??[]).some(e=>{let t=m(g(e));return t===`object`||t===`array`||t===`record`})?`json`:`string`;default:return`string`}}function x(e){let t=g(e);if(m(t)===`enum`)return t.options}function S(e,t){if(t&&t.length>0)return`<${t.join(`|`)}>`;switch(e){case`boolean`:return``;case`number`:return`<number>`;case`json`:return`<json>`;default:return`<string>`}}function C(e,t){let n=b(t),r=x(t),i=v(t),a=y(t);return{flag:`--${e}`,type:n,required:_(t),description:a,default:i,choices:r,typeLabel:c(t)}}function w(e,t){return e.length>=t?`${e} `:e.padEnd(t)}function T(e){let t=S(e.type,e.choices),n=t?`${e.flag} ${t}`:e.flag,r=e.type===`json`?` — ${e.typeLabel}`:``,i=e.default===void 0?``:` [default: ${JSON.stringify(e.default)}]`,a=`${e.description}${r}${i}`.trim();return` ${w(n,36)}${a}`}function E(e,t){let n=[],r=t.command??`<tool>`;n.push(`Usage: ${r} [options]`),t.description&&(n.push(``),n.push(t.description));let i=e.filter(e=>e.required),a=e.filter(e=>!e.required);if(i.length>0){n.push(``),n.push(`Required:`);for(let e of i)n.push(T(e))}if(a.length>0){n.push(``),n.push(`Optional:`);for(let e of a)n.push(T(e))}return n.join(`
|
|
3
|
+
`)}function D(e,t){let n=Object.entries(e.shape).map(([e,t])=>C(e,t));return{args:n,help:E(n,t??{})}}function O(e){return(e.startsWith(`--`)?e.slice(2):e).replace(/-([a-z])/gi,(e,t)=>t.toUpperCase())}function k(e,t){let{args:n}=D(t),r=new Map(n.map(e=>[O(e.flag),e])),i=new Map(n.map(e=>[e.flag,e])),a={},o=0;for(;o<e.length;){let t=e[o];if(!t.startsWith(`--`)){o++;continue}if(t.startsWith(`--no-`)){let e=O(t.slice(5));a[e]=!1,o++;continue}let n=t.indexOf(`=`),s,c;n===-1?(s=t,c=void 0):(s=t.slice(0,n),c=t.slice(n+1));let l=O(s),u=r.get(l)??i.get(s);if(u?.type===`boolean`){a[l]=!0,o++;continue}let d;if(c!==void 0)d=c,o++;else if(o+1<e.length&&!e[o+1].startsWith(`--`))d=e[o+1],o+=2;else{a[l]=!0,o++;continue}if(u?.type===`json`)try{a[l]=JSON.parse(d)}catch{a[l]=d}else if(u?.type===`number`){let e=Number.parseFloat(d);a[l]=Number.isNaN(e)?d:e}else a[l]=d}return a}function A(t){if(!t||typeof t!=`object`||Array.isArray(t))return e.unknown();let n=t,r=n.anyOf??n.oneOf;if(Array.isArray(r)&&r.length>0){let t=r.map(A);return t.length===1?t[0]:e.union([t[0],t[1],...t.slice(2)])}if(Array.isArray(n.enum)&&n.enum.every(e=>typeof e==`string`)){let[t,r,...i]=n.enum;return t===void 0?e.unknown():r===void 0?e.literal(t):e.enum([t,r,...i])}let i=n.type;if(Array.isArray(i)){let t=i.filter(e=>e!==`null`),r=i.includes(`null`);if(t.length===0)return r?e.null():e.unknown();let a=t.length===1?A({...n,type:t[0]}):e.union(t.map(e=>A({...n,type:e})));return r?e.union([a,e.null()]):a}if(i===`string`)return e.string();if(i===`number`||i===`integer`)return e.number();if(i===`boolean`)return e.boolean();if(i===`null`)return e.null();if(i===`array`){let t=n.items?A(n.items):e.unknown();return e.array(t)}return i===`object`?n.properties&&typeof n.properties==`object`&&!Array.isArray(n.properties)?j(n):e.record(e.string(),e.unknown()):e.unknown()}function j(t){let n=t.properties,r=new Set(Array.isArray(t.required)?t.required:[]);if(!n)return e.object({});let i={};for(let[e,t]of Object.entries(n)){let n=A(t);i[e]=r.has(e)?n:n.optional()}return e.object(i)}export{k as cliArgsToObject,i as coerceArgs,c as describeType,p as formatZodError,j as jsonSchemaToZod,D as zodToCliArgs};
|
|
4
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["defType","defType","defInnerType","isRequired","lines: string[]","lines: string[]","result: Record<string, unknown>","key","flagToken: string","inlineValue: string | undefined","rawValue: string | undefined","shape: Record<string, z.ZodTypeAny>"],"sources":["../src/utils/coerceArgs.ts","../src/utils/formatZodError.ts","../src/utils/zodToCliArgs.ts","../src/utils/cliArgsToObject.ts","../src/utils/jsonSchemaToZod.ts"],"sourcesContent":["import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Zod v4 schema shapes expose $ZodType internally; use a structural interface\n// to avoid the public ZodType vs $ZodType mismatch.\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; options?: ZodLike[] };\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction unwrapZodLike(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = schema._def.innerType;\n return inner ? unwrapZodLike(inner) : schema;\n }\n return schema;\n}\n\nfunction isNonPrimitive(schema: ZodLike): boolean {\n const core = unwrapZodLike(schema);\n const t = defType(core);\n if (t === 'object' || t === 'array' || t === 'record') return true;\n if (t === 'union') {\n return (core._def.options ?? []).some(isNonPrimitive);\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Walks a ZodObject's shape and, for any field that expects a non-primitive\n * type (object, array, record, or union containing one), attempts to\n * JSON.parse string values. Leaves the value unchanged if:\n * - it is not a string\n * - the schema expects a primitive\n * - the string is not valid JSON\n *\n * This handles the common Claude Code behaviour of stringifying nested args\n * (e.g. env: '{\"KEY\":\"val\"}' instead of env: { KEY: 'val' }).\n */\nexport function coerceArgs(args: Record<string, unknown>, schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const result = { ...args };\n\n for (const [key, rawSchema] of Object.entries(schema.shape)) {\n const value = result[key];\n if (typeof value !== 'string') continue;\n if (!isNonPrimitive(rawSchema as unknown as ZodLike)) continue;\n\n try {\n result[key] = JSON.parse(value);\n } catch {\n // keep as string — not valid JSON\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal schema introspection — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: {\n type?: string;\n innerType?: ZodLike;\n element?: ZodLike;\n valueType?: ZodLike;\n options?: readonly ZodLike[];\n value?: unknown;\n };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\n/**\n * Produces a concise human-readable type label for a Zod schema.\n * Examples: 'string', 'string[]', 'Record<string, string>', 'enum [a, b]'\n */\nexport function describeType(schema: ZodLike): string {\n const t = defType(schema);\n switch (t) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'bigint':\n return 'bigint';\n case 'null':\n return 'null';\n case 'undefined':\n return 'undefined';\n case 'any':\n return 'any';\n case 'unknown':\n return 'unknown';\n case 'literal':\n return JSON.stringify(schema._def.value);\n case 'enum': {\n // ZodEnum in v4 exposes .options as a getter\n const opts = (schema as unknown as { options: string[] }).options ?? [];\n return `enum [${opts.join(', ')}]`;\n }\n case 'array': {\n const el = schema._def.element;\n return el ? `${describeType(el)}[]` : 'unknown[]';\n }\n case 'record': {\n const valType = schema._def.valueType;\n return valType ? `Record<string, ${describeType(valType)}>` : 'Record<string, unknown>';\n }\n case 'object':\n return 'object';\n case 'optional':\n case 'nullable':\n case 'default': {\n const inner = defInnerType(schema);\n return inner ? describeType(inner) : 'unknown';\n }\n case 'union': {\n const opts = schema._def.options ?? [];\n return opts.map(describeType).join(' | ');\n }\n default:\n return 'unknown';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Issue formatting — Zod v4 issue shapes\n// ---------------------------------------------------------------------------\n\n// Zod v4 uses 'invalid_value' (not 'invalid_enum_value') for enum violations.\n// Use string cast on issue.code to avoid ZodIssueCode constraint errors.\n\ninterface InvalidTypeIssueV4 {\n code: string;\n expected: string;\n message: string;\n path: (string | number)[];\n}\n\ninterface InvalidValueIssueV4 {\n code: string;\n values: (string | number)[];\n message: string;\n path: (string | number)[];\n}\n\ninterface TooSmallIssueV4 {\n code: string;\n minimum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface TooBigIssueV4 {\n code: string;\n maximum: number | bigint;\n inclusive: boolean;\n message: string;\n path: (string | number)[];\n}\n\ninterface UnrecognizedKeysIssueV4 {\n code: string;\n keys: string[];\n message: string;\n path: (string | number)[];\n}\n\nfunction extractReceived(message: string): string | undefined {\n return message.match(/received (\\w+)(?:\\s|$)/)?.[1];\n}\n\nfunction formatIssueMessage(issue: z.ZodIssue): string {\n const code = issue.code as string;\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n if (received === 'undefined') return 'Required field is missing';\n return i.message;\n }\n // Zod v4 uses 'invalid_value' for enum violations\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n return `Invalid value — must be one of: ${i.values.join(', ')}`;\n }\n case 'too_small': {\n const i = issue as unknown as TooSmallIssueV4;\n return `Value too small — minimum is ${String(i.minimum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'too_big': {\n const i = issue as unknown as TooBigIssueV4;\n return `Value too large — maximum is ${String(i.maximum)}${i.inclusive ? ' (inclusive)' : ' (exclusive)'}`;\n }\n case 'unrecognized_keys': {\n const i = issue as unknown as UnrecognizedKeysIssueV4;\n return `Unrecognized keys: ${i.keys.join(', ')}`;\n }\n default:\n return issue.message;\n }\n}\n\nfunction getActionableHint(issue: z.ZodIssue, fieldPath: string, fieldSchema: ZodLike | undefined): string | undefined {\n const flag = `--${fieldPath}`;\n const code = issue.code as string;\n\n switch (code) {\n case 'invalid_type': {\n const i = issue as unknown as InvalidTypeIssueV4;\n const received = extractReceived(i.message);\n\n if (received === 'undefined') {\n const typeLabel = fieldSchema ? describeType(fieldSchema) : 'value';\n return `Provide: ${flag} <${typeLabel}>`;\n }\n\n if (received === 'string' && (i.expected === 'record' || i.expected === 'array' || i.expected === 'object')) {\n return `Received a JSON string instead of ${i.expected}.\\n → The coercion layer should handle this automatically.\\n → CLI usage: ${flag} '<json ${i.expected}>'`;\n }\n\n return undefined;\n }\n\n case 'invalid_value': {\n const i = issue as unknown as InvalidValueIssueV4;\n const example = i.values[0];\n return `Use: ${flag} ${String(example)}`;\n }\n\n default:\n return undefined;\n }\n}\n\nfunction getFieldSchema(pathSegments: string[], schema: z.ZodObject<z.ZodRawShape>): ZodLike | undefined {\n if (pathSegments.length === 0) return undefined;\n return schema.shape[pathSegments[0]] as unknown as ZodLike | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodError into a multi-line string optimized for AI agents.\n *\n * Each field with errors shows:\n * - field name, whether it is required/optional, and its expected type\n * - a concise description of what went wrong\n * - a concrete actionable hint (e.g. CLI flag usage)\n *\n * Detecting stringified objects: when the error says \"expected record/array,\n * received string\", it calls out the common Claude Code serialisation issue\n * and explains that the coercion layer should handle it automatically.\n *\n * @example\n * try {\n * schema.parse(args);\n * } catch (err) {\n * if (err instanceof z.ZodError) {\n * console.error(formatZodError(err, { schemaName: 'run_spec', schema }));\n * }\n * }\n */\nexport function formatZodError(\n error: z.ZodError,\n options?: { schemaName?: string; schema?: z.ZodObject<z.ZodRawShape> },\n): string {\n const { schemaName, schema } = options ?? {};\n\n // Group issues by dotted path\n const byPath = new Map<string, z.ZodIssue[]>();\n for (const issue of error.issues) {\n const path = issue.path.length > 0 ? issue.path.map(String).join('.') : '(root)';\n const existing = byPath.get(path) ?? [];\n existing.push(issue);\n byPath.set(path, existing);\n }\n\n const header = schemaName ? `Validation failed for \"${schemaName}\":` : 'Validation failed:';\n const lines: string[] = [header];\n\n for (const [path, issues] of byPath) {\n lines.push('');\n\n const fieldSchema = schema ? getFieldSchema(path.split('.'), schema) : undefined;\n const required = fieldSchema\n ? isRequired(fieldSchema)\n : issues.some((i) => {\n if ((i.code as string) !== 'invalid_type') return false;\n const msg = (i as unknown as { message: string }).message;\n return extractReceived(msg) === 'undefined';\n });\n\n const typeDesc = fieldSchema ? describeType(fieldSchema) : '';\n const meta = `(${required ? 'required' : 'optional'})${typeDesc ? ` — ${typeDesc}` : ''}`;\n\n lines.push(` • ${path} ${meta}`);\n\n for (const issue of issues) {\n lines.push(` ✗ ${formatIssueMessage(issue)}`);\n const hint = getActionableHint(issue, path, fieldSchema);\n if (hint) {\n lines.push(` → ${hint}`);\n }\n }\n }\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\nimport type { CliArgDefinition, CliArgType, CliArgsResult } from '../types/index.js';\nimport { describeType } from './formatZodError.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers — Zod v4 compatible\n// ---------------------------------------------------------------------------\n\n// Structural interface compatible with both $ZodType (internal) and ZodType (public)\ninterface ZodLike {\n _def: { type?: string; innerType?: ZodLike; defaultValue?: unknown; options?: readonly ZodLike[] };\n description?: string;\n}\n\nfunction defType(schema: ZodLike): string {\n return schema._def.type ?? '';\n}\n\nfunction defInnerType(schema: ZodLike): ZodLike | undefined {\n return schema._def.innerType;\n}\n\nfunction unwrapSchema(schema: ZodLike): ZodLike {\n const t = defType(schema);\n if (t === 'optional' || t === 'nullable' || t === 'default') {\n const inner = defInnerType(schema);\n return inner ? unwrapSchema(inner) : schema;\n }\n return schema;\n}\n\nfunction isRequired(schema: ZodLike): boolean {\n const t = defType(schema);\n return t !== 'optional' && t !== 'default';\n}\n\nfunction getDefault(schema: ZodLike): unknown {\n if (defType(schema) === 'default') {\n return schema._def.defaultValue;\n }\n return undefined;\n}\n\nfunction getDescription(schema: ZodLike): string {\n return schema.description ?? '';\n}\n\n/**\n * Maps a Zod schema field to a CliArgType used for help text and parsing.\n */\nfunction resolveCliType(schema: ZodLike): CliArgType {\n const core = unwrapSchema(schema);\n const t = defType(core);\n\n switch (t) {\n case 'boolean':\n return 'boolean';\n case 'number':\n return 'number';\n case 'object':\n case 'record':\n case 'array':\n return 'json';\n case 'union': {\n const opts: readonly ZodLike[] = core._def.options ?? [];\n const hasNonPrimitive = opts.some((o) => {\n const ot = defType(unwrapSchema(o));\n return ot === 'object' || ot === 'array' || ot === 'record';\n });\n return hasNonPrimitive ? 'json' : 'string';\n }\n default:\n return 'string';\n }\n}\n\n/**\n * Returns enum choices if the (unwrapped) schema is a ZodEnum.\n */\nfunction getChoices(schema: ZodLike): string[] | undefined {\n const core = unwrapSchema(schema);\n if (defType(core) === 'enum') {\n return (core as unknown as { options: string[] }).options;\n }\n return undefined;\n}\n\n/**\n * Builds the value placeholder shown in help text, e.g. '<string>', '<json>',\n * '<playwright|extension>'.\n */\nfunction buildValuePlaceholder(argType: CliArgType, choices?: string[]): string {\n if (choices && choices.length > 0) return `<${choices.join('|')}>`;\n switch (argType) {\n case 'boolean':\n return '';\n case 'number':\n return '<number>';\n case 'json':\n return '<json>';\n default:\n return '<string>';\n }\n}\n\n/**\n * Converts a single schema field to a CliArgDefinition.\n */\nfunction fieldToCliArg(key: string, schema: ZodLike): CliArgDefinition {\n const argType = resolveCliType(schema);\n const choices = getChoices(schema);\n const defaultVal = getDefault(schema);\n const desc = getDescription(schema);\n\n return {\n flag: `--${key}`,\n type: argType,\n required: isRequired(schema),\n description: desc,\n default: defaultVal,\n choices,\n typeLabel: describeType(schema),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Help text formatting\n// ---------------------------------------------------------------------------\n\nconst COL_WIDTH = 36;\n\nfunction padEnd(str: string, width: number): string {\n return str.length >= width ? `${str} ` : str.padEnd(width);\n}\n\nfunction renderArg(arg: CliArgDefinition): string {\n const placeholder = buildValuePlaceholder(arg.type, arg.choices);\n const flagPart = placeholder ? `${arg.flag} ${placeholder}` : arg.flag;\n\n const typeAnnotation = arg.type === 'json' ? ` — ${arg.typeLabel}` : '';\n const defaultAnnotation = arg.default !== undefined ? ` [default: ${JSON.stringify(arg.default)}]` : '';\n const description = `${arg.description}${typeAnnotation}${defaultAnnotation}`.trim();\n\n return ` ${padEnd(flagPart, COL_WIDTH)}${description}`;\n}\n\nfunction formatHelp(args: CliArgDefinition[], options: { command?: string; description?: string }): string {\n const lines: string[] = [];\n\n const commandName = options.command ?? '<tool>';\n lines.push(`Usage: ${commandName} [options]`);\n\n if (options.description) {\n lines.push('');\n lines.push(options.description);\n }\n\n const required = args.filter((a) => a.required);\n const optional = args.filter((a) => !a.required);\n\n if (required.length > 0) {\n lines.push('');\n lines.push('Required:');\n for (const arg of required) {\n lines.push(renderArg(arg));\n }\n }\n\n if (optional.length > 0) {\n lines.push('');\n lines.push('Optional:');\n for (const arg of optional) {\n lines.push(renderArg(arg));\n }\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a ZodObject schema to:\n * - `args`: structured CliArgDefinition[] for programmatic use (e.g. parsing)\n * - `help`: formatted help string equivalent to `--help` output\n *\n * Enables AI agents to inspect a tool's expected arguments as CLI flags,\n * then reconstruct a valid call using {@link cliArgsToObject}.\n *\n * @example\n * const { help } = zodToCliArgs(RunSpecToolInputSchema, { command: 'run_spec' });\n * console.log(help);\n * // Usage: run_spec [options]\n * //\n * // Required:\n * // --specPath <string> Absolute path to the spec file\n * //\n * // Optional:\n * // --headless Run in headless mode [default: true]\n * // --env <json> Environment variables — Record<string, string>\n */\nexport function zodToCliArgs(\n schema: z.ZodObject<z.ZodRawShape>,\n options?: { command?: string; description?: string },\n): CliArgsResult {\n const args = Object.entries(schema.shape).map(([key, fieldSchema]) =>\n fieldToCliArg(key, fieldSchema as unknown as ZodLike),\n );\n\n const help = formatHelp(args, options ?? {});\n\n return { args, help };\n}\n","import { z } from 'zod';\nimport { zodToCliArgs } from './zodToCliArgs.js';\n\n// ---------------------------------------------------------------------------\n// Key normalisation\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a CLI flag name (without --) to a camelCase object key.\n * Supports both kebab-case and camelCase input:\n * 'spec-path' → 'specPath'\n * 'specPath' → 'specPath'\n * 'base-url' → 'baseURL' (only uppercases the first letter after -)\n */\nfunction flagToKey(flag: string): string {\n // strip leading -- if present\n const raw = flag.startsWith('--') ? flag.slice(2) : flag;\n // kebab-case → camelCase\n return raw.replace(/-([a-z])/gi, (_, c: string) => c.toUpperCase());\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parses a CLI argv array (e.g. process.argv.slice(2)) into a\n * Record<string, unknown> that can be validated by a Zod schema.\n *\n * Uses the schema to determine which flags are booleans (no value expected)\n * and which expect a JSON value (auto-parsed). The result can be passed\n * directly to {@link coerceArgs} or schema.parse().\n *\n * Parsing rules:\n * --flag (boolean in schema) → { flag: true }\n * --no-flag → { flag: false }\n * --key value (json in schema) → { key: JSON.parse(value) }\n * --key value (number in schema) → { key: parseFloat(value) }\n * --key value (string/default) → { key: value }\n * Kebab-case flags are converted to camelCase automatically.\n *\n * @example\n * const obj = cliArgsToObject(\n * ['--specPath', '/tests/foo.spec.ts', '--headless', '--env', '{\"KEY\":\"val\"}'],\n * RunSpecToolInputSchema,\n * );\n * // { specPath: '/tests/foo.spec.ts', headless: true, env: { KEY: 'val' } }\n */\nexport function cliArgsToObject(argv: string[], schema: z.ZodObject<z.ZodRawShape>): Record<string, unknown> {\n const { args: argDefs } = zodToCliArgs(schema);\n\n // Build lookup maps: both camelCase and kebab forms → CliArgDefinition\n const byKey = new Map(argDefs.map((d) => [flagToKey(d.flag), d]));\n // Also support kebab-case lookups (the flag already starts with --)\n const byFlag = new Map(argDefs.map((d) => [d.flag, d]));\n\n const result: Record<string, unknown> = {};\n\n let i = 0;\n while (i < argv.length) {\n const token = argv[i];\n\n if (!token.startsWith('--')) {\n i++;\n continue;\n }\n\n // Handle --no-<flag> negation\n if (token.startsWith('--no-')) {\n const key = flagToKey(token.slice(5)); // strip --no-\n result[key] = false;\n i++;\n continue;\n }\n\n // Support --key=value syntax\n const eqIdx = token.indexOf('=');\n let flagToken: string;\n let inlineValue: string | undefined;\n\n if (eqIdx !== -1) {\n flagToken = token.slice(0, eqIdx);\n inlineValue = token.slice(eqIdx + 1);\n } else {\n flagToken = token;\n inlineValue = undefined;\n }\n\n const key = flagToKey(flagToken);\n const argDef = byKey.get(key) ?? byFlag.get(flagToken);\n\n // Boolean flags: presence alone means true\n if (argDef?.type === 'boolean') {\n result[key] = true;\n i++;\n continue;\n }\n\n // Determine the value: inline (--key=val) or next token\n let rawValue: string | undefined;\n if (inlineValue !== undefined) {\n rawValue = inlineValue;\n i++;\n } else if (i + 1 < argv.length && !argv[i + 1].startsWith('--')) {\n rawValue = argv[i + 1];\n i += 2;\n } else {\n // No value token following — treat as boolean true\n result[key] = true;\n i++;\n continue;\n }\n\n // Parse value based on schema type\n if (argDef?.type === 'json') {\n try {\n result[key] = JSON.parse(rawValue);\n } catch {\n result[key] = rawValue;\n }\n } else if (argDef?.type === 'number') {\n const parsed = Number.parseFloat(rawValue);\n result[key] = Number.isNaN(parsed) ? rawValue : parsed;\n } else {\n result[key] = rawValue;\n }\n }\n\n return result;\n}\n","import { z } from 'zod';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ntype JsonSchemaNode = Record<string, unknown>;\n\n/**\n * Convert a single JSON Schema property node to a Zod type.\n * Handles: string, number, integer, boolean, null, array, object,\n * anyOf/oneOf, enum, and array-of-types (e.g. [\"string\",\"null\"]).\n */\nfunction propertyToZod(node: unknown): z.ZodTypeAny {\n if (!node || typeof node !== 'object' || Array.isArray(node)) return z.unknown();\n const n = node as JsonSchemaNode;\n\n // anyOf / oneOf → union\n const variants = (n.anyOf ?? n.oneOf) as unknown[] | undefined;\n if (Array.isArray(variants) && variants.length > 0) {\n const members = variants.map(propertyToZod);\n if (members.length === 1) return members[0];\n return z.union([members[0], members[1], ...members.slice(2)] as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]);\n }\n\n // enum\n if (Array.isArray(n.enum) && n.enum.every((v) => typeof v === 'string')) {\n const [first, second, ...rest] = n.enum as string[];\n if (first === undefined) return z.unknown();\n if (second === undefined) return z.literal(first);\n return z.enum([first, second, ...rest]);\n }\n\n const type = n.type;\n\n // Array-of-types: [\"string\", \"null\"] → optional string\n if (Array.isArray(type)) {\n const nonNull = type.filter((t) => t !== 'null') as string[];\n const nullable = type.includes('null');\n if (nonNull.length === 0) return nullable ? z.null() : z.unknown();\n const inner =\n nonNull.length === 1\n ? propertyToZod({ ...n, type: nonNull[0] })\n : z.union(\n nonNull.map((t) => propertyToZod({ ...n, type: t })) as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]],\n );\n return nullable ? z.union([inner, z.null()]) : inner;\n }\n\n if (type === 'string') return z.string();\n if (type === 'number' || type === 'integer') return z.number();\n if (type === 'boolean') return z.boolean();\n if (type === 'null') return z.null();\n\n if (type === 'array') {\n const items = n.items ? propertyToZod(n.items) : z.unknown();\n return z.array(items);\n }\n\n if (type === 'object') {\n if (n.properties && typeof n.properties === 'object' && !Array.isArray(n.properties)) {\n return jsonSchemaToZod(n);\n }\n return z.record(z.string(), z.unknown());\n }\n\n return z.unknown();\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a JSON Schema object definition to a Zod object schema.\n *\n * Handles `properties`, `required`, `anyOf`/`oneOf`, `enum`, and the\n * common scalar types. Fields not listed in `required` are made optional.\n * Unknown/unsupported nodes map to `z.unknown()`.\n *\n * This is intentionally non-exhaustive: the goal is accurate type\n * classification for coercion (primitive vs non-primitive), not strict\n * schema validation.\n *\n * @example\n * const schema = jsonSchemaToZod({\n * type: 'object',\n * properties: {\n * env: { type: 'object' },\n * headless: { type: 'boolean' },\n * },\n * required: ['env'],\n * });\n * // schema.shape.env → ZodRecord (non-primitive → will be JSON.parsed if string)\n * // schema.shape.headless → ZodOptional<ZodBoolean>\n */\nexport function jsonSchemaToZod(schema: Record<string, unknown>): z.ZodObject<z.ZodRawShape> {\n const properties = schema.properties as Record<string, unknown> | undefined;\n const required = new Set<string>(Array.isArray(schema.required) ? (schema.required as string[]) : []);\n\n if (!properties) return z.object({});\n\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(properties)) {\n const zodType = propertyToZod(prop);\n shape[key] = required.has(key) ? zodType : zodType.optional();\n }\n\n return z.object(shape);\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agimon-ai/foundation-validator",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Zod-based validation utilities: schema coercion, AI-readable error formatting, and CLI arg conversion",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.mts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"zod": "4.3.6"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/node": "^22.0.0",
|
|
17
|
+
"tsdown": "0.16.1",
|
|
18
|
+
"typescript": "5.9.3",
|
|
19
|
+
"vitest": "4.0.18"
|
|
20
|
+
},
|
|
21
|
+
"author": "Vuong Ngo",
|
|
22
|
+
"license": "BUSL-1.1",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.mts",
|
|
27
|
+
"import": "./dist/index.mjs",
|
|
28
|
+
"require": "./dist/index.cjs"
|
|
29
|
+
},
|
|
30
|
+
"./*": "./*"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsdown",
|
|
38
|
+
"test": "vitest run --coverage.enabled=false",
|
|
39
|
+
"lint": "eslint src",
|
|
40
|
+
"fixcode": "pnpm exec biome check --write",
|
|
41
|
+
"typecheck": "tsc --noEmit"
|
|
42
|
+
}
|
|
43
|
+
}
|