UNPKG

decentralized-internet

Version:

An NPM library of programs to create decentralized web and distributed computing projects

1 lines 11.4 kB
"use strict";const Hoek=require("hoek"),Topo=require("topo"),Any=require("./any"),Errors=require("./errors"),Cast=require("./cast"),Ref=require("./ref"),internals={};internals.Object=class extends Any{constructor(){super(),this._type="object",this._inner.children=null,this._inner.renames=[],this._inner.dependencies=[],this._inner.patterns=[]}_base(e,t,r){let n=e;const s=[],i=()=>({value:n,errors:s.length?s:null});"string"==typeof e&&r.convert&&(e=internals.safeParse(e));const o=this._flags.func?"function":"object";if(!e||typeof e!==o||Array.isArray(e))return s.push(this.createError(o+".base",null,t,r)),i();if(!(this._inner.renames.length||this._inner.dependencies.length||this._inner.children||this._inner.patterns.length))return n=e,i();if(n===e){"object"===o?n=Object.create(Object.getPrototypeOf(e)):(n=function(){return e.apply(this,arguments)}).prototype=Hoek.clone(e.prototype);const t=Object.keys(e);for(let r=0;r<t.length;++r)n[t[r]]=e[t[r]]}else n=e;const a={};for(let e=0;e<this._inner.renames.length;++e){const o=this._inner.renames[e];if(!o.options.ignoreUndefined||void 0!==n[o.from]){if(!o.options.multiple&&a[o.to]&&(s.push(this.createError("object.rename.multiple",{from:o.from,to:o.to},t,r)),r.abortEarly))return i();if(Object.prototype.hasOwnProperty.call(n,o.to)&&!o.options.override&&!a[o.to]&&(s.push(this.createError("object.rename.override",{from:o.from,to:o.to},t,r)),r.abortEarly))return i();void 0===n[o.from]?delete n[o.to]:n[o.to]=n[o.from],a[o.to]=!0,o.options.alias||delete n[o.from]}}if(!this._inner.children&&!this._inner.patterns.length&&!this._inner.dependencies.length)return i();const l=Hoek.mapToObject(Object.keys(n));if(this._inner.children)for(let e=0;e<this._inner.children.length;++e){const o=this._inner.children[e],a=o.key,c=n[a];delete l[a];const h={key:a,path:(t.path||"")+(t.path&&a?".":"")+a,parent:n,reference:t.reference},p=o.schema._validate(c,h,r);if(p.errors&&(s.push(this.createError("object.child",{key:a,child:o.schema._getLabel(a),reason:p.errors},h,r)),r.abortEarly))return i();o.schema._flags.strip||void 0===p.value&&p.value!==c?delete n[a]:void 0!==p.value&&(n[a]=p.value)}let c=Object.keys(l);if(c.length&&this._inner.patterns.length){for(let e=0;e<c.length;++e){const o=c[e],a={key:o,path:(t.path?t.path+".":"")+o,parent:n,reference:t.reference},h=n[o];for(let e=0;e<this._inner.patterns.length;++e){const t=this._inner.patterns[e];if(t.regex.test(o)){delete l[o];const e=t.rule._validate(h,a,r);if(e.errors&&(s.push(this.createError("object.child",{key:o,child:t.rule._getLabel(o),reason:e.errors},a,r)),r.abortEarly))return i();void 0!==e.value&&(n[o]=e.value)}}}c=Object.keys(l)}if((this._inner.children||this._inner.patterns.length)&&c.length){if(r.stripUnknown||r.skipFunctions){const e=!!r.stripUnknown&&(!0===r.stripUnknown||!!r.stripUnknown.objects);for(let t=0;t<c.length;++t){const r=c[t];e?(delete n[r],delete l[r]):"function"==typeof n[r]&&delete l[r]}c=Object.keys(l)}if(c.length&&(void 0!==this._flags.allowUnknown?!this._flags.allowUnknown:!r.allowUnknown))for(let e=0;e<c.length;++e){const n=c[e];s.push(this.createError("object.allowUnknown",{child:n},{key:n,path:t.path+(t.path?".":"")+n},r))}}for(let e=0;e<this._inner.dependencies.length;++e){const o=this._inner.dependencies[e],a=internals[o.type].call(this,null!==o.key&&n[o.key],o.peers,n,{key:o.key,path:(t.path||"")+(o.key?"."+o.key:"")},r);if(a instanceof Errors.Err&&(s.push(a),r.abortEarly))return i()}return i()}_func(){const e=this.clone();return e._flags.func=!0,e}keys(e){Hoek.assert(null==e||"object"==typeof e,"Object schema must be a valid object"),Hoek.assert(!(e&&e instanceof Any),"Object schema cannot be a joi schema");const t=this.clone();if(!e)return t._inner.children=null,t;const r=Object.keys(e);if(!r.length)return t._inner.children=[],t;const n=new Topo;if(t._inner.children)for(let e=0;e<t._inner.children.length;++e){const s=t._inner.children[e];-1===r.indexOf(s.key)&&n.add(s,{after:s._refs,group:s.key})}for(let t=0;t<r.length;++t){const s=r[t],i=e[s];try{const e=Cast.schema(i);n.add({key:s,schema:e},{after:e._refs,group:s})}catch(e){throw e.hasOwnProperty("path")?e.path=s+"."+e.path:e.path=s,e}}return t._inner.children=n.nodes,t}unknown(e){const t=this.clone();return t._flags.allowUnknown=!1!==e,t}length(e){return Hoek.assert(Hoek.isInteger(e)&&e>=0,"limit must be a positive integer"),this._test("length",e,function(t,r,n){return Object.keys(t).length===e?t:this.createError("object.length",{limit:e},r,n)})}arity(e){return Hoek.assert(Hoek.isInteger(e)&&e>=0,"n must be a positive integer"),this._test("arity",e,function(t,r,n){return t.length===e?t:this.createError("function.arity",{n:e},r,n)})}minArity(e){return Hoek.assert(Hoek.isInteger(e)&&e>0,"n must be a strict positive integer"),this._test("minArity",e,function(t,r,n){return t.length>=e?t:this.createError("function.minArity",{n:e},r,n)})}maxArity(e){return Hoek.assert(Hoek.isInteger(e)&&e>=0,"n must be a positive integer"),this._test("maxArity",e,function(t,r,n){return t.length<=e?t:this.createError("function.maxArity",{n:e},r,n)})}min(e){return Hoek.assert(Hoek.isInteger(e)&&e>=0,"limit must be a positive integer"),this._test("min",e,function(t,r,n){return Object.keys(t).length>=e?t:this.createError("object.min",{limit:e},r,n)})}max(e){return Hoek.assert(Hoek.isInteger(e)&&e>=0,"limit must be a positive integer"),this._test("max",e,function(t,r,n){return Object.keys(t).length<=e?t:this.createError("object.max",{limit:e},r,n)})}pattern(e,t){Hoek.assert(e instanceof RegExp,"Invalid regular expression"),Hoek.assert(void 0!==t,"Invalid rule"),e=new RegExp(e.source,e.ignoreCase?"i":void 0);try{t=Cast.schema(t)}catch(e){throw e.hasOwnProperty("path")&&(e.message=e.message+"("+e.path+")"),e}const r=this.clone();return r._inner.patterns.push({regex:e,rule:t}),r}schema(){return this._test("schema",null,function(e,t,r){return e instanceof Any?e:this.createError("object.schema",null,t,r)})}with(e,t){return this._dependency("with",e,t)}without(e,t){return this._dependency("without",e,t)}xor(){const e=Hoek.flatten(Array.prototype.slice.call(arguments));return this._dependency("xor",null,e)}or(){const e=Hoek.flatten(Array.prototype.slice.call(arguments));return this._dependency("or",null,e)}and(){const e=Hoek.flatten(Array.prototype.slice.call(arguments));return this._dependency("and",null,e)}nand(){const e=Hoek.flatten(Array.prototype.slice.call(arguments));return this._dependency("nand",null,e)}requiredKeys(e){return e=Hoek.flatten(Array.prototype.slice.call(arguments)),this.applyFunctionToChildren(e,"required")}optionalKeys(e){return e=Hoek.flatten(Array.prototype.slice.call(arguments)),this.applyFunctionToChildren(e,"optional")}rename(e,t,r){Hoek.assert("string"==typeof e,"Rename missing the from argument"),Hoek.assert("string"==typeof t,"Rename missing the to argument"),Hoek.assert(t!==e,"Cannot rename key to same name:",e);for(let t=0;t<this._inner.renames.length;++t)Hoek.assert(this._inner.renames[t].from!==e,"Cannot rename the same key multiple times");const n=this.clone();return n._inner.renames.push({from:e,to:t,options:Hoek.applyToDefaults(internals.renameDefaults,r||{})}),n}applyFunctionToChildren(e,t,r,n){e=[].concat(e),Hoek.assert(e.length>0,"expected at least one children");const s=internals.groupChildren(e);let i;if(""in s?(i=this[t].apply(this,r),delete s[""]):i=this.clone(),i._inner.children){n=n?n+".":"";for(let e=0;e<i._inner.children.length;++e){const o=i._inner.children[e],a=s[o.key];a&&(i._inner.children[e]={key:o.key,_refs:o._refs,schema:o.schema.applyFunctionToChildren(a,t,r,n+o.key)},delete s[o.key])}}const o=Object.keys(s);return Hoek.assert(0===o.length,"unknown key(s)",o.join(", ")),i}_dependency(e,t,r){r=[].concat(r);for(let t=0;t<r.length;++t)Hoek.assert("string"==typeof r[t],e,"peers must be a string or array of strings");const n=this.clone();return n._inner.dependencies.push({type:e,key:t,peers:r}),n}describe(e){const t=Any.prototype.describe.call(this);if(t.rules)for(let e=0;e<t.rules.length;++e){const r=t.rules[e];r.arg&&"object"==typeof r.arg&&r.arg.schema&&r.arg.ref&&(r.arg={schema:r.arg.schema.describe(),ref:r.arg.ref.toString()})}if(this._inner.children&&!e){t.children={};for(let e=0;e<this._inner.children.length;++e){const r=this._inner.children[e];t.children[r.key]=r.schema.describe()}}if(this._inner.dependencies.length&&(t.dependencies=Hoek.clone(this._inner.dependencies)),this._inner.patterns.length){t.patterns=[];for(let e=0;e<this._inner.patterns.length;++e){const r=this._inner.patterns[e];t.patterns.push({regex:r.regex.toString(),rule:r.rule.describe()})}}return t}assert(e,t,r){e=Cast.ref(e),Hoek.assert(e.isContext||e.depth>1,"Cannot use assertions for root level references - use direct key rules instead"),r=r||"pass the assertion test";try{t=Cast.schema(t)}catch(e){throw e.hasOwnProperty("path")&&(e.message=e.message+"("+e.path+")"),e}const n=e.path[e.path.length-1],s=e.path.join(".");return this._test("assert",{schema:t,ref:e},function(i,o,a){if(!t._validate(e(i),null,a,i).errors)return i;const l=Hoek.merge({},o);return l.key=n,l.path=s,this.createError("object.assert",{ref:l.path,message:r},l,a)})}type(e,t){return Hoek.assert("function"==typeof e,"type must be a constructor function"),t=t||e.name,this._test("type",t,function(r,n,s){return r instanceof e?r:this.createError("object.type",{type:t},n,s)})}ref(){return this._test("ref",null,function(e,t,r){return Ref.isRef(e)?e:this.createError("function.ref",null,t,r)})}},internals.safeParse=function(e){try{return JSON.parse(e)}catch(e){}return e},internals.renameDefaults={alias:!1,multiple:!1,override:!1},internals.groupChildren=function(e){e.sort();const t={};for(let r=0;r<e.length;++r){const n=e[r];Hoek.assert("string"==typeof n,"children must be strings");const s=n.split(".")[0];(t[s]=t[s]||[]).push(n.substring(s.length+1))}return t},internals.with=function(e,t,r,n,s){if(void 0===e)return e;for(let e=0;e<t.length;++e){const i=t[e];if(!Object.prototype.hasOwnProperty.call(r,i)||void 0===r[i])return this.createError("object.with",{peer:i},n,s)}return e},internals.without=function(e,t,r,n,s){if(void 0===e)return e;for(let e=0;e<t.length;++e){const i=t[e];if(Object.prototype.hasOwnProperty.call(r,i)&&void 0!==r[i])return this.createError("object.without",{peer:i},n,s)}return e},internals.xor=function(e,t,r,n,s){const i=[];for(let e=0;e<t.length;++e){const n=t[e];Object.prototype.hasOwnProperty.call(r,n)&&void 0!==r[n]&&i.push(n)}return 1===i.length?e:0===i.length?this.createError("object.missing",{peers:t},n,s):this.createError("object.xor",{peers:t},n,s)},internals.or=function(e,t,r,n,s){for(let n=0;n<t.length;++n){const s=t[n];if(Object.prototype.hasOwnProperty.call(r,s)&&void 0!==r[s])return e}return this.createError("object.missing",{peers:t},n,s)},internals.and=function(e,t,r,n,s){const i=[],o=[],a=t.length;for(let e=0;e<a;++e){const n=t[e];Object.prototype.hasOwnProperty.call(r,n)&&void 0!==r[n]?o.push(n):i.push(n)}return i.length===a||o.length===a?null:this.createError("object.and",{present:o,missing:i},n,s)},internals.nand=function(e,t,r,n,s){const i=[];for(let e=0;e<t.length;++e){const n=t[e];Object.prototype.hasOwnProperty.call(r,n)&&void 0!==r[n]&&i.push(n)}const o=Hoek.clone(t),a=o.splice(0,1)[0];return i.length===t.length?this.createError("object.nand",{main:a,peers:o},n,s):null},module.exports=new internals.Object;