@valibot/to-json-schema
Version:
The official JSON schema converter for Valibot
1 lines • 11.8 kB
JavaScript
function e(e,t){return e?(e.push(t),e):[t]}const t=/[.*+?^${}()|[\]\\]/g;function n(e){return e.replace(t,`\\$&`)}function r(e,t){switch(t?.errorMode){case`ignore`:break;case`warn`:console.warn(e);break;default:throw Error(e)}}function i(e){return typeof e==`boolean`||typeof e==`number`&&Number.isFinite(e)||typeof e==`string`}function a(e){return e.every(i)}function o(t,o,s){if(s?.ignoreActions?.includes(o.type))return t;let c;switch(o.type){case`base64`:t.contentEncoding=`base64`;break;case`bic`:case`cuid2`:case`decimal`:case`digits`:case`domain`:case`emoji`:case`hash`:case`hexadecimal`:case`hex_color`:case`isrc`:case`iso_time_second`:case`iso_week`:case`mac`:case`mac48`:case`mac64`:case`nanoid`:case`octal`:case`slug`:case`ulid`:t.pattern?c=e(c,`The "${o.type}" action is not supported in combination with another regex action.`):t.pattern=o.requirement.source;break;case`description`:t.description=o.description;break;case`email`:case`rfc_email`:t.format=`email`;break;case`ends_with`:t.pattern?c=e(c,`The "${o.type}" action is not supported in combination with another regex action.`):t.pattern=`${n(o.requirement)}$`;break;case`empty`:t.type===`array`?t.maxItems=0:(t.type!==`string`&&(c=e(c,`The "${o.type}" action is not supported on type "${t.type}".`)),t.maxLength=0);break;case`entries`:t.minProperties=o.requirement,t.maxProperties=o.requirement;break;case`examples`:Array.isArray(t.examples)?t.examples=[...t.examples,...o.examples]:t.examples=o.examples;break;case`gt_value`:if(t.type!==`number`&&t.type!==`integer`&&(c=e(c,`The "gt_value" action is not supported on type "${t.type}".`)),s?.target===`openapi-3.0`){c=e(c,`The "gt_value" action is not supported for OpenAPI 3.0.`);break}t.exclusiveMinimum=o.requirement;break;case`includes`:t.pattern?c=e(c,`The "${o.type}" action is not supported in combination with another regex action.`):t.pattern=n(o.requirement);break;case`integer`:t.type=`integer`;break;case`ipv4`:t.format=`ipv4`;break;case`ipv6`:t.format=`ipv6`;break;case`iso_date`:t.format=`date`;break;case`iso_date_time`:case`iso_timestamp`:t.format=`date-time`;break;case`iso_time`:t.format=`time`;break;case`jws_compact`:t.pattern?c=e(c,`The "${o.type}" action is not supported in combination with another regex action.`):t.pattern=o.requirement.source;break;case`length`:t.type===`array`?(t.minItems=o.requirement,t.maxItems=o.requirement):(t.type!==`string`&&(c=e(c,`The "${o.type}" action is not supported on type "${t.type}".`)),t.minLength=o.requirement,t.maxLength=o.requirement);break;case`lt_value`:if(t.type!==`number`&&t.type!==`integer`&&(c=e(c,`The "lt_value" action is not supported on type "${t.type}".`)),s?.target===`openapi-3.0`){c=e(c,`The "lt_value" action is not supported for OpenAPI 3.0.`);break}t.exclusiveMaximum=o.requirement;break;case`max_entries`:t.maxProperties=o.requirement;break;case`max_length`:t.type===`array`?t.maxItems=o.requirement:(t.type!==`string`&&(c=e(c,`The "${o.type}" action is not supported on type "${t.type}".`)),t.maxLength=o.requirement);break;case`max_value`:t.type!==`number`&&t.type!==`integer`&&(c=e(c,`The "max_value" action is not supported on type "${t.type}".`)),t.maximum=o.requirement;break;case`metadata`:typeof o.metadata.title==`string`&&(t.title=o.metadata.title),typeof o.metadata.description==`string`&&(t.description=o.metadata.description),Array.isArray(o.metadata.examples)&&(Array.isArray(t.examples)?t.examples=[...t.examples,...o.metadata.examples]:t.examples=o.metadata.examples);break;case`min_entries`:t.minProperties=o.requirement;break;case`min_length`:t.type===`array`?t.minItems=o.requirement:(t.type!==`string`&&(c=e(c,`The "${o.type}" action is not supported on type "${t.type}".`)),t.minLength=o.requirement);break;case`min_value`:t.type!==`number`&&t.type!==`integer`&&(c=e(c,`The "min_value" action is not supported on type "${t.type}".`)),t.minimum=o.requirement;break;case`multiple_of`:t.multipleOf=o.requirement;break;case`non_empty`:t.type===`array`?t.minItems=1:(t.type!==`string`&&(c=e(c,`The "${o.type}" action is not supported on type "${t.type}".`)),t.minLength=1);break;case`not_value`:if(!i(o.requirement)){c=e(c,`The requirement of the "not_value" action is not JSON compatible.`);break}s?.target===`openapi-3.0`?t.not={enum:[o.requirement]}:t.not={const:o.requirement};break;case`not_values`:if(!a(o.requirement)){c=e(c,`A requirement of the "not_values" action is not JSON compatible.`);break}t.not={enum:o.requirement};break;case`regex`:o.requirement.flags&&(c=e(c,`RegExp flags are not supported by JSON Schema.`)),t.pattern?c=e(c,`The "${o.type}" action is not supported in combination with another regex action.`):t.pattern=o.requirement.source;break;case`safe_integer`:t.type=`integer`,(typeof t.minimum!=`number`||t.minimum<-(2**53-1))&&(t.minimum=-(2**53-1)),(typeof t.maximum!=`number`||t.maximum>2**53-1)&&(t.maximum=2**53-1);break;case`starts_with`:t.pattern?c=e(c,`The "${o.type}" action is not supported in combination with another regex action.`):t.pattern=`^${n(o.requirement)}`;break;case`title`:t.title=o.title;break;case`url`:t.format=`uri`;break;case`uuid`:t.format=`uuid`;break;case`value`:if(!i(o.requirement)){c=e(c,`The requirement of the "value" action is not JSON compatible.`);break}s?.target===`openapi-3.0`?t.enum=[o.requirement]:t.const=o.requirement;break;case`values`:if(!a(o.requirement)){c=e(c,`A requirement of the "values" action is not JSON compatible.`);break}t.enum=o.requirement;break;default:c=e(c,`The "${o.type}" action cannot be converted to JSON Schema.`)}if(s?.overrideAction){let e=s.overrideAction({valibotAction:o,jsonSchema:t,errors:c});if(e)return{...e}}if(c)for(let e of c)r(e,s);return t}function s(e){return e.flatMap(e=>`pipe`in e?s(e.pipe):e)}let c=0;function l(t,n,i,a,u=!1){if(!u){let e=a.referenceMap.get(n);if(e){if(t.$ref=`#/$defs/${e}`,i?.overrideRef){let r=i.overrideRef({...a,referenceId:e,valibotSchema:n,jsonSchema:t});r&&(t.$ref=r)}return t}}if(`pipe`in n){let e=s(n.pipe),c=0,u=e.length-1;if(i?.typeMode===`input`){let t=e.slice(1).findIndex(e=>e.kind===`schema`||e.kind===`transformation`&&(e.type===`find_item`||e.type===`parse_json`||e.type===`raw_transform`||e.type===`reduce_items`||e.type===`stringify_json`||e.type===`to_bigint`||e.type===`to_boolean`||e.type===`to_date`||e.type===`to_number`||e.type===`to_string`||e.type===`transform`));t!==-1&&(u=t)}else if(i?.typeMode===`output`){let t=e.findLastIndex(e=>e.kind===`schema`);t!==-1&&(c=t)}for(let n=c;n<=u;n++){let s=e[n];s.kind===`schema`?(n>c&&r(`Set the "typeMode" config to "input" or "output" to convert pipelines with multiple schemas.`,i),t=l(t,s,i,a,!0)):t=o(t,s,i)}return t}let d;switch(n.type){case`boolean`:t.type=`boolean`;break;case`null`:i?.target===`openapi-3.0`?t.enum=[null]:t.type=`null`;break;case`number`:t.type=`number`;break;case`string`:t.type=`string`;break;case`array`:t.type=`array`,t.items=l({},n.item,i,a);break;case`tuple`:case`tuple_with_rest`:case`loose_tuple`:case`strict_tuple`:if(t.type=`array`,i?.target===`openapi-3.0`){t.items={anyOf:[]},t.minItems=n.items.length;for(let e of n.items)t.items.anyOf.push(l({},e,i,a));n.type===`tuple_with_rest`?t.items.anyOf.push(l({},n.rest,i,a)):(n.type===`strict_tuple`||n.type===`tuple`)&&(t.maxItems=n.items.length)}else if(i?.target===`draft-2020-12`){t.prefixItems=[],t.minItems=n.items.length;for(let e of n.items)t.prefixItems.push(l({},e,i,a));n.type===`tuple_with_rest`?t.items=l({},n.rest,i,a):n.type===`strict_tuple`&&(t.items=!1)}else{t.items=[],t.minItems=n.items.length;for(let e of n.items)t.items.push(l({},e,i,a));n.type===`tuple_with_rest`?t.additionalItems=l({},n.rest,i,a):n.type===`strict_tuple`&&(t.additionalItems=!1)}break;case`object`:case`object_with_rest`:case`loose_object`:case`strict_object`:for(let e in t.type=`object`,t.properties={},t.required=[],n.entries){let r=n.entries[e];t.properties[e]=l({},r,i,a),r.type!==`exact_optional`&&r.type!==`nullish`&&r.type!==`optional`&&t.required.push(e)}n.type===`object_with_rest`?t.additionalProperties=l({},n.rest,i,a):n.type===`strict_object`&&(t.additionalProperties=!1);break;case`record`:i?.target===`openapi-3.0`&&`pipe`in n.key&&(d=e(d,`The "record" schema with a schema for the key that contains a "pipe" cannot be converted to JSON Schema.`)),n.key.type!==`string`&&(d=e(d,`The "record" schema with the "${n.key.type}" schema for the key cannot be converted to JSON Schema.`)),t.type=`object`,i?.target!==`openapi-3.0`&&(t.propertyNames=l({},n.key,i,a)),t.additionalProperties=l({},n.value,i,a);break;case`any`:case`unknown`:break;case`never`:t.not={};break;case`nullable`:case`nullish`:if(i?.target===`openapi-3.0`){let e=l({},n.wrapped,i,a);Object.assign(t,e),t.nullable=!0}else t.anyOf=[l({},n.wrapped,i,a),{type:`null`}];n.default!==void 0&&(t.default=typeof n.default==`function`?n.default():n.default);break;case`exact_optional`:case`optional`:case`undefinedable`:t=l(t,n.wrapped,i,a),n.default!==void 0&&(t.default=typeof n.default==`function`?n.default():n.default);break;case`literal`:typeof n.literal!=`boolean`&&typeof n.literal!=`number`&&typeof n.literal!=`string`&&(d=e(d,`The value of the "literal" schema is not JSON compatible.`)),i?.target===`openapi-3.0`?t.enum=[n.literal]:t.const=n.literal;break;case`enum`:t.enum=n.options,n.options.every(e=>typeof e==`string`)?t.type=`string`:n.options.every(e=>typeof e==`number`)?t.type=`number`:i?.target!==`openapi-3.0`&&(t.type=[`string`,`number`]);break;case`picklist`:{let r=n.options.some(e=>typeof e!=`number`&&typeof e!=`string`);r&&(d=e(d,`An option of the "picklist" schema is not JSON compatible.`)),t.enum=n.options,n.options.every(e=>typeof e==`string`)?t.type=`string`:n.options.every(e=>typeof e==`number`)?t.type=`number`:!r&&i?.target!==`openapi-3.0`&&(t.type=[`string`,`number`]);break}case`union`:t.anyOf=n.options.map(e=>l({},e,i,a));break;case`variant`:t.oneOf=n.options.map(e=>l({},e,i,a));break;case`intersect`:t.allOf=n.options.map(e=>l({},e,i,a));break;case`lazy`:{let e=a.getterMap.get(n.getter);e||(e=n.getter(void 0),a.getterMap.set(n.getter,e));let r=a.referenceMap.get(e);if(r||(r=`${c++}`,a.referenceMap.set(e,r),a.definitions[r]=l({},e,i,a,!0)),t.$ref=`#/$defs/${r}`,i?.overrideRef){let n=i.overrideRef({...a,referenceId:r,valibotSchema:e,jsonSchema:t});n&&(t.$ref=n)}break}default:d=e(d,`The "${n.type}" schema cannot be converted to JSON Schema.`)}if(i?.overrideSchema){let e=i.overrideSchema({...a,referenceId:a.referenceMap.get(n),valibotSchema:n,jsonSchema:t,errors:d});if(e)return{...e}}if(d)for(let e of d)r(e,i);return t}let u;function d(e){u={...u??{},...e}}function f(){return u}function p(e,t){let n={definitions:{},referenceMap:new Map,getterMap:new Map},r=t?.definitions??f();if(r){for(let e in r)n.referenceMap.set(r[e],e);for(let e in r)n.definitions[e]=l({},r[e],t,n,!0)}let i=l({},e,t,n),a=t?.target??`draft-07`;return a===`draft-2020-12`?i.$schema=`https://json-schema.org/draft/2020-12/schema`:a===`draft-07`&&(i.$schema=`http://json-schema.org/draft-07/schema#`),n.referenceMap.size&&(i.$defs=n.definitions),i}function m(e,t){let n={definitions:{},referenceMap:new Map,getterMap:new Map};for(let t in e)n.referenceMap.set(e[t],t);for(let r in e)n.definitions[r]=l({},e[r],t,n,!0);return n.definitions}const h=[`draft-07`,`draft-2020-12`,`openapi-3.0`];function g(e){return{"~standard":{...e[`~standard`],jsonSchema:{input(t){if(h.includes(t.target))return p(e,{typeMode:`input`,target:t.target,...t.libraryOptions});throw Error(`Unsupported target: ${t.target}`)},output(t){if(h.includes(t.target))return p(e,{typeMode:`output`,target:t.target,...t.libraryOptions});throw Error(`Unsupported target: ${t.target}`)}}}}}exports.addGlobalDefs=d,exports.getGlobalDefs=f,exports.toJsonSchema=p,exports.toJsonSchemaDefs=m,exports.toStandardJsonSchema=g;