generate-pw 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
  ### Randomly generate cryptographically-secure passwords.
18
18
 
19
19
  <a href="#%EF%B8%8F-mit-license"><img height=31 src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
20
- <a href="https://github.com/adamlui/js-utils/releases/tag/generate-pw-1.2.2"><img height=31 src="https://img.shields.io/badge/Latest_Build-1.2.2-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
20
+ <a href="https://github.com/adamlui/js-utils/releases/tag/generate-pw-1.3.0"><img height=31 src="https://img.shields.io/badge/Latest_Build-1.3.0-44cc11.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
21
21
  <a href="https://www.npmjs.com/package/generate-pw?activeTab=code"><img height=31 src="https://img.shields.io/npm/unpacked-size/generate-pw?style=for-the-badge&logo=ebox&logoColor=white&labelColor=464646&color=blue"></a>
22
22
  <a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_js-utils:generate-pw/generate-pw.js"><img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_js-utils%3Agenerate-pw%2Fgenerate-pw.js%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=Vulnerabilities&color=gold"></a>
23
23
 
@@ -101,25 +101,35 @@ See: [Available options](#available-options-for-generate-functions)
101
101
 
102
102
  #
103
103
 
104
- ### `strictify(password[, requiredCharTypes])`
104
+ ### `strictify(password[, requiredCharTypes, options])`
105
105
 
106
106
  Modifies `password` given to use at least one character of each `requiredCharTypes` element passed, returning a string:
107
107
 
108
108
  ```js
109
- const password = 'abcdef',
110
- strictPW = pw.strictify(password, ['numbers', 'symbols']);
111
-
109
+ const strictPW = pw.strictify('abcdef', ['numbers', 'symbols']);
112
110
  console.log(strictPW);
113
- // sample output: 'a!c2ef'
111
+
112
+ /* sample output:
113
+
114
+ strictify() » Strictifying password...
115
+ strictify() » Strictification complete!
116
+ a!c2ef
117
+ */
114
118
  ```
115
119
 
120
+ **💡 Note:** If no `requiredCharTypes` array is passed, all available types will be required.
121
+
116
122
  Available `requiredCharTypes` are: `['number', 'symbol', 'lower', 'upper']`
117
123
 
118
- **💡 Note:** If no `requiredCharTypes` array is passed, all available types will be required.
124
+ Available options (passed as object properties):
125
+
126
+ Name | Type | Description | Default Value
127
+ ----------|---------|-----------------------------------|---------------
128
+ `verbose` | Boolean | Show logging in console/terminal. | `true`
119
129
 
120
130
  #
121
131
 
122
- ### `validateStrength(password)`
132
+ ### `validateStrength(password[, options])`
123
133
 
124
134
  Validates the strength of a password, returning an object containing:
125
135
  - `strengthScore` (0–100)
@@ -136,14 +146,26 @@ console.log(pwStrength);
136
146
 
137
147
  /* outputs:
138
148
 
149
+ validateStrength() » Validating password strength...
150
+ validateStrength() » Password strength validated!
151
+ validateStrength() » Check returned object for score/recommendations.
139
152
  {
140
153
  strengthScore: 60,
141
- recommendations: [ 'Include at least one number.', 'Include at least one symbol.' ],
154
+ recommendations: [
155
+ 'Make it at least 8 characters long.',
156
+ 'Include at least one number.'
157
+ ],
142
158
  isGood: false
143
159
  }
144
160
  */
145
161
  ```
146
162
 
163
+ Available options (passed as object properties):
164
+
165
+ Name | Type | Description | Default Value
166
+ ----------|---------|-----------------------------------|---------------
167
+ `verbose` | Boolean | Show logging in console/terminal. | `true`
168
+
147
169
  #
148
170
 
149
171
  ### Available options for `generate*()` functions
@@ -1,10 +1,14 @@
1
1
  #!/usr/bin/env node
2
- const p=require("crypto")["randomInt"],s=require("child_process")["execSync"],u={lower:"abcdefghijklmnopqrstuvwxyz",upper:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",numbers:"0123456789",symbols:"!@#$%^&*()-_=+[]{}/\\|;:'\",.<>?"};function a(o={}){var e,s={length:8,qty:1,charset:"",exclude:"",numbers:!1,symbols:!1,lowercase:!0,uppercase:!0,strict:!1};o={...s,...o};for(const r of Object.keys(o))if(!Object.prototype.hasOwnProperty.call(s,r))return console.error(`generatePassword() » ERROR: \`${r}\` is an invalid option.`+`
3
- generatePassword() » Valid options:
4
- [ ${Object.keys(s).join(", ")} ]`);for(const n of["length","qty"])if(isNaN(o[n])||o[n]<1)return console.error(`generatePassword() » ERROR: [${n}] option must be > 1.`);for(const a of["numbers","symbols","lowercase","uppercase","strict"])if("boolean"!=typeof o[a])return console.error(`generatePassword() » ERROR: [${a}] option can only be \`true\` or \`false\`.`);if(1<o.qty){const{qty:l,...c}=o;return i(l,c)}{let s=o.charset||(o.numbers?u.numbers:"")+(o.symbols?u.symbols:"")+(o.lowercase?u.lower:"")+(o.uppercase?u.upper:""),r=(s=(s=""===s?u.lower+u.upper:s).replace(new RegExp(`[${o.exclude}]`,"g"),""),"");for(let e=0;e<o.length;e++){var t=p(0,s.length);r+=s.charAt(t)}return o.strict&&(e=["number","symbol","lower","upper"].filter(e=>o[e+"s"]||o[e+"case"]),r=m(r,e)),r}}function i(s,r={}){var e={length:8,qty:1,charset:"",exclude:"",numbers:!1,symbols:!1,lowercase:!0,uppercase:!0,strict:!1};if(r={...e,...r},s=parseInt(s),isNaN(s))return console.error("generatePasswords() » ERROR: First argument [qty] of generatePasswords() must be an integer");for(const t of Object.keys(r))if(!Object.prototype.hasOwnProperty.call(e,t))return console.error(`generatePasswords() » ERROR: \`${t}\` is an invalid option.`+`
5
- generatePassword() » Valid options:
6
- [ ${Object.keys(e).join(", ")} ]`);if(isNaN(r.length)||r.length<1)return console.error("generatePasswords() » ERROR: [length] options must be > 1.");for(const n of["numbers","symbols","lowercase","uppercase","strict"])if("boolean"!=typeof r[n])return console.error(`generatePasswords() » ERROR: [${n}] option can only be \`true\` or \`false\`.`);var o=[];for(let e=0;e<s;e++)o.push(a(r));return o}function m(s,r=["number","symbol","lower","upper"]){for(const l of r)global["has"+l.charAt(0).toUpperCase()+l.slice(1)]=!1;for(let e=0;e<s.length;e++)for(const c of r)(u[c]||u[c+"s"]).includes(s.charAt(e))&&(global["has"+c.charAt(0).toUpperCase()+c.slice(1)]=!0);var e=Math.min(s.length,r.length),o=[];let t=0,n=s;for(const i of r)if(t<e&&!global["has"+i.charAt(0).toUpperCase()+i.slice(1)]){let e;for(;e=p(0,s.length),o.includes(e););o.push(e);var a=u[i]||u[i+"s"];n=n.substring(0,e)+a.charAt(p(0,a.length))+n.substring(e+1),t++}return n}function e(e){var s={minLength:8,minLower:1,minUpper:1,minNumber:1,minSymbol:1},r={lower:0,upper:0,number:0,symbol:0};for(const n of e)for(const a of Object.keys(r))(u[a]||u[a+"s"]).includes(n)&&r[a]++;var o=[];e.length<s.minLength&&o.push(`Make it at least ${s.minLength} characters long.`);for(const l of Object.keys(r))r[l]<s["min"+l.charAt(0).toUpperCase()+l.slice(1)]&&o.push("Include at least one "+l+`${["upper","lower"].includes(l)?"case letter":""}.`);let t=0;t+=e.length>=s.minLength?20:0;for(const c of Object.keys(r))t+=r[c]>=s["min"+c.charAt(0).toUpperCase()+c.slice(1)]?20:0;return{strengthScore:t,recommendations:o,isGood:80<=t}}if(require.main!==module)module.exports={generatePassword:a,generatePasswords:i,strictify:m,validateStrength:e};else{const n="",l="",c="",h={},d={paramOptions:{length:/^--?length/,qty:/^--?qu?a?n?ti?t?y=.*$/,charset:/^--?chars/,excludeChars:/^--?exclude=/},flags:{includeNums:/^--?(?:n|(?:include-?)?num(?:ber)?s?=?(?:true|1)?)$/,includeSymbols:/^--?(?:s|(?:include-?)?symbols?=?(?:true|1)?)$/,excludeLowerChars:/^--?(?:L|(?:exclude|disable|no)-?lower-?(?:case)?|lower-?(?:case)?=(?:false|0))$/,excludeUpperChars:/^--?(?:U|(?:exclude|disable|no)-?upper-?(?:case)?|upper-?(?:case)?=(?:false|0))$/,strictMode:/^--?s(?:trict)?(?:-?mode)?$/},cmds:{help:/^--?h(?:elp)?$/,version:/^--?ve?r?s?i?o?n?$/}};if(process.argv.forEach(s=>{var e,r,o;s.startsWith("-")&&(o=Object.keys(d.flags).find(e=>d.flags[e].test(s)),e=Object.keys(d.paramOptions).find(e=>d.paramOptions[e].test(s)),r=Object.keys(d.cmds).find(e=>d.cmds[e].test(s)),o?h[o]=!0:e?(o=s.split("=")[1],h[e]=parseInt(o)||o):r||(console.error(`
7
- ${l}ERROR: Arg [${s}] not recognized.`+n),console.info(`
8
- ${c}Valid arguments are below.`+n),t(["paramOptions","booelanOptions","infoCmds"]),process.exit(1)))}),process.argv.some(e=>/^--?h(?:elp)?$/.test(e)))t();else if(process.argv.some(e=>/^--?ve?r?s?i?o?n?$/.test(e)))console.info("v"+require("./package.json").version);else{for(const g of["length","qty"])h[g]&&(isNaN(h[g])||h[g]<1)&&(console.error(`
9
- ${l}Error: [${g}] argument must be > 1.`+n),process.exit(1));const o={length:h.length||8,qty:h.qty||1,charset:h.charset,exclude:h.excludeChars,numbers:!!h.includeNums,symbols:!!h.includeSymbols,lowercase:!h.excludeLowerChars,uppercase:!h.excludeUpperChars,strict:!!h.strictMode},f=a(o);r(Array.isArray(f)?f.join("\n"):f)}function t(e=["cmdFormat","paramOptions","booelanOptions","infoCmds"]){const s={cmdFormat:[`
10
- ${c}generate-pw [options|commands]`+n],paramOptions:["\nParameter options:"," --length=n Generate password(s) of n length."," --qty=n Generate n password(s)."," --charset=chars Only include chars in password(s)."," --charset=chars Only include chars in password(s)."," --exclude=chars Exclude chars from password(s)."],booelanOptions:["\nBoolean options:"," -n, --include-numbers Allow numbers in password(s)."," -s, --include-symbols Allow symbols in password(s)."," -L, --no-lowercase Disallow lowercase letters in password(s)."," -U, --no-uppercase Disallow uppercase letters in password(s)."],infoCmds:["\nInfo commands:"," -h, --help Display help screen."," -v, --version Show version number."]};e.forEach(e=>{s[e]?.forEach(e=>{{const o=process.stdout.columns||80,t=[],s=e.match(/\S+|\s+/g);let r="";s.forEach(e=>{var s=o-(0===t.length?0:29);r.length+e.length>s&&(t.push(0===t.length?r:r.trimStart()),r=""),r+=e}),t.push(0===t.length?r:r.trimStart()),t.forEach((e,s)=>console.info(0===s?e:" ".repeat(29)+e))}})})}function r(e){e=e.replace(/\s+$/m,"").replace(/"/g,'""'),"darwin"===process.platform?s(`printf "${e}" | pbcopy`):"linux"===process.platform?s(`printf "${e}" | xclip -selection clipboard`):"win32"===process.platform&&s(`Set-Clipboard -Value "${e}"`,{shell:"powershell"})}}
2
+ const m=require("crypto")["randomInt"],r=require("child_process")["execSync"],g={lower:"abcdefghijklmnopqrstuvwxyz",upper:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",numbers:"0123456789",symbols:"!@#$%^&*()-_=+[]{}/\\|;:'\",.<>?"};function a(o={}){var e,r={length:8,qty:1,charset:"",exclude:"",numbers:!1,symbols:!1,lowercase:!0,uppercase:!0,strict:!1};o={...r,...o};for(const s of Object.keys(o))if(!Object.prototype.hasOwnProperty.call(r,s))return console.error(`generatePassword() » ERROR: \`${s}\` is an invalid option.
3
+ `+`generatePassword() » Valid options:
4
+ [ ${Object.keys(r).join(", ")} ]`);for(const n of["length","qty"])if(o[n]=parseInt(o[n],10),isNaN(o[n])||o[n]<1)return console.error(`generatePassword() » ERROR: [${n}] option can only be an integer > 0.`);for(const a of["numbers","symbols","lowercase","uppercase","strict"])if("boolean"!=typeof o[a])return console.error(`generatePassword() » ERROR: [${a}] option can only be \`true\` or \`false\`.`);if(1<o.qty){const{qty:l,...i}=o;return c(l,i)}{let r=o.charset||(o.numbers?g.numbers:"")+(o.symbols?g.symbols:"")+(o.lowercase?g.lower:"")+(o.uppercase?g.upper:""),s=(r=(r=""===r?g.lower+g.upper:r).replace(new RegExp(`[${o.exclude}]`,"g"),""),"");for(let e=0;e<o.length;e++){var t=m(0,r.length);s+=r.charAt(t)}return o.strict&&(e=["number","symbol","lower","upper"].filter(e=>o[e+"s"]||o[e+"case"]),s=p(s,e)),s}}function c(r,s={}){var e={length:8,charset:"",exclude:"",numbers:!1,symbols:!1,lowercase:!0,uppercase:!0,strict:!1};if(s={...e,...s},r=parseInt(r,10),isNaN(r)||r<1)return console.error("generatePasswords() » ERROR: 1st arg [qty] can only be an integer > 0.");for(const t of Object.keys(s))if(!Object.prototype.hasOwnProperty.call(e,t))return console.error(`generatePasswords() » ERROR: \`${t}\` is an invalid option.
5
+ `+`generatePasswords() » Valid options:
6
+ [ ${Object.keys(e).join(", ")} ]`);if(s.length=parseInt(s.length),isNaN(s.length)||s.length<1)return console.error("generatePasswords() » ERROR: [length] option can only be an integer > 0.");for(const n of["numbers","symbols","lowercase","uppercase","strict"])if("boolean"!=typeof s[n])return console.error(`generatePasswords() » ERROR: [${n}] option can only be \`true\` or \`false\`.`);var o=[];for(let e=0;e<r;e++)o.push(a(s));return o}function p(r,s=["number","symbol","lower","upper"],e={}){var o={verbose:!0};if(e={...o,...e},"string"!=typeof r)return console.error("strictify() » ERROR: 1st arg <password> must be a string.");var t=["number","symbol","lower","upper"];for(const p of s)if(!t.includes(p))return console.error(`strictify() » ERROR: \`${p}\` is an invalid character type.
7
+ `+`strictify() » Valid character types: [ ${t.join(", ")} ]`);for(const f of Object.keys(e)){if(!Object.prototype.hasOwnProperty.call(o,f))return console.error(`strictify() » ERROR: \`${f}\` is an invalid option.
8
+ `+`strictify() » Valid options: [ ${Object.keys(o).join(", ")} ]`);if("boolean"!=typeof e[f])return console.error(`strictify() » ERROR: \`${f}\` option can only be set to \`true\` or \`false\`.`)}for(const u of s)global["has"+u.charAt(0).toUpperCase()+u.slice(1)]=!1;for(let e=0;e<r.length;e++)for(const d of s)(g[d]||g[d+"s"]).includes(r.charAt(e))&&(global["has"+d.charAt(0).toUpperCase()+d.slice(1)]=!0);e.verbose&&console.info("strictify() » Strictifying password...");var n=Math.min(r.length,s.length),a=[];let l=0,i=r;for(const h of s)if(l<n&&!global["has"+h.charAt(0).toUpperCase()+h.slice(1)]){let e;for(;e=m(0,r.length),a.includes(e););a.push(e);var c=g[h]||g[h+"s"];i=i.substring(0,e)+c.charAt(m(0,c.length))+i.substring(e+1),l++}return e.verbose&&(0<l?console.info("strictify() » Strictification complete!"):console.info(`strictify() » Password already includes ${s.join(" + ")} characters!
9
+ `+"strictify() » No modifications made.")),i}function e(e,r={}){var s={minLength:8,minLower:1,minUpper:1,minNumber:1,minSymbol:1},o={verbose:!0};if(r={...o,...r},"string"!=typeof e)return console.error("validateStrength() » ERROR: 1st arg <password> must be a string.");for(const l of Object.keys(r)){if(!Object.prototype.hasOwnProperty.call(o,l))return console.error(`validateStrength() » ERROR: \`${l}\` is an invalid option.
10
+ `+`validateStrength() » Valid options: [ ${Object.keys(o).join(", ")} ]`);if("boolean"!=typeof r[l])return console.error(`validateStrength() » ERROR: \`${l}\` option can only be set to \`true\` or \`false\`.`)}r.verbose&&console.info("validateStrength() » Validating password strength...");var t={lower:0,upper:0,number:0,symbol:0};for(const i of e)for(const c of Object.keys(t))(g[c]||g[c+"s"]).includes(i)&&t[c]++;var n=[];e.length<s.minLength&&n.push(`Make it at least ${s.minLength} characters long.`);for(const p of Object.keys(t))t[p]<s["min"+p.charAt(0).toUpperCase()+p.slice(1)]&&n.push("Include at least one "+p+`${["upper","lower"].includes(p)?"case letter":""}.`);let a=0;a+=e.length>=s.minLength?20:0;for(const f of Object.keys(t))a+=t[f]>=s["min"+f.charAt(0).toUpperCase()+f.slice(1)]?20:0;return r.verbose&&console.info("validateStrength() » Password strength validated!\n"+(require.main!==module?"validateStrength() » Check returned object for score/recommendations.":"")),{strengthScore:a,recommendations:n,isGood:80<=a}}if(require.main!==module)module.exports={generatePassword:a,generatePasswords:c,strictify:p,validateStrength:e};else{const n="",l="",i="",f={},u={paramOptions:{length:/^--?length/,qty:/^--?qu?a?n?ti?t?y=.*$/,charset:/^--?chars/,excludeChars:/^--?exclude=/},flags:{includeNums:/^--?(?:n|(?:include-?)?num(?:ber)?s?=?(?:true|1)?)$/,includeSymbols:/^--?(?:s|(?:include-?)?symbols?=?(?:true|1)?)$/,excludeLowerChars:/^--?(?:L|(?:exclude|disable|no)-?lower-?(?:case)?|lower-?(?:case)?=(?:false|0))$/,excludeUpperChars:/^--?(?:U|(?:exclude|disable|no)-?upper-?(?:case)?|upper-?(?:case)?=(?:false|0))$/,strictMode:/^--?s(?:trict)?(?:-?mode)?$/},infoCmds:{help:/^--?h(?:elp)?$/,version:/^--?ve?r?s?i?o?n?$/}};if(process.argv.forEach(r=>{var e,s,o;r.startsWith("-")&&(e=Object.keys(u.paramOptions).find(e=>u.paramOptions[e].test(r)),o=Object.keys(u.flags).find(e=>u.flags[e].test(r)),s=Object.keys(u.infoCmds).find(e=>u.infoCmds[e].test(r)),o?f[o]=!0:e?(o=r.split("=")[1],f[e]=parseInt(o)||o):s||(console.error(`
11
+ ${l}ERROR: Arg [${r}] not recognized.`+n),console.info(`
12
+ ${i}Valid arguments are below.`+n),t(["paramOptions","flags","infoCmds"]),process.exit(1)))}),process.argv.some(e=>u.infoCmds.help.test(e)))t();else if(process.argv.some(e=>u.infoCmds.version.test(e)))console.info("v"+require("./package.json").version);else{for(const h of["length","qty"])f[h]&&(isNaN(f[h])||f[h]<1)&&(console.error(`
13
+ ${l}Error: [${h}] argument can only be > 0.`+n),process.exit(1));const o={length:f.length||8,qty:f.qty||1,charset:f.charset,exclude:f.excludeChars,numbers:!!f.includeNums,symbols:!!f.includeSymbols,lowercase:!f.excludeLowerChars,uppercase:!f.excludeUpperChars,strict:!!f.strictMode},d=a(o);s(Array.isArray(d)?d.join("\n"):d)}function t(e=["cmdFormat","paramOptions","flags","infoCmds"]){const r={cmdFormat:[`
14
+ ${i}generate-pw [options|commands]`+n],paramOptions:["\nParameter options:"," --length=n Generate password(s) of n length."," --qty=n Generate n password(s)."," --charset=chars Only include chars in password(s)."," --charset=chars Only include chars in password(s)."," --exclude=chars Exclude chars from password(s)."],flags:["\nBoolean options:"," -n, --include-numbers Allow numbers in password(s)."," -s, --include-symbols Allow symbols in password(s)."," -L, --no-lowercase Disallow lowercase letters in password(s)."," -U, --no-uppercase Disallow uppercase letters in password(s)."],infoCmds:["\nInfo commands:"," -h, --help Display help screen."," -v, --version Show version number."]};e.forEach(e=>{r[e]?.forEach(e=>{{const o=process.stdout.columns||80,t=[],r=e.match(/\S+|\s+/g);let s="";r.forEach(e=>{var r=o-(0===t.length?0:29);s.length+e.length>r&&(t.push(0===t.length?s:s.trimStart()),s=""),s+=e}),t.push(0===t.length?s:s.trimStart()),t.forEach((e,r)=>console.info(0===r?e:" ".repeat(29)+e))}})})}function s(e){e=e.replace(/\s+$/m,"").replace(/"/g,'""'),"darwin"===process.platform?r(`printf "${e}" | pbcopy`):"linux"===process.platform?r(`printf "${e}" | xclip -selection clipboard`):"win32"===process.platform&&r(`Set-Clipboard -Value "${e}"`,{shell:"powershell"})}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generate-pw",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "Randomly generate cryptographically-secure passwords.",
5
5
  "author": {
6
6
  "name": "Adam Lui",