@muze-nl/assert 0.2.0 → 0.3.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/dist/browser.js CHANGED
@@ -1,2 +1,2 @@
1
- function t(t,e,a,n){Object.defineProperty(t,e,{get:a,set:n,enumerable:!0,configurable:!0})}var e={};function a(){globalThis.assertEnabled=!0}function n(){globalThis.assertEnabled=!1}t(e,"enable",()=>a),t(e,"disable",()=>n),t(e,"assert",()=>r),t(e,"fails",()=>p),t(e,"Optional",()=>s),t(e,"Required",()=>o),t(e,"Recommended",()=>i),t(e,"oneOf",()=>l),t(e,"error",()=>y),t(e,"anyOf",()=>f),t(e,"validURL",()=>d),t(e,"validEmail",()=>c),t(e,"instanceOf",()=>u),t(e,"not",()=>h),globalThis.assertEnabled=!1;const r=(t,e)=>{if(globalThis.assertEnabled){let a=p(t,e);if(a)throw new b("Assertions failed",a,t)}},s=t=>e=>null!=e&&void 0!==e&&p(e,t),o=t=>e=>p(e,t),i=t=>e=>null==e||void 0===e?(console.warning("data does not contain recommended value",e,t),!1):p(e,t),l=(...t)=>e=>{for(let a of t)if(!p(e,a))return!1;return y("data does not match oneOf patterns",e,t)},f=(...t)=>e=>{if(!Array.isArray(e))return y("data is not an array",e,"anyOf");for(let a of e)if(l(...t)(a))return y("data does not match anyOf patterns",a,t);return!1};function d(t){try{if(t instanceof URL&&(t=t.href),new URL(t).href!=t)return y("data is not a valid url",t,"validURL")}catch(e){return y("data is not a valid url",t,"validURL")}return!1}function c(t){return!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)&&y("data is not a valid email",t,"validEmail")}const u=t=>e=>!(e instanceof t)&&y("data is not an instanceof pattern",e,t),h=t=>e=>!p(e,t)&&y("data matches pattern, when required not to",e,t);function p(t,e,a){a||(a=t);let n=[];if(e===Boolean)"boolean"==typeof t||t instanceof Boolean||n.push(y("data is not a boolean",t,e));else if(e===Number)"number"==typeof t||t instanceof Number||n.push(y("data is not a number",t,e));else if(e===String)"string"==typeof t||t instanceof String||n.push(y("data is not a string",t,e)),""==t&&n.push(y("data is an empty string, which is not allowed",t,e));else if(e instanceof RegExp){if(Array.isArray(t)){let r=t.findIndex(t=>p(t,e,a));r>-1&&n.push(y("data["+r+"] does not match pattern",t[r],e))}else e.test(t)||n.push(y("data does not match pattern",t,e))}else if(e instanceof Function)e(t,a)&&n.push(y("data does not match function",t,e));else if(Array.isArray(e))for(let r of(Array.isArray(t)||n.push(y("data is not an array",t,[])),e))for(let e of t){let t=p(e,r,a);Array.isArray(t)?n=n.concat(t):t&&n.push(t)}else if(e&&"object"==typeof e){if(Array.isArray(t)){let r=t.findIndex(t=>p(t,e,a));r>-1&&n.push(y("data["+r+"] does not match pattern",t[r],e))}else if(t&&"object"==typeof t)for(let[r,s]of(t instanceof URLSearchParams&&(t=Object.fromEntries(t)),Object.entries(e))){let e=p(t[r],s,a);e&&(n=n.concat(e))}else n.push(y("data is not an object, pattern is",t,e))}else e!=t&&n.push(y("data and pattern are not equal",t,e));return!!n.length&&n}class b extends Error{constructor(t,e,...a){super(t),this.problems=e,this.details=a}}function y(t,e,a){return{message:t,found:e,expected:a}}globalThis.assert=e;
1
+ function e(e,t,a,n){Object.defineProperty(e,t,{get:a,set:n,enumerable:!0,configurable:!0})}var t={};function a(){globalThis.assertEnabled=!0}function n(){globalThis.assertEnabled=!1}e(t,"enable",()=>a),e(t,"disable",()=>n),e(t,"assert",()=>r),e(t,"fails",()=>p),e(t,"Optional",()=>s),e(t,"Required",()=>o),e(t,"error",()=>b),e(t,"Recommended",()=>i),e(t,"oneOf",()=>l),e(t,"anyOf",()=>f),e(t,"validURL",()=>d),e(t,"validEmail",()=>c),e(t,"instanceOf",()=>u),e(t,"not",()=>h),globalThis.assertEnabled=!1;const r=(e,t)=>{if(globalThis.assertEnabled){let a=p(e,t);if(a)throw new y("Assertions failed",a,e)}},s=e=>(t,a,n)=>null!=t&&void 0!==t&&p(t,e,a,n),o=e=>(t,a,n)=>null==t||void 0===t?b("data is required",t,e||"any value",n):void 0!==e&&p(t,e,a,n),i=e=>(t,a,n)=>null==t||void 0===t?(console.warn("data does not contain recommended value",t,e,n),!1):p(t,e,a,n),l=(...e)=>(t,a,n)=>{for(let r of e)if(!p(t,r,a,n))return!1;return b("data does not match oneOf patterns",t,e,n)},f=(...e)=>(t,a,n)=>{if(!Array.isArray(t))return b("data is not an array",t,"anyOf",n);for(let a of t)if(l(...e)(a))return b("data does not match anyOf patterns",a,e,n);return!1};function d(e,t,a){try{e instanceof URL&&(e=e.href);let t=new URL(e);if(t.href!=e){if(t.href+"/"==e||t.href==e+"/")return!1;return b("data is not a valid url",e,"validURL",a)}}catch(t){return b("data is not a valid url",e,"validURL",a)}return!1}function c(e,t,a){return!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)&&b("data is not a valid email",e,"validEmail",a)}const u=e=>(t,a,n)=>!(t instanceof e)&&b("data is not an instanceof pattern",t,e,n),h=e=>(t,a,n)=>!p(t,e,a,n)&&b("data matches pattern, when required not to",t,e,n);function p(e,t,a,n=""){a||(a=e);let r=[];if(t===Boolean)"boolean"==typeof e||e instanceof Boolean||r.push(b("data is not a boolean",e,t,n));else if(t===Number)"number"==typeof e||e instanceof Number||r.push(b("data is not a number",e,t,n));else if(t===String)"string"==typeof e||e instanceof String||r.push(b("data is not a string",e,t,n)),""==e&&r.push(b("data is an empty string, which is not allowed",e,t,n));else if(t instanceof RegExp){if(Array.isArray(e)){let s=e.findIndex((e,r)=>p(e,t,a,n+"["+r+"]"));s>-1&&r.push(b("data["+s+"] does not match pattern",e[s],t,n+"["+s+"]"))}else void 0===e?r.push(b("data is undefined, should match pattern",e,t,n)):t.test(e)||r.push(b("data does not match pattern",e,t,n))}else if(t instanceof Function){let s=t(e,a,n);s&&(Array.isArray(s)?r=r.concat(s):r.push(s))}else if(Array.isArray(t))for(let s of(Array.isArray(e)||r.push(b("data is not an array",e,[],n)),t))for(let t of e.keys()){let o=p(e[t],s,a,n+"["+t+"]");Array.isArray(o)?r=r.concat(o):o&&r.push(o)}else if(t&&"object"==typeof t){if(Array.isArray(e)){let s=e.findIndex((e,r)=>p(e,t,a,n+"["+r+"]"));s>-1&&r.push(b("data["+s+"] does not match pattern",e[s],t,n+"["+s+"]"))}else if(e&&"object"==typeof e){if(e instanceof URLSearchParams&&(e=Object.fromEntries(e)),t instanceof Function){let s=p(e,t,a,n);s&&(r=r.concat(s))}else for(let[s,o]of Object.entries(t)){let t=p(e[s],o,a,n+"."+s);t&&(r=r.concat(t))}}else r.push(b("data is not an object, pattern is",e,t,n))}else t!=e&&r.push(b("data and pattern are not equal",e,t,n));return!!r.length&&r}class y extends Error{constructor(e,t,...a){super(e),this.problems=t,this.details=a}}function b(e,t,a,n){return{message:e,found:t,expected:a,path:n}}globalThis.assert=t;
2
2
  //# sourceMappingURL=browser.js.map
@@ -1 +1 @@
1
- {"mappings":"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","sources":["<anon>","src/browser.mjs","src/assert.mjs"],"sourcesContent":["\nfunction $parcel$export(e, n, v, s) {\n Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});\n}\nvar $2ddd80d1adc2ea42$exports = {};\n\n$parcel$export($2ddd80d1adc2ea42$exports, \"enable\", () => $2ddd80d1adc2ea42$export$d7c4a0dd6a4567e5);\n$parcel$export($2ddd80d1adc2ea42$exports, \"disable\", () => $2ddd80d1adc2ea42$export$e20fbacbb41798b);\n$parcel$export($2ddd80d1adc2ea42$exports, \"assert\", () => $2ddd80d1adc2ea42$export$a7a9523472993e97);\n$parcel$export($2ddd80d1adc2ea42$exports, \"fails\", () => $2ddd80d1adc2ea42$export$478159de811fd37d);\n$parcel$export($2ddd80d1adc2ea42$exports, \"Optional\", () => $2ddd80d1adc2ea42$export$7acb7b24c478f9c6);\n$parcel$export($2ddd80d1adc2ea42$exports, \"Required\", () => $2ddd80d1adc2ea42$export$1788c381af06add2);\n$parcel$export($2ddd80d1adc2ea42$exports, \"Recommended\", () => $2ddd80d1adc2ea42$export$a83bcf183f49ea9);\n$parcel$export($2ddd80d1adc2ea42$exports, \"oneOf\", () => $2ddd80d1adc2ea42$export$a9a18ae5ba42aeab);\n$parcel$export($2ddd80d1adc2ea42$exports, \"error\", () => $2ddd80d1adc2ea42$export$a3bc9b8ed74fc);\n$parcel$export($2ddd80d1adc2ea42$exports, \"anyOf\", () => $2ddd80d1adc2ea42$export$b26c150f612c10f7);\n$parcel$export($2ddd80d1adc2ea42$exports, \"validURL\", () => $2ddd80d1adc2ea42$export$c6f1a4382426409f);\n$parcel$export($2ddd80d1adc2ea42$exports, \"validEmail\", () => $2ddd80d1adc2ea42$export$9ab921aaffe56820);\n$parcel$export($2ddd80d1adc2ea42$exports, \"instanceOf\", () => $2ddd80d1adc2ea42$export$ca03416d6c9e029e);\n$parcel$export($2ddd80d1adc2ea42$exports, \"not\", () => $2ddd80d1adc2ea42$export$6003a5f097c73977);\n/**\n * assertEnabled (Boolean) used to toggle whether the assert()\n * method should test assertions or not.\n */ globalThis.assertEnabled = false;\nfunction $2ddd80d1adc2ea42$export$d7c4a0dd6a4567e5() {\n globalThis.assertEnabled = true;\n}\nfunction $2ddd80d1adc2ea42$export$e20fbacbb41798b() {\n globalThis.assertEnabled = false;\n}\nconst $2ddd80d1adc2ea42$export$a7a9523472993e97 = (source, test)=>{\n if (globalThis.assertEnabled) {\n let problems = $2ddd80d1adc2ea42$export$478159de811fd37d(source, test);\n if (problems) throw new $2ddd80d1adc2ea42$var$assertError(\"Assertions failed\", problems, source);\n }\n};\nconst $2ddd80d1adc2ea42$export$7acb7b24c478f9c6 = (pattern)=>(data)=>data == null || typeof data == \"undefined\" ? false : $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern);\nconst $2ddd80d1adc2ea42$export$1788c381af06add2 = (pattern)=>(data)=>$2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern);\nconst $2ddd80d1adc2ea42$export$a83bcf183f49ea9 = (pattern)=>(data)=>data == null || typeof data == \"undefined\" ? (()=>{\n console.warning(\"data does not contain recommended value\", data, pattern);\n return false;\n })() : $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern);\nconst $2ddd80d1adc2ea42$export$a9a18ae5ba42aeab = (...patterns)=>(data)=>{\n for (let pattern of patterns){\n if (!$2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern)) return false;\n }\n return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match oneOf patterns\", data, patterns);\n };\nconst $2ddd80d1adc2ea42$export$b26c150f612c10f7 = (...patterns)=>(data)=>{\n if (!Array.isArray(data)) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an array\", data, \"anyOf\");\n for (let value of data){\n if ($2ddd80d1adc2ea42$export$a9a18ae5ba42aeab(...patterns)(value)) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match anyOf patterns\", value, patterns);\n }\n return false;\n };\nfunction $2ddd80d1adc2ea42$export$c6f1a4382426409f(data) {\n try {\n if (data instanceof URL) data = data.href;\n let url = new URL(data);\n if (url.href != data) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a valid url\", data, \"validURL\");\n } catch (e) {\n return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a valid url\", data, \"validURL\");\n }\n return false;\n}\nfunction $2ddd80d1adc2ea42$export$9ab921aaffe56820(data) {\n if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(data)) return false // data matches email regex\n ;\n return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a valid email\", data, \"validEmail\");\n}\nconst $2ddd80d1adc2ea42$export$ca03416d6c9e029e = (constructor)=>(data)=>!(data instanceof constructor) ? $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an instanceof pattern\", data, constructor) : false;\nconst $2ddd80d1adc2ea42$export$6003a5f097c73977 = (pattern)=>(data)=>$2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern) ? false : $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data matches pattern, when required not to\", data, pattern);\nfunction $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root) {\n if (!root) root = data;\n let problems = [];\n if (pattern === Boolean) {\n if (typeof data != \"boolean\" && !(data instanceof Boolean)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a boolean\", data, pattern));\n } else if (pattern === Number) {\n if (typeof data != \"number\" && !(data instanceof Number)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a number\", data, pattern));\n } else if (pattern === String) {\n if (typeof data != \"string\" && !(data instanceof String)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a string\", data, pattern));\n if (data == \"\") problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is an empty string, which is not allowed\", data, pattern));\n } else if (pattern instanceof RegExp) {\n if (Array.isArray(data)) {\n let index = data.findIndex((element)=>$2ddd80d1adc2ea42$export$478159de811fd37d(element, pattern, root));\n if (index > -1) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data[\" + index + \"] does not match pattern\", data[index], pattern));\n } else if (!pattern.test(data)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match pattern\", data, pattern));\n } else if (pattern instanceof Function) {\n if (pattern(data, root)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match function\", data, pattern));\n } else if (Array.isArray(pattern)) {\n if (!Array.isArray(data)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an array\", data, []));\n for (let p of pattern)for (let val of data){\n let problem = $2ddd80d1adc2ea42$export$478159de811fd37d(val, p, root);\n if (Array.isArray(problem)) problems = problems.concat(problem);\n else if (problem) problems.push(problem);\n }\n } else if (pattern && typeof pattern == \"object\") {\n if (Array.isArray(data)) {\n let index = data.findIndex((element)=>$2ddd80d1adc2ea42$export$478159de811fd37d(element, pattern, root));\n if (index > -1) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data[\" + index + \"] does not match pattern\", data[index], pattern));\n } else if (!data || typeof data != \"object\") problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an object, pattern is\", data, pattern));\n else {\n if (data instanceof URLSearchParams) data = Object.fromEntries(data);\n for (const [wKey, wVal] of Object.entries(pattern)){\n let result = $2ddd80d1adc2ea42$export$478159de811fd37d(data[wKey], wVal, root);\n if (result) problems = problems.concat(result);\n }\n }\n } else if (pattern != data) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data and pattern are not equal\", data, pattern));\n if (problems.length) return problems;\n return false;\n}\n/**\n * Class used in assert() to add problems found and details to the error object\n */ class $2ddd80d1adc2ea42$var$assertError extends Error {\n constructor(message, problems, ...details){\n super(message);\n this.problems = problems;\n this.details = details;\n }\n}\nfunction $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(message, found, expected) {\n return {\n message: message,\n found: found,\n expected: expected\n };\n}\n\n\nglobalThis.assert = $2ddd80d1adc2ea42$exports;\n\n\n//# sourceMappingURL=browser.js.map\n","import * as assert from './assert.mjs'\n\nglobalThis.assert = assert\n","/**\n * assertEnabled (Boolean) used to toggle whether the assert()\n * method should test assertions or not.\n */\nglobalThis.assertEnabled = false\n\n/**\n * Enables assertion testing with assert()\n */\nexport function enable() {\n\tglobalThis.assertEnabled = true\n}\n\n/**\n * Disables assertion testing with assert()\n */\nexport function disable() {\n\tglobalThis.assertEnabled = false\n}\n\n/**\n * This function will check the source for the assertions in test, if\n * assertion checking is enabled globally.\n * If it is, and any assertion fails, it will throw an assertError\n * with a list of problems and other details.\n */\nexport const assert = (source, test) => {\n\tif (globalThis.assertEnabled) {\n\t\tlet problems = fails(source,test)\n\t\tif (problems) {\n\t\t\tthrow new assertError('Assertions failed', problems, source)\n\t\t}\n\t}\n}\n\n/**\n * Tests a given value against a pattern, only if the value is not null or undefined\n */\nexport const Optional = (pattern) => \n\t(data) => (data==null || typeof data == 'undefined') ? false : fails(data, pattern)\n\n/**\n * Tests a given value against a pattern, always.\n */\nexport const Required = (pattern) =>\n\t(data) => fails(data, pattern)\n\n/**\n * Tests a given value against a pattern, only if the value is not null or undefined\n * If null or undefined, it does print a warning to the console.\n */\nexport const Recommended = (pattern) =>\n\t(data) => (data==null || typeof data == 'undefined') ? (() => {\n\t\tconsole.warning('data does not contain recommended value', data, pattern)\n\t\treturn false\n\t})() : fails(data, pattern)\n\n/**\n * Tests a given value against a set of patterns, untill one succeeds\n * Returns an error if none succeed\n */\nexport const oneOf = (...patterns) => \n\t(data) => {\n\t\tfor(let pattern of patterns) {\n\t\t\tif (!fails(data, pattern)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn error('data does not match oneOf patterns',data,patterns)\n\t}\n\n/**\n * Tests a given array of values against a set of patterns\n * If any value does not match one of the patterns, it will return an error\n * If not given an array to test, it will return an error\n */\nexport const anyOf = (...patterns) =>\n\t(data) => {\n\t\tif (!Array.isArray(data)) {\n\t\t\treturn error('data is not an array',data,'anyOf')\n\t\t}\n\t\tfor (let value of data) {\n\t\t\tif (oneOf(...patterns)(value)) {\n\t\t\t\treturn error('data does not match anyOf patterns',value,patterns)\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n/**\n * Tests a given value to see if it is a valid (and absolute) URL, by\n * parsing it with the URL() constructor, and then testing the href\n * value to be equal to the initial value.\n */\nexport function validURL(data) {\n\ttry {\n\t\tif (data instanceof URL) {\n\t\t\tdata = data.href\n\t\t}\n\t\tlet url = new URL(data)\n\t\tif (url.href!=data) {\n\t\t\treturn error('data is not a valid url',data,'validURL')\n\t\t}\n\t} catch(e) {\n\t\treturn error('data is not a valid url',data,'validURL')\n\t}\n\treturn false\n}\n\n/**\n * Tests a given value to see if it looks like a valid email address, by\n * testing it against a regular expression. So there are no guarantees that\n * it is an actual working email address, just that it looks like one.\n */\nexport function validEmail(data) {\n\tif (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(data)) {\n\t\treturn false // data matches email regex\n\t}\n\treturn error('data is not a valid email',data,'validEmail')\n}\n\n/**\n * Tests a given value to see if it is an object which is an instance of the given\n * constructor\n */\nexport const instanceOf = (constructor) =>\n\t(data) => !(data instanceof constructor) \n\t\t? error('data is not an instanceof pattern',data,constructor)\n\t\t: false\n\n/**\n * Runs the given test pattern on a value, if the test succeeds, it fails\n * the not() test.\n */\nexport const not = (pattern) =>\n\t(data) => fails(data, pattern) \n\t\t? false \n\t\t: error('data matches pattern, when required not to', data, pattern)\n\n/**\n * returns an array of problems if the data fails to satisfy \n * the assertions in the given pattern, false otherwise\n * @param {any} data The data to match\n * @param {any} pattern The pattern to match\n * @param {any} root Root object for assertions, set to data by default\n * @return {Array|false} Array with problems if the pattern fails, false otherwise\n */\nexport function fails(data, pattern, root) {\n\tif (!root) {\n\t\troot = data\n\t}\n\tlet problems = []\n\tif (pattern === Boolean) {\n\t\tif (typeof data != 'boolean' && !(data instanceof Boolean)) {\n\t\t\tproblems.push(error('data is not a boolean', data, pattern))\n\t\t}\t\t\n\t} else if (pattern === Number) {\n\t\tif (typeof data != 'number' && !(data instanceof Number)) {\n\t\t\tproblems.push(error('data is not a number', data, pattern))\n\t\t}\n\t} else if (pattern === String) {\n\t\tif (typeof data != 'string' && !(data instanceof String)) {\n\t\t\tproblems.push(error('data is not a string', data, pattern))\n\t\t}\n\t\tif (data == \"\") {\n\t\t\tproblems.push(error('data is an empty string, which is not allowed', data, pattern))\n\t\t}\n\t} else if (pattern instanceof RegExp) {\n \tif (Array.isArray(data)) {\n\t\t\tlet index = data.findIndex(element => fails(element,pattern,root))\n if (index>-1) {\n \tproblems.push(error('data['+index+'] does not match pattern', data[index], pattern))\n }\n \t} else if (!pattern.test(data)) {\n \tproblems.push(error('data does not match pattern', data, pattern))\n }\n } else if (pattern instanceof Function) {\n if (pattern(data, root)) {\n \tproblems.push(error('data does not match function', data, pattern))\n }\n } else if (Array.isArray(pattern)) {\n\t\tif (!Array.isArray(data)) {\n\t\t\tproblems.push(error('data is not an array',data,[]))\n\t\t}\n\t\tfor (let p of pattern) {\n\t\t\tfor (let val of data) {\n\t\t\t\tlet problem = fails(val, p, root)\n\t\t\t\tif (Array.isArray(problem)) {\n\t\t\t\t\tproblems = problems.concat(problem)\n\t\t\t\t} else if (problem) {\n\t\t\t\t\tproblems.push(problem)\n\t\t\t\t}\n\t\t\t}\n \t}\n } else if (pattern && typeof pattern == 'object') {\n if (Array.isArray(data)) {\n let index = data.findIndex(element => fails(element,pattern,root))\n if (index>-1) {\n \tproblems.push(error('data['+index+'] does not match pattern', data[index], pattern))\n }\n } else if (!data || typeof data != 'object') {\n \tproblems.push(error('data is not an object, pattern is', data, pattern))\n } else {\n \tif (data instanceof URLSearchParams) {\n \t\tdata = Object.fromEntries(data)\n \t}\n\t for (const [wKey, wVal] of Object.entries(pattern)) {\n\t let result = fails(data[wKey], wVal, root)\n\t if (result) {\n\t \tproblems = problems.concat(result)\n\t }\n\t }\n\t }\n } else {\n \tif (pattern!=data) {\n \t\tproblems.push(error('data and pattern are not equal', data, pattern))\n \t}\n }\n if (problems.length) {\n \treturn problems\n }\n return false\n}\n\n\n/**\n * Class used in assert() to add problems found and details to the error object\n */\nclass assertError extends Error {\n\tconstructor(message, problems, ...details) {\n\t\tsuper(message)\n\t\tthis.problems = problems\n\t\tthis.details = details\n\t}\n}\n\n/**\n * Returns an object with message, found and expected properties\n */ \nexport function error(message, found, expected) {\n\treturn {\n\t\tmessage,\n\t\tfound,\n\t\texpected\n\t}\n}\n"],"names":["$parcel$export","e","n","v","s","Object","defineProperty","get","set","enumerable","configurable","$2ddd80d1adc2ea42$exports","$2ddd80d1adc2ea42$export$d7c4a0dd6a4567e5","globalThis","assertEnabled","$2ddd80d1adc2ea42$export$e20fbacbb41798b","$2ddd80d1adc2ea42$export$a7a9523472993e97","$2ddd80d1adc2ea42$export$478159de811fd37d","$2ddd80d1adc2ea42$export$7acb7b24c478f9c6","$2ddd80d1adc2ea42$export$1788c381af06add2","$2ddd80d1adc2ea42$export$a83bcf183f49ea9","$2ddd80d1adc2ea42$export$a9a18ae5ba42aeab","$2ddd80d1adc2ea42$export$a3bc9b8ed74fc","$2ddd80d1adc2ea42$export$b26c150f612c10f7","$2ddd80d1adc2ea42$export$c6f1a4382426409f","$2ddd80d1adc2ea42$export$9ab921aaffe56820","$2ddd80d1adc2ea42$export$ca03416d6c9e029e","$2ddd80d1adc2ea42$export$6003a5f097c73977","source","test","problems","$2ddd80d1adc2ea42$var$assertError","pattern","data","console","warning","patterns","Array","isArray","value","URL","href","url","constructor","root","Boolean","push","Number","String","RegExp","index","findIndex","element","Function","p","val","problem","concat","wKey","wVal","URLSearchParams","fromEntries","entries","result","length","Error","message","details","found","expected","assert"],"version":3,"file":"browser.js.map","sourceRoot":"../"}
1
+ {"mappings":"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","sources":["<anon>","src/browser.mjs","src/assert.mjs"],"sourcesContent":["\nfunction $parcel$export(e, n, v, s) {\n Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});\n}\nvar $2ddd80d1adc2ea42$exports = {};\n\n$parcel$export($2ddd80d1adc2ea42$exports, \"enable\", () => $2ddd80d1adc2ea42$export$d7c4a0dd6a4567e5);\n$parcel$export($2ddd80d1adc2ea42$exports, \"disable\", () => $2ddd80d1adc2ea42$export$e20fbacbb41798b);\n$parcel$export($2ddd80d1adc2ea42$exports, \"assert\", () => $2ddd80d1adc2ea42$export$a7a9523472993e97);\n$parcel$export($2ddd80d1adc2ea42$exports, \"fails\", () => $2ddd80d1adc2ea42$export$478159de811fd37d);\n$parcel$export($2ddd80d1adc2ea42$exports, \"Optional\", () => $2ddd80d1adc2ea42$export$7acb7b24c478f9c6);\n$parcel$export($2ddd80d1adc2ea42$exports, \"Required\", () => $2ddd80d1adc2ea42$export$1788c381af06add2);\n$parcel$export($2ddd80d1adc2ea42$exports, \"error\", () => $2ddd80d1adc2ea42$export$a3bc9b8ed74fc);\n$parcel$export($2ddd80d1adc2ea42$exports, \"Recommended\", () => $2ddd80d1adc2ea42$export$a83bcf183f49ea9);\n$parcel$export($2ddd80d1adc2ea42$exports, \"oneOf\", () => $2ddd80d1adc2ea42$export$a9a18ae5ba42aeab);\n$parcel$export($2ddd80d1adc2ea42$exports, \"anyOf\", () => $2ddd80d1adc2ea42$export$b26c150f612c10f7);\n$parcel$export($2ddd80d1adc2ea42$exports, \"validURL\", () => $2ddd80d1adc2ea42$export$c6f1a4382426409f);\n$parcel$export($2ddd80d1adc2ea42$exports, \"validEmail\", () => $2ddd80d1adc2ea42$export$9ab921aaffe56820);\n$parcel$export($2ddd80d1adc2ea42$exports, \"instanceOf\", () => $2ddd80d1adc2ea42$export$ca03416d6c9e029e);\n$parcel$export($2ddd80d1adc2ea42$exports, \"not\", () => $2ddd80d1adc2ea42$export$6003a5f097c73977);\n/*\nFIXME: instead of root, pass the current path to each call to fails,\nso that Recommended for instance can tell you which entry is missing\n*/ /**\n * assertEnabled (Boolean) used to toggle whether the assert()\n * method should test assertions or not.\n */ globalThis.assertEnabled = false;\nfunction $2ddd80d1adc2ea42$export$d7c4a0dd6a4567e5() {\n globalThis.assertEnabled = true;\n}\nfunction $2ddd80d1adc2ea42$export$e20fbacbb41798b() {\n globalThis.assertEnabled = false;\n}\nconst $2ddd80d1adc2ea42$export$a7a9523472993e97 = (source, test)=>{\n if (globalThis.assertEnabled) {\n let problems = $2ddd80d1adc2ea42$export$478159de811fd37d(source, test);\n if (problems) throw new $2ddd80d1adc2ea42$var$assertError(\"Assertions failed\", problems, source);\n }\n};\nconst $2ddd80d1adc2ea42$export$7acb7b24c478f9c6 = (pattern)=>(data, root, path)=>{\n if (data == null || typeof data == \"undefined\") return false;\n else return $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path);\n };\nconst $2ddd80d1adc2ea42$export$1788c381af06add2 = (pattern)=>(data, root, path)=>{\n if (data == null || typeof data == \"undefined\") return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is required\", data, pattern || \"any value\", path);\n else if (typeof pattern != \"undefined\") return $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path);\n else return false;\n };\nconst $2ddd80d1adc2ea42$export$a83bcf183f49ea9 = (pattern)=>(data, root, path)=>{\n if (data == null || typeof data == \"undefined\") {\n console.warn(\"data does not contain recommended value\", data, pattern, path);\n return false;\n } else return $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path);\n };\nconst $2ddd80d1adc2ea42$export$a9a18ae5ba42aeab = (...patterns)=>(data, root, path)=>{\n for (let pattern of patterns){\n if (!$2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path)) return false;\n }\n return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match oneOf patterns\", data, patterns, path);\n };\nconst $2ddd80d1adc2ea42$export$b26c150f612c10f7 = (...patterns)=>(data, root, path)=>{\n if (!Array.isArray(data)) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an array\", data, \"anyOf\", path);\n for (let value of data){\n if ($2ddd80d1adc2ea42$export$a9a18ae5ba42aeab(...patterns)(value)) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match anyOf patterns\", value, patterns, path);\n }\n return false;\n };\nfunction $2ddd80d1adc2ea42$export$c6f1a4382426409f(data, root, path) {\n try {\n if (data instanceof URL) data = data.href;\n let url = new URL(data);\n if (url.href != data) {\n if (url.href + \"/\" == data || url.href == data + \"/\") return false // new URL() always adds a / as path\n ;\n return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a valid url\", data, \"validURL\", path);\n }\n } catch (e) {\n return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a valid url\", data, \"validURL\", path);\n }\n return false;\n}\nfunction $2ddd80d1adc2ea42$export$9ab921aaffe56820(data, root, path) {\n if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(data)) return false // data matches email regex\n ;\n return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a valid email\", data, \"validEmail\", path);\n}\nconst $2ddd80d1adc2ea42$export$ca03416d6c9e029e = (constructor)=>(data, root, path)=>!(data instanceof constructor) ? $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an instanceof pattern\", data, constructor, path) : false;\nconst $2ddd80d1adc2ea42$export$6003a5f097c73977 = (pattern)=>(data, root, path)=>{\n let problems = $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path);\n if (!problems) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data matches pattern, when required not to\", data, pattern, path);\n return false;\n };\nfunction $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path = \"\") {\n if (!root) root = data;\n let problems = [];\n if (pattern === Boolean) {\n if (typeof data != \"boolean\" && !(data instanceof Boolean)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a boolean\", data, pattern, path));\n } else if (pattern === Number) {\n if (typeof data != \"number\" && !(data instanceof Number)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a number\", data, pattern, path));\n } else if (pattern === String) {\n if (typeof data != \"string\" && !(data instanceof String)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a string\", data, pattern, path));\n if (data == \"\") problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is an empty string, which is not allowed\", data, pattern, path));\n } else if (pattern instanceof RegExp) {\n if (Array.isArray(data)) {\n let index = data.findIndex((element, index)=>$2ddd80d1adc2ea42$export$478159de811fd37d(element, pattern, root, path + \"[\" + index + \"]\"));\n if (index > -1) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data[\" + index + \"] does not match pattern\", data[index], pattern, path + \"[\" + index + \"]\"));\n } else if (typeof data == \"undefined\") problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is undefined, should match pattern\", data, pattern, path));\n else if (!pattern.test(data)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match pattern\", data, pattern, path));\n } else if (pattern instanceof Function) {\n let problem = pattern(data, root, path);\n if (problem) {\n if (Array.isArray(problem)) problems = problems.concat(problem);\n else problems.push(problem);\n }\n } else if (Array.isArray(pattern)) {\n if (!Array.isArray(data)) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an array\", data, [], path));\n for (let p of pattern)for (let index of data.keys()){\n let problem = $2ddd80d1adc2ea42$export$478159de811fd37d(data[index], p, root, path + \"[\" + index + \"]\");\n if (Array.isArray(problem)) problems = problems.concat(problem);\n else if (problem) problems.push(problem);\n }\n } else if (pattern && typeof pattern == \"object\") {\n if (Array.isArray(data)) {\n let index = data.findIndex((element, index)=>$2ddd80d1adc2ea42$export$478159de811fd37d(element, pattern, root, path + \"[\" + index + \"]\"));\n if (index > -1) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data[\" + index + \"] does not match pattern\", data[index], pattern, path + \"[\" + index + \"]\"));\n } else if (!data || typeof data != \"object\") problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an object, pattern is\", data, pattern, path));\n else {\n if (data instanceof URLSearchParams) data = Object.fromEntries(data);\n if (pattern instanceof Function) {\n let result = $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path);\n if (result) problems = problems.concat(result);\n } else for (const [wKey, wVal] of Object.entries(pattern)){\n let result = $2ddd80d1adc2ea42$export$478159de811fd37d(data[wKey], wVal, root, path + \".\" + wKey);\n if (result) problems = problems.concat(result);\n }\n }\n } else if (pattern != data) problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data and pattern are not equal\", data, pattern, path));\n if (problems.length) return problems;\n return false;\n}\n/**\n * Class used in assert() to add problems found and details to the error object\n */ class $2ddd80d1adc2ea42$var$assertError extends Error {\n constructor(message, problems, ...details){\n super(message);\n this.problems = problems;\n this.details = details;\n }\n}\nfunction $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(message, found, expected, path) {\n return {\n message: message,\n found: found,\n expected: expected,\n path: path\n };\n}\n\n\nglobalThis.assert = $2ddd80d1adc2ea42$exports;\n\n\n//# sourceMappingURL=browser.js.map\n","import * as assert from './assert.mjs'\n\nglobalThis.assert = assert\n","/*\nFIXME: instead of root, pass the current path to each call to fails,\nso that Recommended for instance can tell you which entry is missing\n*/\n\n/**\n * assertEnabled (Boolean) used to toggle whether the assert()\n * method should test assertions or not.\n */\nglobalThis.assertEnabled = false\n\n/**\n * Enables assertion testing with assert()\n */\nexport function enable() {\n\tglobalThis.assertEnabled = true\n}\n\n/**\n * Disables assertion testing with assert()\n */\nexport function disable() {\n\tglobalThis.assertEnabled = false\n}\n\n/**\n * This function will check the source for the assertions in test, if\n * assertion checking is enabled globally.\n * If it is, and any assertion fails, it will throw an assertError\n * with a list of problems and other details.\n */\nexport const assert = (source, test) => {\n\tif (globalThis.assertEnabled) {\n\t\tlet problems = fails(source,test)\n\t\tif (problems) {\n\t\t\tthrow new assertError('Assertions failed', problems, source)\n\t\t}\n\t}\n}\n\n/**\n * Tests a given value against a pattern, only if the value is not null or undefined\n */\nexport const Optional = (pattern) => \n\t(data, root, path) => {\n\t\tif (data==null || typeof data == 'undefined') {\n\t\t\treturn false \n\t\t} else {\n\t\t\treturn fails(data, pattern, root, path)\n\t\t}\n\t}\n\n/**\n * Tests a given value against a pattern, always.\n */\nexport const Required = (pattern) =>\n\t(data, root, path) => {\n\t\tif (data==null || typeof data == 'undefined') {\n\t\t\treturn error('data is required', data, pattern || 'any value', path)\n\t\t} else if (typeof pattern != 'undefined') {\n\t\t\treturn fails(data, pattern, root, path)\n\t\t} else {\n\t\t\treturn false\n\t\t}\n\t}\n\n/**\n * Tests a given value against a pattern, only if the value is not null or undefined\n * If null or undefined, it does print a warning to the console.\n */\nexport const Recommended = (pattern) =>\n\t(data, root, path) => {\n\t\tif (data==null || typeof data == 'undefined') {\n\t\t\tconsole.warn('data does not contain recommended value', data, pattern, path)\n\t\t\treturn false\n\t\t} else {\n\t\t\treturn fails(data, pattern, root, path)\n\t\t}\n\t}\n\n/**\n * Tests a given value against a set of patterns, untill one succeeds\n * Returns an error if none succeed\n */\nexport const oneOf = (...patterns) => \n\t(data, root, path) => {\n\t\tfor(let pattern of patterns) {\n\t\t\tif (!fails(data, pattern, root, path)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn error('data does not match oneOf patterns', data, patterns, path)\n\t}\n\n/**\n * Tests a given array of values against a set of patterns\n * If any value does not match one of the patterns, it will return an error\n * If not given an array to test, it will return an error\n */\nexport const anyOf = (...patterns) =>\n\t(data, root, path) => {\n\t\tif (!Array.isArray(data)) {\n\t\t\treturn error('data is not an array',data,'anyOf',path)\n\t\t}\n\t\tfor (let value of data) {\n\t\t\tif (oneOf(...patterns)(value)) {\n\t\t\t\treturn error('data does not match anyOf patterns',value,patterns,path)\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n/**\n * Tests a given value to see if it is a valid (and absolute) URL, by\n * parsing it with the URL() constructor, and then testing the href\n * value to be equal to the initial value.\n */\nexport function validURL(data, root, path) {\n\ttry {\n\t\tif (data instanceof URL) {\n\t\t\tdata = data.href\n\t\t}\n\t\tlet url = new URL(data)\n\t\tif (url.href!=data) {\n\t\t\tif (url.href+'/'==data || url.href==data+'/') {\n\t\t\t\treturn false // new URL() always adds a / as path\n\t\t\t}\n\t\t\treturn error('data is not a valid url',data,'validURL',path)\n\t\t}\n\t} catch(e) {\n\t\treturn error('data is not a valid url',data,'validURL',path)\n\t}\n\treturn false\n}\n\n/**\n * Tests a given value to see if it looks like a valid email address, by\n * testing it against a regular expression. So there are no guarantees that\n * it is an actual working email address, just that it looks like one.\n */\nexport function validEmail(data, root, path) {\n\tif (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(data)) {\n\t\treturn false // data matches email regex\n\t}\n\treturn error('data is not a valid email',data,'validEmail',path)\n}\n\n/**\n * Tests a given value to see if it is an object which is an instance of the given\n * constructor\n */\nexport const instanceOf = (constructor) =>\n\t(data, root, path) => !(data instanceof constructor) \n\t\t? error('data is not an instanceof pattern',data,constructor,path)\n\t\t: false\n\n/**\n * Runs the given test pattern on a value, if the test succeeds, it fails\n * the not() test.\n */\nexport const not = (pattern) =>\n\t(data, root, path) => {\n\t\tlet problems = fails(data, pattern, root, path) \n\t\tif (!problems) {\n\t\t\treturn error('data matches pattern, when required not to', data, pattern, path)\n\t\t}\n\t\treturn false\n\t}\n\n/**\n * returns an array of problems if the data fails to satisfy \n * the assertions in the given pattern, false otherwise\n * @param {any} data The data to match\n * @param {any} pattern The pattern to match\n * @param {any} root Root object for assertions, set to data by default\n * @return {Array|false} Array with problems if the pattern fails, false otherwise\n */\nexport function fails(data, pattern, root, path='') {\n\tif (!root) {\n\t\troot = data\n\t}\n\tlet problems = []\n\tif (pattern === Boolean) {\n\t\tif (typeof data != 'boolean' && !(data instanceof Boolean)) {\n\t\t\tproblems.push(error('data is not a boolean', data, pattern, path))\n\t\t}\t\t\n\t} else if (pattern === Number) {\n\t\tif (typeof data != 'number' && !(data instanceof Number)) {\n\t\t\tproblems.push(error('data is not a number', data, pattern, path))\n\t\t}\n\t} else if (pattern === String) {\n\t\tif (typeof data != 'string' && !(data instanceof String)) {\n\t\t\tproblems.push(error('data is not a string', data, pattern, path))\n\t\t}\n\t\tif (data == \"\") {\n\t\t\tproblems.push(error('data is an empty string, which is not allowed', data, pattern, path))\n\t\t}\n\t} else if (pattern instanceof RegExp) {\n \tif (Array.isArray(data)) {\n\t\t\tlet index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))\n if (index>-1) {\n \tproblems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))\n }\n } else if (typeof data == 'undefined') {\n \tproblems.push(error('data is undefined, should match pattern', data, pattern, path))\n \t} else if (!pattern.test(data)) {\n \tproblems.push(error('data does not match pattern', data, pattern, path))\n }\n } else if (pattern instanceof Function) {\n let problem = pattern(data, root, path)\n if (problem) {\n \tif (Array.isArray(problem)) {\n \t\tproblems = problems.concat(problem)\n \t} else {\n\t \tproblems.push(problem)\n\t }\n }\n } else if (Array.isArray(pattern)) {\n\t\tif (!Array.isArray(data)) {\n\t\t\tproblems.push(error('data is not an array',data,[],path))\n\t\t}\n\t\tfor (let p of pattern) {\n\t\t\tfor (let index of data.keys()) {\n\t\t\t\tlet problem = fails(data[index], p, root, path+'['+index+']')\n\t\t\t\tif (Array.isArray(problem)) {\n\t\t\t\t\tproblems = problems.concat(problem)\n\t\t\t\t} else if (problem) {\n\t\t\t\t\tproblems.push(problem)\n\t\t\t\t}\n\t\t\t}\n \t}\n } else if (pattern && typeof pattern == 'object') {\n if (Array.isArray(data)) {\n let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))\n if (index>-1) {\n \tproblems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))\n }\n } else if (!data || typeof data != 'object') {\n \tproblems.push(error('data is not an object, pattern is', data, pattern, path))\n } else {\n \tif (data instanceof URLSearchParams) {\n \t\tdata = Object.fromEntries(data)\n \t}\n \tif (pattern instanceof Function) {\n \t\tlet result = fails(data, pattern, root, path)\n\t if (result) {\n\t \tproblems = problems.concat(result)\n\t }\n \t} else {\n\t\t for (const [wKey, wVal] of Object.entries(pattern)) {\n\t\t let result = fails(data[wKey], wVal, root, path+'.'+wKey)\n\t\t if (result) {\n\t\t \tproblems = problems.concat(result)\n\t\t }\n\t\t }\n\t\t }\n\t }\n } else {\n \tif (pattern!=data) {\n \t\tproblems.push(error('data and pattern are not equal', data, pattern, path))\n \t}\n }\n if (problems.length) {\n \treturn problems\n }\n return false\n}\n\n\n/**\n * Class used in assert() to add problems found and details to the error object\n */\nclass assertError extends Error {\n\tconstructor(message, problems, ...details) {\n\t\tsuper(message)\n\t\tthis.problems = problems\n\t\tthis.details = details\n\t}\n}\n\n/**\n * Returns an object with message, found and expected properties\n */ \nexport function error(message, found, expected, path) {\n\treturn {\n\t\tmessage,\n\t\tfound,\n\t\texpected,\n\t\tpath\n\t}\n}\n"],"names":["$parcel$export","e","n","v","s","Object","defineProperty","get","set","enumerable","configurable","$2ddd80d1adc2ea42$exports","$2ddd80d1adc2ea42$export$d7c4a0dd6a4567e5","globalThis","assertEnabled","$2ddd80d1adc2ea42$export$e20fbacbb41798b","$2ddd80d1adc2ea42$export$a7a9523472993e97","$2ddd80d1adc2ea42$export$478159de811fd37d","$2ddd80d1adc2ea42$export$7acb7b24c478f9c6","$2ddd80d1adc2ea42$export$1788c381af06add2","$2ddd80d1adc2ea42$export$a3bc9b8ed74fc","$2ddd80d1adc2ea42$export$a83bcf183f49ea9","$2ddd80d1adc2ea42$export$a9a18ae5ba42aeab","$2ddd80d1adc2ea42$export$b26c150f612c10f7","$2ddd80d1adc2ea42$export$c6f1a4382426409f","$2ddd80d1adc2ea42$export$9ab921aaffe56820","$2ddd80d1adc2ea42$export$ca03416d6c9e029e","$2ddd80d1adc2ea42$export$6003a5f097c73977","source","test","problems","$2ddd80d1adc2ea42$var$assertError","pattern","data","root","path","console","warn","patterns","Array","isArray","value","URL","href","url","constructor","Boolean","push","Number","String","RegExp","index","findIndex","element","Function","problem","concat","p","keys","URLSearchParams","fromEntries","result","wKey","wVal","entries","length","Error","message","details","found","expected","assert"],"version":3,"file":"browser.js.map","sourceRoot":"../"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muze-nl/assert",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "light optional assert library",
5
5
  "type": "module",
6
6
  "main": "src/assert.mjs",
package/src/assert.mjs CHANGED
@@ -1,3 +1,8 @@
1
+ /*
2
+ FIXME: instead of root, pass the current path to each call to fails,
3
+ so that Recommended for instance can tell you which entry is missing
4
+ */
5
+
1
6
  /**
2
7
  * assertEnabled (Boolean) used to toggle whether the assert()
3
8
  * method should test assertions or not.
@@ -37,36 +42,54 @@ export const assert = (source, test) => {
37
42
  * Tests a given value against a pattern, only if the value is not null or undefined
38
43
  */
39
44
  export const Optional = (pattern) =>
40
- (data) => (data==null || typeof data == 'undefined') ? false : fails(data, pattern)
45
+ (data, root, path) => {
46
+ if (data==null || typeof data == 'undefined') {
47
+ return false
48
+ } else {
49
+ return fails(data, pattern, root, path)
50
+ }
51
+ }
41
52
 
42
53
  /**
43
54
  * Tests a given value against a pattern, always.
44
55
  */
45
56
  export const Required = (pattern) =>
46
- (data) => fails(data, pattern)
57
+ (data, root, path) => {
58
+ if (data==null || typeof data == 'undefined') {
59
+ return error('data is required', data, pattern || 'any value', path)
60
+ } else if (typeof pattern != 'undefined') {
61
+ return fails(data, pattern, root, path)
62
+ } else {
63
+ return false
64
+ }
65
+ }
47
66
 
48
67
  /**
49
68
  * Tests a given value against a pattern, only if the value is not null or undefined
50
69
  * If null or undefined, it does print a warning to the console.
51
70
  */
52
71
  export const Recommended = (pattern) =>
53
- (data) => (data==null || typeof data == 'undefined') ? (() => {
54
- console.warning('data does not contain recommended value', data, pattern)
55
- return false
56
- })() : fails(data, pattern)
72
+ (data, root, path) => {
73
+ if (data==null || typeof data == 'undefined') {
74
+ console.warn('data does not contain recommended value', data, pattern, path)
75
+ return false
76
+ } else {
77
+ return fails(data, pattern, root, path)
78
+ }
79
+ }
57
80
 
58
81
  /**
59
82
  * Tests a given value against a set of patterns, untill one succeeds
60
83
  * Returns an error if none succeed
61
84
  */
62
85
  export const oneOf = (...patterns) =>
63
- (data) => {
86
+ (data, root, path) => {
64
87
  for(let pattern of patterns) {
65
- if (!fails(data, pattern)) {
88
+ if (!fails(data, pattern, root, path)) {
66
89
  return false
67
90
  }
68
91
  }
69
- return error('data does not match oneOf patterns',data,patterns)
92
+ return error('data does not match oneOf patterns', data, patterns, path)
70
93
  }
71
94
 
72
95
  /**
@@ -75,13 +98,13 @@ export const oneOf = (...patterns) =>
75
98
  * If not given an array to test, it will return an error
76
99
  */
77
100
  export const anyOf = (...patterns) =>
78
- (data) => {
101
+ (data, root, path) => {
79
102
  if (!Array.isArray(data)) {
80
- return error('data is not an array',data,'anyOf')
103
+ return error('data is not an array',data,'anyOf',path)
81
104
  }
82
105
  for (let value of data) {
83
106
  if (oneOf(...patterns)(value)) {
84
- return error('data does not match anyOf patterns',value,patterns)
107
+ return error('data does not match anyOf patterns',value,patterns,path)
85
108
  }
86
109
  }
87
110
  return false
@@ -92,17 +115,20 @@ export const anyOf = (...patterns) =>
92
115
  * parsing it with the URL() constructor, and then testing the href
93
116
  * value to be equal to the initial value.
94
117
  */
95
- export function validURL(data) {
118
+ export function validURL(data, root, path) {
96
119
  try {
97
120
  if (data instanceof URL) {
98
121
  data = data.href
99
122
  }
100
123
  let url = new URL(data)
101
124
  if (url.href!=data) {
102
- return error('data is not a valid url',data,'validURL')
125
+ if (url.href+'/'==data || url.href==data+'/') {
126
+ return false // new URL() always adds a / as path
127
+ }
128
+ return error('data is not a valid url',data,'validURL',path)
103
129
  }
104
130
  } catch(e) {
105
- return error('data is not a valid url',data,'validURL')
131
+ return error('data is not a valid url',data,'validURL',path)
106
132
  }
107
133
  return false
108
134
  }
@@ -112,11 +138,11 @@ export function validURL(data) {
112
138
  * testing it against a regular expression. So there are no guarantees that
113
139
  * it is an actual working email address, just that it looks like one.
114
140
  */
115
- export function validEmail(data) {
141
+ export function validEmail(data, root, path) {
116
142
  if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data)) {
117
143
  return false // data matches email regex
118
144
  }
119
- return error('data is not a valid email',data,'validEmail')
145
+ return error('data is not a valid email',data,'validEmail',path)
120
146
  }
121
147
 
122
148
  /**
@@ -124,8 +150,8 @@ export function validEmail(data) {
124
150
  * constructor
125
151
  */
126
152
  export const instanceOf = (constructor) =>
127
- (data) => !(data instanceof constructor)
128
- ? error('data is not an instanceof pattern',data,constructor)
153
+ (data, root, path) => !(data instanceof constructor)
154
+ ? error('data is not an instanceof pattern',data,constructor,path)
129
155
  : false
130
156
 
131
157
  /**
@@ -133,9 +159,13 @@ export const instanceOf = (constructor) =>
133
159
  * the not() test.
134
160
  */
135
161
  export const not = (pattern) =>
136
- (data) => fails(data, pattern)
137
- ? false
138
- : error('data matches pattern, when required not to', data, pattern)
162
+ (data, root, path) => {
163
+ let problems = fails(data, pattern, root, path)
164
+ if (!problems) {
165
+ return error('data matches pattern, when required not to', data, pattern, path)
166
+ }
167
+ return false
168
+ }
139
169
 
140
170
  /**
141
171
  * returns an array of problems if the data fails to satisfy
@@ -145,46 +175,53 @@ export const not = (pattern) =>
145
175
  * @param {any} root Root object for assertions, set to data by default
146
176
  * @return {Array|false} Array with problems if the pattern fails, false otherwise
147
177
  */
148
- export function fails(data, pattern, root) {
178
+ export function fails(data, pattern, root, path='') {
149
179
  if (!root) {
150
180
  root = data
151
181
  }
152
182
  let problems = []
153
183
  if (pattern === Boolean) {
154
184
  if (typeof data != 'boolean' && !(data instanceof Boolean)) {
155
- problems.push(error('data is not a boolean', data, pattern))
185
+ problems.push(error('data is not a boolean', data, pattern, path))
156
186
  }
157
187
  } else if (pattern === Number) {
158
188
  if (typeof data != 'number' && !(data instanceof Number)) {
159
- problems.push(error('data is not a number', data, pattern))
189
+ problems.push(error('data is not a number', data, pattern, path))
160
190
  }
161
191
  } else if (pattern === String) {
162
192
  if (typeof data != 'string' && !(data instanceof String)) {
163
- problems.push(error('data is not a string', data, pattern))
193
+ problems.push(error('data is not a string', data, pattern, path))
164
194
  }
165
195
  if (data == "") {
166
- problems.push(error('data is an empty string, which is not allowed', data, pattern))
196
+ problems.push(error('data is an empty string, which is not allowed', data, pattern, path))
167
197
  }
168
198
  } else if (pattern instanceof RegExp) {
169
199
  if (Array.isArray(data)) {
170
- let index = data.findIndex(element => fails(element,pattern,root))
200
+ let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))
171
201
  if (index>-1) {
172
- problems.push(error('data['+index+'] does not match pattern', data[index], pattern))
202
+ problems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))
173
203
  }
204
+ } else if (typeof data == 'undefined') {
205
+ problems.push(error('data is undefined, should match pattern', data, pattern, path))
174
206
  } else if (!pattern.test(data)) {
175
- problems.push(error('data does not match pattern', data, pattern))
207
+ problems.push(error('data does not match pattern', data, pattern, path))
176
208
  }
177
209
  } else if (pattern instanceof Function) {
178
- if (pattern(data, root)) {
179
- problems.push(error('data does not match function', data, pattern))
210
+ let problem = pattern(data, root, path)
211
+ if (problem) {
212
+ if (Array.isArray(problem)) {
213
+ problems = problems.concat(problem)
214
+ } else {
215
+ problems.push(problem)
216
+ }
180
217
  }
181
218
  } else if (Array.isArray(pattern)) {
182
219
  if (!Array.isArray(data)) {
183
- problems.push(error('data is not an array',data,[]))
220
+ problems.push(error('data is not an array',data,[],path))
184
221
  }
185
222
  for (let p of pattern) {
186
- for (let val of data) {
187
- let problem = fails(val, p, root)
223
+ for (let index of data.keys()) {
224
+ let problem = fails(data[index], p, root, path+'['+index+']')
188
225
  if (Array.isArray(problem)) {
189
226
  problems = problems.concat(problem)
190
227
  } else if (problem) {
@@ -194,26 +231,33 @@ export function fails(data, pattern, root) {
194
231
  }
195
232
  } else if (pattern && typeof pattern == 'object') {
196
233
  if (Array.isArray(data)) {
197
- let index = data.findIndex(element => fails(element,pattern,root))
234
+ let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))
198
235
  if (index>-1) {
199
- problems.push(error('data['+index+'] does not match pattern', data[index], pattern))
236
+ problems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))
200
237
  }
201
238
  } else if (!data || typeof data != 'object') {
202
- problems.push(error('data is not an object, pattern is', data, pattern))
239
+ problems.push(error('data is not an object, pattern is', data, pattern, path))
203
240
  } else {
204
241
  if (data instanceof URLSearchParams) {
205
242
  data = Object.fromEntries(data)
206
243
  }
207
- for (const [wKey, wVal] of Object.entries(pattern)) {
208
- let result = fails(data[wKey], wVal, root)
244
+ if (pattern instanceof Function) {
245
+ let result = fails(data, pattern, root, path)
209
246
  if (result) {
210
247
  problems = problems.concat(result)
211
248
  }
212
- }
249
+ } else {
250
+ for (const [wKey, wVal] of Object.entries(pattern)) {
251
+ let result = fails(data[wKey], wVal, root, path+'.'+wKey)
252
+ if (result) {
253
+ problems = problems.concat(result)
254
+ }
255
+ }
256
+ }
213
257
  }
214
258
  } else {
215
259
  if (pattern!=data) {
216
- problems.push(error('data and pattern are not equal', data, pattern))
260
+ problems.push(error('data and pattern are not equal', data, pattern, path))
217
261
  }
218
262
  }
219
263
  if (problems.length) {
@@ -237,10 +281,11 @@ class assertError extends Error {
237
281
  /**
238
282
  * Returns an object with message, found and expected properties
239
283
  */
240
- export function error(message, found, expected) {
284
+ export function error(message, found, expected, path) {
241
285
  return {
242
286
  message,
243
287
  found,
244
- expected
288
+ expected,
289
+ path
245
290
  }
246
291
  }