@cleverbrush/schema-json 4.0.0 → 4.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/README.md CHANGED
@@ -116,7 +116,7 @@ const schema = fromJsonSchema(S); // ObjectSchemaBuilder<{ x: NumberSchemaBuilde
116
116
  | `enum` | `union(…)` of const builders |
117
117
  | `anyOf` | `union(…)` of sub-builders |
118
118
  | `anyOf` + `discriminator` | auto-emitted for discriminated `union()` branches (see below) |
119
- | `allOf` | not supported falls back to `any()` |
119
+ | `allOf` | `intersection(...)`chains sub-schemas via the `intersection()` builder |
120
120
  | `minLength` / `maxLength` | `.minLength()` / `.maxLength()` |
121
121
  | `pattern` | `.matches(regex)` (invalid patterns silently ignored) |
122
122
  | `minimum` / `maximum` | `.min()` / `.max()` |
@@ -288,7 +288,6 @@ type B = JsonSchemaNodeToBuilder<typeof S>;
288
288
  | `$ref` / `$defs` | Not supported in `fromJsonSchema` |
289
289
  | `if` / `then` / `else` | Not supported |
290
290
  | `not` | Not supported |
291
- | `allOf` in `fromJsonSchema` | Falls back to `SchemaBuilder<unknown>` (no deep merge) |
292
291
  | Dual IP format (`ip()` with both v4 + v6) | `format` is omitted in `toJsonSchema` output (no standard keyword covers both) |
293
292
  | JSDoc comments on properties | Not preserved in `toJsonSchema` output |
294
293
  | `nameResolver` + `$ref` / `$defs` round-trip | `nameResolver` emits `$ref` pointers based on external registry; `fromJsonSchema` does not resolve `$ref` references — they fall back to `any()` |
@@ -37,9 +37,8 @@ import type { JsonSchemaNodeToBuilder } from './types.js';
37
37
  * | `format: 'ipv6'` | `.ip({ version: 'v6' })` |
38
38
  * | `format: 'date-time'` | `.matches(iso8601 regex)` |
39
39
  *
40
- * Keywords **not** supported: `allOf` (falls back to `any()`), `$ref`,
41
- * `$defs`, `if/then/else`, `not`, `contains`, `unevaluatedProperties`,
42
- * `contentEncoding`.
40
+ * Keywords **not** supported: `$ref`, `$defs`, `if/then/else`, `not`,
41
+ * `contains`, `unevaluatedProperties`, `contentEncoding`.
43
42
  *
44
43
  * @param schema - A JSON Schema literal. Pass with `as const` for precise
45
44
  * TypeScript type inference on the returned builder.
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{any as f,array as j,boolean as R,nul as q,number as b,object as I,string as v,tuple as V,union as T}from"@cleverbrush/schema";function O(n){return{valid:!1,errors:[{message:n}]}}function x(){return{valid:!0,errors:[]}}function m(n){if(typeof n!="object"||n===null)return f();let t=n,e;if("enum"in t&&Array.isArray(t.enum))e=M(t.enum);else if("const"in t)e=k(t.const);else if("anyOf"in t&&Array.isArray(t.anyOf))e=C(t.anyOf);else if("allOf"in t&&Array.isArray(t.allOf))e=f();else if(!("type"in t))e=f();else switch(t.type){case"string":e=A(t);break;case"number":e=B(t,!1);break;case"integer":e=B(t,!0);break;case"boolean":e=R();break;case"null":e=q();break;case"array":e=P(t);break;case"object":e=E(t);break;default:e=f()}return t.readOnly===!0&&(e=e.readonly()),typeof t.description=="string"&&t.description&&(e=e.describe(t.description)),e}function k(n){return typeof n=="string"?v(n):typeof n=="number"?b(n):typeof n=="boolean"?R().equals(n):f()}function A(n){let t=v(),e=n.format;if(e==="email"?t=t.email():e==="uuid"?t=t.uuid():e==="uri"||e==="url"?t=t.url():e==="ipv4"?t=t.ip({version:"v4"}):e==="ipv6"?t=t.ip({version:"v6"}):e==="date-time"&&(t=t.addValidator(r=>typeof r=="string"&&!Number.isNaN(Date.parse(r))?x():O("must be a valid date-time string"))),typeof n.minLength=="number"&&(t=t.minLength(n.minLength)),typeof n.maxLength=="number"&&(t=t.maxLength(n.maxLength)),typeof n.pattern=="string")try{t=t.matches(new RegExp(n.pattern))}catch{}return t}function B(n,t){let e=t?b().isInteger():b().isFloat();if(typeof n.minimum=="number"&&(e=e.min(n.minimum)),typeof n.maximum=="number"&&(e=e.max(n.maximum)),typeof n.multipleOf=="number"&&(e=e.multipleOf(n.multipleOf)),typeof n.exclusiveMinimum=="number"){let r=n.exclusiveMinimum;e=e.addValidator(i=>typeof i=="number"&&i>r?x():O(`must be greater than ${r}`))}if(typeof n.exclusiveMaximum=="number"){let r=n.exclusiveMaximum;e=e.addValidator(i=>typeof i=="number"&&i<r?x():O(`must be less than ${r}`))}return e}function P(n){if(Array.isArray(n.prefixItems)){let e=n.prefixItems.map(m),r=V(e);return n.items!==void 0&&n.items!==!1&&typeof n.items=="object"&&(r=r.rest(m(n.items))),r}let t=j();return n.items!==void 0&&(t=t.of(m(n.items))),typeof n.minItems=="number"&&(t=t.minLength(n.minItems)),typeof n.maxItems=="number"&&(t=t.maxLength(n.maxItems)),t}function E(n){let t=n.properties,e=new Set(Array.isArray(n.required)?n.required:[]),r=I();if(t)for(let[i,a]of Object.entries(t)){let s=m(a);r=r.addProp(i,e.has(i)?s.required():s.optional())}return n.additionalProperties!==!1&&(r=r.acceptUnknownProps()),r}function M(n){if(n.length===0)return f();let[t,...e]=n,r=T(k(t));for(let i of e)r=r.or(k(i));return r}function C(n){if(n.length===0)return f();let[t,...e]=n,r=T(m(t));for(let i of e)r=r.or(m(i));return r}function W(n){return m(n)}function L(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function D(n){return n.replace(/~/g,"~0").replace(/\//g,"~1")}function F(n,t){let e=n.introspect(),r=e.extensions??{},i=e.isReadonly===!0?{readOnly:!0}:{};switch(e.type){case"string":{if(e.equalsTo!==void 0)return{...i,const:e.equalsTo};let a={...i,type:"string"};if(r.email===!0)a.format="email";else if(r.uuid===!0)a.format="uuid";else if(r.url)a.format="uri";else if(r.ip){let s=typeof r.ip=="object"?r.ip.version:void 0;s==="v4"?a.format="ipv4":s==="v6"&&(a.format="ipv6")}if(e.minLength!==void 0&&(a.minLength=e.minLength),e.maxLength!==void 0&&(a.maxLength=e.maxLength),r.nonempty===!0&&a.minLength===void 0&&(a.minLength=1),e.matches instanceof RegExp){if(e.matches.flags!=="")throw new Error(`Cannot convert RegExp /${e.matches.source}/${e.matches.flags} to JSON Schema pattern: RegExp flags are not representable in standard JSON Schema.`);a.pattern=e.matches.source}else e.startsWith!==void 0?a.pattern=`^${L(e.startsWith)}`:e.endsWith!==void 0&&(a.pattern=`${L(e.endsWith)}$`);return Array.isArray(r.oneOf)&&r.oneOf.length>0&&(a.enum=[...r.oneOf]),a}case"number":{if(e.equalsTo!==void 0)return{...i,const:e.equalsTo};let a={...i,type:e.isInteger?"integer":"number"};return e.min!==void 0&&(a.minimum=e.min),e.max!==void 0&&(a.maximum=e.max),r.multipleOf!==void 0&&(a.multipleOf=r.multipleOf),r.positive===!0&&(a.exclusiveMinimum=0),r.negative===!0&&(a.exclusiveMaximum=0),Array.isArray(r.oneOf)&&r.oneOf.length>0&&(a.enum=[...r.oneOf]),a}case"boolean":return e.equalsTo!==void 0?{...i,const:e.equalsTo}:{...i,type:"boolean"};case"date":return{...i,type:"string",format:"date-time"};case"array":{let a={...i,type:"array"};return e.elementSchema&&(a.items=c(e.elementSchema,t)),e.minLength!==void 0&&(a.minItems=e.minLength),e.maxLength!==void 0&&(a.maxItems=e.maxLength),r.nonempty===!0&&a.minItems===void 0&&(a.minItems=1),a}case"tuple":{let a=e.elements??[],s={type:"array",prefixItems:a.map(u=>c(u,t)),minItems:a.length};return e.restSchema?s.items=c(e.restSchema,t):(s.items=!1,s.maxItems=a.length),s}case"object":{let a={...i,type:"object"},s=e.properties;if(s){let u={},l=[];for(let[y,d]of Object.entries(s))u[y]=c(d,t),d.introspect().isRequired!==!1&&l.push(y);a.properties=u,l.length>0&&(a.required=l)}return e.acceptUnknownProps===!1&&(a.additionalProperties=!1),a}case"null":return{...i,type:"null"};case"union":{let a=e.options??[],s=[],u=a.length>0;for(let p of a){let o=p.introspect();if((o.type==="string"||o.type==="number"||o.type==="boolean")&&o.equalsTo!==void 0)s.push(o.equalsTo);else{u=!1;break}}if(u)return{...i,enum:s};let l=a.map(p=>c(p,t)),y={...i,anyOf:l},d=e.discriminatorPropertyName;if(d){let p={propertyName:d},o={},h=a.length>0;for(let g=0;g<a.length;g++){let w=l[g].$ref;if(typeof w!="string"){h=!1;break}let N=a[g].introspect().properties?.[d];if(!N){h=!1;break}let J=N.introspect();if(J.equalsTo===void 0){h=!1;break}o[String(J.equalsTo)]=w}h&&(p.mapping=o),y.discriminator=p}return y}case"lazy":{let a=e.getter();return c(a,t)}default:return{}}}function c(n,t){if(t){let i=t(n);if(typeof i=="string"&&i.length>0)return{$ref:`#/components/schemas/${D(i)}`}}let e=F(n,t),r=n.introspect();if(typeof r.description=="string"&&r.description!==""&&(e.description=r.description),r.example!==void 0&&(e.examples=[r.example]),r.hasDefault===!0&&r.defaultValue!==void 0&&typeof r.defaultValue!="function"&&(e.default=r.defaultValue),r.isNullable===!0){if(e.anyOf!==void 0){let i=e.anyOf;i.some(s=>s.type==="null")||i.push({type:"null"})}else if(e.enum!==void 0){let i=e.enum;i.includes(null)||(e.enum=[...i,null])}else if(typeof e.type=="string")e.type=[e.type,"null"];else if(e.const!==void 0){let i=e.const;delete e.const,e.anyOf=[{const:i},{type:"null"}]}}return e}function S(n,t){let e=c(n,t?.nameResolver);return t?.$schema===!1?e:{$schema:(t?.draft??"2020-12")==="07"?"http://json-schema.org/draft-07/schema#":"https://json-schema.org/draft/2020-12/schema",...e}}function $(n){switch(n){case"draft-2020-12":return{draft:"2020-12",$schema:!1};case"draft-07":return{draft:"07",$schema:!1};case"openapi-3.0":return{draft:"07",$schema:!1};default:throw new Error(`@cleverbrush/schema-json: unsupported JSON Schema target "${n}".`)}}function U(n){let t={input(i){return S(n,$(i.target))},output(i){return S(n,$(i.target))}},r={...n["~standard"],jsonSchema:t};return Object.defineProperty(n,"~standard",{value:r,configurable:!0,writable:!1,enumerable:!1}),n}export{W as fromJsonSchema,S as toJsonSchema,U as withStandardJsonSchema};
1
+ import{any as c,array as j,boolean as R,intersection as q,nul as I,number as b,object as V,string as T,tuple as A,union as v}from"@cleverbrush/schema";function O(n){return{valid:!1,errors:[{message:n}]}}function x(){return{valid:!0,errors:[]}}function o(n){if(typeof n!="object"||n===null)return c();let t=n,e;if("enum"in t&&Array.isArray(t.enum))e=C(t.enum);else if("const"in t)e=k(t.const);else if("anyOf"in t&&Array.isArray(t.anyOf))e=W(t.anyOf);else if("allOf"in t&&Array.isArray(t.allOf))e=D(t.allOf);else if(!("type"in t))e=c();else switch(t.type){case"string":e=P(t);break;case"number":e=J(t,!1);break;case"integer":e=J(t,!0);break;case"boolean":e=R();break;case"null":e=I();break;case"array":e=E(t);break;case"object":e=M(t);break;default:e=c()}return t.readOnly===!0&&(e=e.readonly()),typeof t.description=="string"&&t.description&&(e=e.describe(t.description)),e}function k(n){return typeof n=="string"?T(n):typeof n=="number"?b(n):typeof n=="boolean"?R().equals(n):c()}function P(n){let t=T(),e=n.format;if(e==="email"?t=t.email():e==="uuid"?t=t.uuid():e==="uri"||e==="url"?t=t.url():e==="ipv4"?t=t.ip({version:"v4"}):e==="ipv6"?t=t.ip({version:"v6"}):e==="date-time"&&(t=t.addValidator(r=>typeof r=="string"&&!Number.isNaN(Date.parse(r))?x():O("must be a valid date-time string"))),typeof n.minLength=="number"&&(t=t.minLength(n.minLength)),typeof n.maxLength=="number"&&(t=t.maxLength(n.maxLength)),typeof n.pattern=="string")try{t=t.matches(new RegExp(n.pattern))}catch{}return t}function J(n,t){let e=t?b().isInteger():b().isFloat();if(typeof n.minimum=="number"&&(e=e.min(n.minimum)),typeof n.maximum=="number"&&(e=e.max(n.maximum)),typeof n.multipleOf=="number"&&(e=e.multipleOf(n.multipleOf)),typeof n.exclusiveMinimum=="number"){let r=n.exclusiveMinimum;e=e.addValidator(i=>typeof i=="number"&&i>r?x():O(`must be greater than ${r}`))}if(typeof n.exclusiveMaximum=="number"){let r=n.exclusiveMaximum;e=e.addValidator(i=>typeof i=="number"&&i<r?x():O(`must be less than ${r}`))}return e}function E(n){if(Array.isArray(n.prefixItems)){let e=n.prefixItems.map(o),r=A(e);return n.items!==void 0&&n.items!==!1&&typeof n.items=="object"&&(r=r.rest(o(n.items))),r}let t=j();return n.items!==void 0&&(t=t.of(o(n.items))),typeof n.minItems=="number"&&(t=t.minLength(n.minItems)),typeof n.maxItems=="number"&&(t=t.maxLength(n.maxItems)),t}function M(n){let t=n.properties,e=new Set(Array.isArray(n.required)?n.required:[]),r=V();if(t)for(let[i,a]of Object.entries(t)){let s=o(a);r=r.addProp(i,e.has(i)?s.required():s.optional())}return n.additionalProperties!==!1&&(r=r.acceptUnknownProps()),r}function C(n){if(n.length===0)return c();let[t,...e]=n,r=v(k(t));for(let i of e)r=r.or(k(i));return r}function W(n){if(n.length===0)return c();let[t,...e]=n,r=v(o(t));for(let i of e)r=r.or(o(i));return r}function D(n){if(n.length===0)return c();let t=o(n[0]);for(let e=1;e<n.length;e++)t=q(t,o(n[e]));return t}function F(n){return o(n)}function L(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function U(n){return n.replace(/~/g,"~0").replace(/\//g,"~1")}function z(n,t){let e=n.introspect(),r=e.extensions??{},i=e.isReadonly===!0?{readOnly:!0}:{};switch(e.type){case"string":{if(e.equalsTo!==void 0)return{...i,const:e.equalsTo};let a={...i,type:"string"};if(r.email===!0)a.format="email";else if(r.uuid===!0)a.format="uuid";else if(r.url)a.format="uri";else if(r.ip){let s=typeof r.ip=="object"?r.ip.version:void 0;s==="v4"?a.format="ipv4":s==="v6"&&(a.format="ipv6")}if(e.minLength!==void 0&&(a.minLength=e.minLength),e.maxLength!==void 0&&(a.maxLength=e.maxLength),r.nonempty===!0&&a.minLength===void 0&&(a.minLength=1),e.matches instanceof RegExp){if(e.matches.flags!=="")throw new Error(`Cannot convert RegExp /${e.matches.source}/${e.matches.flags} to JSON Schema pattern: RegExp flags are not representable in standard JSON Schema.`);a.pattern=e.matches.source}else e.startsWith!==void 0?a.pattern=`^${L(e.startsWith)}`:e.endsWith!==void 0&&(a.pattern=`${L(e.endsWith)}$`);return Array.isArray(r.oneOf)&&r.oneOf.length>0&&(a.enum=[...r.oneOf]),a}case"number":{if(e.equalsTo!==void 0)return{...i,const:e.equalsTo};let a={...i,type:e.isInteger?"integer":"number"};return e.min!==void 0&&(a.minimum=e.min),e.max!==void 0&&(a.maximum=e.max),r.multipleOf!==void 0&&(a.multipleOf=r.multipleOf),r.positive===!0&&(a.exclusiveMinimum=0),r.negative===!0&&(a.exclusiveMaximum=0),Array.isArray(r.oneOf)&&r.oneOf.length>0&&(a.enum=[...r.oneOf]),a}case"boolean":return e.equalsTo!==void 0?{...i,const:e.equalsTo}:{...i,type:"boolean"};case"date":return{...i,type:"string",format:"date-time"};case"array":{let a={...i,type:"array"};return e.elementSchema&&(a.items=u(e.elementSchema,t)),e.minLength!==void 0&&(a.minItems=e.minLength),e.maxLength!==void 0&&(a.maxItems=e.maxLength),r.nonempty===!0&&a.minItems===void 0&&(a.minItems=1),a}case"tuple":{let a=e.elements??[],s={type:"array",prefixItems:a.map(m=>u(m,t)),minItems:a.length};return e.restSchema?s.items=u(e.restSchema,t):(s.items=!1,s.maxItems=a.length),s}case"object":{let a={...i,type:"object"},s=e.properties;if(s){let m={},l=[];for(let[y,d]of Object.entries(s))m[y]=u(d,t),d.introspect().isRequired!==!1&&l.push(y);a.properties=m,l.length>0&&(a.required=l)}return e.acceptUnknownProps===!1&&(a.additionalProperties=!1),a}case"null":return{...i,type:"null"};case"union":{let a=e.options??[],s=[],m=a.length>0;for(let p of a){let f=p.introspect();if((f.type==="string"||f.type==="number"||f.type==="boolean")&&f.equalsTo!==void 0)s.push(f.equalsTo);else{m=!1;break}}if(m)return{...i,enum:s};let l=a.map(p=>u(p,t)),y={...i,anyOf:l},d=e.discriminatorPropertyName;if(d){let p={propertyName:d},f={},h=a.length>0;for(let g=0;g<a.length;g++){let w=l[g].$ref;if(typeof w!="string"){h=!1;break}let B=a[g].introspect().properties?.[d];if(!B){h=!1;break}let N=B.introspect();if(N.equalsTo===void 0){h=!1;break}f[String(N.equalsTo)]=w}h&&(p.mapping=f),y.discriminator=p}return y}case"intersection":{let a=e.left,s=e.right;return{...i,allOf:[u(a,t),u(s,t)]}}case"lazy":{let a=e.getter();return u(a,t)}default:return{}}}function u(n,t){if(t){let i=t(n);if(typeof i=="string"&&i.length>0)return{$ref:`#/components/schemas/${U(i)}`}}let e=z(n,t),r=n.introspect();if(typeof r.description=="string"&&r.description!==""&&(e.description=r.description),r.example!==void 0&&(e.examples=[r.example]),r.hasDefault===!0&&r.defaultValue!==void 0&&typeof r.defaultValue!="function"&&(e.default=r.defaultValue),r.isNullable===!0){if(e.anyOf!==void 0){let i=e.anyOf;i.some(s=>s.type==="null")||i.push({type:"null"})}else if(e.allOf!==void 0&&e.type===void 0)e.oneOf=[{allOf:e.allOf},{type:"null"}],delete e.allOf;else if(e.enum!==void 0){let i=e.enum;i.includes(null)||(e.enum=[...i,null])}else if(typeof e.type=="string")e.type=[e.type,"null"];else if(e.const!==void 0){let i=e.const;delete e.const,e.anyOf=[{const:i},{type:"null"}]}}return e}function S(n,t){let e=u(n,t?.nameResolver);return t?.$schema===!1?e:{$schema:(t?.draft??"2020-12")==="07"?"http://json-schema.org/draft-07/schema#":"https://json-schema.org/draft/2020-12/schema",...e}}function $(n){switch(n){case"draft-2020-12":return{draft:"2020-12",$schema:!1};case"draft-07":return{draft:"07",$schema:!1};case"openapi-3.0":return{draft:"07",$schema:!1};default:throw new Error(`@cleverbrush/schema-json: unsupported JSON Schema target "${n}".`)}}function G(n){let t={input(i){return S(n,$(i.target))},output(i){return S(n,$(i.target))}},r={...n["~standard"],jsonSchema:t};return Object.defineProperty(n,"~standard",{value:r,configurable:!0,writable:!1,enumerable:!1}),n}export{F as fromJsonSchema,S as toJsonSchema,G as withStandardJsonSchema};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/fromJsonSchema.ts","../src/toJsonSchema.ts","../src/standardJsonSchema.ts"],"sourcesContent":["import type { SchemaBuilder } from '@cleverbrush/schema';\nimport {\n any,\n array,\n boolean,\n nul,\n number,\n object,\n string,\n tuple,\n union\n} from '@cleverbrush/schema';\nimport type { JsonSchemaNodeToBuilder } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction fail(msg: string) {\n return { valid: false as const, errors: [{ message: msg }] };\n}\n\nfunction ok() {\n return { valid: true as const, errors: [] };\n}\n\nfunction buildNode(s: unknown): SchemaBuilder<any, any, any> {\n if (typeof s !== 'object' || s === null) return any();\n const node = s as Record<string, unknown>;\n\n let b: SchemaBuilder<any, any, any>;\n\n if ('enum' in node && Array.isArray(node['enum']))\n b = buildEnum(node['enum']);\n else if ('const' in node) b = buildConst(node['const']);\n else if ('anyOf' in node && Array.isArray(node['anyOf']))\n b = buildAnyOf(node['anyOf']);\n // allOf is not supported (no intersection builder); fall back to any()\n else if ('allOf' in node && Array.isArray(node['allOf'])) b = any();\n else if (!('type' in node)) b = any();\n else {\n switch (node['type']) {\n case 'string':\n b = buildString(node);\n break;\n case 'number':\n b = buildNumber(node, false);\n break;\n case 'integer':\n b = buildNumber(node, true);\n break;\n case 'boolean':\n b = boolean();\n break;\n case 'null':\n b = nul();\n break;\n case 'array':\n b = buildArray(node);\n break;\n case 'object':\n b = buildObject(node);\n break;\n default:\n b = any();\n }\n }\n\n if (node['readOnly'] === true) b = (b as any).readonly();\n if (typeof node['description'] === 'string' && node['description'])\n b = (b as any).describe(node['description']);\n return b;\n}\n\nfunction buildConst(val: unknown): SchemaBuilder<any, any, any> {\n if (typeof val === 'string') return string(val as any);\n if (typeof val === 'number') return number(val as any);\n if (typeof val === 'boolean') return boolean().equals(val);\n return any();\n}\n\nfunction buildString(\n node: Record<string, unknown>\n): SchemaBuilder<any, any, any> {\n let b: any = string();\n const format = node['format'] as string | undefined;\n\n if (format === 'email') {\n b = b.email();\n } else if (format === 'uuid') {\n b = b.uuid();\n } else if (format === 'uri' || format === 'url') {\n b = b.url();\n } else if (format === 'ipv4') {\n b = b.ip({ version: 'v4' });\n } else if (format === 'ipv6') {\n b = b.ip({ version: 'v6' });\n } else if (format === 'date-time') {\n b = b.addValidator((v: unknown) =>\n typeof v === 'string' && !Number.isNaN(Date.parse(v))\n ? ok()\n : fail('must be a valid date-time string')\n );\n }\n\n if (typeof node['minLength'] === 'number')\n b = b.minLength(node['minLength']);\n if (typeof node['maxLength'] === 'number')\n b = b.maxLength(node['maxLength']);\n if (typeof node['pattern'] === 'string') {\n try {\n b = b.matches(new RegExp(node['pattern']));\n } catch {\n // invalid regex pattern — silently ignore\n }\n }\n return b;\n}\n\nfunction buildNumber(\n node: Record<string, unknown>,\n integer: boolean\n): SchemaBuilder<any, any, any> {\n let b: any = integer ? number().isInteger() : number().isFloat();\n if (typeof node['minimum'] === 'number') b = b.min(node['minimum']);\n if (typeof node['maximum'] === 'number') b = b.max(node['maximum']);\n if (typeof node['multipleOf'] === 'number') {\n b = b.multipleOf(node['multipleOf']);\n }\n if (typeof node['exclusiveMinimum'] === 'number') {\n const min = node['exclusiveMinimum'];\n b = b.addValidator((v: unknown) =>\n typeof v === 'number' && v > min\n ? ok()\n : fail(`must be greater than ${min}`)\n );\n }\n if (typeof node['exclusiveMaximum'] === 'number') {\n const max = node['exclusiveMaximum'];\n b = b.addValidator((v: unknown) =>\n typeof v === 'number' && v < max\n ? ok()\n : fail(`must be less than ${max}`)\n );\n }\n return b;\n}\n\nfunction buildArray(\n node: Record<string, unknown>\n): SchemaBuilder<any, any, any> {\n // JSON Schema 2020-12 tuples use `prefixItems`\n if (Array.isArray(node['prefixItems'])) {\n const elements = (node['prefixItems'] as unknown[]).map(buildNode);\n let b: any = tuple(elements as any);\n // `items: false` means no extra elements (default for tuple)\n // `items: <schema>` means rest elements validated against that schema\n if (\n node['items'] !== undefined &&\n node['items'] !== false &&\n typeof node['items'] === 'object'\n ) {\n b = b.rest(buildNode(node['items']));\n }\n return b;\n }\n let b: any = array();\n if (node['items'] !== undefined) b = b.of(buildNode(node['items']));\n if (typeof node['minItems'] === 'number') b = b.minLength(node['minItems']);\n if (typeof node['maxItems'] === 'number') b = b.maxLength(node['maxItems']);\n return b;\n}\n\nfunction buildObject(\n node: Record<string, unknown>\n): SchemaBuilder<any, any, any> {\n const props = node['properties'] as Record<string, unknown> | undefined;\n const requiredSet = new Set<string>(\n Array.isArray(node['required']) ? (node['required'] as string[]) : []\n );\n let b: any = object();\n if (props) {\n for (const [key, propNode] of Object.entries(props)) {\n const propBuilder = buildNode(propNode);\n b = b.addProp(\n key,\n requiredSet.has(key)\n ? propBuilder.required()\n : propBuilder.optional()\n );\n }\n }\n if (node['additionalProperties'] !== false) b = b.acceptUnknownProps();\n return b;\n}\n\nfunction buildEnum(values: unknown[]): SchemaBuilder<any, any, any> {\n if (values.length === 0) return any();\n const [first, ...rest] = values;\n let b: any = union(buildConst(first));\n for (const v of rest) b = b.or(buildConst(v));\n return b;\n}\n\nfunction buildAnyOf(options: unknown[]): SchemaBuilder<any, any, any> {\n if (options.length === 0) return any();\n const [first, ...rest] = options;\n let b: any = union(buildNode(first));\n for (const opt of rest) b = b.or(buildNode(opt));\n return b;\n}\n\n/**\n * Converts a JSON Schema object into a `@cleverbrush/schema` builder.\n *\n * @remarks\n * **`as const` is required for precise TypeScript inference.** Without it\n * TypeScript widens string literals to `string` and the inferred builder\n * type collapses to `SchemaBuilder<unknown>`. Always pass the schema literal\n * (or the variable holding it) with `as const`.\n *\n * **Supported JSON Schema keywords**\n *\n * | Keyword | Builder equivalent |\n * | ------------------------------ | ------------------------------- |\n * | `type: 'string'` | `string()` |\n * | `type: 'number'` | `number()` |\n * | `type: 'integer'` | `number()` (integer flag) |\n * | `type: 'boolean'` | `boolean()` |\n * | `type: 'null'` | `SchemaBuilder<null>` |\n * | `type: 'array'` + `items` | `array(itemBuilder)` |\n * | `type: 'object'` + `properties`| `object({ … })` |\n * | `required: […]` | required / optional per-prop |\n * | `additionalProperties: true` | `.acceptUnknownProps()` |\n * | `const` | `string/number/boolean eq` |\n * | `enum` | `union(…)` |\n * | `anyOf` | `union(…)` |\n * | `minLength` / `maxLength` | `.minLength()` / `.maxLength()` |\n * | `pattern` | `.matches(regex)` (invalid patterns silently ignored) |\n * | `minimum` / `maximum` | `.min()` / `.max()` |\n * | `exclusiveMinimum` / `exclusiveMaximum` | custom validator (not round-trippable via `toJsonSchema`) |\n * | `multipleOf` | `.multipleOf()` |\n * | `minItems` / `maxItems` | `.minLength()` / `.maxLength()` |\n * | `format: 'email'` | `.email()` extension |\n * | `format: 'uuid'` | `.uuid()` extension |\n * | `format: 'uri'` / `'url'` | `.url()` extension |\n * | `format: 'ipv4'` | `.ip({ version: 'v4' })` |\n * | `format: 'ipv6'` | `.ip({ version: 'v6' })` |\n * | `format: 'date-time'` | `.matches(iso8601 regex)` |\n *\n * Keywords **not** supported: `allOf` (falls back to `any()`), `$ref`,\n * `$defs`, `if/then/else`, `not`, `contains`, `unevaluatedProperties`,\n * `contentEncoding`.\n *\n * @param schema - A JSON Schema literal. Pass with `as const` for precise\n * TypeScript type inference on the returned builder.\n * @returns A `@cleverbrush/schema` builder whose static type mirrors the\n * structure described by the JSON Schema node.\n *\n * @example\n * ```ts\n * import { fromJsonSchema } from '@cleverbrush/schema-json';\n *\n * const schema = fromJsonSchema({\n * type: 'object',\n * properties: {\n * name: { type: 'string', minLength: 1 },\n * score: { type: 'number', minimum: 0, maximum: 100 },\n * },\n * required: ['name'],\n * } as const);\n *\n * schema.parse({ name: 'Alice', score: 95 });\n * // TypeScript infers: { name: string; score?: number }\n * ```\n *\n * @example\n * ```ts\n * // Union types via `enum`\n * const statusSchema = fromJsonSchema({\n * enum: ['active', 'inactive', 'pending']\n * } as const);\n *\n * statusSchema.parse('active'); // valid — 'active' | 'inactive' | 'pending'\n * ```\n *\n * @example\n * ```ts\n * // Use InferFromJsonSchema to derive the TypeScript type statically\n * import type { InferFromJsonSchema } from '@cleverbrush/schema-json';\n *\n * const S = { type: 'object', properties: { id: { type: 'integer' } }, required: ['id'] } as const;\n * type Payload = InferFromJsonSchema<typeof S>; // { id: number }\n * const payloadSchema = fromJsonSchema(S);\n * ```\n */\nexport function fromJsonSchema<const S>(schema: S): JsonSchemaNodeToBuilder<S> {\n return buildNode(schema) as JsonSchemaNodeToBuilder<S>;\n}\n","import type { SchemaBuilder } from '@cleverbrush/schema';\nimport type { ToJsonSchemaOptions } from './types.js';\n\ntype Out = Record<string, unknown>;\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction escapeJsonPointerSegment(s: string): string {\n return s.replace(/~/g, '~0').replace(/\\//g, '~1');\n}\n\ntype Resolver =\n | ((schema: SchemaBuilder<any, any, any>) => string | null)\n | undefined;\n\nfunction convertNodeInner(\n schema: SchemaBuilder<any, any, any>,\n resolver: Resolver\n): Out {\n const info = schema.introspect() as any;\n const ext: Record<string, unknown> = info.extensions ?? {};\n const readOnly: Out = info.isReadonly === true ? { readOnly: true } : {};\n\n switch (info.type) {\n case 'string': {\n if (info.equalsTo !== undefined)\n return { ...readOnly, const: info.equalsTo };\n const out: Out = { ...readOnly, type: 'string' };\n if (ext['email'] === true) {\n out['format'] = 'email';\n } else if (ext['uuid'] === true) {\n out['format'] = 'uuid';\n } else if (ext['url']) {\n out['format'] = 'uri';\n } else if (ext['ip']) {\n const ver =\n typeof ext['ip'] === 'object'\n ? (ext['ip'] as any).version\n : undefined;\n if (ver === 'v4') out['format'] = 'ipv4';\n else if (ver === 'v6') out['format'] = 'ipv6';\n // both versions: no single standard JSON Schema format — omit\n }\n if (info.minLength !== undefined) out['minLength'] = info.minLength;\n if (info.maxLength !== undefined) out['maxLength'] = info.maxLength;\n // .nonempty() sets minLength via extension; if not already set\n if (ext['nonempty'] === true && out['minLength'] === undefined)\n out['minLength'] = 1;\n if (info.matches instanceof RegExp) {\n if (info.matches.flags !== '') {\n throw new Error(\n `Cannot convert RegExp /${info.matches.source}/${info.matches.flags} to JSON Schema pattern: RegExp flags are not representable in standard JSON Schema.`\n );\n }\n out['pattern'] = info.matches.source;\n } else if (info.startsWith !== undefined) {\n out['pattern'] = `^${escapeRegex(info.startsWith)}`;\n } else if (info.endsWith !== undefined) {\n out['pattern'] = `${escapeRegex(info.endsWith)}$`;\n }\n if (Array.isArray(ext['oneOf']) && ext['oneOf'].length > 0)\n out['enum'] = [...(ext['oneOf'] as unknown[])];\n return out;\n }\n\n case 'number': {\n if (info.equalsTo !== undefined)\n return { ...readOnly, const: info.equalsTo };\n const out: Out = {\n ...readOnly,\n type: info.isInteger ? 'integer' : 'number'\n };\n if (info.min !== undefined) out['minimum'] = info.min;\n if (info.max !== undefined) out['maximum'] = info.max;\n if (ext['multipleOf'] !== undefined)\n out['multipleOf'] = ext['multipleOf'];\n if (ext['positive'] === true) out['exclusiveMinimum'] = 0;\n if (ext['negative'] === true) out['exclusiveMaximum'] = 0;\n if (Array.isArray(ext['oneOf']) && ext['oneOf'].length > 0)\n out['enum'] = [...(ext['oneOf'] as unknown[])];\n return out;\n }\n\n case 'boolean': {\n if (info.equalsTo !== undefined)\n return { ...readOnly, const: info.equalsTo };\n return { ...readOnly, type: 'boolean' };\n }\n\n case 'date':\n return { ...readOnly, type: 'string', format: 'date-time' };\n\n case 'array': {\n const out: Out = { ...readOnly, type: 'array' };\n if (info.elementSchema)\n out['items'] = convertNode(info.elementSchema, resolver);\n if (info.minLength !== undefined) out['minItems'] = info.minLength;\n if (info.maxLength !== undefined) out['maxItems'] = info.maxLength;\n if (ext['nonempty'] === true && out['minItems'] === undefined)\n out['minItems'] = 1;\n return out;\n }\n\n case 'tuple': {\n const elements: SchemaBuilder<any, any, any>[] =\n info.elements ?? [];\n const out: Out = {\n type: 'array',\n prefixItems: elements.map(e => convertNode(e, resolver)),\n minItems: elements.length\n };\n if (info.restSchema) {\n out['items'] = convertNode(info.restSchema, resolver);\n } else {\n out['items'] = false;\n out['maxItems'] = elements.length;\n }\n return out;\n }\n\n case 'object': {\n const out: Out = { ...readOnly, type: 'object' };\n const props = info.properties as\n | Record<string, SchemaBuilder<any, any, any>>\n | undefined;\n if (props) {\n const outProps: Record<string, unknown> = {};\n const required: string[] = [];\n for (const [key, propSchema] of Object.entries(props)) {\n outProps[key] = convertNode(propSchema, resolver);\n if ((propSchema.introspect() as any).isRequired !== false)\n required.push(key);\n }\n out['properties'] = outProps;\n if (required.length > 0) out['required'] = required;\n }\n if (info.acceptUnknownProps === false)\n out['additionalProperties'] = false;\n return out;\n }\n\n case 'null':\n return { ...readOnly, type: 'null' };\n\n case 'union': {\n const options: SchemaBuilder<any, any, any>[] = info.options ?? [];\n const enumValues: unknown[] = [];\n let allConst = options.length > 0;\n for (const opt of options) {\n const oi = opt.introspect() as any;\n if (\n (oi.type === 'string' ||\n oi.type === 'number' ||\n oi.type === 'boolean') &&\n oi.equalsTo !== undefined\n ) {\n enumValues.push(oi.equalsTo);\n } else {\n allConst = false;\n break;\n }\n }\n if (allConst) return { ...readOnly, enum: enumValues };\n\n const converted = options.map(o => convertNode(o, resolver));\n const out: Out = {\n ...readOnly,\n anyOf: converted\n };\n\n // Emit discriminator keyword for discriminated unions\n const discriminatorProp: string | undefined =\n info.discriminatorPropertyName;\n if (discriminatorProp) {\n const disc: Out = { propertyName: discriminatorProp };\n // Only emit mapping when every option resolved to a $ref\n // and every discriminator value can be populated.\n const mapping: Record<string, string> = {};\n let allRefsMapped = options.length > 0;\n for (let i = 0; i < options.length; i++) {\n const ref = converted[i]['$ref'];\n if (typeof ref !== 'string') {\n allRefsMapped = false;\n break;\n }\n\n const oi = options[i].introspect() as any;\n const props:\n | Record<string, SchemaBuilder<any, any, any>>\n | undefined = oi.properties;\n const discriminatorSchema = props?.[discriminatorProp];\n if (!discriminatorSchema) {\n allRefsMapped = false;\n break;\n }\n\n const propInfo = discriminatorSchema.introspect() as any;\n if (propInfo.equalsTo === undefined) {\n allRefsMapped = false;\n break;\n }\n\n mapping[String(propInfo.equalsTo)] = ref;\n }\n if (allRefsMapped) disc['mapping'] = mapping;\n out['discriminator'] = disc;\n }\n\n return out;\n }\n\n case 'lazy': {\n // Resolve the lazy schema once and delegate conversion.\n // If the resolved schema has a name registered in the nameResolver,\n // convertNode will short-circuit to a $ref — breaking recursive cycles.\n // Recursive schemas without a registered name will cause infinite\n // recursion here; callers must use .schemaName() to break the cycle.\n const resolved: SchemaBuilder<any, any, any> = info.getter();\n return convertNode(resolved, resolver);\n }\n\n default:\n return {};\n }\n}\n\nfunction convertNode(\n schema: SchemaBuilder<any, any, any>,\n resolver: Resolver\n): Out {\n if (resolver) {\n const name = resolver(schema);\n if (typeof name === 'string' && name.length > 0) {\n return {\n $ref: `#/components/schemas/${escapeJsonPointerSegment(name)}`\n };\n }\n }\n const out = convertNodeInner(schema, resolver);\n const info = schema.introspect() as any;\n if (typeof info.description === 'string' && info.description !== '')\n out['description'] = info.description;\n\n // Emit example value if set\n if (info.example !== undefined) {\n out['examples'] = [info.example];\n }\n\n // Emit default for serializable primitives (not factory functions)\n if (\n info.hasDefault === true &&\n info.defaultValue !== undefined &&\n typeof info.defaultValue !== 'function'\n ) {\n out['default'] = info.defaultValue;\n }\n\n // Handle nullable — JSON Schema 2020-12 style: type becomes an array\n if (info.isNullable === true) {\n if (out['anyOf'] !== undefined) {\n // Union type — add { type: 'null' } to anyOf if not already present\n const anyOf = out['anyOf'] as Out[];\n const hasNull = anyOf.some(o => o['type'] === 'null');\n if (!hasNull) anyOf.push({ type: 'null' });\n } else if (out['enum'] !== undefined) {\n // Enum — add null to enum values if not already present\n const enumValues = out['enum'] as unknown[];\n if (!enumValues.includes(null)) out['enum'] = [...enumValues, null];\n } else if (typeof out['type'] === 'string') {\n // Simple type — make it an array: [\"string\", \"null\"]\n out['type'] = [out['type'], 'null'];\n } else if (out['const'] !== undefined) {\n // Const value — convert to oneOf with null\n const constVal = out['const'];\n delete out['const'];\n out['anyOf'] = [{ const: constVal }, { type: 'null' }];\n }\n }\n\n return out;\n}\n\n/**\n * Converts a `@cleverbrush/schema` builder to a JSON Schema object.\n *\n * @remarks\n * **What round-trips cleanly**: all declarative constraints — type, format,\n * minLength/maxLength, minimum/maximum, multipleOf, pattern, required/optional\n * per property, additionalProperties, items, enum/const literals, anyOf/union.\n *\n * **What is silently omitted**:\n * - Custom validators added via `addValidator` (no JSON Schema equivalent)\n * - Preprocessors added via `addPreprocessor`\n * - JSDoc comments on schema properties\n * - `exclusiveMinimum`/`exclusiveMaximum` constraints from `fromJsonSchema`\n * (stored as custom validators — not introspectable; only `positive()`/\n * `negative()` extension-based exclusives are emitted)\n * - IP format with both v4 _and_ v6 allowed simultaneously (no single\n * standard JSON Schema format covers both; the `format` keyword is omitted\n * in that case)\n *\n * By default the output includes a `$schema` header for JSON Schema Draft\n * 2020-12. Pass `{ $schema: false }` when embedding the result in an OpenAPI\n * specification, or `{ draft: '07' }` for Draft 07 compatibility.\n *\n * @param schema - Any `@cleverbrush/schema` builder instance.\n * @param opts - Optional output configuration (see {@link ToJsonSchemaOptions}).\n * @returns A plain JSON-serialisable object representing the schema.\n *\n * @example\n * ```ts\n * import { toJsonSchema } from '@cleverbrush/schema-json';\n * import { object, string, number } from '@cleverbrush/schema';\n *\n * const UserSchema = object({\n * name: string().minLength(1),\n * email: string().email(),\n * age: number().optional(),\n * });\n *\n * const spec = toJsonSchema(UserSchema);\n * // {\n * // \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n * // \"type\": \"object\",\n * // \"properties\": {\n * // \"name\": { \"type\": \"string\", \"minLength\": 1 },\n * // \"email\": { \"type\": \"string\", \"format\": \"email\" },\n * // \"age\": { \"type\": \"number\" }\n * // },\n * // \"required\": [\"name\", \"email\"]\n * // }\n * ```\n *\n * @example\n * ```ts\n * // Embed in an OpenAPI spec (strip the $schema header)\n * toJsonSchema(schema, { $schema: false });\n *\n * // Use JSON Schema Draft 07\n * toJsonSchema(schema, { draft: '07' });\n * ```\n */\nexport function toJsonSchema(\n schema: SchemaBuilder<any, any, any, any, any>,\n opts?: ToJsonSchemaOptions\n): Record<string, unknown> {\n const body = convertNode(schema, opts?.nameResolver);\n if (opts?.$schema === false) return body;\n const draft = opts?.draft ?? '2020-12';\n const uri =\n draft === '07'\n ? 'http://json-schema.org/draft-07/schema#'\n : 'https://json-schema.org/draft/2020-12/schema';\n return { $schema: uri, ...body };\n}\n","import type { SchemaBuilder } from '@cleverbrush/schema';\nimport type { StandardJSONSchemaV1 } from '@standard-schema/spec';\nimport { toJsonSchema } from './toJsonSchema.js';\n\n/**\n * Maps Standard JSON Schema target identifiers to the options accepted by\n * {@link toJsonSchema}.\n */\nfunction targetToOptions(target: StandardJSONSchemaV1.Target): {\n draft: '2020-12' | '07';\n $schema: false;\n} {\n switch (target) {\n case 'draft-2020-12':\n return { draft: '2020-12', $schema: false };\n case 'draft-07':\n return { draft: '07', $schema: false };\n case 'openapi-3.0':\n // OpenAPI 3.0 is a superset of JSON Schema Draft 04; Draft 07 is\n // the closest we support.\n return { draft: '07', $schema: false };\n default:\n throw new Error(\n `@cleverbrush/schema-json: unsupported JSON Schema target \"${target}\".`\n );\n }\n}\n\n/**\n * Wraps a `@cleverbrush/schema` builder with the\n * [Standard JSON Schema v1](https://standardschema.dev/) interface.\n *\n * The returned schema object's `~standard` property is enriched with a\n * `jsonSchema` converter. Because `@cleverbrush/schema` does not\n * distinguish between input and output types, both `input()` and `output()`\n * produce the same JSON Schema document.\n *\n * **Note:** this mutates the schema instance by overriding the `~standard`\n * property. The returned reference is the same schema object.\n *\n * @example\n * ```ts\n * import { object, string, number } from '@cleverbrush/schema';\n * import { withStandardJsonSchema } from '@cleverbrush/schema-json';\n *\n * const schema = object({ name: string(), age: number().optional() });\n * const wrapped = withStandardJsonSchema(schema);\n *\n * // Access standard JSON Schema properties\n * wrapped['~standard'].jsonSchema.input({ target: 'draft-2020-12' });\n * wrapped['~standard'].jsonSchema.output({ target: 'draft-07' });\n * ```\n *\n * @param schema - Any `@cleverbrush/schema` builder instance.\n * @returns The same schema instance, now also conforming to `StandardJSONSchemaV1`.\n */\nexport function withStandardJsonSchema<\n T extends SchemaBuilder<any, any, any, any, any>\n>(schema: T): T & StandardJSONSchemaV1 {\n const converter: StandardJSONSchemaV1.Converter = {\n input(options: StandardJSONSchemaV1.Options): Record<string, unknown> {\n return toJsonSchema(schema, targetToOptions(options.target));\n },\n output(options: StandardJSONSchemaV1.Options): Record<string, unknown> {\n return toJsonSchema(schema, targetToOptions(options.target));\n }\n };\n\n // Extend the existing `~standard` props (which already include the\n // StandardSchemaV1 validate function from the schema library) with the\n // jsonSchema converter.\n const existingStandard = schema['~standard'];\n const enrichedStandard = { ...existingStandard, jsonSchema: converter };\n\n // Override the prototype getter with an instance-level property.\n // A Proxy wrapper was considered but JavaScript private fields (#field)\n // are bound to the original class instance; when a method is invoked\n // through a Proxy the receiver is the Proxy, not the real instance, so\n // private-field access throws a TypeError. defineProperty avoids this\n // because `this` inside methods still refers to the original schema.\n Object.defineProperty(schema, '~standard', {\n value: enrichedStandard,\n configurable: true,\n writable: false,\n enumerable: false\n });\n\n return schema as T & StandardJSONSchemaV1;\n}\n"],"mappings":"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","names":["any","array","boolean","nul","number","object","string","tuple","union","fail","msg","ok","buildNode","s","node","b","buildEnum","buildConst","buildAnyOf","buildString","buildNumber","buildArray","buildObject","val","format","v","integer","min","max","elements","props","requiredSet","key","propNode","propBuilder","values","first","rest","options","opt","fromJsonSchema","schema","escapeRegex","s","escapeJsonPointerSegment","convertNodeInner","schema","resolver","info","ext","readOnly","out","ver","convertNode","elements","e","props","outProps","required","key","propSchema","options","enumValues","allConst","opt","oi","converted","o","discriminatorProp","disc","mapping","allRefsMapped","i","ref","discriminatorSchema","propInfo","resolved","name","anyOf","constVal","toJsonSchema","opts","body","targetToOptions","target","withStandardJsonSchema","schema","converter","options","toJsonSchema","enrichedStandard"]}
1
+ {"version":3,"sources":["../src/fromJsonSchema.ts","../src/toJsonSchema.ts","../src/standardJsonSchema.ts"],"sourcesContent":["import type { SchemaBuilder } from '@cleverbrush/schema';\nimport {\n any,\n array,\n boolean,\n intersection,\n nul,\n number,\n object,\n string,\n tuple,\n union\n} from '@cleverbrush/schema';\nimport type { JsonSchemaNodeToBuilder } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction fail(msg: string) {\n return { valid: false as const, errors: [{ message: msg }] };\n}\n\nfunction ok() {\n return { valid: true as const, errors: [] };\n}\n\nfunction buildNode(s: unknown): SchemaBuilder<any, any, any> {\n if (typeof s !== 'object' || s === null) return any();\n const node = s as Record<string, unknown>;\n\n let b: SchemaBuilder<any, any, any>;\n\n if ('enum' in node && Array.isArray(node['enum']))\n b = buildEnum(node['enum']);\n else if ('const' in node) b = buildConst(node['const']);\n else if ('anyOf' in node && Array.isArray(node['anyOf']))\n b = buildAnyOf(node['anyOf']);\n else if ('allOf' in node && Array.isArray(node['allOf']))\n b = buildAllOf(node['allOf']);\n else if (!('type' in node)) b = any();\n else {\n switch (node['type']) {\n case 'string':\n b = buildString(node);\n break;\n case 'number':\n b = buildNumber(node, false);\n break;\n case 'integer':\n b = buildNumber(node, true);\n break;\n case 'boolean':\n b = boolean();\n break;\n case 'null':\n b = nul();\n break;\n case 'array':\n b = buildArray(node);\n break;\n case 'object':\n b = buildObject(node);\n break;\n default:\n b = any();\n }\n }\n\n if (node['readOnly'] === true) b = (b as any).readonly();\n if (typeof node['description'] === 'string' && node['description'])\n b = (b as any).describe(node['description']);\n return b;\n}\n\nfunction buildConst(val: unknown): SchemaBuilder<any, any, any> {\n if (typeof val === 'string') return string(val as any);\n if (typeof val === 'number') return number(val as any);\n if (typeof val === 'boolean') return boolean().equals(val);\n return any();\n}\n\nfunction buildString(\n node: Record<string, unknown>\n): SchemaBuilder<any, any, any> {\n let b: any = string();\n const format = node['format'] as string | undefined;\n\n if (format === 'email') {\n b = b.email();\n } else if (format === 'uuid') {\n b = b.uuid();\n } else if (format === 'uri' || format === 'url') {\n b = b.url();\n } else if (format === 'ipv4') {\n b = b.ip({ version: 'v4' });\n } else if (format === 'ipv6') {\n b = b.ip({ version: 'v6' });\n } else if (format === 'date-time') {\n b = b.addValidator((v: unknown) =>\n typeof v === 'string' && !Number.isNaN(Date.parse(v))\n ? ok()\n : fail('must be a valid date-time string')\n );\n }\n\n if (typeof node['minLength'] === 'number')\n b = b.minLength(node['minLength']);\n if (typeof node['maxLength'] === 'number')\n b = b.maxLength(node['maxLength']);\n if (typeof node['pattern'] === 'string') {\n try {\n b = b.matches(new RegExp(node['pattern']));\n } catch {\n // invalid regex pattern — silently ignore\n }\n }\n return b;\n}\n\nfunction buildNumber(\n node: Record<string, unknown>,\n integer: boolean\n): SchemaBuilder<any, any, any> {\n let b: any = integer ? number().isInteger() : number().isFloat();\n if (typeof node['minimum'] === 'number') b = b.min(node['minimum']);\n if (typeof node['maximum'] === 'number') b = b.max(node['maximum']);\n if (typeof node['multipleOf'] === 'number') {\n b = b.multipleOf(node['multipleOf']);\n }\n if (typeof node['exclusiveMinimum'] === 'number') {\n const min = node['exclusiveMinimum'];\n b = b.addValidator((v: unknown) =>\n typeof v === 'number' && v > min\n ? ok()\n : fail(`must be greater than ${min}`)\n );\n }\n if (typeof node['exclusiveMaximum'] === 'number') {\n const max = node['exclusiveMaximum'];\n b = b.addValidator((v: unknown) =>\n typeof v === 'number' && v < max\n ? ok()\n : fail(`must be less than ${max}`)\n );\n }\n return b;\n}\n\nfunction buildArray(\n node: Record<string, unknown>\n): SchemaBuilder<any, any, any> {\n // JSON Schema 2020-12 tuples use `prefixItems`\n if (Array.isArray(node['prefixItems'])) {\n const elements = (node['prefixItems'] as unknown[]).map(buildNode);\n let b: any = tuple(elements as any);\n // `items: false` means no extra elements (default for tuple)\n // `items: <schema>` means rest elements validated against that schema\n if (\n node['items'] !== undefined &&\n node['items'] !== false &&\n typeof node['items'] === 'object'\n ) {\n b = b.rest(buildNode(node['items']));\n }\n return b;\n }\n let b: any = array();\n if (node['items'] !== undefined) b = b.of(buildNode(node['items']));\n if (typeof node['minItems'] === 'number') b = b.minLength(node['minItems']);\n if (typeof node['maxItems'] === 'number') b = b.maxLength(node['maxItems']);\n return b;\n}\n\nfunction buildObject(\n node: Record<string, unknown>\n): SchemaBuilder<any, any, any> {\n const props = node['properties'] as Record<string, unknown> | undefined;\n const requiredSet = new Set<string>(\n Array.isArray(node['required']) ? (node['required'] as string[]) : []\n );\n let b: any = object();\n if (props) {\n for (const [key, propNode] of Object.entries(props)) {\n const propBuilder = buildNode(propNode);\n b = b.addProp(\n key,\n requiredSet.has(key)\n ? propBuilder.required()\n : propBuilder.optional()\n );\n }\n }\n if (node['additionalProperties'] !== false) b = b.acceptUnknownProps();\n return b;\n}\n\nfunction buildEnum(values: unknown[]): SchemaBuilder<any, any, any> {\n if (values.length === 0) return any();\n const [first, ...rest] = values;\n let b: any = union(buildConst(first));\n for (const v of rest) b = b.or(buildConst(v));\n return b;\n}\n\nfunction buildAnyOf(options: unknown[]): SchemaBuilder<any, any, any> {\n if (options.length === 0) return any();\n const [first, ...rest] = options;\n let b: any = union(buildNode(first));\n for (const opt of rest) b = b.or(buildNode(opt));\n return b;\n}\n\nfunction buildAllOf(options: unknown[]): SchemaBuilder<any, any, any> {\n if (options.length === 0) return any();\n let b: any = buildNode(options[0]);\n for (let i = 1; i < options.length; i++) {\n b = intersection(b, buildNode(options[i]));\n }\n return b;\n}\n\n/**\n * Converts a JSON Schema object into a `@cleverbrush/schema` builder.\n *\n * @remarks\n * **`as const` is required for precise TypeScript inference.** Without it\n * TypeScript widens string literals to `string` and the inferred builder\n * type collapses to `SchemaBuilder<unknown>`. Always pass the schema literal\n * (or the variable holding it) with `as const`.\n *\n * **Supported JSON Schema keywords**\n *\n * | Keyword | Builder equivalent |\n * | ------------------------------ | ------------------------------- |\n * | `type: 'string'` | `string()` |\n * | `type: 'number'` | `number()` |\n * | `type: 'integer'` | `number()` (integer flag) |\n * | `type: 'boolean'` | `boolean()` |\n * | `type: 'null'` | `SchemaBuilder<null>` |\n * | `type: 'array'` + `items` | `array(itemBuilder)` |\n * | `type: 'object'` + `properties`| `object({ … })` |\n * | `required: […]` | required / optional per-prop |\n * | `additionalProperties: true` | `.acceptUnknownProps()` |\n * | `const` | `string/number/boolean eq` |\n * | `enum` | `union(…)` |\n * | `anyOf` | `union(…)` |\n * | `minLength` / `maxLength` | `.minLength()` / `.maxLength()` |\n * | `pattern` | `.matches(regex)` (invalid patterns silently ignored) |\n * | `minimum` / `maximum` | `.min()` / `.max()` |\n * | `exclusiveMinimum` / `exclusiveMaximum` | custom validator (not round-trippable via `toJsonSchema`) |\n * | `multipleOf` | `.multipleOf()` |\n * | `minItems` / `maxItems` | `.minLength()` / `.maxLength()` |\n * | `format: 'email'` | `.email()` extension |\n * | `format: 'uuid'` | `.uuid()` extension |\n * | `format: 'uri'` / `'url'` | `.url()` extension |\n * | `format: 'ipv4'` | `.ip({ version: 'v4' })` |\n * | `format: 'ipv6'` | `.ip({ version: 'v6' })` |\n * | `format: 'date-time'` | `.matches(iso8601 regex)` |\n *\n * Keywords **not** supported: `$ref`, `$defs`, `if/then/else`, `not`,\n * `contains`, `unevaluatedProperties`, `contentEncoding`.\n *\n * @param schema - A JSON Schema literal. Pass with `as const` for precise\n * TypeScript type inference on the returned builder.\n * @returns A `@cleverbrush/schema` builder whose static type mirrors the\n * structure described by the JSON Schema node.\n *\n * @example\n * ```ts\n * import { fromJsonSchema } from '@cleverbrush/schema-json';\n *\n * const schema = fromJsonSchema({\n * type: 'object',\n * properties: {\n * name: { type: 'string', minLength: 1 },\n * score: { type: 'number', minimum: 0, maximum: 100 },\n * },\n * required: ['name'],\n * } as const);\n *\n * schema.parse({ name: 'Alice', score: 95 });\n * // TypeScript infers: { name: string; score?: number }\n * ```\n *\n * @example\n * ```ts\n * // Union types via `enum`\n * const statusSchema = fromJsonSchema({\n * enum: ['active', 'inactive', 'pending']\n * } as const);\n *\n * statusSchema.parse('active'); // valid — 'active' | 'inactive' | 'pending'\n * ```\n *\n * @example\n * ```ts\n * // Use InferFromJsonSchema to derive the TypeScript type statically\n * import type { InferFromJsonSchema } from '@cleverbrush/schema-json';\n *\n * const S = { type: 'object', properties: { id: { type: 'integer' } }, required: ['id'] } as const;\n * type Payload = InferFromJsonSchema<typeof S>; // { id: number }\n * const payloadSchema = fromJsonSchema(S);\n * ```\n */\nexport function fromJsonSchema<const S>(schema: S): JsonSchemaNodeToBuilder<S> {\n return buildNode(schema) as JsonSchemaNodeToBuilder<S>;\n}\n","import type { SchemaBuilder } from '@cleverbrush/schema';\nimport type { ToJsonSchemaOptions } from './types.js';\n\ntype Out = Record<string, unknown>;\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction escapeJsonPointerSegment(s: string): string {\n return s.replace(/~/g, '~0').replace(/\\//g, '~1');\n}\n\ntype Resolver =\n | ((schema: SchemaBuilder<any, any, any>) => string | null)\n | undefined;\n\nfunction convertNodeInner(\n schema: SchemaBuilder<any, any, any>,\n resolver: Resolver\n): Out {\n const info = schema.introspect() as any;\n const ext: Record<string, unknown> = info.extensions ?? {};\n const readOnly: Out = info.isReadonly === true ? { readOnly: true } : {};\n\n switch (info.type) {\n case 'string': {\n if (info.equalsTo !== undefined)\n return { ...readOnly, const: info.equalsTo };\n const out: Out = { ...readOnly, type: 'string' };\n if (ext['email'] === true) {\n out['format'] = 'email';\n } else if (ext['uuid'] === true) {\n out['format'] = 'uuid';\n } else if (ext['url']) {\n out['format'] = 'uri';\n } else if (ext['ip']) {\n const ver =\n typeof ext['ip'] === 'object'\n ? (ext['ip'] as any).version\n : undefined;\n if (ver === 'v4') out['format'] = 'ipv4';\n else if (ver === 'v6') out['format'] = 'ipv6';\n // both versions: no single standard JSON Schema format — omit\n }\n if (info.minLength !== undefined) out['minLength'] = info.minLength;\n if (info.maxLength !== undefined) out['maxLength'] = info.maxLength;\n // .nonempty() sets minLength via extension; if not already set\n if (ext['nonempty'] === true && out['minLength'] === undefined)\n out['minLength'] = 1;\n if (info.matches instanceof RegExp) {\n if (info.matches.flags !== '') {\n throw new Error(\n `Cannot convert RegExp /${info.matches.source}/${info.matches.flags} to JSON Schema pattern: RegExp flags are not representable in standard JSON Schema.`\n );\n }\n out['pattern'] = info.matches.source;\n } else if (info.startsWith !== undefined) {\n out['pattern'] = `^${escapeRegex(info.startsWith)}`;\n } else if (info.endsWith !== undefined) {\n out['pattern'] = `${escapeRegex(info.endsWith)}$`;\n }\n if (Array.isArray(ext['oneOf']) && ext['oneOf'].length > 0)\n out['enum'] = [...(ext['oneOf'] as unknown[])];\n return out;\n }\n\n case 'number': {\n if (info.equalsTo !== undefined)\n return { ...readOnly, const: info.equalsTo };\n const out: Out = {\n ...readOnly,\n type: info.isInteger ? 'integer' : 'number'\n };\n if (info.min !== undefined) out['minimum'] = info.min;\n if (info.max !== undefined) out['maximum'] = info.max;\n if (ext['multipleOf'] !== undefined)\n out['multipleOf'] = ext['multipleOf'];\n if (ext['positive'] === true) out['exclusiveMinimum'] = 0;\n if (ext['negative'] === true) out['exclusiveMaximum'] = 0;\n if (Array.isArray(ext['oneOf']) && ext['oneOf'].length > 0)\n out['enum'] = [...(ext['oneOf'] as unknown[])];\n return out;\n }\n\n case 'boolean': {\n if (info.equalsTo !== undefined)\n return { ...readOnly, const: info.equalsTo };\n return { ...readOnly, type: 'boolean' };\n }\n\n case 'date':\n return { ...readOnly, type: 'string', format: 'date-time' };\n\n case 'array': {\n const out: Out = { ...readOnly, type: 'array' };\n if (info.elementSchema)\n out['items'] = convertNode(info.elementSchema, resolver);\n if (info.minLength !== undefined) out['minItems'] = info.minLength;\n if (info.maxLength !== undefined) out['maxItems'] = info.maxLength;\n if (ext['nonempty'] === true && out['minItems'] === undefined)\n out['minItems'] = 1;\n return out;\n }\n\n case 'tuple': {\n const elements: SchemaBuilder<any, any, any>[] =\n info.elements ?? [];\n const out: Out = {\n type: 'array',\n prefixItems: elements.map(e => convertNode(e, resolver)),\n minItems: elements.length\n };\n if (info.restSchema) {\n out['items'] = convertNode(info.restSchema, resolver);\n } else {\n out['items'] = false;\n out['maxItems'] = elements.length;\n }\n return out;\n }\n\n case 'object': {\n const out: Out = { ...readOnly, type: 'object' };\n const props = info.properties as\n | Record<string, SchemaBuilder<any, any, any>>\n | undefined;\n if (props) {\n const outProps: Record<string, unknown> = {};\n const required: string[] = [];\n for (const [key, propSchema] of Object.entries(props)) {\n outProps[key] = convertNode(propSchema, resolver);\n if ((propSchema.introspect() as any).isRequired !== false)\n required.push(key);\n }\n out['properties'] = outProps;\n if (required.length > 0) out['required'] = required;\n }\n if (info.acceptUnknownProps === false)\n out['additionalProperties'] = false;\n return out;\n }\n\n case 'null':\n return { ...readOnly, type: 'null' };\n\n case 'union': {\n const options: SchemaBuilder<any, any, any>[] = info.options ?? [];\n const enumValues: unknown[] = [];\n let allConst = options.length > 0;\n for (const opt of options) {\n const oi = opt.introspect() as any;\n if (\n (oi.type === 'string' ||\n oi.type === 'number' ||\n oi.type === 'boolean') &&\n oi.equalsTo !== undefined\n ) {\n enumValues.push(oi.equalsTo);\n } else {\n allConst = false;\n break;\n }\n }\n if (allConst) return { ...readOnly, enum: enumValues };\n\n const converted = options.map(o => convertNode(o, resolver));\n const out: Out = {\n ...readOnly,\n anyOf: converted\n };\n\n // Emit discriminator keyword for discriminated unions\n const discriminatorProp: string | undefined =\n info.discriminatorPropertyName;\n if (discriminatorProp) {\n const disc: Out = { propertyName: discriminatorProp };\n // Only emit mapping when every option resolved to a $ref\n // and every discriminator value can be populated.\n const mapping: Record<string, string> = {};\n let allRefsMapped = options.length > 0;\n for (let i = 0; i < options.length; i++) {\n const ref = converted[i]['$ref'];\n if (typeof ref !== 'string') {\n allRefsMapped = false;\n break;\n }\n\n const oi = options[i].introspect() as any;\n const props:\n | Record<string, SchemaBuilder<any, any, any>>\n | undefined = oi.properties;\n const discriminatorSchema = props?.[discriminatorProp];\n if (!discriminatorSchema) {\n allRefsMapped = false;\n break;\n }\n\n const propInfo = discriminatorSchema.introspect() as any;\n if (propInfo.equalsTo === undefined) {\n allRefsMapped = false;\n break;\n }\n\n mapping[String(propInfo.equalsTo)] = ref;\n }\n if (allRefsMapped) disc['mapping'] = mapping;\n out['discriminator'] = disc;\n }\n\n return out;\n }\n\n case 'intersection': {\n const left = info.left as SchemaBuilder<any, any, any>;\n const right = info.right as SchemaBuilder<any, any, any>;\n return {\n ...readOnly,\n allOf: [\n convertNode(left, resolver),\n convertNode(right, resolver)\n ]\n };\n }\n\n case 'lazy': {\n // Resolve the lazy schema once and delegate conversion.\n // If the resolved schema has a name registered in the nameResolver,\n // convertNode will short-circuit to a $ref — breaking recursive cycles.\n // Recursive schemas without a registered name will cause infinite\n // recursion here; callers must use .schemaName() to break the cycle.\n const resolved: SchemaBuilder<any, any, any> = info.getter();\n return convertNode(resolved, resolver);\n }\n\n default:\n return {};\n }\n}\n\nfunction convertNode(\n schema: SchemaBuilder<any, any, any>,\n resolver: Resolver\n): Out {\n if (resolver) {\n const name = resolver(schema);\n if (typeof name === 'string' && name.length > 0) {\n return {\n $ref: `#/components/schemas/${escapeJsonPointerSegment(name)}`\n };\n }\n }\n const out = convertNodeInner(schema, resolver);\n const info = schema.introspect() as any;\n if (typeof info.description === 'string' && info.description !== '')\n out['description'] = info.description;\n\n // Emit example value if set\n if (info.example !== undefined) {\n out['examples'] = [info.example];\n }\n\n // Emit default for serializable primitives (not factory functions)\n if (\n info.hasDefault === true &&\n info.defaultValue !== undefined &&\n typeof info.defaultValue !== 'function'\n ) {\n out['default'] = info.defaultValue;\n }\n\n // Handle nullable — JSON Schema 2020-12 style: type becomes an array\n if (info.isNullable === true) {\n if (out['anyOf'] !== undefined) {\n // Union type — add { type: 'null' } to anyOf if not already present\n const anyOf = out['anyOf'] as Out[];\n const hasNull = anyOf.some(o => o['type'] === 'null');\n if (!hasNull) anyOf.push({ type: 'null' });\n } else if (out['allOf'] !== undefined && out['type'] === undefined) {\n // Intersection type without a top-level type — wrap in oneOf with null\n out['oneOf'] = [{ allOf: out['allOf'] as Out[] }, { type: 'null' }];\n delete out['allOf'];\n } else if (out['enum'] !== undefined) {\n // Enum — add null to enum values if not already present\n const enumValues = out['enum'] as unknown[];\n if (!enumValues.includes(null)) out['enum'] = [...enumValues, null];\n } else if (typeof out['type'] === 'string') {\n // Simple type — make it an array: [\"string\", \"null\"]\n out['type'] = [out['type'], 'null'];\n } else if (out['const'] !== undefined) {\n // Const value — convert to oneOf with null\n const constVal = out['const'];\n delete out['const'];\n out['anyOf'] = [{ const: constVal }, { type: 'null' }];\n }\n }\n\n return out;\n}\n\n/**\n * Converts a `@cleverbrush/schema` builder to a JSON Schema object.\n *\n * @remarks\n * **What round-trips cleanly**: all declarative constraints — type, format,\n * minLength/maxLength, minimum/maximum, multipleOf, pattern, required/optional\n * per property, additionalProperties, items, enum/const literals, anyOf/union.\n *\n * **What is silently omitted**:\n * - Custom validators added via `addValidator` (no JSON Schema equivalent)\n * - Preprocessors added via `addPreprocessor`\n * - JSDoc comments on schema properties\n * - `exclusiveMinimum`/`exclusiveMaximum` constraints from `fromJsonSchema`\n * (stored as custom validators — not introspectable; only `positive()`/\n * `negative()` extension-based exclusives are emitted)\n * - IP format with both v4 _and_ v6 allowed simultaneously (no single\n * standard JSON Schema format covers both; the `format` keyword is omitted\n * in that case)\n *\n * By default the output includes a `$schema` header for JSON Schema Draft\n * 2020-12. Pass `{ $schema: false }` when embedding the result in an OpenAPI\n * specification, or `{ draft: '07' }` for Draft 07 compatibility.\n *\n * @param schema - Any `@cleverbrush/schema` builder instance.\n * @param opts - Optional output configuration (see {@link ToJsonSchemaOptions}).\n * @returns A plain JSON-serialisable object representing the schema.\n *\n * @example\n * ```ts\n * import { toJsonSchema } from '@cleverbrush/schema-json';\n * import { object, string, number } from '@cleverbrush/schema';\n *\n * const UserSchema = object({\n * name: string().minLength(1),\n * email: string().email(),\n * age: number().optional(),\n * });\n *\n * const spec = toJsonSchema(UserSchema);\n * // {\n * // \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n * // \"type\": \"object\",\n * // \"properties\": {\n * // \"name\": { \"type\": \"string\", \"minLength\": 1 },\n * // \"email\": { \"type\": \"string\", \"format\": \"email\" },\n * // \"age\": { \"type\": \"number\" }\n * // },\n * // \"required\": [\"name\", \"email\"]\n * // }\n * ```\n *\n * @example\n * ```ts\n * // Embed in an OpenAPI spec (strip the $schema header)\n * toJsonSchema(schema, { $schema: false });\n *\n * // Use JSON Schema Draft 07\n * toJsonSchema(schema, { draft: '07' });\n * ```\n */\nexport function toJsonSchema(\n schema: SchemaBuilder<any, any, any, any, any>,\n opts?: ToJsonSchemaOptions\n): Record<string, unknown> {\n const body = convertNode(schema, opts?.nameResolver);\n if (opts?.$schema === false) return body;\n const draft = opts?.draft ?? '2020-12';\n const uri =\n draft === '07'\n ? 'http://json-schema.org/draft-07/schema#'\n : 'https://json-schema.org/draft/2020-12/schema';\n return { $schema: uri, ...body };\n}\n","import type { SchemaBuilder } from '@cleverbrush/schema';\nimport type { StandardJSONSchemaV1 } from '@standard-schema/spec';\nimport { toJsonSchema } from './toJsonSchema.js';\n\n/**\n * Maps Standard JSON Schema target identifiers to the options accepted by\n * {@link toJsonSchema}.\n */\nfunction targetToOptions(target: StandardJSONSchemaV1.Target): {\n draft: '2020-12' | '07';\n $schema: false;\n} {\n switch (target) {\n case 'draft-2020-12':\n return { draft: '2020-12', $schema: false };\n case 'draft-07':\n return { draft: '07', $schema: false };\n case 'openapi-3.0':\n // OpenAPI 3.0 is a superset of JSON Schema Draft 04; Draft 07 is\n // the closest we support.\n return { draft: '07', $schema: false };\n default:\n throw new Error(\n `@cleverbrush/schema-json: unsupported JSON Schema target \"${target}\".`\n );\n }\n}\n\n/**\n * Wraps a `@cleverbrush/schema` builder with the\n * [Standard JSON Schema v1](https://standardschema.dev/) interface.\n *\n * The returned schema object's `~standard` property is enriched with a\n * `jsonSchema` converter. Because `@cleverbrush/schema` does not\n * distinguish between input and output types, both `input()` and `output()`\n * produce the same JSON Schema document.\n *\n * **Note:** this mutates the schema instance by overriding the `~standard`\n * property. The returned reference is the same schema object.\n *\n * @example\n * ```ts\n * import { object, string, number } from '@cleverbrush/schema';\n * import { withStandardJsonSchema } from '@cleverbrush/schema-json';\n *\n * const schema = object({ name: string(), age: number().optional() });\n * const wrapped = withStandardJsonSchema(schema);\n *\n * // Access standard JSON Schema properties\n * wrapped['~standard'].jsonSchema.input({ target: 'draft-2020-12' });\n * wrapped['~standard'].jsonSchema.output({ target: 'draft-07' });\n * ```\n *\n * @param schema - Any `@cleverbrush/schema` builder instance.\n * @returns The same schema instance, now also conforming to `StandardJSONSchemaV1`.\n */\nexport function withStandardJsonSchema<\n T extends SchemaBuilder<any, any, any, any, any>\n>(schema: T): T & StandardJSONSchemaV1 {\n const converter: StandardJSONSchemaV1.Converter = {\n input(options: StandardJSONSchemaV1.Options): Record<string, unknown> {\n return toJsonSchema(schema, targetToOptions(options.target));\n },\n output(options: StandardJSONSchemaV1.Options): Record<string, unknown> {\n return toJsonSchema(schema, targetToOptions(options.target));\n }\n };\n\n // Extend the existing `~standard` props (which already include the\n // StandardSchemaV1 validate function from the schema library) with the\n // jsonSchema converter.\n const existingStandard = schema['~standard'];\n const enrichedStandard = { ...existingStandard, jsonSchema: converter };\n\n // Override the prototype getter with an instance-level property.\n // A Proxy wrapper was considered but JavaScript private fields (#field)\n // are bound to the original class instance; when a method is invoked\n // through a Proxy the receiver is the Proxy, not the real instance, so\n // private-field access throws a TypeError. defineProperty avoids this\n // because `this` inside methods still refers to the original schema.\n Object.defineProperty(schema, '~standard', {\n value: enrichedStandard,\n configurable: true,\n writable: false,\n enumerable: false\n });\n\n return schema as T & StandardJSONSchemaV1;\n}\n"],"mappings":"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","names":["any","array","boolean","intersection","nul","number","object","string","tuple","union","fail","msg","ok","buildNode","s","node","b","buildEnum","buildConst","buildAnyOf","buildAllOf","buildString","buildNumber","buildArray","buildObject","val","format","v","integer","min","max","elements","props","requiredSet","key","propNode","propBuilder","values","first","rest","options","opt","i","fromJsonSchema","schema","escapeRegex","s","escapeJsonPointerSegment","convertNodeInner","schema","resolver","info","ext","readOnly","out","ver","convertNode","elements","e","props","outProps","required","key","propSchema","options","enumValues","allConst","opt","oi","converted","o","discriminatorProp","disc","mapping","allRefsMapped","i","ref","discriminatorSchema","propInfo","left","right","resolved","name","anyOf","constVal","toJsonSchema","opts","body","targetToOptions","target","withStandardJsonSchema","schema","converter","options","toJsonSchema","enrichedStandard"]}
package/dist/types.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import type { BooleanSchemaBuilder, ExtendedArray, ExtendedNumber, ExtendedString, ObjectSchemaBuilder, SchemaBuilder, UnionSchemaBuilder } from '@cleverbrush/schema';
6
+ import type { BooleanSchemaBuilder, ExtendedArray, ExtendedNumber, ExtendedString, IntersectionSchemaBuilder, ObjectSchemaBuilder, SchemaBuilder, UnionSchemaBuilder } from '@cleverbrush/schema';
7
7
  /**
8
8
  * Subset of JSON Schema (Draft 7 / 2020-12) accepted as input.
9
9
  *
@@ -108,8 +108,13 @@ export type InferFromJsonSchema<S> = S extends {
108
108
  } ? Record<string, unknown> : S extends {
109
109
  readonly anyOf: readonly (infer U)[];
110
110
  } ? InferFromJsonSchema<U> : S extends {
111
- readonly allOf: readonly JsonSchemaNode[];
112
- } ? unknown : unknown;
111
+ readonly allOf: readonly [
112
+ infer First extends JsonSchemaNode,
113
+ ...infer Rest extends readonly JsonSchemaNode[]
114
+ ];
115
+ } ? Rest extends readonly [] ? InferFromJsonSchema<First> : InferFromJsonSchema<First> & InferFromJsonSchema<{
116
+ readonly allOf: Rest;
117
+ }> : unknown;
113
118
  /** Options accepted by {@link toJsonSchema}. */
114
119
  export type ToJsonSchemaOptions = {
115
120
  /**
@@ -200,6 +205,29 @@ type ObjectPropertiesToBuilders<P extends Record<string, unknown>, R extends str
200
205
  } & {
201
206
  [K in keyof P as K extends R ? never : K]: JsonSchemaNodeToBuilder<P[K], false>;
202
207
  };
208
+ /**
209
+ * When folding an allOf tuple, some accumulator elements may already be
210
+ * resolved builders from previous fold steps. This helper returns the
211
+ * input unchanged when it is already a schema builder, and otherwise
212
+ * maps it through {@link JsonSchemaNodeToBuilder}.
213
+ * @internal
214
+ */
215
+ type AsBuilderIfNeeded<X, R extends boolean = true> = X extends SchemaBuilder<any, any, any, any, any> ? X : JsonSchemaNodeToBuilder<X, R>;
216
+ /**
217
+ * Recursively folds an `allOf` tuple left-to-right into a nested
218
+ * {@link IntersectionSchemaBuilder} chain, matching the runtime behavior
219
+ * of {@link fromJsonSchema}.
220
+ *
221
+ * @internal
222
+ */
223
+ type AllOfNodesToBuilder<Acc extends readonly unknown[], TRequired extends boolean = true> = Acc extends readonly [
224
+ infer First,
225
+ infer Second,
226
+ ...infer Rest extends readonly unknown[]
227
+ ] ? Rest extends readonly [] ? IntersectionSchemaBuilder<AsBuilderIfNeeded<First>, AsBuilderIfNeeded<Second>, TRequired> : AllOfNodesToBuilder<[
228
+ IntersectionSchemaBuilder<AsBuilderIfNeeded<First>, AsBuilderIfNeeded<Second>>,
229
+ ...Rest
230
+ ], TRequired> : Acc extends readonly [infer Only] ? AsBuilderIfNeeded<Only, TRequired> : SchemaBuilder<unknown, TRequired>;
203
231
  /**
204
232
  * Recursively maps a statically-known JSON Schema node (passed with
205
233
  * `as const`) to the exact `@cleverbrush/schema` builder type, including:
@@ -249,8 +277,8 @@ export type JsonSchemaNodeToBuilder<S, TRequired extends boolean = true> = S ext
249
277
  } ? UnionSchemaBuilder<EnumTupleToBuilders<Vals>, TRequired> : S extends {
250
278
  readonly anyOf: infer Opts extends readonly unknown[];
251
279
  } ? UnionSchemaBuilder<SchemaNodesTupleToBuilders<Opts>, TRequired> : S extends {
252
- readonly allOf: infer _Opts extends readonly unknown[];
253
- } ? SchemaBuilder<unknown, TRequired> : S extends {
280
+ readonly allOf: infer Opts extends readonly unknown[];
281
+ } ? AllOfNodesToBuilder<Opts, TRequired> : S extends {
254
282
  readonly type: 'string';
255
283
  } ? ExtendedStringBuilder<string, TRequired> : S extends {
256
284
  readonly type: 'number';
package/package.json CHANGED
@@ -41,5 +41,5 @@
41
41
  },
42
42
  "type": "module",
43
43
  "types": "./dist/index.d.ts",
44
- "version": "4.0.0"
44
+ "version": "4.2.0"
45
45
  }