tiny-essentials 1.0.0 โ†’ 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,18 +11,18 @@
11
11
  </p>
12
12
  </div>
13
13
 
14
- # Tiny Essentials
14
+ # ๐Ÿงฉ Tiny Essentials
15
15
 
16
16
  **Tiny Essentials** is a collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility. From date calculations to formatting, object manipulations, and array operations, these scripts serve as building blocks for more complex applications.
17
17
 
18
- ## Features
18
+ ## โœจ Features
19
19
 
20
- - **Array Manipulations**: Functions like `shuffleArray` to randomize elements in place.
21
- - **Time Calculations**: Easily calculate durations, format timers, and more.
22
- - **Object Utilities**: Perform type checks, count object properties, and calculate percentages.
23
- - **Custom Utilities**: Includes various helper functions like `ruleOfThree` for proportion calculations and `getAge` to calculate the age based on a given birth date.
20
+ - ๐Ÿ”€ **Array Manipulations**: Functions like `shuffleArray` to randomize elements in place.
21
+ - โฑ๏ธ **Time Calculations**: Easily calculate durations, format timers, and more.
22
+ - ๐Ÿง  **Object Utilities**: Perform type checks, count object properties, and calculate percentages.
23
+ - ๐Ÿ› ๏ธ **Custom Utilities**: Includes various helper functions like `ruleOfThree` for proportion calculations and `getAge` to calculate the age based on a given birth date.
24
24
 
25
- ## Installation
25
+ ## ๐Ÿ“ฆ Installation
26
26
 
27
27
  You can install Tiny Essentials via npm:
28
28
 
@@ -32,7 +32,7 @@ npm install tiny-essentials
32
32
 
33
33
  Or download the scripts directly from this repository.
34
34
 
35
- ## Legacy Code
35
+ ## ๐Ÿ—ƒ๏ธ Legacy Code
36
36
 
37
37
  Some scripts in this repository have been preserved for backwards compatibility. These include modules like:
38
38
 
@@ -43,25 +43,33 @@ Some scripts in this repository have been preserved for backwards compatibility.
43
43
 
44
44
  These modules have been updated to work with modern environments but may not be actively developed further.
45
45
 
46
- ## Module Versions
46
+ ## ๐Ÿงช Module Versions
47
+
47
48
  The core version of Tiny Essentials (version 1) is located in the folder [`/src/v1`](./src/v1).
48
49
 
49
50
  A detailed README is available inside the [`v1`](./src/v1) folder, which contains a full description of all utility modules and their functionalities.
50
51
  We recommend checking it out if you want to see all available tools in this version and how to use them individually or collectively via the `index.mjs` global module.
51
52
 
52
- ## Contributions
53
+ ## ๐Ÿ“š Documentation
54
+
55
+ Looking for detailed module explanations and usage examples?
56
+ Check out the full documentation here:
57
+
58
+ ๐Ÿ‘‰ [Go to docs page](./docs/README.md)
59
+
60
+ ## ๐Ÿค Contributions
53
61
 
54
62
  Feel free to fork, contribute, and create pull requests for improvements! Whether it's a bug fix or an additional feature, contributions are always welcome.
55
63
 
56
- ## License
64
+ ## ๐Ÿ“ License
57
65
 
58
66
  This project is licensed under the GPL-3.0 License - see the [LICENSE](LICENSE) file for details.
59
67
 
60
68
  ---
61
69
 
62
- ### Credits
70
+ ### ๐Ÿ’ก Credits
63
71
 
64
72
  This project was inspired by the need for lightweight, reusable code that can be used across many different kinds of applications. Contributions and suggestions are always appreciated!
65
73
 
66
- > **Note**: This documentation was written by [ChatGPT](https://openai.com/chatgpt), an AI assistant developed by OpenAI, based on the project structure and descriptions provided by the repository author.
74
+ > ๐Ÿง  **Note**: This documentation was written by [ChatGPT](https://openai.com/chatgpt), an AI assistant developed by OpenAI, based on the project structure and descriptions provided by the repository author.
67
75
  > If you find any inaccuracies or need improvements, feel free to contribute or open an issue!
@@ -1 +1 @@
1
- var TinyEssentials=function(e){"use strict";function t(e,t="seconds",r="{time}"){e=Math.max(0,Math.floor(e));const a=["seconds","minutes","hours","days","months","years"].indexOf(t),s=a>=5,n=a>=4,o=a>=3,l=a>=2,i=a>=1,u=a>=0,c={years:s?0:NaN,months:n?0:NaN,days:o?0:NaN,hours:l?0:NaN,minutes:i?0:NaN,seconds:u?0:NaN,total:NaN};let h=e;if(s||n||o){const e=new Date(1980,0,1),t=new Date(e.getTime()+1e3*h),r=new Date(e);if(s)for(;new Date(r.getFullYear()+1,r.getMonth(),r.getDate())<=t;)r.setFullYear(r.getFullYear()+1),c.years++;if(n)for(;new Date(r.getFullYear(),r.getMonth()+1,r.getDate())<=t;)r.setMonth(r.getMonth()+1),c.months++;if(o)for(;new Date(r.getFullYear(),r.getMonth(),r.getDate()+1)<=t;)r.setDate(r.getDate()+1),c.days++;h=Math.floor((t-r)/1e3)}l&&(c.hours=Math.floor(h/3600),h%=3600),i&&(c.minutes=Math.floor(h/60),h%=60),u&&(c.seconds=h);const p={seconds:u?e:NaN,minutes:i?e/60:NaN,hours:l?e/3600:NaN,days:o?e/86400:NaN,months:n?12*c.years+c.months+(c.days||0)/30:NaN,years:s?c.years+(c.months||0)/12+(c.days||0)/365:NaN};c.total=+(p[t]||0).toFixed(2).replace(/\.00$/,"");const g=e=>isNaN(e)?"NaN":String(e).padStart(2,"0"),f=[l?g(c.hours):null,i?g(c.minutes):null,u?g(c.seconds):null].filter((e=>null!==e)).join(":");return r.replace(/\{years\}/g,c.years).replace(/\{months\}/g,c.months).replace(/\{days\}/g,c.days).replace(/\{hours\}/g,g(c.hours)).replace(/\{minutes\}/g,g(c.minutes)).replace(/\{seconds\}/g,g(c.seconds)).replace(/\{time\}/g,f).replace(/\{total\}/g,c.total).trim()}function r(e,t){if(void 0!==e){const r=Object.prototype.toString.call(e).toLowerCase();return"string"==typeof t?r===`[object ${t}]`:r.substring(8,r.length-1)}return null}return e.TinyLevelUp=class{constructor(e,t){this.giveExp=e,this.expLevel=t}expValidator(e){let t=0;const r=this.expLevel*e.level;return e.exp>=r&&(e.level++,t=e.exp-r,e.exp=0,t>0)?this.give(e,t,"extra"):e.exp<1&&e.level>1&&(e.level--,t=Math.abs(e.exp),e.exp=this.expLevel*e.level,t>0)?this.remove(e,t,"extra"):e}getTotalExp(e){let t=0;for(let r=1;r<=e.level;r++)t+=this.expLevel*r;return t+=e.exp,t}expGenerator(e=1){return Math.floor(Math.random()*this.giveExp)+1*e}progress(e){return this.expLevel*e.level}getProgress(e){return this.expLevel*e.level}set(e,t){return e.exp=t,this.expValidator(e),e.totalExp=this.getTotalExp(e),e}give(e,t=0,r="add",a=1){return"add"===r?e.exp+=this.expGenerator(a)+t:"extra"===r&&(e.exp+=t),this.expValidator(e),e.totalExp=this.getTotalExp(e),e}remove(e,t=0,r="add",a=1){return"add"===r?e.exp-=this.expGenerator(a)+t:"extra"===r&&(e.exp-=t),this.expValidator(e),e.totalExp=this.getTotalExp(e),e}},e.asyncReplace=async function(e,t,r){const a=[];e.replace(t,((e,...t)=>(a.push(r(e,...t)),e)));const s=await Promise.all(a);return e.replace(t,(()=>s.shift()))},e.countObj=function(e){return Array.isArray(e)?e.length:r(e,"object")?Object.keys(e).length:0},e.formatCustomTimer=t,e.formatDayTimer=function(e){return t(e,"days","{days}d {hours}:{minutes}:{seconds}")},e.formatTimer=function(e){return t(e,"hours","{hours}:{minutes}:{seconds}")},e.getAge=function(e=0,t=null){if(null!=e&&0!==e){const r=new Date(e);if(isNaN(r))return null;const a=t instanceof Date?t:new Date;let s=a.getFullYear()-r.getFullYear();const n=a.getMonth(),o=r.getMonth(),l=a.getDate(),i=r.getDate();return(n<o||n===o&&l<i)&&s--,Math.abs(s)}return null},e.getSimplePerc=function(e,t){return e*(t/100)},e.getTimeDuration=function(e=new Date,t="asSeconds",r=null){if(e instanceof Date){const a=e-(r instanceof Date?r:new Date);switch(t){case"asMilliseconds":return a;case"asSeconds":default:return a/1e3;case"asMinutes":return a/6e4;case"asHours":return a/36e5;case"asDays":return a/864e5}}return null},e.objType=r,e.ruleOfThree=function(e,t,r,a){return a?Number(e*t)/r:Number(r*t)/e},e.shuffleArray=function(e){let t,r=e.length;for(;0!==r;)t=Math.floor(Math.random()*r),r--,[e[r],e[t]]=[e[t],e[r]];return e},e.toTitleCase=function(e){return e.replace(/\w\S*/g,(e=>e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()))},e.toTitleCaseLowerFirst=function(e){const t=e.replace(/\w\S*/g,(e=>e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()));return t.charAt(0).toLowerCase()+t.slice(1)},e}({});
1
+ var TinyEssentials=function(e){"use strict";function t(e,t="seconds",n="{time}"){e=Math.max(0,Math.floor(e));const r=["seconds","minutes","hours","days","months","years"].indexOf(t),o=r>=5,i=r>=4,a=r>=3,s=r>=2,u=r>=1,l=r>=0,c={years:o?0:NaN,months:i?0:NaN,days:a?0:NaN,hours:s?0:NaN,minutes:u?0:NaN,seconds:l?0:NaN,total:NaN};let p=e;if(o||i||a){const e=new Date(1980,0,1),t=new Date(e.getTime()+1e3*p),n=new Date(e);if(o)for(;new Date(n.getFullYear()+1,n.getMonth(),n.getDate())<=t;)n.setFullYear(n.getFullYear()+1),c.years++;if(i)for(;new Date(n.getFullYear(),n.getMonth()+1,n.getDate())<=t;)n.setMonth(n.getMonth()+1),c.months++;if(a)for(;new Date(n.getFullYear(),n.getMonth(),n.getDate()+1)<=t;)n.setDate(n.getDate()+1),c.days++;p=Math.floor((t-n)/1e3)}s&&(c.hours=Math.floor(p/3600),p%=3600),u&&(c.minutes=Math.floor(p/60),p%=60),l&&(c.seconds=p);const g={seconds:l?e:NaN,minutes:u?e/60:NaN,hours:s?e/3600:NaN,days:a?e/86400:NaN,months:i?12*c.years+c.months+(c.days||0)/30:NaN,years:o?c.years+(c.months||0)/12+(c.days||0)/365:NaN};c.total=+(g[t]||0).toFixed(2).replace(/\.00$/,"");const f=e=>isNaN(e)?"NaN":String(e).padStart(2,"0"),h=[s?f(c.hours):null,u?f(c.minutes):null,l?f(c.seconds):null].filter((e=>null!==e)).join(":");return n.replace(/\{years\}/g,c.years).replace(/\{months\}/g,c.months).replace(/\{days\}/g,c.days).replace(/\{hours\}/g,f(c.hours)).replace(/\{minutes\}/g,f(c.minutes)).replace(/\{seconds\}/g,f(c.seconds)).replace(/\{time\}/g,h).replace(/\{total\}/g,c.total).trim()}const n={items:{undefined:e=>void 0===e,null:e=>null===e,boolean:e=>"boolean"==typeof e,number:e=>"number"==typeof e&&!isNaN(e),bigint:e=>"bigint"==typeof e,string:e=>"string"==typeof e,symbol:e=>"symbol"==typeof e,function:e=>"function"==typeof e,array:e=>Array.isArray(e),date:e=>e instanceof Date,regexp:e=>e instanceof RegExp,map:e=>e instanceof Map,set:e=>e instanceof Set,weakmap:e=>e instanceof WeakMap,weakset:e=>e instanceof WeakSet,promise:e=>e instanceof Promise,buffer:e=>"undefined"!=typeof Buffer&&Buffer.isBuffer(e),htmlElement:e=>"undefined"!=typeof HTMLElement&&e instanceof HTMLElement,object:e=>"object"==typeof e&&null!==e},order:["undefined","null","boolean","number","bigint","string","symbol","function","array","buffer","date","regexp","map","set","weakmap","weakset","promise","htmlElement","object"]};function r(e,t){if(void 0===e)return null;const r=(e=>{if(null===e)return"null";for(const t of n.order)if(!n.items[t]||n.items[t](e))return t;return"unknown"})(e);return"string"==typeof t?r===t.toLowerCase():r}var o={},i={};const a="undefined"!=typeof window&&void 0!==window.document;return e.TinyCrypto=class{constructor(e={}){this.algorithm=e.algorithm||"aes-256-gcm",this.outputEncoding=e.outputEncoding||"hex",this.inputEncoding=e.inputEncoding||"utf8",this.authTagLength=e.authTagLength||16,this.key=e.key||this.generateKey()}generateKey(e=32){return o.randomBytes(e)}generateIV(e=12){return o.randomBytes(e)}encrypt(e,t=this.generateIV()){const n=this.#e(e),r=o.createCipheriv(this.algorithm,this.key,t,{authTagLength:this.authTagLength});let i=r.update(n,this.inputEncoding);i=Buffer.concat([i,r.final()]);const a=r.getAuthTag();return{iv:t.toString(this.outputEncoding),encrypted:i.toString(this.outputEncoding),authTag:a.toString(this.outputEncoding)}}decrypt({iv:e,encrypted:t,authTag:n},r=null){const i=Buffer.from(e,this.outputEncoding),a=Buffer.from(t,this.outputEncoding),s=Buffer.from(n,this.outputEncoding),u=o.createDecipheriv(this.algorithm,this.key,i,{authTagLength:this.authTagLength});u.setAuthTag(s);let l=u.update(a,null,this.inputEncoding);l+=u.final(this.inputEncoding);const{value:c,type:p}=this.#t(l);return r&&this.#n(r,p),c}getTypeFromEncrypted({iv:e,encrypted:t,authTag:n}){const r=Buffer.from(e,this.outputEncoding),i=Buffer.from(t,this.outputEncoding),a=Buffer.from(n,this.outputEncoding),s=o.createDecipheriv(this.algorithm,this.key,r,{authTagLength:this.authTagLength});s.setAuthTag(a);let u=s.update(i,null,this.inputEncoding);u+=s.final(this.inputEncoding);const{type:l}=this.#t(u);return"string"==typeof l?l.toLowerCase():"unknown"}saveKeyToFile(e="secret.key"){const t=this.key.toString("hex");if(a){const n=new Blob([t],{type:"text/plain"}),r=URL.createObjectURL(n),o=document.createElement("a");o.href=r,o.download=e,o.click(),URL.revokeObjectURL(r)}else i.writeFileSync(e,t)}saveConfigToFile(e="crypto-config.json"){const t=JSON.stringify(this.exportConfig(),null,2);if(a){const n=new Blob([t],{type:"application/json"}),r=URL.createObjectURL(n),o=document.createElement("a");o.href=r,o.download=e,o.click(),URL.revokeObjectURL(r)}else i.writeFileSync(e,t)}async loadConfigFromFile(e){if(a)return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{try{const e=JSON.parse(r.result);t(this.importConfig(e))}catch(e){n(new Error("Invalid config JSON file"))}},r.onerror=()=>n(r.error),r.readAsText(e)}));{const t=i.readFileSync(e,"utf8"),n=JSON.parse(t);return this.importConfig(n)}}async loadKeyFromFile(e){if(a)return new Promise(((t,n)=>{const r=new FileReader;r.onload=()=>{const e=r.result.trim(),n=Buffer.from(e,"hex");this.key=n,t(n)},r.onerror=()=>n(r.error),r.readAsText(e)}));{const t=i.readFileSync(e,"utf8"),n=Buffer.from(t,"hex");return this.key=n,n}}exportConfig(){return{algorithm:this.algorithm,outputEncoding:this.outputEncoding,inputEncoding:this.inputEncoding,key:this.key.toString("hex"),authTagLength:this.authTagLength}}importConfig(e){if("string"==typeof e.algorithm)this.algorithm=e.algorithm;else if(void 0!==e.algorithm)throw new Error('Invalid or missing "algorithm" property. Expected a string.');if("string"==typeof e.outputEncoding)this.outputEncoding=e.outputEncoding;else if(void 0!==e.outputEncoding)throw new Error('Invalid or missing "outputEncoding" property. Expected a string.');if("string"==typeof e.inputEncoding)this.inputEncoding=e.inputEncoding;else if(void 0!==e.inputEncoding)throw new Error('Invalid or missing "inputEncoding" property. Expected a string.');if("number"==typeof e.authTagLength)this.authTagLength=e.authTagLength;else if(void 0!==e.authTagLength)throw new Error('Invalid or missing "authTagLength" property. Expected a number.');if("string"==typeof e.key)this.key=Buffer.from(e.key,"hex");else if(void 0!==e.key)throw new Error('Invalid or missing "key" property. Expected a hexadecimal string.')}#r={weakmap:()=>{throw new Error("WeakMap cannot be serialized")},weakset:()=>{throw new Error("WeakSet cannot be serialized")},promise:()=>{throw new Error("Promise cannot be serialized")},function:()=>{throw new Error("Function cannot be serialized")},regexp:e=>JSON.stringify({__type:"RegExp",value:e.toString()}),htmlElement:e=>JSON.stringify({__type:"HTMLElement",value:e.outerHTML}),date:e=>JSON.stringify({__type:"Date",value:e.toISOString()}),bigint:e=>JSON.stringify({__type:"BigInt",value:e.toString()}),number:e=>JSON.stringify({__type:"Number",value:e}),boolean:e=>JSON.stringify({__type:"Boolean",value:e}),string:e=>JSON.stringify({__type:"String",value:e}),null:e=>JSON.stringify({__type:"Null"}),undefined:e=>JSON.stringify({__type:"Undefined"}),map:e=>JSON.stringify({__type:"Map",value:Array.from(e.entries())}),set:e=>JSON.stringify({__type:"Set",value:Array.from(e.values())}),symbol:e=>JSON.stringify({__type:"Symbol",value:e.description}),array:e=>JSON.stringify({__type:"Array",value:e}),object:e=>JSON.stringify({__type:"JSON",value:e}),buffer:e=>JSON.stringify({__type:"Buffer",value:e.toString("base64")})};#o={RegExp:e=>{const t=e.match(/^\/(.*)\/([gimsuy]*)$/);return t?new RegExp(t[1],t[2]):new RegExp(e)},HTMLElement:e=>{if("undefined"==typeof document)throw new Error("HTMLElement deserialization is only supported in browsers");const t=document.createElement("div");return t.innerHTML=e,t.firstElementChild},Date:e=>new Date(e),BigInt:e=>BigInt(e),Number:e=>Number(e),Boolean:e=>Boolean(e),Null:e=>null,Undefined:e=>{},Map:e=>new Map(e),Set:e=>new Set(e),Symbol:e=>Symbol(e),Array:e=>e,JSON:e=>e,String:e=>String(e),Buffer:e=>Buffer.from(e,"base64")};#e(e){const t=r(e)||"undefined";if(this.#r[t])return this.#r[t](e);throw new Error(`Unsupported data type for encryption: ${t}`)}#t(e){try{const t=JSON.parse(e),n=t.__type;return"string"!=typeof n?{value:e,type:"String"}:"function"==typeof this.#o[n]?{value:this.#o[n](t.value),type:n}:{value:e,type:"Unknown"}}catch{return{value:e,type:"Unknown"}}}#n(e,t){if(e.toLowerCase()!==t.toLowerCase())throw new Error(`Type mismatch: expected ${e.toLowerCase()}, but got ${t.toLowerCase()}`)}},e.TinyLevelUp=class{constructor(e,t){this.giveExp=e,this.expLevel=t}expValidator(e){let t=0;const n=this.expLevel*e.level;return e.exp>=n&&(e.level++,t=e.exp-n,e.exp=0,t>0)?this.give(e,t,"extra"):e.exp<1&&e.level>1&&(e.level--,t=Math.abs(e.exp),e.exp=this.expLevel*e.level,t>0)?this.remove(e,t,"extra"):e}getTotalExp(e){let t=0;for(let n=1;n<=e.level;n++)t+=this.expLevel*n;return t+=e.exp,t}expGenerator(e=1){return Math.floor(Math.random()*this.giveExp)+1*e}progress(e){return this.expLevel*e.level}getProgress(e){return this.expLevel*e.level}set(e,t){return e.exp=t,this.expValidator(e),e.totalExp=this.getTotalExp(e),e}give(e,t=0,n="add",r=1){return"add"===n?e.exp+=this.expGenerator(r)+t:"extra"===n&&(e.exp+=t),this.expValidator(e),e.totalExp=this.getTotalExp(e),e}remove(e,t=0,n="add",r=1){return"add"===n?e.exp-=this.expGenerator(r)+t:"extra"===n&&(e.exp-=t),this.expValidator(e),e.totalExp=this.getTotalExp(e),e}},e.asyncReplace=async function(e,t,n){const r=[];e.replace(t,((e,...t)=>(r.push(n(e,...t)),e)));const o=await Promise.all(r);return e.replace(t,(()=>o.shift()))},e.cloneObjTypeOrder=function(){return[...n.order]},e.countObj=function(e){return Array.isArray(e)?e.length:r(e,"object")?Object.keys(e).length:0},e.extendObjType=function(e,t){const r=[];for(const[o,i]of Object.entries(e))if(!n.items.hasOwnProperty(o)){n.items[o]=i;let e="number"==typeof t?t:-1;if(-1===e){const t=n.order.indexOf("object");e=t>-1?t:n.order.length}e=Math.min(Math.max(0,e),n.order.length),n.order.splice(e,0,o),r.push(o)}return r},e.formatCustomTimer=t,e.formatDayTimer=function(e){return t(e,"days","{days}d {hours}:{minutes}:{seconds}")},e.formatTimer=function(e){return t(e,"hours","{hours}:{minutes}:{seconds}")},e.getAge=function(e=0,t=null){if(null!=e&&0!==e){const n=new Date(e);if(isNaN(n))return null;const r=t instanceof Date?t:new Date;let o=r.getFullYear()-n.getFullYear();const i=r.getMonth(),a=n.getMonth(),s=r.getDate(),u=n.getDate();return(i<a||i===a&&s<u)&&o--,Math.abs(o)}return null},e.getSimplePerc=function(e,t){return e*(t/100)},e.getTimeDuration=function(e=new Date,t="asSeconds",n=null){if(e instanceof Date){const r=e-(n instanceof Date?n:new Date);switch(t){case"asMilliseconds":return r;case"asSeconds":default:return r/1e3;case"asMinutes":return r/6e4;case"asHours":return r/36e5;case"asDays":return r/864e5}}return null},e.objType=r,e.reorderObjTypeOrder=function(e){const t=[...n.order];return!!e.every((e=>t.includes(e)))&&(n.order=e.slice(),!0)},e.ruleOfThree=function(e,t,n,r){return r?Number(e*t)/n:Number(n*t)/e},e.shuffleArray=function(e){let t,n=e.length;for(;0!==n;)t=Math.floor(Math.random()*n),n--,[e[n],e[t]]=[e[t],e[n]];return e},e.toTitleCase=function(e){return e.replace(/\w\S*/g,(e=>e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()))},e.toTitleCaseLowerFirst=function(e){const t=e.replace(/\w\S*/g,(e=>e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()));return t.charAt(0).toLowerCase()+t.slice(1)},e}({});
@@ -1,5 +1,210 @@
1
1
  'use strict';
2
2
 
3
+ /**
4
+ * An object containing type validation functions and their evaluation order.
5
+ *
6
+ * Each item in `typeValidator.items` is a function that receives any value
7
+ * and returns a boolean indicating whether the value matches the corresponding type.
8
+ *
9
+ * The `order` array defines the priority in which types should be checked,
10
+ * which can be useful for functions that infer types in a consistent manner.
11
+ *
12
+ * @typedef {Object} TypeValidator
13
+ * @property {Object.<string, (val: any) => boolean>} items - A dictionary of type validation functions.
14
+ * @property {string[]} order - The order in which types should be evaluated.
15
+ */
16
+
17
+ /**
18
+ * Validates values against specific types using predefined functions.
19
+ *
20
+ * @type {TypeValidator}
21
+ */
22
+ const typeValidator = {
23
+ items: {
24
+ /** Checks if the value is undefined. */
25
+ undefined: (val) => typeof val === 'undefined',
26
+
27
+ /** Checks if the value is null. */
28
+ null: (val) => val === null,
29
+
30
+ /** Checks if the value is a boolean. */
31
+ boolean: (val) => typeof val === 'boolean',
32
+
33
+ /** Checks if the value is a number. */
34
+ number: (val) => typeof val === 'number' && !isNaN(val),
35
+
36
+ /** Checks if the value is a bigint. */
37
+ bigint: (val) => typeof val === 'bigint',
38
+
39
+ /** Checks if the value is a string. */
40
+ string: (val) => typeof val === 'string',
41
+
42
+ /** Checks if the value is a symbol. */
43
+ symbol: (val) => typeof val === 'symbol',
44
+
45
+ /** Checks if the value is a function. */
46
+ function: (val) => typeof val === 'function',
47
+
48
+ /** Checks if the value is an array. */
49
+ array: (val) => Array.isArray(val),
50
+
51
+ /** Checks if the value is a Date object. */
52
+ date: (val) => val instanceof Date,
53
+
54
+ /** Checks if the value is a regular expression. */
55
+ regexp: (val) => val instanceof RegExp,
56
+
57
+ /** Checks if the value is a Map. */
58
+ map: (val) => val instanceof Map,
59
+
60
+ /** Checks if the value is a Set. */
61
+ set: (val) => val instanceof Set,
62
+
63
+ /** Checks if the value is a WeakMap. */
64
+ weakmap: (val) => val instanceof WeakMap,
65
+
66
+ /** Checks if the value is a WeakSet. */
67
+ weakset: (val) => val instanceof WeakSet,
68
+
69
+ /** Checks if the value is a Promise. */
70
+ promise: (val) => val instanceof Promise,
71
+
72
+ /** Checks if the value is a Buffer. */
73
+ buffer: (val) => typeof Buffer !== 'undefined' && Buffer.isBuffer(val),
74
+
75
+ /** Checks if the value is a Html Element. */
76
+ htmlElement: (val) => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement,
77
+
78
+ /** Checks if the value is a non-null plain object or instance of a class. */
79
+ object: (val) => typeof val === 'object' && val !== null,
80
+ },
81
+
82
+ /** Evaluation order of the type checkers. */
83
+ order: [
84
+ 'undefined',
85
+ 'null',
86
+ 'boolean',
87
+ 'number',
88
+ 'bigint',
89
+ 'string',
90
+ 'symbol',
91
+ 'function',
92
+ 'array',
93
+ 'buffer',
94
+ 'date',
95
+ 'regexp',
96
+ 'map',
97
+ 'set',
98
+ 'weakmap',
99
+ 'weakset',
100
+ 'promise',
101
+ 'htmlElement',
102
+ 'object',
103
+ ],
104
+ };
105
+
106
+ /**
107
+ * Adds new type checkers to the typeValidator without overwriting existing ones.
108
+ *
109
+ * Optionally, you can specify the index at which the new type should be inserted in the order.
110
+ * If no index is provided, the type is inserted just before 'object' (if it exists), or at the end.
111
+ *
112
+ * @param {Object.<string, (val: any) => boolean>} newItems - New type validators to be added.
113
+ * @param {number} [index] - Optional. Position at which to insert each new type. Ignored if the type already exists.
114
+ * @returns {string[]} - A list of successfully added type names.
115
+ *
116
+ * @example
117
+ * extendObjType({
118
+ * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
119
+ * });
120
+ */
121
+ function extendObjType(newItems, index) {
122
+ const added = [];
123
+
124
+ for (const [key, fn] of Object.entries(newItems)) {
125
+ if (!typeValidator.items.hasOwnProperty(key)) {
126
+ typeValidator.items[key] = fn;
127
+
128
+ let insertAt = typeof index === 'number' ? index : -1; // Default to -1 if index isn't provided
129
+
130
+ // Default to before 'object', or to the end
131
+ if (insertAt === -1) {
132
+ const objectIndex = typeValidator.order.indexOf('object');
133
+ insertAt = objectIndex > -1 ? objectIndex : typeValidator.order.length;
134
+ }
135
+
136
+ // Ensure insertAt is a valid number and not out of bounds
137
+ insertAt = Math.min(Math.max(0, insertAt), typeValidator.order.length);
138
+
139
+ typeValidator.order.splice(insertAt, 0, key);
140
+ added.push(key);
141
+ }
142
+ }
143
+
144
+ return added;
145
+ }
146
+
147
+ /**
148
+ * Reorders the typeValidator.order array according to a custom new order.
149
+ * All values in the new order must already exist in the current order.
150
+ * The function does not mutate the original array structure directly.
151
+ *
152
+ * @param {string[]} newOrder - The new order of type names.
153
+ * @returns {boolean} - Returns true if the reorder was successful, false if invalid keys were found.
154
+ *
155
+ * @example
156
+ * reorderObjTypeOrder([
157
+ * 'string', 'number', 'array', 'object'
158
+ * ]);
159
+ */
160
+ function reorderObjTypeOrder(newOrder) {
161
+ const currentOrder = [...typeValidator.order]; // shallow clone
162
+
163
+ // All keys in newOrder must exist in currentOrder
164
+ const isValid = newOrder.every((type) => currentOrder.includes(type));
165
+
166
+ if (!isValid) return false;
167
+
168
+ // Reassign only if valid
169
+ typeValidator.order = newOrder.slice(); // assign shallow copy
170
+ return true;
171
+ }
172
+
173
+ /**
174
+ * Returns a cloned version of the `typeValidator.order` array.
175
+ * The cloned array will not be affected by future changes to the original `order`.
176
+ *
177
+ * @returns {string[]} - A new array with the same values as `typeValidator.order`.
178
+ */
179
+ function cloneObjTypeOrder() {
180
+ return [...typeValidator.order]; // Creates a shallow copy of the array
181
+ }
182
+
183
+ /**
184
+ * Returns the detected type name of a given value based on predefined type validators.
185
+ *
186
+ * This function uses `getType` with a predefined `typeValidator` to determine or compare types safely.
187
+ * in the specified `typeValidator.order`. The first matching type is returned.
188
+ *
189
+ * If `val` is `null`, it immediately returns `'null'`.
190
+ * If no match is found, it returns `'unknown'`.
191
+ *
192
+ * @param {any} val - The value whose type should be determined.
193
+ * @returns {string} - The type name of the value (e.g., "array", "date", "map"), or "unknown" if no match is found.
194
+ *
195
+ * @example
196
+ * getType([]); // "array"
197
+ * getType(null); // "null"
198
+ * getType(new Set()); // "set"
199
+ * getType(() => {}); // "unknown"
200
+ */
201
+ const getType = (val) => {
202
+ if (val === null) return 'null';
203
+ for (const name of typeValidator.order)
204
+ if (!typeValidator.items[name] || typeValidator.items[name](val)) return name;
205
+ return 'unknown';
206
+ };
207
+
3
208
  /**
4
209
  * Checks the type of a given object or returns its type as a string.
5
210
  *
@@ -15,20 +220,10 @@
15
220
  * objType(undefined); // null
16
221
  */
17
222
  function objType(obj, type) {
18
- // Is Defined
19
- if (typeof obj !== 'undefined') {
20
- // Get Obj Type
21
- const result = Object.prototype.toString.call(obj).toLowerCase();
22
- // Check Obj Type
23
- if (typeof type === 'string') {
24
- if (result === `[object ${type}]`) return true;
25
- return false;
26
- }
27
- // Send Result
28
- return result.substring(8, result.length - 1);
29
- }
30
- // Nope
31
- return null;
223
+ if (typeof obj === 'undefined') return null;
224
+ const result = getType(obj);
225
+ if (typeof type === 'string') return result === type.toLowerCase();
226
+ return result;
32
227
  }
33
228
 
34
229
  /**
@@ -51,5 +246,8 @@ function countObj(obj) {
51
246
  return 0;
52
247
  }
53
248
 
249
+ exports.cloneObjTypeOrder = cloneObjTypeOrder;
54
250
  exports.countObj = countObj;
251
+ exports.extendObjType = extendObjType;
55
252
  exports.objType = objType;
253
+ exports.reorderObjTypeOrder = reorderObjTypeOrder;
@@ -1,3 +1,42 @@
1
+ /**
2
+ * Adds new type checkers to the typeValidator without overwriting existing ones.
3
+ *
4
+ * Optionally, you can specify the index at which the new type should be inserted in the order.
5
+ * If no index is provided, the type is inserted just before 'object' (if it exists), or at the end.
6
+ *
7
+ * @param {Object.<string, (val: any) => boolean>} newItems - New type validators to be added.
8
+ * @param {number} [index] - Optional. Position at which to insert each new type. Ignored if the type already exists.
9
+ * @returns {string[]} - A list of successfully added type names.
10
+ *
11
+ * @example
12
+ * extendObjType({
13
+ * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
14
+ * });
15
+ */
16
+ export function extendObjType(newItems: {
17
+ [x: string]: (val: any) => boolean;
18
+ }, index?: number): string[];
19
+ /**
20
+ * Reorders the typeValidator.order array according to a custom new order.
21
+ * All values in the new order must already exist in the current order.
22
+ * The function does not mutate the original array structure directly.
23
+ *
24
+ * @param {string[]} newOrder - The new order of type names.
25
+ * @returns {boolean} - Returns true if the reorder was successful, false if invalid keys were found.
26
+ *
27
+ * @example
28
+ * reorderObjTypeOrder([
29
+ * 'string', 'number', 'array', 'object'
30
+ * ]);
31
+ */
32
+ export function reorderObjTypeOrder(newOrder: string[]): boolean;
33
+ /**
34
+ * Returns a cloned version of the `typeValidator.order` array.
35
+ * The cloned array will not be affected by future changes to the original `order`.
36
+ *
37
+ * @returns {string[]} - A new array with the same values as `typeValidator.order`.
38
+ */
39
+ export function cloneObjTypeOrder(): string[];
1
40
  /**
2
41
  * Checks the type of a given object or returns its type as a string.
3
42
  *
@@ -25,3 +64,24 @@ export function objType(obj: any, type?: string): boolean | string | null;
25
64
  * countObj('not an object'); // 0
26
65
  */
27
66
  export function countObj(obj: any): number;
67
+ /**
68
+ * An object containing type validation functions and their evaluation order.
69
+ *
70
+ * Each item in `typeValidator.items` is a function that receives any value
71
+ * and returns a boolean indicating whether the value matches the corresponding type.
72
+ *
73
+ * The `order` array defines the priority in which types should be checked,
74
+ * which can be useful for functions that infer types in a consistent manner.
75
+ */
76
+ export type TypeValidator = {
77
+ /**
78
+ * - A dictionary of type validation functions.
79
+ */
80
+ items: {
81
+ [x: string]: (val: any) => boolean;
82
+ };
83
+ /**
84
+ * - The order in which types should be evaluated.
85
+ */
86
+ order: string[];
87
+ };
@@ -1,3 +1,177 @@
1
+ /**
2
+ * An object containing type validation functions and their evaluation order.
3
+ *
4
+ * Each item in `typeValidator.items` is a function that receives any value
5
+ * and returns a boolean indicating whether the value matches the corresponding type.
6
+ *
7
+ * The `order` array defines the priority in which types should be checked,
8
+ * which can be useful for functions that infer types in a consistent manner.
9
+ *
10
+ * @typedef {Object} TypeValidator
11
+ * @property {Object.<string, (val: any) => boolean>} items - A dictionary of type validation functions.
12
+ * @property {string[]} order - The order in which types should be evaluated.
13
+ */
14
+ /**
15
+ * Validates values against specific types using predefined functions.
16
+ *
17
+ * @type {TypeValidator}
18
+ */
19
+ const typeValidator = {
20
+ items: {
21
+ /** Checks if the value is undefined. */
22
+ undefined: (val) => typeof val === 'undefined',
23
+ /** Checks if the value is null. */
24
+ null: (val) => val === null,
25
+ /** Checks if the value is a boolean. */
26
+ boolean: (val) => typeof val === 'boolean',
27
+ /** Checks if the value is a number. */
28
+ number: (val) => typeof val === 'number' && !isNaN(val),
29
+ /** Checks if the value is a bigint. */
30
+ bigint: (val) => typeof val === 'bigint',
31
+ /** Checks if the value is a string. */
32
+ string: (val) => typeof val === 'string',
33
+ /** Checks if the value is a symbol. */
34
+ symbol: (val) => typeof val === 'symbol',
35
+ /** Checks if the value is a function. */
36
+ function: (val) => typeof val === 'function',
37
+ /** Checks if the value is an array. */
38
+ array: (val) => Array.isArray(val),
39
+ /** Checks if the value is a Date object. */
40
+ date: (val) => val instanceof Date,
41
+ /** Checks if the value is a regular expression. */
42
+ regexp: (val) => val instanceof RegExp,
43
+ /** Checks if the value is a Map. */
44
+ map: (val) => val instanceof Map,
45
+ /** Checks if the value is a Set. */
46
+ set: (val) => val instanceof Set,
47
+ /** Checks if the value is a WeakMap. */
48
+ weakmap: (val) => val instanceof WeakMap,
49
+ /** Checks if the value is a WeakSet. */
50
+ weakset: (val) => val instanceof WeakSet,
51
+ /** Checks if the value is a Promise. */
52
+ promise: (val) => val instanceof Promise,
53
+ /** Checks if the value is a Buffer. */
54
+ buffer: (val) => typeof Buffer !== 'undefined' && Buffer.isBuffer(val),
55
+ /** Checks if the value is a Html Element. */
56
+ htmlElement: (val) => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement,
57
+ /** Checks if the value is a non-null plain object or instance of a class. */
58
+ object: (val) => typeof val === 'object' && val !== null,
59
+ },
60
+ /** Evaluation order of the type checkers. */
61
+ order: [
62
+ 'undefined',
63
+ 'null',
64
+ 'boolean',
65
+ 'number',
66
+ 'bigint',
67
+ 'string',
68
+ 'symbol',
69
+ 'function',
70
+ 'array',
71
+ 'buffer',
72
+ 'date',
73
+ 'regexp',
74
+ 'map',
75
+ 'set',
76
+ 'weakmap',
77
+ 'weakset',
78
+ 'promise',
79
+ 'htmlElement',
80
+ 'object',
81
+ ],
82
+ };
83
+ /**
84
+ * Adds new type checkers to the typeValidator without overwriting existing ones.
85
+ *
86
+ * Optionally, you can specify the index at which the new type should be inserted in the order.
87
+ * If no index is provided, the type is inserted just before 'object' (if it exists), or at the end.
88
+ *
89
+ * @param {Object.<string, (val: any) => boolean>} newItems - New type validators to be added.
90
+ * @param {number} [index] - Optional. Position at which to insert each new type. Ignored if the type already exists.
91
+ * @returns {string[]} - A list of successfully added type names.
92
+ *
93
+ * @example
94
+ * extendObjType({
95
+ * htmlElement2: val => typeof HTMLElement !== 'undefined' && val instanceof HTMLElement
96
+ * });
97
+ */
98
+ export function extendObjType(newItems, index) {
99
+ const added = [];
100
+ for (const [key, fn] of Object.entries(newItems)) {
101
+ if (!typeValidator.items.hasOwnProperty(key)) {
102
+ typeValidator.items[key] = fn;
103
+ let insertAt = typeof index === 'number' ? index : -1; // Default to -1 if index isn't provided
104
+ // Default to before 'object', or to the end
105
+ if (insertAt === -1) {
106
+ const objectIndex = typeValidator.order.indexOf('object');
107
+ insertAt = objectIndex > -1 ? objectIndex : typeValidator.order.length;
108
+ }
109
+ // Ensure insertAt is a valid number and not out of bounds
110
+ insertAt = Math.min(Math.max(0, insertAt), typeValidator.order.length);
111
+ typeValidator.order.splice(insertAt, 0, key);
112
+ added.push(key);
113
+ }
114
+ }
115
+ return added;
116
+ }
117
+ /**
118
+ * Reorders the typeValidator.order array according to a custom new order.
119
+ * All values in the new order must already exist in the current order.
120
+ * The function does not mutate the original array structure directly.
121
+ *
122
+ * @param {string[]} newOrder - The new order of type names.
123
+ * @returns {boolean} - Returns true if the reorder was successful, false if invalid keys were found.
124
+ *
125
+ * @example
126
+ * reorderObjTypeOrder([
127
+ * 'string', 'number', 'array', 'object'
128
+ * ]);
129
+ */
130
+ export function reorderObjTypeOrder(newOrder) {
131
+ const currentOrder = [...typeValidator.order]; // shallow clone
132
+ // All keys in newOrder must exist in currentOrder
133
+ const isValid = newOrder.every((type) => currentOrder.includes(type));
134
+ if (!isValid)
135
+ return false;
136
+ // Reassign only if valid
137
+ typeValidator.order = newOrder.slice(); // assign shallow copy
138
+ return true;
139
+ }
140
+ /**
141
+ * Returns a cloned version of the `typeValidator.order` array.
142
+ * The cloned array will not be affected by future changes to the original `order`.
143
+ *
144
+ * @returns {string[]} - A new array with the same values as `typeValidator.order`.
145
+ */
146
+ export function cloneObjTypeOrder() {
147
+ return [...typeValidator.order]; // Creates a shallow copy of the array
148
+ }
149
+ /**
150
+ * Returns the detected type name of a given value based on predefined type validators.
151
+ *
152
+ * This function uses `getType` with a predefined `typeValidator` to determine or compare types safely.
153
+ * in the specified `typeValidator.order`. The first matching type is returned.
154
+ *
155
+ * If `val` is `null`, it immediately returns `'null'`.
156
+ * If no match is found, it returns `'unknown'`.
157
+ *
158
+ * @param {any} val - The value whose type should be determined.
159
+ * @returns {string} - The type name of the value (e.g., "array", "date", "map"), or "unknown" if no match is found.
160
+ *
161
+ * @example
162
+ * getType([]); // "array"
163
+ * getType(null); // "null"
164
+ * getType(new Set()); // "set"
165
+ * getType(() => {}); // "unknown"
166
+ */
167
+ const getType = (val) => {
168
+ if (val === null)
169
+ return 'null';
170
+ for (const name of typeValidator.order)
171
+ if (!typeValidator.items[name] || typeValidator.items[name](val))
172
+ return name;
173
+ return 'unknown';
174
+ };
1
175
  /**
2
176
  * Checks the type of a given object or returns its type as a string.
3
177
  *
@@ -13,21 +187,12 @@
13
187
  * objType(undefined); // null
14
188
  */
15
189
  export function objType(obj, type) {
16
- // Is Defined
17
- if (typeof obj !== 'undefined') {
18
- // Get Obj Type
19
- const result = Object.prototype.toString.call(obj).toLowerCase();
20
- // Check Obj Type
21
- if (typeof type === 'string') {
22
- if (result === `[object ${type}]`)
23
- return true;
24
- return false;
25
- }
26
- // Send Result
27
- return result.substring(8, result.length - 1);
28
- }
29
- // Nope
30
- return null;
190
+ if (typeof obj === 'undefined')
191
+ return null;
192
+ const result = getType(obj);
193
+ if (typeof type === 'string')
194
+ return result === type.toLowerCase();
195
+ return result;
31
196
  }
32
197
  /**
33
198
  * Counts the number of elements in an array or the number of properties in an object.
package/dist/v1/index.cjs CHANGED
@@ -7,6 +7,7 @@ var clock = require('./basics/clock.cjs');
7
7
  var objFilter = require('./basics/objFilter.cjs');
8
8
  var simpleMath = require('./basics/simpleMath.cjs');
9
9
  var text = require('./basics/text.cjs');
10
+ var TinyCrypto = require('./libs/TinyCrypto.cjs');
10
11
 
11
12
 
12
13
 
@@ -17,10 +18,14 @@ exports.formatCustomTimer = clock.formatCustomTimer;
17
18
  exports.formatDayTimer = clock.formatDayTimer;
18
19
  exports.formatTimer = clock.formatTimer;
19
20
  exports.getTimeDuration = clock.getTimeDuration;
21
+ exports.cloneObjTypeOrder = objFilter.cloneObjTypeOrder;
20
22
  exports.countObj = objFilter.countObj;
23
+ exports.extendObjType = objFilter.extendObjType;
21
24
  exports.objType = objFilter.objType;
25
+ exports.reorderObjTypeOrder = objFilter.reorderObjTypeOrder;
22
26
  exports.getAge = simpleMath.getAge;
23
27
  exports.getSimplePerc = simpleMath.getSimplePerc;
24
28
  exports.ruleOfThree = simpleMath.ruleOfThree;
25
29
  exports.toTitleCase = text.toTitleCase;
26
30
  exports.toTitleCaseLowerFirst = text.toTitleCaseLowerFirst;
31
+ exports.TinyCrypto = TinyCrypto;
@@ -1,4 +1,8 @@
1
+ import TinyCrypto from './libs/TinyCrypto.mjs';
1
2
  import TinyLevelUp from '../legacy/libs/userLevel.mjs';
3
+ import { extendObjType } from './basics/objFilter.mjs';
4
+ import { reorderObjTypeOrder } from './basics/objFilter.mjs';
5
+ import { cloneObjTypeOrder } from './basics/objFilter.mjs';
2
6
  import { countObj } from './basics/objFilter.mjs';
3
7
  import { objType } from './basics/objFilter.mjs';
4
8
  import { ruleOfThree } from './basics/simpleMath.mjs';
@@ -12,4 +16,4 @@ import { getTimeDuration } from './basics/clock.mjs';
12
16
  import { shuffleArray } from './basics/array.mjs';
13
17
  import { toTitleCase } from './basics/text.mjs';
14
18
  import { toTitleCaseLowerFirst } from './basics/text.mjs';
15
- export { TinyLevelUp, countObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
19
+ export { TinyCrypto, TinyLevelUp, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };