@muze-nl/assert 0.2.1 → 0.3.1

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,"error",()=>m),t(e,"Recommended",()=>i),t(e,"oneOf",()=>l),t(e,"anyOf",()=>d),t(e,"validURL",()=>f),t(e,"validEmail",()=>u),t(e,"instanceOf",()=>c),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=>null==e||void 0===e?m("data is required"):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 m("data does not match oneOf patterns",e,t)},d=(...t)=>e=>{if(!Array.isArray(e))return m("data is not an array",e,"anyOf");for(let a of e)if(l(...t)(a))return m("data does not match anyOf patterns",a,t);return!1};function f(t){try{if(t instanceof URL&&(t=t.href),new URL(t).href!=t)return m("data is not a valid url",t,"validURL")}catch(e){return m("data is not a valid url",t,"validURL")}return!1}function u(t){return!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)&&m("data is not a valid email",t,"validEmail")}const c=t=>e=>!(e instanceof t)&&m("data is not an instanceof pattern",e,t),h=t=>e=>!p(e,t)&&m("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(m("data is not a boolean",t,e));else if(e===Number)"number"==typeof t||t instanceof Number||n.push(m("data is not a number",t,e));else if(e===String)"string"==typeof t||t instanceof String||n.push(m("data is not a string",t,e)),""==t&&n.push(m("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(m("data["+r+"] does not match pattern",t[r],e))}else void 0===t?n.push(m("data is undefined, should match pattern",t,e)):e.test(t)||n.push(m("data does not match pattern",t,e))}else if(e instanceof Function)e(t,a)&&n.push(m("data does not match function",t,e));else if(Array.isArray(e))for(let r of(Array.isArray(t)||n.push(m("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(m("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(m("data is not an object, pattern is",t,e))}else e!=t&&n.push(m("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 m(t,e,a){return{message:t,found:e,expected:a}}globalThis.assert=e;
1
+ function t(t,n,e,a){Object.defineProperty(t,n,{get:e,set:a,enumerable:!0,configurable:!0})}var n={};function e(){globalThis.assertEnabled=!0}function a(){globalThis.assertEnabled=!1}function r(t,n){if(globalThis.assertEnabled){let e=y(t,n);if(e)throw new b("Assertions failed",e,t)}}function o(t){return function(n,e,a){return null!=n&&void 0!==n&&y(n,t,e,a)}}function i(t){return function(n,e,a){return null==n||void 0===n?m("data is required",n,t||"any value",a):void 0!==t&&y(n,t,e,a)}}function s(...t){return function(n,e,a){return null==n||void 0===n?(console.warn("data does not contain recommended value",n,t,a),!1):y(n,t,e,a)}}function f(...t){return function(n,e,a){for(let r of t)if(!y(n,r,e,a))return!1;return m("data does not match oneOf patterns",n,t,a)}}function l(...t){return function(n,e,a){if(!Array.isArray(n))return m("data is not an array",n,"anyOf",a);for(let e of n)if(f(...t)(e))return m("data does not match anyOf patterns",e,t,a);return!1}}function u(...t){return function(n,e,a){let r=[];for(let o of t)r=r.concat(y(n,o,e,a));if((r=r.filter(Boolean)).length)return m("data does not match all given patterns",n,t,a,r)}}function c(t,n,e){try{t instanceof URL&&(t=t.href);let n=new URL(t);if(n.href!=t&&!(n.href+"/"==t||n.href==t+"/"))return m("data is not a valid url",t,"validURL",e)}catch(n){return m("data is not a valid url",t,"validURL",e)}}function d(t,n,e){if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t))return m("data is not a valid email",t,"validEmail",e)}function h(t){return function(n,e,a){if(!(n instanceof t))return m("data is not an instanceof pattern",n,t,a)}}function p(t){return function(n,e,a){if(!y(n,t,e,a))return m("data matches pattern, when required not to",n,t,a)}}function y(t,n,e,a=""){e||(e=t);let r=[];if(n===Boolean)"boolean"==typeof t||t instanceof Boolean||r.push(m("data is not a boolean",t,n,a));else if(n===Number)"number"==typeof t||t instanceof Number||r.push(m("data is not a number",t,n,a));else if(n===String)"string"==typeof t||t instanceof String||r.push(m("data is not a string",t,n,a)),""==t&&r.push(m("data is an empty string, which is not allowed",t,n,a));else if(n instanceof RegExp){if(Array.isArray(t)){let o=t.findIndex((t,r)=>y(t,n,e,a+"["+r+"]"));o>-1&&r.push(m("data["+o+"] does not match pattern",t[o],n,a+"["+o+"]"))}else void 0===t?r.push(m("data is undefined, should match pattern",t,n,a)):n.test(t)||r.push(m("data does not match pattern",t,n,a))}else if(n instanceof Function){let o=n(t,e,a);o&&(Array.isArray(o)?r=r.concat(o):r.push(o))}else if(Array.isArray(n))for(let o of(Array.isArray(t)||r.push(m("data is not an array",t,[],a)),n))for(let n of t.keys()){let i=y(t[n],o,e,a+"["+n+"]");Array.isArray(i)?r=r.concat(i):i&&r.push(i)}else if(n&&"object"==typeof n){if(Array.isArray(t)){let o=t.findIndex((t,r)=>y(t,n,e,a+"["+r+"]"));o>-1&&r.push(m("data["+o+"] does not match pattern",t[o],n,a+"["+o+"]"))}else if(t&&"object"==typeof t){if(t instanceof URLSearchParams&&(t=Object.fromEntries(t)),n instanceof Function){let o=y(t,n,e,a);o&&(r=r.concat(o))}else for(let[o,i]of Object.entries(n)){let n=y(t[o],i,e,a+"."+o);n&&(r=r.concat(n))}}else r.push(m("data is not an object, pattern is",t,n,a))}else n!=t&&r.push(m("data and pattern are not equal",t,n,a));return!!r.length&&r}t(n,"enable",()=>e),t(n,"disable",()=>a),t(n,"assert",()=>r),t(n,"fails",()=>y),t(n,"Optional",()=>o),t(n,"Required",()=>i),t(n,"error",()=>m),t(n,"Recommended",()=>s),t(n,"oneOf",()=>f),t(n,"anyOf",()=>l),t(n,"allOf",()=>u),t(n,"validURL",()=>c),t(n,"validEmail",()=>d),t(n,"instanceOf",()=>h),t(n,"not",()=>p),globalThis.assertEnabled=!1;class b extends Error{constructor(t,n,...e){super(t),this.problems=n,this.details=e}}function m(t,n,e,a,r){let o={message:t,found:n,expected:e,path:a};return r&&(o.problems=r),o}globalThis.assert=n;
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, \"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/**\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)=>data == null || typeof data == \"undefined\" ? $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is required\") : $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 (typeof data == \"undefined\") problems.push($2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is undefined, should match pattern\", data, 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) => (data==null || typeof data == 'undefined') ? error('data is required') : 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 } else if (typeof data == 'undefined') {\n \tproblems.push(error('data is undefined, should match pattern', data, pattern))\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$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","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, \"allOf\", () => $2ddd80d1adc2ea42$export$f632c79c8963a286);\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: Optional() fails if the pattern is not set and the value is\nTODO: scratch: Required() and Optional() and Recommended() should test multiple patterns\n instead: add allOf(...patterns) function\nTODO: add assertExplain global flag, so that if assert() fails, you can call explain() with\n the same pattern and it will return text explanation of why it failed, each assertion function must \n then check assertExplain, and return a text explanation of what fails or succeeds\n top level can then filter to show only the failures\n (so that not(x) can show the succeeds message of x)\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}\nfunction $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}\nfunction $2ddd80d1adc2ea42$export$7acb7b24c478f9c6(pattern) {\n return function _Optional(data, root, path) {\n if (data == null || typeof data == \"undefined\") return false;\n else return $2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path);\n };\n}\nfunction $2ddd80d1adc2ea42$export$1788c381af06add2(pattern) {\n return function _Required(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 };\n}\nfunction $2ddd80d1adc2ea42$export$a83bcf183f49ea9(...pattern) {\n return function _Recommended(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 };\n}\nfunction $2ddd80d1adc2ea42$export$a9a18ae5ba42aeab(...patterns) {\n return function _oneOf(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 };\n}\nfunction $2ddd80d1adc2ea42$export$b26c150f612c10f7(...patterns) {\n return function _anyOf(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 };\n}\nfunction $2ddd80d1adc2ea42$export$f632c79c8963a286(...patterns) {\n return function _allOf(data, root, path) {\n let problems = [];\n for (let pattern of patterns)problems = problems.concat($2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path));\n problems = problems.filter(Boolean);\n if (problems.length) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data does not match all given patterns\", data, patterns, path, problems);\n };\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 + \"/\")) // new URL() always adds a / as path\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}\nfunction $2ddd80d1adc2ea42$export$9ab921aaffe56820(data, root, path) {\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(data)) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not a valid email\", data, \"validEmail\", path);\n}\nfunction $2ddd80d1adc2ea42$export$ca03416d6c9e029e(constructor) {\n return function _instanceOf(data, root, path) {\n if (!(data instanceof constructor)) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data is not an instanceof pattern\", data, constructor, path);\n };\n}\nfunction $2ddd80d1adc2ea42$export$6003a5f097c73977(pattern) {\n return function _not(data, root, path) {\n if (!$2ddd80d1adc2ea42$export$478159de811fd37d(data, pattern, root, path)) return $2ddd80d1adc2ea42$export$a3bc9b8ed74fc(\"data matches pattern, when required not to\", data, pattern, path);\n };\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, problems) {\n let result = {\n message: message,\n found: found,\n expected: expected,\n path: path\n };\n if (problems) result.problems = problems;\n return result;\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: Optional() fails if the pattern is not set and the value is\nTODO: scratch: Required() and Optional() and Recommended() should test multiple patterns\n instead: add allOf(...patterns) function\nTODO: add assertExplain global flag, so that if assert() fails, you can call explain() with\n the same pattern and it will return text explanation of why it failed, each assertion function must \n then check assertExplain, and return a text explanation of what fails or succeeds\n top level can then filter to show only the failures\n (so that not(x) can show the succeeds message of x)\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 function 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 function Optional(pattern) {\n\treturn function _Optional(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/**\n * Tests a given value against a pattern, always.\n */\nexport function Required(pattern) {\n\treturn function _Required(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/**\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 function Recommended(...pattern) {\n\treturn function _Recommended(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/**\n * Tests a given value against a set of patterns, untill one succeeds\n * Returns an error if none succeed\n */\nexport function oneOf(...patterns) { \n\treturn function _oneOf(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/**\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 function anyOf(...patterns) {\n\treturn function _anyOf(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\nexport function allOf(...patterns) {\n\treturn function _allOf(data, root, path) {\n\t\tlet problems = []\n\t\tfor (let pattern of patterns) {\n\t\t\tproblems = problems.concat(fails(data, pattern, root, path))\n\t\t}\n\t\tproblems = problems.filter(Boolean)\n\t\tif (problems.length) {\n\t\t\treturn error('data does not match all given patterns', data, patterns, path, problems)\n\t\t}\n\t}\n}\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\t// new URL() always adds a / as path\n\t\t\t\treturn error('data is not a valid url',data,'validURL',path)\n\t\t\t}\n\t\t}\n\t} catch(e) {\n\t\treturn error('data is not a valid url',data,'validURL',path)\n\t}\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 error('data is not a valid email',data,'validEmail',path)\n\t}\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 function instanceOf(constructor) {\n\treturn function _instanceOf(data, root, path) {\n\t\tif (!(data instanceof constructor)) {\n\t\t\treturn error('data is not an instanceof pattern',data,constructor,path)\n\t\t}\n\t}\n}\n\n/**\n * Runs the given test pattern on a value, if the test succeeds, it fails\n * the not() test.\n */\nexport function not(pattern) {\n\treturn function _not(data, root, path) {\n\t\tif (!fails(data, pattern, root, path)) {\n\t\t\treturn error('data matches pattern, when required not to', data, pattern, path)\n\t\t}\n\t}\n}\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, problems) {\n\tlet result = {\n\t\tmessage,\n\t\tfound,\n\t\texpected,\n\t\tpath\n\t}\n\tif (problems) {\n\t\tresult.problems = problems\n\t}\n\treturn result\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","source","test","problems","$2ddd80d1adc2ea42$export$478159de811fd37d","$2ddd80d1adc2ea42$var$assertError","$2ddd80d1adc2ea42$export$7acb7b24c478f9c6","pattern","data","root","path","$2ddd80d1adc2ea42$export$1788c381af06add2","$2ddd80d1adc2ea42$export$a3bc9b8ed74fc","$2ddd80d1adc2ea42$export$a83bcf183f49ea9","console","warn","$2ddd80d1adc2ea42$export$a9a18ae5ba42aeab","patterns","$2ddd80d1adc2ea42$export$b26c150f612c10f7","Array","isArray","value","$2ddd80d1adc2ea42$export$f632c79c8963a286","concat","filter","Boolean","length","$2ddd80d1adc2ea42$export$c6f1a4382426409f","URL","href","url","$2ddd80d1adc2ea42$export$9ab921aaffe56820","$2ddd80d1adc2ea42$export$ca03416d6c9e029e","constructor","$2ddd80d1adc2ea42$export$6003a5f097c73977","push","Number","String","RegExp","index","findIndex","element","Function","problem","p","keys","URLSearchParams","fromEntries","result","wKey","wVal","entries","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.1",
3
+ "version": "0.3.1",
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,14 @@
1
+ /*
2
+ FIXME: Optional() fails if the pattern is not set and the value is
3
+ TODO: scratch: Required() and Optional() and Recommended() should test multiple patterns
4
+ instead: add allOf(...patterns) function
5
+ TODO: add assertExplain global flag, so that if assert() fails, you can call explain() with
6
+ the same pattern and it will return text explanation of why it failed, each assertion function must
7
+ then check assertExplain, and return a text explanation of what fails or succeeds
8
+ top level can then filter to show only the failures
9
+ (so that not(x) can show the succeeds message of x)
10
+ */
11
+
1
12
  /**
2
13
  * assertEnabled (Boolean) used to toggle whether the assert()
3
14
  * method should test assertions or not.
@@ -24,7 +35,7 @@ export function disable() {
24
35
  * If it is, and any assertion fails, it will throw an assertError
25
36
  * with a list of problems and other details.
26
37
  */
27
- export const assert = (source, test) => {
38
+ export function assert(source, test) {
28
39
  if (globalThis.assertEnabled) {
29
40
  let problems = fails(source,test)
30
41
  if (problems) {
@@ -36,75 +47,113 @@ export const assert = (source, test) => {
36
47
  /**
37
48
  * Tests a given value against a pattern, only if the value is not null or undefined
38
49
  */
39
- export const Optional = (pattern) =>
40
- (data) => (data==null || typeof data == 'undefined') ? false : fails(data, pattern)
50
+ export function Optional(pattern) {
51
+ return function _Optional(data, root, path) {
52
+ if (data==null || typeof data == 'undefined') {
53
+ return false
54
+ } else {
55
+ return fails(data, pattern, root, path)
56
+ }
57
+ }
58
+ }
41
59
 
42
60
  /**
43
61
  * Tests a given value against a pattern, always.
44
62
  */
45
- export const Required = (pattern) =>
46
- (data) => (data==null || typeof data == 'undefined') ? error('data is required') : fails(data, pattern)
63
+ export function Required(pattern) {
64
+ return function _Required(data, root, path) {
65
+ if (data==null || typeof data == 'undefined') {
66
+ return error('data is required', data, pattern || 'any value', path)
67
+ } else if (typeof pattern != 'undefined') {
68
+ return fails(data, pattern, root, path)
69
+ } else {
70
+ return false
71
+ }
72
+ }
73
+ }
47
74
 
48
75
  /**
49
76
  * Tests a given value against a pattern, only if the value is not null or undefined
50
77
  * If null or undefined, it does print a warning to the console.
51
78
  */
52
- 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)
79
+ export function Recommended(...pattern) {
80
+ return function _Recommended(data, root, path) {
81
+ if (data==null || typeof data == 'undefined') {
82
+ console.warn('data does not contain recommended value', data, pattern, path)
83
+ return false
84
+ } else {
85
+ return fails(data, pattern, root, path)
86
+ }
87
+ }
88
+ }
57
89
 
58
90
  /**
59
91
  * Tests a given value against a set of patterns, untill one succeeds
60
92
  * Returns an error if none succeed
61
93
  */
62
- export const oneOf = (...patterns) =>
63
- (data) => {
94
+ export function oneOf(...patterns) {
95
+ return function _oneOf(data, root, path) {
64
96
  for(let pattern of patterns) {
65
- if (!fails(data, pattern)) {
97
+ if (!fails(data, pattern, root, path)) {
66
98
  return false
67
99
  }
68
100
  }
69
- return error('data does not match oneOf patterns',data,patterns)
101
+ return error('data does not match oneOf patterns', data, patterns, path)
70
102
  }
103
+ }
71
104
 
72
105
  /**
73
106
  * Tests a given array of values against a set of patterns
74
107
  * If any value does not match one of the patterns, it will return an error
75
108
  * If not given an array to test, it will return an error
76
109
  */
77
- export const anyOf = (...patterns) =>
78
- (data) => {
110
+ export function anyOf(...patterns) {
111
+ return function _anyOf(data, root, path) {
79
112
  if (!Array.isArray(data)) {
80
- return error('data is not an array',data,'anyOf')
113
+ return error('data is not an array',data,'anyOf',path)
81
114
  }
82
115
  for (let value of data) {
83
116
  if (oneOf(...patterns)(value)) {
84
- return error('data does not match anyOf patterns',value,patterns)
117
+ return error('data does not match anyOf patterns',value,patterns,path)
85
118
  }
86
119
  }
87
120
  return false
88
121
  }
122
+ }
123
+
124
+ export function allOf(...patterns) {
125
+ return function _allOf(data, root, path) {
126
+ let problems = []
127
+ for (let pattern of patterns) {
128
+ problems = problems.concat(fails(data, pattern, root, path))
129
+ }
130
+ problems = problems.filter(Boolean)
131
+ if (problems.length) {
132
+ return error('data does not match all given patterns', data, patterns, path, problems)
133
+ }
134
+ }
135
+ }
89
136
 
90
137
  /**
91
138
  * Tests a given value to see if it is a valid (and absolute) URL, by
92
139
  * parsing it with the URL() constructor, and then testing the href
93
140
  * value to be equal to the initial value.
94
141
  */
95
- export function validURL(data) {
142
+ export function validURL(data, root, path) {
96
143
  try {
97
144
  if (data instanceof URL) {
98
145
  data = data.href
99
146
  }
100
147
  let url = new URL(data)
101
148
  if (url.href!=data) {
102
- return error('data is not a valid url',data,'validURL')
149
+ if (!(url.href+'/'==data || url.href==data+'/')) {
150
+ // new URL() always adds a / as path
151
+ return error('data is not a valid url',data,'validURL',path)
152
+ }
103
153
  }
104
154
  } catch(e) {
105
- return error('data is not a valid url',data,'validURL')
155
+ return error('data is not a valid url',data,'validURL',path)
106
156
  }
107
- return false
108
157
  }
109
158
 
110
159
  /**
@@ -112,30 +161,35 @@ export function validURL(data) {
112
161
  * testing it against a regular expression. So there are no guarantees that
113
162
  * it is an actual working email address, just that it looks like one.
114
163
  */
115
- export function validEmail(data) {
116
- if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data)) {
117
- return false // data matches email regex
164
+ export function validEmail(data, root, path) {
165
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data)) {
166
+ return error('data is not a valid email',data,'validEmail',path)
118
167
  }
119
- return error('data is not a valid email',data,'validEmail')
120
168
  }
121
169
 
122
170
  /**
123
171
  * Tests a given value to see if it is an object which is an instance of the given
124
172
  * constructor
125
173
  */
126
- export const instanceOf = (constructor) =>
127
- (data) => !(data instanceof constructor)
128
- ? error('data is not an instanceof pattern',data,constructor)
129
- : false
174
+ export function instanceOf(constructor) {
175
+ return function _instanceOf(data, root, path) {
176
+ if (!(data instanceof constructor)) {
177
+ return error('data is not an instanceof pattern',data,constructor,path)
178
+ }
179
+ }
180
+ }
130
181
 
131
182
  /**
132
183
  * Runs the given test pattern on a value, if the test succeeds, it fails
133
184
  * the not() test.
134
185
  */
135
- export const not = (pattern) =>
136
- (data) => fails(data, pattern)
137
- ? false
138
- : error('data matches pattern, when required not to', data, pattern)
186
+ export function not(pattern) {
187
+ return function _not(data, root, path) {
188
+ if (!fails(data, pattern, root, path)) {
189
+ return error('data matches pattern, when required not to', data, pattern, path)
190
+ }
191
+ }
192
+ }
139
193
 
140
194
  /**
141
195
  * returns an array of problems if the data fails to satisfy
@@ -145,48 +199,53 @@ export const not = (pattern) =>
145
199
  * @param {any} root Root object for assertions, set to data by default
146
200
  * @return {Array|false} Array with problems if the pattern fails, false otherwise
147
201
  */
148
- export function fails(data, pattern, root) {
202
+ export function fails(data, pattern, root, path='') {
149
203
  if (!root) {
150
204
  root = data
151
205
  }
152
206
  let problems = []
153
207
  if (pattern === Boolean) {
154
208
  if (typeof data != 'boolean' && !(data instanceof Boolean)) {
155
- problems.push(error('data is not a boolean', data, pattern))
209
+ problems.push(error('data is not a boolean', data, pattern, path))
156
210
  }
157
211
  } else if (pattern === Number) {
158
212
  if (typeof data != 'number' && !(data instanceof Number)) {
159
- problems.push(error('data is not a number', data, pattern))
213
+ problems.push(error('data is not a number', data, pattern, path))
160
214
  }
161
215
  } else if (pattern === String) {
162
216
  if (typeof data != 'string' && !(data instanceof String)) {
163
- problems.push(error('data is not a string', data, pattern))
217
+ problems.push(error('data is not a string', data, pattern, path))
164
218
  }
165
219
  if (data == "") {
166
- problems.push(error('data is an empty string, which is not allowed', data, pattern))
220
+ problems.push(error('data is an empty string, which is not allowed', data, pattern, path))
167
221
  }
168
222
  } else if (pattern instanceof RegExp) {
169
223
  if (Array.isArray(data)) {
170
- let index = data.findIndex(element => fails(element,pattern,root))
224
+ let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))
171
225
  if (index>-1) {
172
- problems.push(error('data['+index+'] does not match pattern', data[index], pattern))
226
+ problems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))
173
227
  }
174
228
  } else if (typeof data == 'undefined') {
175
- problems.push(error('data is undefined, should match pattern', data, pattern))
229
+ problems.push(error('data is undefined, should match pattern', data, pattern, path))
176
230
  } else if (!pattern.test(data)) {
177
- problems.push(error('data does not match pattern', data, pattern))
231
+ problems.push(error('data does not match pattern', data, pattern, path))
178
232
  }
179
233
  } else if (pattern instanceof Function) {
180
- if (pattern(data, root)) {
181
- problems.push(error('data does not match function', data, pattern))
234
+ let problem = pattern(data, root, path)
235
+ if (problem) {
236
+ if (Array.isArray(problem)) {
237
+ problems = problems.concat(problem)
238
+ } else {
239
+ problems.push(problem)
240
+ }
182
241
  }
183
242
  } else if (Array.isArray(pattern)) {
184
243
  if (!Array.isArray(data)) {
185
- problems.push(error('data is not an array',data,[]))
244
+ problems.push(error('data is not an array',data,[],path))
186
245
  }
187
246
  for (let p of pattern) {
188
- for (let val of data) {
189
- let problem = fails(val, p, root)
247
+ for (let index of data.keys()) {
248
+ let problem = fails(data[index], p, root, path+'['+index+']')
190
249
  if (Array.isArray(problem)) {
191
250
  problems = problems.concat(problem)
192
251
  } else if (problem) {
@@ -196,26 +255,33 @@ export function fails(data, pattern, root) {
196
255
  }
197
256
  } else if (pattern && typeof pattern == 'object') {
198
257
  if (Array.isArray(data)) {
199
- let index = data.findIndex(element => fails(element,pattern,root))
258
+ let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))
200
259
  if (index>-1) {
201
- problems.push(error('data['+index+'] does not match pattern', data[index], pattern))
260
+ problems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))
202
261
  }
203
262
  } else if (!data || typeof data != 'object') {
204
- problems.push(error('data is not an object, pattern is', data, pattern))
263
+ problems.push(error('data is not an object, pattern is', data, pattern, path))
205
264
  } else {
206
265
  if (data instanceof URLSearchParams) {
207
266
  data = Object.fromEntries(data)
208
267
  }
209
- for (const [wKey, wVal] of Object.entries(pattern)) {
210
- let result = fails(data[wKey], wVal, root)
268
+ if (pattern instanceof Function) {
269
+ let result = fails(data, pattern, root, path)
211
270
  if (result) {
212
271
  problems = problems.concat(result)
213
272
  }
214
- }
273
+ } else {
274
+ for (const [wKey, wVal] of Object.entries(pattern)) {
275
+ let result = fails(data[wKey], wVal, root, path+'.'+wKey)
276
+ if (result) {
277
+ problems = problems.concat(result)
278
+ }
279
+ }
280
+ }
215
281
  }
216
282
  } else {
217
283
  if (pattern!=data) {
218
- problems.push(error('data and pattern are not equal', data, pattern))
284
+ problems.push(error('data and pattern are not equal', data, pattern, path))
219
285
  }
220
286
  }
221
287
  if (problems.length) {
@@ -239,10 +305,15 @@ class assertError extends Error {
239
305
  /**
240
306
  * Returns an object with message, found and expected properties
241
307
  */
242
- export function error(message, found, expected) {
243
- return {
308
+ export function error(message, found, expected, path, problems) {
309
+ let result = {
244
310
  message,
245
311
  found,
246
- expected
312
+ expected,
313
+ path
314
+ }
315
+ if (problems) {
316
+ result.problems = problems
247
317
  }
318
+ return result
248
319
  }