@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) • 6.57 kB
JavaScript
"use strict";var k=Object.create;var o=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var i=(r,e)=>o(r,"name",{value:e,configurable:!0});var j=(r,e)=>{for(var a in e)o(r,a,{get:e[a],enumerable:!0})},f=(r,e,a,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of b(e))!O.call(r,s)&&s!==a&&o(r,s,{get:()=>e[s],enumerable:!(t=K(e,s))||t.enumerable});return r};var d=(r,e,a)=>(a=r!=null?k(x(r)):{},f(e||!r||!r.__esModule?o(a,"default",{value:r,enumerable:!0}):a,r)),P=r=>f(o({},"__esModule",{value:!0}),r);var M={};j(M,{ValidatorBuilder:()=>m});module.exports=P(M);var y=d(require("ajv"),1),T=d(require("ajv-formats"),1),p=d(require("ajv-errors"),1),v=d(require("ajv-keywords"),1),u=require("@fajarnugraha37/error"),g=require("@fajarnugraha37/cache");var l=class{static{i(this,"Validator")}ajv;validators=new Map;schemas={};schemaLoader;schemaCache;schemaCacheTtl;constructor(e={}){let a={strict:!0,allErrors:!0,removeAdditional:!1,useDefaults:!0,coerceTypes:!1,verbose:!0,...e};this.ajv=new y.default.default({...a,strict:!1,validateSchema:!1,addUsedSchema:!1});try{T.default.default(this.ajv)}catch{}try{p.default.default(this.ajv)}catch{}try{v.default.default(this.ajv)}catch{}}static builder(){return new m}registerSchema(e,a){try{this.schemas[e]=a;let t=this.ajv.compile(a);return this.validators.set(e,t),this.cacheSchema(e,a),this}catch(t){throw new Error(`Failed to register schema for type '${String(e)}': ${t}`)}}registerSchemas(e){for(let[a,t]of Object.entries(e))this.registerSchema(a,t);return this}registerSchemaBuilder(e,a){return this.registerSchema(e,a.build())}registerSchemaBuilders(e){for(let[a,t]of Object.entries(e))t&&this.registerSchemaBuilder(a,t);return this}enableSchemaCache(e={}){this.schemaCache=new g.LruTtlCache({maxEntries:e.maxEntries,maxSize:e.maxSize,sizer:e.sizer,sweepIntervalMs:e.sweepIntervalMs}),this.schemaCacheTtl={ttlMs:e.ttlMs,slidingTtlMs:e.slidingTtlMs};for(let[a,t]of Object.entries(this.schemas))t&&this.cacheSchema(a,t);return this}setSchemaLoader(e){return this.schemaLoader=e,this}importSchemasFromJSON(e,a={}){let t=this.normalizeSchemaInput(e);return(a.register??!0)&&this.registerSchemas(t),t}exportSchemas(e){let a=e??Object.keys(this.schemas),t={};for(let s of a){let h=this.schemas[s];h&&(t[s]=h)}return t}exportSchemasToJSON(e,a=2){return JSON.stringify(this.exportSchemas(e),null,a)}validate(e,a){let t=this.validators.get(e);if(!t)throw new Error(`No schema registered for type '${String(e)}'`);try{return t(a)?{valid:!0,data:a}:{valid:!1,errors:this.formatErrors(t.errors||[])}}catch(s){return{valid:!1,errors:[{keyword:"exception",instancePath:"",schemaPath:"",params:{},message:`Validation exception: ${s}`,data:a}]}}}async validateAsync(e,a){return await this.ensureSchemaLoaded(e),this.validate(e,a)}validateStrict(e,a){let t=this.validate(e,a);if(!t.valid){let s=t.errors?.map(h=>h.message).join(", ")||"Unknown validation error";throw new u.ValidationError(`Validation failed for type '${String(e)}': ${s}`)}return t.data}async validateStrictAsync(e,a){let t=await this.validateAsync(e,a);if(!t.valid){let s=t.errors?.map(h=>h.message).join(", ")||"Unknown validation error";throw new u.ValidationError(`Validation failed for type '${String(e)}': ${s}`)}return t.data}hasSchema(e){return this.validators.has(e)}getSchema(e){return this.schemas[e]}getRegisteredTypes(){return Array.from(this.validators.keys())}validateMany(e,a){let t=a.map(c=>this.validate(e,c)),s=[],h=[];return t.forEach((c,n)=>{if(c.valid&&c.data)h.push(c.data);else if(c.errors){let w=c.errors.map(S=>({...S,instancePath:`[${n}]${S.instancePath}`,message:`Item ${n}: ${S.message}`}));s.push(...w)}}),{valid:s.length===0,data:s.length===0?h:void 0,errors:s.length>0?s:void 0}}async validateManyAsync(e,a){return await this.ensureSchemaLoaded(e),this.validateMany(e,a)}createTypeValidator(e){if(!this.hasSchema(e))throw new Error(`No schema registered for type '${String(e)}'`);return{validate:i(a=>this.validate(e,a),"validate"),validateAsync:i(a=>this.validateAsync(e,a),"validateAsync"),validateStrict:i(a=>this.validateStrict(e,a),"validateStrict"),validateStrictAsync:i(a=>this.validateStrictAsync(e,a),"validateStrictAsync"),validateMany:i(a=>this.validateMany(e,a),"validateMany"),validateManyAsync:i(a=>this.validateManyAsync(e,a),"validateManyAsync")}}addCustomValidation(e,a,t){return this.ajv.addKeyword({keyword:a,validate:i(function s(h,c){let n=t(c);return typeof n=="string"?(s.errors=[{message:n}],!1):n},"validate")}),this}async ensureSchemaLoaded(e){if(this.hasSchema(e))return;let a=this.schemaCache?.get(e);if(a){this.registerSchema(e,a);return}if(!this.schemaLoader)throw new Error(`No schema registered for type '${String(e)}' and no schema loader configured`);let t=await this.schemaLoader(e);if(!t)throw new Error(`Schema loader did not return a schema for type '${String(e)}'`);this.registerSchema(e,t)}cacheSchema(e,a){this.schemaCache&&this.schemaCache.set(e,a,{ttlMs:this.schemaCacheTtl?.ttlMs,slidingTtlMs:this.schemaCacheTtl?.slidingTtlMs})}normalizeSchemaInput(e){let a=typeof e=="string"?JSON.parse(e):e;if(typeof a!="object"||a===null||Array.isArray(a))throw new Error("Schema JSON must be an object keyed by schema type");return a}formatErrors(e){return e.map(a=>({keyword:a.keyword,instancePath:a.instancePath||"",schemaPath:a.schemaPath||"",params:a.params||{},message:a.message||"Validation error",data:a.data,parentSchema:a.parentSchema,schema:a.schema}))}};var m=class r{static{i(this,"ValidatorBuilder")}options={};schemas={};loader;cacheOptions;static create(){return new r}withOptions(e){return this.options={...this.options,...e},this}withSchema(e,a){return this.schemas={...this.schemas,[e]:a},this}withSchemaBuilder(e,a){return this.withSchema(e,a.build())}withSchemas(e){return this.schemas={...this.schemas,...e},this}withSchemaBuilders(e){for(let[a,t]of Object.entries(e))t&&this.withSchemaBuilder(a,t);return this}fromJSON(e){let a=typeof e=="string"?JSON.parse(e):e;if(typeof a!="object"||a===null||Array.isArray(a))throw new Error("Schema JSON must be an object keyed by schema type");return this.withSchemas(a),this}withSchemaLoader(e){return this.loader=e,this}withCache(e={}){return this.cacheOptions=e,this}build(){let e=new l(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}};0&&(module.exports={ValidatorBuilder});