@fajarnugraha37/validator
Version:
A typed façade over [AJV](https://ajv.js.org/) that brings schema builders, caching, and loader pipelines to the `nope` workspace
2 lines (1 loc) • 12 kB
JavaScript
"use strict";var j=Object.create;var d=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var C=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var r=(s,e)=>d(s,"name",{value:e,configurable:!0});var B=(s,e)=>{for(var t in e)d(s,t,{get:e[t],enumerable:!0})},w=(s,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of J(e))!A.call(s,i)&&i!==t&&d(s,i,{get:()=>e[i],enumerable:!(a=M(e,i))||a.enumerable});return s};var u=(s,e,t)=>(t=s!=null?j(C(s)):{},w(e||!s||!s.__esModule?d(t,"default",{value:s,enumerable:!0}):t,s)),E=s=>w(d({},"__esModule",{value:!0}),s);var H={};B(H,{SchemaBuilder:()=>S,Validator:()=>n,ValidatorBuilder:()=>l,buildSchemaMap:()=>L,createTypeValidatorFromBuilders:()=>G,createTypeValidatorFromJSON:()=>U,createValidator:()=>z,createValidatorFromBuilders:()=>V,createValidatorFromJSON:()=>k,defaultValidator:()=>x,defineSchemas:()=>N,validateExpression:()=>q,validateExpressionStrict:()=>F,validatorBuilder:()=>D});module.exports=E(H);var b=u(require("ajv"),1),v=u(require("ajv-formats"),1),O=u(require("ajv-errors"),1),K=u(require("ajv-keywords"),1),y=require("@fajarnugraha37/error"),R=require("@fajarnugraha37/cache");var l=class s{static{r(this,"ValidatorBuilder")}options={};schemas={};loader;cacheOptions;static create(){return new s}withOptions(e){return this.options={...this.options,...e},this}withSchema(e,t){return this.schemas={...this.schemas,[e]:t},this}withSchemaBuilder(e,t){return this.withSchema(e,t.build())}withSchemas(e){return this.schemas={...this.schemas,...e},this}withSchemaBuilders(e){for(let[t,a]of Object.entries(e))a&&this.withSchemaBuilder(t,a);return this}fromJSON(e){let t=typeof e=="string"?JSON.parse(e):e;if(typeof t!="object"||t===null||Array.isArray(t))throw new Error("Schema JSON must be an object keyed by schema type");return this.withSchemas(t),this}withSchemaLoader(e){return this.loader=e,this}withCache(e={}){return this.cacheOptions=e,this}build(){let e=new n(this.options);return this.cacheOptions&&e.enableSchemaCache(this.cacheOptions),this.loader&&e.setSchemaLoader(this.loader),Object.keys(this.schemas).length>0&&e.registerSchemas(this.schemas),e}};var n=class{static{r(this,"Validator")}ajv;validators=new Map;schemas={};schemaLoader;schemaCache;schemaCacheTtl;constructor(e={}){let t={strict:!0,allErrors:!0,removeAdditional:!1,useDefaults:!0,coerceTypes:!1,verbose:!0,...e};this.ajv=new b.default.default({...t,strict:!1,validateSchema:!1,addUsedSchema:!1});try{v.default.default(this.ajv)}catch{}try{O.default.default(this.ajv)}catch{}try{K.default.default(this.ajv)}catch{}}static builder(){return new l}registerSchema(e,t){try{this.schemas[e]=t;let a=this.ajv.compile(t);return this.validators.set(e,a),this.cacheSchema(e,t),this}catch(a){throw new Error(`Failed to register schema for type '${String(e)}': ${a}`)}}registerSchemas(e){for(let[t,a]of Object.entries(e))this.registerSchema(t,a);return this}registerSchemaBuilder(e,t){return this.registerSchema(e,t.build())}registerSchemaBuilders(e){for(let[t,a]of Object.entries(e))a&&this.registerSchemaBuilder(t,a);return this}enableSchemaCache(e={}){this.schemaCache=new R.LruTtlCache({maxEntries:e.maxEntries,maxSize:e.maxSize,sizer:e.sizer,sweepIntervalMs:e.sweepIntervalMs}),this.schemaCacheTtl={ttlMs:e.ttlMs,slidingTtlMs:e.slidingTtlMs};for(let[t,a]of Object.entries(this.schemas))a&&this.cacheSchema(t,a);return this}setSchemaLoader(e){return this.schemaLoader=e,this}importSchemasFromJSON(e,t={}){let a=this.normalizeSchemaInput(e);return(t.register??!0)&&this.registerSchemas(a),a}exportSchemas(e){let t=e??Object.keys(this.schemas),a={};for(let i of t){let c=this.schemas[i];c&&(a[i]=c)}return a}exportSchemasToJSON(e,t=2){return JSON.stringify(this.exportSchemas(e),null,t)}validate(e,t){let a=this.validators.get(e);if(!a)throw new Error(`No schema registered for type '${String(e)}'`);try{return a(t)?{valid:!0,data:t}:{valid:!1,errors:this.formatErrors(a.errors||[])}}catch(i){return{valid:!1,errors:[{keyword:"exception",instancePath:"",schemaPath:"",params:{},message:`Validation exception: ${i}`,data:t}]}}}async validateAsync(e,t){return await this.ensureSchemaLoaded(e),this.validate(e,t)}validateStrict(e,t){let a=this.validate(e,t);if(!a.valid){let i=a.errors?.map(c=>c.message).join(", ")||"Unknown validation error";throw new y.ValidationError(`Validation failed for type '${String(e)}': ${i}`)}return a.data}async validateStrictAsync(e,t){let a=await this.validateAsync(e,t);if(!a.valid){let i=a.errors?.map(c=>c.message).join(", ")||"Unknown validation error";throw new y.ValidationError(`Validation failed for type '${String(e)}': ${i}`)}return a.data}hasSchema(e){return this.validators.has(e)}getSchema(e){return this.schemas[e]}getRegisteredTypes(){return Array.from(this.validators.keys())}validateMany(e,t){let a=t.map(m=>this.validate(e,m)),i=[],c=[];return a.forEach((m,o)=>{if(m.valid&&m.data)c.push(m.data);else if(m.errors){let P=m.errors.map(p=>({...p,instancePath:`[${o}]${p.instancePath}`,message:`Item ${o}: ${p.message}`}));i.push(...P)}}),{valid:i.length===0,data:i.length===0?c:void 0,errors:i.length>0?i:void 0}}async validateManyAsync(e,t){return await this.ensureSchemaLoaded(e),this.validateMany(e,t)}createTypeValidator(e){if(!this.hasSchema(e))throw new Error(`No schema registered for type '${String(e)}'`);return{validate:r(t=>this.validate(e,t),"validate"),validateAsync:r(t=>this.validateAsync(e,t),"validateAsync"),validateStrict:r(t=>this.validateStrict(e,t),"validateStrict"),validateStrictAsync:r(t=>this.validateStrictAsync(e,t),"validateStrictAsync"),validateMany:r(t=>this.validateMany(e,t),"validateMany"),validateManyAsync:r(t=>this.validateManyAsync(e,t),"validateManyAsync")}}addCustomValidation(e,t,a){return this.ajv.addKeyword({keyword:t,validate:r(function i(c,m){let o=a(m);return typeof o=="string"?(i.errors=[{message:o}],!1):o},"validate")}),this}async ensureSchemaLoaded(e){if(this.hasSchema(e))return;let t=this.schemaCache?.get(e);if(t){this.registerSchema(e,t);return}if(!this.schemaLoader)throw new Error(`No schema registered for type '${String(e)}' and no schema loader configured`);let a=await this.schemaLoader(e);if(!a)throw new Error(`Schema loader did not return a schema for type '${String(e)}'`);this.registerSchema(e,a)}cacheSchema(e,t){this.schemaCache&&this.schemaCache.set(e,t,{ttlMs:this.schemaCacheTtl?.ttlMs,slidingTtlMs:this.schemaCacheTtl?.slidingTtlMs})}normalizeSchemaInput(e){let t=typeof e=="string"?JSON.parse(e):e;if(typeof t!="object"||t===null||Array.isArray(t))throw new Error("Schema JSON must be an object keyed by schema type");return t}formatErrors(e){return e.map(t=>({keyword:t.keyword,instancePath:t.instancePath||"",schemaPath:t.schemaPath||"",params:t.params||{},message:t.message||"Validation error",data:t.data,parentSchema:t.parentSchema,schema:t.schema}))}};var g=r(s=>{let e=globalThis.structuredClone;return typeof e=="function"?e(s):JSON.parse(JSON.stringify(s))},"clone"),h=r(s=>s instanceof S?s.build():g(s),"normalizeInput"),f=r(s=>!s||typeof s!="object"||Array.isArray(s)?{}:s,"ensureObject"),T=r(s=>Array.from(new Set(s)),"unique"),S=class s{static{r(this,"SchemaBuilder")}schema;constructor(e={}){this.schema=g(e)}static create(e={}){return new s(e)}static object(){return new s({type:"object",properties:{},required:[]})}static array(){return new s({type:"array"})}static string(){return new s({type:"string"})}static number(){return new s({type:"number"})}static integer(){return new s({type:"integer"})}static boolean(){return new s({type:"boolean"})}static nil(){return new s({type:"null"})}clone(){return new s(this.build())}extend(e){return Object.assign(this.schema,h(e)),this}title(e){return this.schema.title=e,this}description(e){return this.schema.description=e,this}default(e){return this.schema.default=e,this}examples(...e){return this.schema.examples=e,this}example(e){let t=Array.isArray(this.schema.examples)?this.schema.examples:[];return t.push(e),this.schema.examples=t,this}const(e){return this.schema.const=e,this}enum(e){return this.schema.enum=e,this}format(e){return this.schema.format=e,this}$id(e){return this.schema.$id=e,this}$schema(e){return this.schema.$schema=e,this}ref(e){return this.schema.$ref=e,this}readOnly(e=!0){return this.schema.readOnly=e,this}writeOnly(e=!0){return this.schema.writeOnly=e,this}nullable(e=!0){let t=this.schema.type;return e?Array.isArray(t)?this.schema.type=T([...t,"null"]):t&&t!=="null"?this.schema.type=T([t,"null"]):this.schema.type="null":Array.isArray(t)?this.schema.type=t.filter(a=>a!=="null"):t==="null"&&delete this.schema.type,this}type(e){return this.schema.type=e,this}property(e,t,a={}){let i=f(this.schema.properties);return i[e]=h(t),this.schema.properties=i,a.required&&this.required(e),this}properties(e,t={}){for(let[a,i]of Object.entries(e))this.property(a,i);return t.required&&this.required(...t.required),this}required(...e){let t=Array.isArray(this.schema.required)?this.schema.required:[];return this.schema.required=T([...t,...e]),this}additionalProperties(e){return this.schema.additionalProperties=typeof e=="boolean"?e:h(e),this}patternProperty(e,t){let a=f(this.schema.patternProperties);return a[e]=h(t),this.schema.patternProperties=a,this}propertyNames(e){return this.schema.propertyNames=h(e),this}minProperties(e){return this.schema.minProperties=e,this}maxProperties(e){return this.schema.maxProperties=e,this}items(e){return this.schema.items=h(e),this}prefixItems(...e){return this.schema.prefixItems=e.map(h),this}contains(e){return this.schema.contains=h(e),this}minItems(e){return this.schema.minItems=e,this}maxItems(e){return this.schema.maxItems=e,this}uniqueItems(e=!0){return this.schema.uniqueItems=e,this}minLength(e){return this.schema.minLength=e,this}maxLength(e){return this.schema.maxLength=e,this}pattern(e){return this.schema.pattern=e,this}minimum(e){return this.schema.minimum=e,this}maximum(e){return this.schema.maximum=e,this}exclusiveMinimum(e){return this.schema.exclusiveMinimum=e,this}exclusiveMaximum(e){return this.schema.exclusiveMaximum=e,this}multipleOf(e){return this.schema.multipleOf=e,this}allOf(...e){return this.schema.allOf=e.map(h),this}anyOf(...e){return this.schema.anyOf=e.map(h),this}oneOf(...e){return this.schema.oneOf=e.map(h),this}not(e){return this.schema.not=h(e),this}ifSchema(e){return this.schema.if=h(e),this}thenSchema(e){return this.schema.then=h(e),this}elseSchema(e){return this.schema.else=h(e),this}definition(e,t){let a=f(this.schema.$defs);return a[e]=h(t),this.schema.$defs=a,this}definitions(e){for(let[t,a]of Object.entries(e))this.definition(t,a);return this}meta(e,t){return this.schema[e]=t,this}build(){return g(this.schema)}toJSON(){return this.build()}};var I=r(s=>s instanceof S,"isSchemaBuilder"),$=r(s=>I(s)?s.build():s,"toSchemaObject"),x=n.builder().withCache({maxEntries:100}).build(),N=r(s=>s,"defineSchemas"),L=r(s=>{let e={};for(let[t,a]of Object.entries(s))a&&(e[t]=$(a));return e},"buildSchemaMap"),q=r(s=>x.validate("expression-schema",s),"validateExpression"),F=r(s=>x.validateStrict("expression-schema",s),"validateExpressionStrict"),z=r((s,e)=>{let t=new n;return t.registerSchema(s,e),t.createTypeValidator(s)},"createValidator"),k=r((s,e={})=>{let t=n.builder();return e.options&&t.withOptions(e.options),e.cache&&t.withCache(e.cache),e.loader&&t.withSchemaLoader(e.loader),t.fromJSON(s),t.build()},"createValidatorFromJSON"),V=r((s,e={})=>k(L(s),e),"createValidatorFromBuilders"),D=r(()=>n.builder(),"validatorBuilder"),U=r((s,e,t={})=>k(e,t).createTypeValidator(s),"createTypeValidatorFromJSON"),G=r((s,e,t={})=>V(e,t).createTypeValidator(s),"createTypeValidatorFromBuilders");0&&(module.exports={SchemaBuilder,Validator,ValidatorBuilder,buildSchemaMap,createTypeValidatorFromBuilders,createTypeValidatorFromJSON,createValidator,createValidatorFromBuilders,createValidatorFromJSON,defaultValidator,defineSchemas,validateExpression,validateExpressionStrict,validatorBuilder});