@muze-nl/assert 0.4.2 → 0.5.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.
@@ -1,30 +1,5 @@
1
1
  (() => {
2
- var __defProp = Object.defineProperty;
3
- var __export = (target, all) => {
4
- for (var name in all)
5
- __defProp(target, name, { get: all[name], enumerable: true });
6
- };
7
-
8
2
  // src/assert.mjs
9
- var assert_exports = {};
10
- __export(assert_exports, {
11
- Optional: () => Optional,
12
- Recommended: () => Recommended,
13
- Required: () => Required,
14
- allOf: () => allOf,
15
- anyOf: () => anyOf,
16
- assert: () => assert,
17
- disable: () => disable,
18
- enable: () => enable,
19
- error: () => error,
20
- fails: () => fails,
21
- instanceOf: () => instanceOf,
22
- not: () => not,
23
- oneOf: () => oneOf,
24
- validEmail: () => validEmail,
25
- validURL: () => validURL,
26
- warn: () => warn
27
- });
28
3
  globalThis.assertEnabled = false;
29
4
  function enable() {
30
5
  globalThis.assertEnabled = true;
@@ -245,7 +220,22 @@
245
220
  function warn(message, data, pattern, path) {
246
221
  console.warn("\u{1F170}\uFE0F Assert: " + path, message, pattern, data);
247
222
  }
248
-
249
- // src/browser.mjs
250
- globalThis.assert = assert_exports;
223
+ globalThis.assert = {
224
+ warn,
225
+ error,
226
+ assert,
227
+ enable,
228
+ disable,
229
+ Required,
230
+ Recommended,
231
+ Optional,
232
+ oneOf,
233
+ anyOf,
234
+ allOf,
235
+ validURL,
236
+ validEmail,
237
+ instanceOf,
238
+ not,
239
+ fails
240
+ };
251
241
  })();
@@ -0,0 +1,2 @@
1
+ (()=>{globalThis.assertEnabled=!1;function b(){globalThis.assertEnabled=!0}function m(){globalThis.assertEnabled=!1}function x(e,o){if(globalThis.assertEnabled){let n=l(e,o);if(n)throw console.error("\u{1F170}\uFE0F Assertions failed because of:",n,"in this source:",e),new Error("Assertions failed",{cause:{problems:n,source:e}})}}function d(e){return function(n,r,i){if(typeof n<"u"&&n!=null&&typeof e<"u")return l(n,e,r,i)}}function h(e){return function(n,r,i){return n==null||typeof n>"u"?s("data is required",n,e||"any value",i):typeof e<"u"?l(n,e,r,i):!1}}function A(e){return function(n,r,i){return n==null||typeof n>"u"?(y("data does not contain recommended value",n,e,i),!1):l(n,e,r,i)}}function c(...e){return function(n,r,i){for(let f of e)if(!l(n,f,r,i))return!1;return s("data does not match oneOf patterns",n,e,i)}}function O(...e){return function(n,r,i){if(!Array.isArray(n))return s("data is not an array",n,"anyOf",i);for(let f of n)if(c(...e)(f))return s("data does not match anyOf patterns",f,e,i);return!1}}function g(...e){return function(n,r,i){let f=[];for(let t of e)f=f.concat(l(n,t,r,i));if(f=f.filter(Boolean),f.length)return s("data does not match all given patterns",n,e,i,f)}}function v(e,o,n){try{e instanceof URL&&(e=e.href);let r=new URL(e);if(r.href!=e&&!(r.href+"/"==e||r.href==e+"/"))return s("data is not a valid url",e,"validURL",n)}catch{return s("data is not a valid url",e,"validURL",n)}}function R(e,o,n){if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))return s("data is not a valid email",e,"validEmail",n)}function E(e){return function(n,r,i){if(!(n instanceof e))return s("data is not an instanceof pattern",n,e,i)}}function p(e){return function(n,r,i){if(!l(n,e,r,i))return s("data matches pattern, when required not to",n,e,i)}}function l(e,o,n,r=""){n||(n=e);let i=[];if(o===Boolean)typeof e!="boolean"&&!(e instanceof Boolean)&&i.push(s("data is not a boolean",e,o,r));else if(o===Number)typeof e!="number"&&!(e instanceof Number)&&i.push(s("data is not a number",e,o,r));else if(o===String)typeof e!="string"&&!(e instanceof String)&&i.push(s("data is not a string",e,o,r)),e==""&&i.push(s("data is an empty string, which is not allowed",e,o,r));else if(o instanceof RegExp)if(Array.isArray(e)){let f=e.findIndex((t,u)=>l(t,o,n,r+"["+u+"]"));f>-1&&i.push(s("data["+f+"] does not match pattern",e[f],o,r+"["+f+"]"))}else typeof e>"u"?i.push(s("data is undefined, should match pattern",e,o,r)):o.test(e)||i.push(s("data does not match pattern",e,o,r));else if(o instanceof Function){let f=o(e,n,r);f&&(Array.isArray(f)?i=i.concat(f):i.push(f))}else if(Array.isArray(o)){Array.isArray(e)||i.push(s("data is not an array",e,[],r));for(let f of o)for(let t of e.keys()){let u=l(e[t],f,n,r+"["+t+"]");Array.isArray(u)?i=i.concat(u):u&&i.push(u)}}else if(o&&typeof o=="object")if(Array.isArray(e)){let f=e.findIndex((t,u)=>l(t,o,n,r+"["+u+"]"));f>-1&&i.push(s("data["+f+"] does not match pattern",e[f],o,r+"["+f+"]"))}else if(!e||typeof e!="object")i.push(s("data is not an object, pattern is",e,o,r));else if(e instanceof URLSearchParams&&(e=Object.fromEntries(e)),o instanceof Function){let f=l(e,o,n,r);f&&(i=i.concat(f))}else for(let[f,t]of Object.entries(o)){let u=l(e[f],t,n,r+"."+f);u&&(i=i.concat(u))}else o!=e&&i.push(s("data and pattern are not equal",e,o,r));return i.length?i:!1}function s(e,o,n,r,i){let f={path:r,message:e,found:o,expected:n};return i&&(f.problems=i),f}function y(e,o,n,r){console.warn("\u{1F170}\uFE0F Assert: "+r,e,n,o)}globalThis.assert={warn:y,error:s,assert:x,enable:b,disable:m,Required:h,Recommended:A,Optional:d,oneOf:c,anyOf:O,allOf:g,validURL:v,validEmail:R,instanceOf:E,not:p,fails:l};})();
2
+ //# sourceMappingURL=assert.min.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/assert.mjs", "../src/browser.mjs"],
4
- "sourcesContent": ["/*\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\tconsole.error('\uD83C\uDD70\uFE0F Assertions failed because of:', problems, 'in this source:', source)\n\t\t\tthrow new Error('Assertions failed', {\n\t\t\t\tcause: { problems, source } \n\t\t\t})\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 (typeof data != 'undefined' && data!=null && typeof pattern != 'undefined' ) {\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\twarn('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 [patternKey, subpattern] of Object.entries(pattern)) {\n\t\t let result = fails(data[patternKey], subpattern, root, path+'.'+patternKey)\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 * Returns an object with message, found and expected properties\n */ \nexport function error(message, found, expected, path, problems) {\n\tlet result = {\n\t\tpath,\n\t\tmessage,\n\t\tfound,\n\t\texpected\n\t}\n\tif (problems) {\n\t\tresult.problems = problems\n\t}\n\treturn result\n}\n\nexport function warn(message, data, pattern, path) {\n\tconsole.warn('\uD83C\uDD70\uFE0F Assert: '+path, message, pattern, data)\n}", "import * as assert from './assert.mjs'\n\nglobalThis.assert = assert\n"],
5
- "mappings": "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",
6
- "names": ["assert_exports", "__export", "Optional", "Recommended", "Required", "allOf", "anyOf", "assert", "disable", "enable", "error", "fails", "instanceOf", "not", "oneOf", "validEmail", "validURL", "warn", "source", "test", "problems", "pattern", "data", "root", "path", "patterns", "value", "url", "constructor", "index", "element", "problem", "p", "result", "patternKey", "subpattern", "message", "found", "expected", "assert_exports"]
3
+ "sources": ["../src/assert.mjs"],
4
+ "sourcesContent": ["/*\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\tconsole.error('\uD83C\uDD70\uFE0F Assertions failed because of:', problems, 'in this source:', source)\n\t\t\tthrow new Error('Assertions failed', {\n\t\t\t\tcause: { problems, source } \n\t\t\t})\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 (typeof data != 'undefined' && data!=null && typeof pattern != 'undefined' ) {\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\twarn('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 [patternKey, subpattern] of Object.entries(pattern)) {\n\t\t let result = fails(data[patternKey], subpattern, root, path+'.'+patternKey)\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 * Returns an object with message, found and expected properties\n */ \nexport function error(message, found, expected, path, problems) {\n\tlet result = {\n\t\tpath,\n\t\tmessage,\n\t\tfound,\n\t\texpected\n\t}\n\tif (problems) {\n\t\tresult.problems = problems\n\t}\n\treturn result\n}\n\nexport function warn(message, data, pattern, path) {\n\tconsole.warn('\uD83C\uDD70\uFE0F Assert: '+path, message, pattern, data)\n}\n\nglobalThis.assert = {\n\twarn,\n\terror,\n\tassert,\n\tenable,\n\tdisable,\n\tRequired,\n\tRecommended,\n\tOptional,\n\toneOf,\n\tanyOf,\n\tallOf,\n\tvalidURL,\n\tvalidEmail,\n\tinstanceOf,\n\tnot,\n\tfails\n}"],
5
+ "mappings": "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",
6
+ "names": ["enable", "disable", "assert", "source", "test", "problems", "fails", "Optional", "pattern", "data", "root", "path", "Required", "error", "Recommended", "warn", "oneOf", "patterns", "anyOf", "value", "allOf", "validURL", "url", "validEmail", "instanceOf", "constructor", "not", "index", "element", "problem", "p", "result", "patternKey", "subpattern", "message", "found", "expected"]
7
7
  }
package/package.json CHANGED
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "@muze-nl/assert",
3
- "version": "0.4.2",
3
+ "version": "0.5.1",
4
4
  "description": "light optional assert library",
5
5
  "type": "module",
6
- "sideEffects": false,
7
6
  "main": "src/assert.mjs",
8
7
  "scripts": {
9
8
  "test": "tap test/*.mjs",
10
9
  "tap": "tap",
11
- "build": "npx esbuild --bundle src/browser.mjs --outfile=dist/browser.min.js --minify --sourcemap",
12
- "build-dev": "npx esbuild --bundle src/browser.mjs --outfile=dist/browser.js"
10
+ "build": "npx esbuild --bundle src/assert.mjs --outfile=dist/assert.min.js --minify --sourcemap",
11
+ "build-dev": "npx esbuild --bundle src/assert.mjs --outfile=dist/assert.js"
13
12
  },
14
13
  "repository": {
15
14
  "type": "git",
package/src/assert.mjs CHANGED
@@ -306,4 +306,23 @@ export function error(message, found, expected, path, problems) {
306
306
 
307
307
  export function warn(message, data, pattern, path) {
308
308
  console.warn('🅰️ Assert: '+path, message, pattern, data)
309
+ }
310
+
311
+ globalThis.assert = {
312
+ warn,
313
+ error,
314
+ assert,
315
+ enable,
316
+ disable,
317
+ Required,
318
+ Recommended,
319
+ Optional,
320
+ oneOf,
321
+ anyOf,
322
+ allOf,
323
+ validURL,
324
+ validEmail,
325
+ instanceOf,
326
+ not,
327
+ fails
309
328
  }
@@ -0,0 +1,309 @@
1
+ /*
2
+ TODO: add assertExplain global flag, so that if assert() fails, you can call explain() with
3
+ the same pattern and it will return text explanation of why it failed, each assertion function must
4
+ then check assertExplain, and return a text explanation of what fails or succeeds
5
+ top level can then filter to show only the failures
6
+ (so that not(x) can show the succeeds message of x)
7
+ */
8
+
9
+ /**
10
+ * assertEnabled (Boolean) used to toggle whether the assert()
11
+ * method should test assertions or not.
12
+ */
13
+ globalThis.assertEnabled = false
14
+
15
+ /**
16
+ * Enables assertion testing with assert()
17
+ */
18
+ export function enable() {
19
+ globalThis.assertEnabled = true
20
+ }
21
+
22
+ /**
23
+ * Disables assertion testing with assert()
24
+ */
25
+ export function disable() {
26
+ globalThis.assertEnabled = false
27
+ }
28
+
29
+ /**
30
+ * This function will check the source for the assertions in test, if
31
+ * assertion checking is enabled globally.
32
+ * If it is, and any assertion fails, it will throw an assertError
33
+ * with a list of problems and other details.
34
+ */
35
+ export function assert(source, test) {
36
+ if (globalThis.assertEnabled) {
37
+ let problems = fails(source,test)
38
+ if (problems) {
39
+ console.error('🅰️ Assertions failed because of:', problems, 'in this source:', source)
40
+ throw new Error('Assertions failed', {
41
+ cause: { problems, source }
42
+ })
43
+ }
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Tests a given value against a pattern, only if the value is not null or undefined
49
+ */
50
+ export function Optional(pattern) {
51
+ return function _Optional(data, root, path) {
52
+ if (typeof data != 'undefined' && data!=null && typeof pattern != 'undefined' ) {
53
+ return fails(data, pattern, root, path)
54
+ }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Tests a given value against a pattern, always.
60
+ */
61
+ export function Required(pattern) {
62
+ return function _Required(data, root, path) {
63
+ if (data==null || typeof data == 'undefined') {
64
+ return error('data is required', data, pattern || 'any value', path)
65
+ } else if (typeof pattern != 'undefined') {
66
+ return fails(data, pattern, root, path)
67
+ } else {
68
+ return false
69
+ }
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Tests a given value against a pattern, only if the value is not null or undefined
75
+ * If null or undefined, it does print a warning to the console.
76
+ */
77
+ export function Recommended(pattern) {
78
+ return function _Recommended(data, root, path) {
79
+ if (data==null || typeof data == 'undefined') {
80
+ warn('data does not contain recommended value', data, pattern, path)
81
+ return false
82
+ } else {
83
+ return fails(data, pattern, root, path)
84
+ }
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Tests a given value against a set of patterns, untill one succeeds
90
+ * Returns an error if none succeed
91
+ */
92
+ export function oneOf(...patterns) {
93
+ return function _oneOf(data, root, path) {
94
+ for(let pattern of patterns) {
95
+ if (!fails(data, pattern, root, path)) {
96
+ return false
97
+ }
98
+ }
99
+ return error('data does not match oneOf patterns', data, patterns, path)
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Tests a given array of values against a set of patterns
105
+ * If any value does not match one of the patterns, it will return an error
106
+ * If not given an array to test, it will return an error
107
+ */
108
+ export function anyOf(...patterns) {
109
+ return function _anyOf(data, root, path) {
110
+ if (!Array.isArray(data)) {
111
+ return error('data is not an array',data,'anyOf',path)
112
+ }
113
+ for (let value of data) {
114
+ if (oneOf(...patterns)(value)) {
115
+ return error('data does not match anyOf patterns',value,patterns,path)
116
+ }
117
+ }
118
+ return false
119
+ }
120
+ }
121
+
122
+ export function allOf(...patterns) {
123
+ return function _allOf(data, root, path) {
124
+ let problems = []
125
+ for (let pattern of patterns) {
126
+ problems = problems.concat(fails(data, pattern, root, path))
127
+ }
128
+ problems = problems.filter(Boolean)
129
+ if (problems.length) {
130
+ return error('data does not match all given patterns', data, patterns, path, problems)
131
+ }
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Tests a given value to see if it is a valid (and absolute) URL, by
137
+ * parsing it with the URL() constructor, and then testing the href
138
+ * value to be equal to the initial value.
139
+ */
140
+ export function validURL(data, root, path) {
141
+ try {
142
+ if (data instanceof URL) {
143
+ data = data.href
144
+ }
145
+ let url = new URL(data)
146
+ if (url.href!=data) {
147
+ if (!(url.href+'/'==data || url.href==data+'/')) {
148
+ // new URL() always adds a / as path
149
+ return error('data is not a valid url',data,'validURL',path)
150
+ }
151
+ }
152
+ } catch(e) {
153
+ return error('data is not a valid url',data,'validURL',path)
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Tests a given value to see if it looks like a valid email address, by
159
+ * testing it against a regular expression. So there are no guarantees that
160
+ * it is an actual working email address, just that it looks like one.
161
+ */
162
+ export function validEmail(data, root, path) {
163
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data)) {
164
+ return error('data is not a valid email',data,'validEmail',path)
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Tests a given value to see if it is an object which is an instance of the given
170
+ * constructor
171
+ */
172
+ export function instanceOf(constructor) {
173
+ return function _instanceOf(data, root, path) {
174
+ if (!(data instanceof constructor)) {
175
+ return error('data is not an instanceof pattern',data,constructor,path)
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Runs the given test pattern on a value, if the test succeeds, it fails
182
+ * the not() test.
183
+ */
184
+ export function not(pattern) {
185
+ return function _not(data, root, path) {
186
+ if (!fails(data, pattern, root, path)) {
187
+ return error('data matches pattern, when required not to', data, pattern, path)
188
+ }
189
+ }
190
+ }
191
+
192
+ /**
193
+ * returns an array of problems if the data fails to satisfy
194
+ * the assertions in the given pattern, false otherwise
195
+ * @param {any} data The data to match
196
+ * @param {any} pattern The pattern to match
197
+ * @param {any} root Root object for assertions, set to data by default
198
+ * @return {Array|false} Array with problems if the pattern fails, false otherwise
199
+ */
200
+ export function fails(data, pattern, root, path='') {
201
+ if (!root) {
202
+ root = data
203
+ }
204
+ let problems = []
205
+ if (pattern === Boolean) {
206
+ if (typeof data != 'boolean' && !(data instanceof Boolean)) {
207
+ problems.push(error('data is not a boolean', data, pattern, path))
208
+ }
209
+ } else if (pattern === Number) {
210
+ if (typeof data != 'number' && !(data instanceof Number)) {
211
+ problems.push(error('data is not a number', data, pattern, path))
212
+ }
213
+ } else if (pattern === String) {
214
+ if (typeof data != 'string' && !(data instanceof String)) {
215
+ problems.push(error('data is not a string', data, pattern, path))
216
+ }
217
+ if (data == "") {
218
+ problems.push(error('data is an empty string, which is not allowed', data, pattern, path))
219
+ }
220
+ } else if (pattern instanceof RegExp) {
221
+ if (Array.isArray(data)) {
222
+ let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))
223
+ if (index>-1) {
224
+ problems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))
225
+ }
226
+ } else if (typeof data == 'undefined') {
227
+ problems.push(error('data is undefined, should match pattern', data, pattern, path))
228
+ } else if (!pattern.test(data)) {
229
+ problems.push(error('data does not match pattern', data, pattern, path))
230
+ }
231
+ } else if (pattern instanceof Function) {
232
+ let problem = pattern(data, root, path)
233
+ if (problem) {
234
+ if (Array.isArray(problem)) {
235
+ problems = problems.concat(problem)
236
+ } else {
237
+ problems.push(problem)
238
+ }
239
+ }
240
+ } else if (Array.isArray(pattern)) {
241
+ if (!Array.isArray(data)) {
242
+ problems.push(error('data is not an array',data,[],path))
243
+ }
244
+ for (let p of pattern) {
245
+ for (let index of data.keys()) {
246
+ let problem = fails(data[index], p, root, path+'['+index+']')
247
+ if (Array.isArray(problem)) {
248
+ problems = problems.concat(problem)
249
+ } else if (problem) {
250
+ problems.push(problem)
251
+ }
252
+ }
253
+ }
254
+ } else if (pattern && typeof pattern == 'object') {
255
+ if (Array.isArray(data)) {
256
+ let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))
257
+ if (index>-1) {
258
+ problems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))
259
+ }
260
+ } else if (!data || typeof data != 'object') {
261
+ problems.push(error('data is not an object, pattern is', data, pattern, path))
262
+ } else {
263
+ if (data instanceof URLSearchParams) {
264
+ data = Object.fromEntries(data)
265
+ }
266
+ if (pattern instanceof Function) {
267
+ let result = fails(data, pattern, root, path)
268
+ if (result) {
269
+ problems = problems.concat(result)
270
+ }
271
+ } else {
272
+ for (const [patternKey, subpattern] of Object.entries(pattern)) {
273
+ let result = fails(data[patternKey], subpattern, root, path+'.'+patternKey)
274
+ if (result) {
275
+ problems = problems.concat(result)
276
+ }
277
+ }
278
+ }
279
+ }
280
+ } else {
281
+ if (pattern!=data) {
282
+ problems.push(error('data and pattern are not equal', data, pattern, path))
283
+ }
284
+ }
285
+ if (problems.length) {
286
+ return problems
287
+ }
288
+ return false
289
+ }
290
+
291
+ /**
292
+ * Returns an object with message, found and expected properties
293
+ */
294
+ export function error(message, found, expected, path, problems) {
295
+ let result = {
296
+ path,
297
+ message,
298
+ found,
299
+ expected
300
+ }
301
+ if (problems) {
302
+ result.problems = problems
303
+ }
304
+ return result
305
+ }
306
+
307
+ export function warn(message, data, pattern, path) {
308
+ console.warn('🅰️ Assert: '+path, message, pattern, data)
309
+ }
@@ -1,2 +0,0 @@
1
- (()=>{var b=Object.defineProperty;var x=(e,o)=>{for(var n in o)b(e,n,{get:o[n],enumerable:!0})};var c={};x(c,{Optional:()=>O,Recommended:()=>v,Required:()=>g,allOf:()=>a,anyOf:()=>R,assert:()=>A,disable:()=>h,enable:()=>d,error:()=>s,fails:()=>l,instanceOf:()=>w,not:()=>_,oneOf:()=>y,validEmail:()=>E,validURL:()=>p,warn:()=>m});globalThis.assertEnabled=!1;function d(){globalThis.assertEnabled=!0}function h(){globalThis.assertEnabled=!1}function A(e,o){if(globalThis.assertEnabled){let n=l(e,o);if(n)throw console.error("\u{1F170}\uFE0F Assertions failed because of:",n,"in this source:",e),new Error("Assertions failed",{cause:{problems:n,source:e}})}}function O(e){return function(n,r,i){if(typeof n<"u"&&n!=null&&typeof e<"u")return l(n,e,r,i)}}function g(e){return function(n,r,i){return n==null||typeof n>"u"?s("data is required",n,e||"any value",i):typeof e<"u"?l(n,e,r,i):!1}}function v(e){return function(n,r,i){return n==null||typeof n>"u"?(m("data does not contain recommended value",n,e,i),!1):l(n,e,r,i)}}function y(...e){return function(n,r,i){for(let f of e)if(!l(n,f,r,i))return!1;return s("data does not match oneOf patterns",n,e,i)}}function R(...e){return function(n,r,i){if(!Array.isArray(n))return s("data is not an array",n,"anyOf",i);for(let f of n)if(y(...e)(f))return s("data does not match anyOf patterns",f,e,i);return!1}}function a(...e){return function(n,r,i){let f=[];for(let t of e)f=f.concat(l(n,t,r,i));if(f=f.filter(Boolean),f.length)return s("data does not match all given patterns",n,e,i,f)}}function p(e,o,n){try{e instanceof URL&&(e=e.href);let r=new URL(e);if(r.href!=e&&!(r.href+"/"==e||r.href==e+"/"))return s("data is not a valid url",e,"validURL",n)}catch{return s("data is not a valid url",e,"validURL",n)}}function E(e,o,n){if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))return s("data is not a valid email",e,"validEmail",n)}function w(e){return function(n,r,i){if(!(n instanceof e))return s("data is not an instanceof pattern",n,e,i)}}function _(e){return function(n,r,i){if(!l(n,e,r,i))return s("data matches pattern, when required not to",n,e,i)}}function l(e,o,n,r=""){n||(n=e);let i=[];if(o===Boolean)typeof e!="boolean"&&!(e instanceof Boolean)&&i.push(s("data is not a boolean",e,o,r));else if(o===Number)typeof e!="number"&&!(e instanceof Number)&&i.push(s("data is not a number",e,o,r));else if(o===String)typeof e!="string"&&!(e instanceof String)&&i.push(s("data is not a string",e,o,r)),e==""&&i.push(s("data is an empty string, which is not allowed",e,o,r));else if(o instanceof RegExp)if(Array.isArray(e)){let f=e.findIndex((t,u)=>l(t,o,n,r+"["+u+"]"));f>-1&&i.push(s("data["+f+"] does not match pattern",e[f],o,r+"["+f+"]"))}else typeof e>"u"?i.push(s("data is undefined, should match pattern",e,o,r)):o.test(e)||i.push(s("data does not match pattern",e,o,r));else if(o instanceof Function){let f=o(e,n,r);f&&(Array.isArray(f)?i=i.concat(f):i.push(f))}else if(Array.isArray(o)){Array.isArray(e)||i.push(s("data is not an array",e,[],r));for(let f of o)for(let t of e.keys()){let u=l(e[t],f,n,r+"["+t+"]");Array.isArray(u)?i=i.concat(u):u&&i.push(u)}}else if(o&&typeof o=="object")if(Array.isArray(e)){let f=e.findIndex((t,u)=>l(t,o,n,r+"["+u+"]"));f>-1&&i.push(s("data["+f+"] does not match pattern",e[f],o,r+"["+f+"]"))}else if(!e||typeof e!="object")i.push(s("data is not an object, pattern is",e,o,r));else if(e instanceof URLSearchParams&&(e=Object.fromEntries(e)),o instanceof Function){let f=l(e,o,n,r);f&&(i=i.concat(f))}else for(let[f,t]of Object.entries(o)){let u=l(e[f],t,n,r+"."+f);u&&(i=i.concat(u))}else o!=e&&i.push(s("data and pattern are not equal",e,o,r));return i.length?i:!1}function s(e,o,n,r,i){let f={path:r,message:e,found:o,expected:n};return i&&(f.problems=i),f}function m(e,o,n,r){console.warn("\u{1F170}\uFE0F Assert: "+r,e,n,o)}globalThis.assert=c;})();
2
- //# sourceMappingURL=browser.min.js.map
package/src/browser.mjs DELETED
@@ -1,3 +0,0 @@
1
- import * as assert from './assert.mjs'
2
-
3
- globalThis.assert = assert