@systemix/password 0.5.0 → 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.
- package/dist/index.cjs +149 -279
- package/dist/index.d.cts +51 -50
- package/dist/index.d.ts +51 -50
- package/dist/index.js +136 -240
- package/package.json +13 -11
package/dist/index.cjs
CHANGED
|
@@ -1,292 +1,162 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/enum/props.enum.ts
|
|
3
|
+
let GeneratePasswordPropsEnum = /* @__PURE__ */ function(GeneratePasswordPropsEnum) {
|
|
4
|
+
GeneratePasswordPropsEnum["LENGTH"] = "length";
|
|
5
|
+
GeneratePasswordPropsEnum["USE_NUMBERS"] = "useNumbers";
|
|
6
|
+
GeneratePasswordPropsEnum["USE_UPPERCASE"] = "useUppercase";
|
|
7
|
+
GeneratePasswordPropsEnum["USE_LOWERCASE"] = "useLowercase";
|
|
8
|
+
GeneratePasswordPropsEnum["USE_SYMBOLS"] = "useSymbols";
|
|
9
|
+
GeneratePasswordPropsEnum["EXCLUDE_SIMILAR_CHARACTERS"] = "excludeSimilarCharacters";
|
|
10
|
+
GeneratePasswordPropsEnum["EXCLUDE"] = "exclude";
|
|
11
|
+
GeneratePasswordPropsEnum["COUNT"] = "count";
|
|
12
|
+
GeneratePasswordPropsEnum["MIN_NUMBERS"] = "minNumbers";
|
|
13
|
+
GeneratePasswordPropsEnum["MIN_UPPERCASE"] = "minUppercase";
|
|
14
|
+
GeneratePasswordPropsEnum["MIN_LOWERCASE"] = "minLowercase";
|
|
15
|
+
GeneratePasswordPropsEnum["MIN_SYMBOLS"] = "minSymbols";
|
|
16
|
+
GeneratePasswordPropsEnum["CUSTOM_LOWERCASE"] = "customLowercase";
|
|
17
|
+
GeneratePasswordPropsEnum["CUSTOM_UPPERCASE"] = "customUppercase";
|
|
18
|
+
GeneratePasswordPropsEnum["CUSTOM_NUMBERS"] = "customNumbers";
|
|
19
|
+
GeneratePasswordPropsEnum["CUSTOM_SYMBOLS"] = "customSymbols";
|
|
20
|
+
return GeneratePasswordPropsEnum;
|
|
21
|
+
}({});
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/utils/error.message.ts
|
|
24
|
+
const lengthError = {
|
|
25
|
+
invalidLength: "Invalid length. Length must be a positive number.",
|
|
26
|
+
lengthTooLarge: "Invalid length. Length must be less than or equal to 100."
|
|
9
27
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
28
|
+
const useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
29
|
+
const useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
30
|
+
const useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
31
|
+
const useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
32
|
+
const excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
33
|
+
const excludeError = "Invalid exclude. It must be a string.";
|
|
34
|
+
const countError = {
|
|
35
|
+
invalidCount: "Invalid count. Count must be a positive number.",
|
|
36
|
+
countTooLarge: "Invalid count. Count must be less than or equal to 10."
|
|
17
37
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
GeneratePasswordPropsEnum: () => GeneratePasswordPropsEnum,
|
|
24
|
-
allOptionsFalseError: () => allOptionsFalseError,
|
|
25
|
-
calculatePasswordEntropy: () => calculatePasswordEntropy,
|
|
26
|
-
countError: () => countError,
|
|
27
|
-
excludeError: () => excludeError,
|
|
28
|
-
excludeSimilarCharactersError: () => excludeSimilarCharactersError,
|
|
29
|
-
generatePassword: () => generatePassword,
|
|
30
|
-
lengthError: () => lengthError,
|
|
31
|
-
unwantedPropsError: () => unwantedPropsError,
|
|
32
|
-
useLowercaseError: () => useLowercaseError,
|
|
33
|
-
useNumbersError: () => useNumbersError,
|
|
34
|
-
useSymbolsError: () => useSymbolsError,
|
|
35
|
-
useUppercaseError: () => useUppercaseError
|
|
36
|
-
});
|
|
37
|
-
module.exports = __toCommonJS(index_exports);
|
|
38
|
-
|
|
39
|
-
// src/enum/props.enum.ts
|
|
40
|
-
var GeneratePasswordPropsEnum = /* @__PURE__ */ ((GeneratePasswordPropsEnum2) => {
|
|
41
|
-
GeneratePasswordPropsEnum2["LENGTH"] = "length";
|
|
42
|
-
GeneratePasswordPropsEnum2["USE_NUMBERS"] = "useNumbers";
|
|
43
|
-
GeneratePasswordPropsEnum2["USE_UPPERCASE"] = "useUppercase";
|
|
44
|
-
GeneratePasswordPropsEnum2["USE_LOWERCASE"] = "useLowercase";
|
|
45
|
-
GeneratePasswordPropsEnum2["USE_SYMBOLS"] = "useSymbols";
|
|
46
|
-
GeneratePasswordPropsEnum2["EXCLUDE_SIMILAR_CHARACTERS"] = "excludeSimilarCharacters";
|
|
47
|
-
GeneratePasswordPropsEnum2["EXCLUDE"] = "exclude";
|
|
48
|
-
GeneratePasswordPropsEnum2["COUNT"] = "count";
|
|
49
|
-
GeneratePasswordPropsEnum2["MIN_NUMBERS"] = "minNumbers";
|
|
50
|
-
GeneratePasswordPropsEnum2["MIN_UPPERCASE"] = "minUppercase";
|
|
51
|
-
GeneratePasswordPropsEnum2["MIN_LOWERCASE"] = "minLowercase";
|
|
52
|
-
GeneratePasswordPropsEnum2["MIN_SYMBOLS"] = "minSymbols";
|
|
53
|
-
GeneratePasswordPropsEnum2["CUSTOM_LOWERCASE"] = "customLowercase";
|
|
54
|
-
GeneratePasswordPropsEnum2["CUSTOM_UPPERCASE"] = "customUppercase";
|
|
55
|
-
GeneratePasswordPropsEnum2["CUSTOM_NUMBERS"] = "customNumbers";
|
|
56
|
-
GeneratePasswordPropsEnum2["CUSTOM_SYMBOLS"] = "customSymbols";
|
|
57
|
-
return GeneratePasswordPropsEnum2;
|
|
58
|
-
})(GeneratePasswordPropsEnum || {});
|
|
59
|
-
|
|
60
|
-
// src/utils/error.message.ts
|
|
61
|
-
var lengthError = {
|
|
62
|
-
invalidLength: "Invalid length. Length must be a positive number.",
|
|
63
|
-
lengthTooLarge: "Invalid length. Length must be less than or equal to 100."
|
|
38
|
+
const unwantedPropsError = (unwantedProps) => {
|
|
39
|
+
return `Invalid prop(s): ${unwantedProps.join(", ")}. Only the following options are allowed: length, useNumbers, useUppercase, useLowercase, useSymbols, excludeSimilarCharacters, exclude, count, minNumbers, minUppercase, minLowercase, minSymbols, customUppercase, customLowercase, customNumbers, customSymbols.`;
|
|
64
40
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
var excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
70
|
-
var excludeError = "Invalid exclude. It must be a string.";
|
|
71
|
-
var countError = {
|
|
72
|
-
invalidCount: "Invalid count. Count must be a positive number.",
|
|
73
|
-
countTooLarge: "Invalid count. Count must be less than or equal to 10."
|
|
74
|
-
};
|
|
75
|
-
var unwantedPropsError = (unwantedProps) => {
|
|
76
|
-
return `Invalid prop(s): ${unwantedProps.join(", ")}. Only the following options are allowed: length, useNumbers, useUppercase, useLowercase, useSymbols, excludeSimilarCharacters, exclude, count, minNumbers, minUppercase, minLowercase, minSymbols, customUppercase, customLowercase, customNumbers, customSymbols.`;
|
|
77
|
-
};
|
|
78
|
-
var allOptionsFalseError = "At least one of the options must be true.";
|
|
79
|
-
|
|
80
|
-
// src/functions/validation.function.ts
|
|
81
|
-
var allValidProps = Object.values(GeneratePasswordPropsEnum);
|
|
41
|
+
const allOptionsFalseError = "At least one of the options must be true.";
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/functions/validation.function.ts
|
|
44
|
+
const allValidProps = Object.values(GeneratePasswordPropsEnum);
|
|
82
45
|
function generatePasswordPropValidation(props) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
const checkMin = (val, name) => {
|
|
117
|
-
if (val !== void 0 && (typeof val !== "number" || val < 0)) {
|
|
118
|
-
throw new Error(`${name} must be a non-negative number.`);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
checkMin(minNumbers, "minNumbers");
|
|
122
|
-
checkMin(minUppercase, "minUppercase");
|
|
123
|
-
checkMin(minLowercase, "minLowercase");
|
|
124
|
-
checkMin(minSymbols, "minSymbols");
|
|
125
|
-
const totalMin = (minNumbers ?? 0) + (minUppercase ?? 0) + (minLowercase ?? 0) + (minSymbols ?? 0);
|
|
126
|
-
const len = length ?? 12;
|
|
127
|
-
if (totalMin > len) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
"Total minimum character requirements exceed requested password length."
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
const checkString = (val, name) => {
|
|
133
|
-
if (val !== void 0 && typeof val !== "string") {
|
|
134
|
-
throw new Error(`${name} must be a string.`);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
checkString(customNumbers, "customNumbers");
|
|
138
|
-
checkString(customUppercase, "customUppercase");
|
|
139
|
-
checkString(customLowercase, "customLowercase");
|
|
140
|
-
checkString(customSymbols, "customSymbols");
|
|
141
|
-
if (useNumbers !== void 0 && typeof useNumbers !== "boolean") {
|
|
142
|
-
throw new Error(useNumbersError);
|
|
143
|
-
}
|
|
144
|
-
if (useUppercase !== void 0 && typeof useUppercase !== "boolean") {
|
|
145
|
-
throw new Error(useUppercaseError);
|
|
146
|
-
}
|
|
147
|
-
if (useLowercase !== void 0 && typeof useLowercase !== "boolean") {
|
|
148
|
-
throw new Error(useLowercaseError);
|
|
149
|
-
}
|
|
150
|
-
if (useSymbols !== void 0 && typeof useSymbols !== "boolean") {
|
|
151
|
-
throw new Error(useSymbolsError);
|
|
152
|
-
}
|
|
153
|
-
if (excludeSimilarCharacters !== void 0 && typeof excludeSimilarCharacters !== "boolean") {
|
|
154
|
-
throw new Error(excludeSimilarCharactersError);
|
|
155
|
-
}
|
|
156
|
-
if (exclude !== void 0 && typeof exclude !== "string") {
|
|
157
|
-
throw new Error(excludeError);
|
|
158
|
-
}
|
|
159
|
-
if (count !== void 0 && (typeof count !== "number" || count < 1)) {
|
|
160
|
-
throw new Error(countError.invalidCount);
|
|
161
|
-
}
|
|
162
|
-
if (count !== void 0 && count > 10) {
|
|
163
|
-
throw new Error(countError.countTooLarge);
|
|
164
|
-
}
|
|
165
|
-
const uN = useNumbers ?? true;
|
|
166
|
-
const uU = useUppercase ?? true;
|
|
167
|
-
const uL = useLowercase ?? true;
|
|
168
|
-
const uS = useSymbols ?? false;
|
|
169
|
-
if (!uN && !uU && !uL && !uS) {
|
|
170
|
-
throw new Error(allOptionsFalseError);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// src/functions/generate.function.ts
|
|
175
|
-
var crypto = globalThis.crypto;
|
|
176
|
-
if (!crypto) {
|
|
177
|
-
throw new Error("Crypto not available. Requires Node 18+ or browser.");
|
|
46
|
+
const unwantedProps = Object.keys(props).filter((prop) => !allValidProps.includes(prop));
|
|
47
|
+
if (unwantedProps.length > 0) throw new Error(unwantedPropsError(unwantedProps));
|
|
48
|
+
const { length, useNumbers, useUppercase, useLowercase, useSymbols, excludeSimilarCharacters, exclude, count, minNumbers, minUppercase, minLowercase, minSymbols, customNumbers, customUppercase, customLowercase, customSymbols } = props;
|
|
49
|
+
if (length !== void 0) {
|
|
50
|
+
if (typeof length !== "number" || length < 1) throw new Error(lengthError.invalidLength);
|
|
51
|
+
if (length > 100) throw new Error(lengthError.lengthTooLarge);
|
|
52
|
+
}
|
|
53
|
+
const checkMin = (val, name) => {
|
|
54
|
+
if (val !== void 0 && (typeof val !== "number" || val < 0)) throw new Error(`${name} must be a non-negative number.`);
|
|
55
|
+
};
|
|
56
|
+
checkMin(minNumbers, "minNumbers");
|
|
57
|
+
checkMin(minUppercase, "minUppercase");
|
|
58
|
+
checkMin(minLowercase, "minLowercase");
|
|
59
|
+
checkMin(minSymbols, "minSymbols");
|
|
60
|
+
if ((minNumbers ?? 0) + (minUppercase ?? 0) + (minLowercase ?? 0) + (minSymbols ?? 0) > (length ?? 12)) throw new Error("Total minimum character requirements exceed requested password length.");
|
|
61
|
+
const checkString = (val, name) => {
|
|
62
|
+
if (val !== void 0 && typeof val !== "string") throw new Error(`${name} must be a string.`);
|
|
63
|
+
};
|
|
64
|
+
checkString(customNumbers, "customNumbers");
|
|
65
|
+
checkString(customUppercase, "customUppercase");
|
|
66
|
+
checkString(customLowercase, "customLowercase");
|
|
67
|
+
checkString(customSymbols, "customSymbols");
|
|
68
|
+
if (useNumbers !== void 0 && typeof useNumbers !== "boolean") throw new Error(useNumbersError);
|
|
69
|
+
if (useUppercase !== void 0 && typeof useUppercase !== "boolean") throw new Error(useUppercaseError);
|
|
70
|
+
if (useLowercase !== void 0 && typeof useLowercase !== "boolean") throw new Error(useLowercaseError);
|
|
71
|
+
if (useSymbols !== void 0 && typeof useSymbols !== "boolean") throw new Error(useSymbolsError);
|
|
72
|
+
if (excludeSimilarCharacters !== void 0 && typeof excludeSimilarCharacters !== "boolean") throw new Error(excludeSimilarCharactersError);
|
|
73
|
+
if (exclude !== void 0 && typeof exclude !== "string") throw new Error(excludeError);
|
|
74
|
+
if (count !== void 0 && (typeof count !== "number" || count < 1)) throw new Error(countError.invalidCount);
|
|
75
|
+
if (count !== void 0 && count > 10) throw new Error(countError.countTooLarge);
|
|
76
|
+
if (!(useNumbers ?? true) && !(useUppercase ?? true) && !(useLowercase ?? true) && !(useSymbols ?? false)) throw new Error(allOptionsFalseError);
|
|
178
77
|
}
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/functions/generate.function.ts
|
|
80
|
+
const crypto = globalThis.crypto;
|
|
81
|
+
if (!crypto) throw new Error("Crypto not available. Requires Node 18+ or browser.");
|
|
82
|
+
/**
|
|
83
|
+
* Calculates the theoretical entropy of a password based on its length and charset size.
|
|
84
|
+
* H = L * log2(N)
|
|
85
|
+
*/
|
|
179
86
|
function calculatePasswordEntropy(length, charsetSize) {
|
|
180
|
-
|
|
181
|
-
|
|
87
|
+
if (length <= 0 || charsetSize <= 0) return 0;
|
|
88
|
+
return length * Math.log2(charsetSize);
|
|
182
89
|
}
|
|
183
90
|
function getRandomInt(max) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
91
|
+
if (max <= 1) return 0;
|
|
92
|
+
const array = /* @__PURE__ */ new Uint32Array(1);
|
|
93
|
+
const range = Math.floor(4294967295 / max) * max;
|
|
94
|
+
let randomValue;
|
|
95
|
+
do {
|
|
96
|
+
crypto.getRandomValues(array);
|
|
97
|
+
randomValue = array[0];
|
|
98
|
+
} while (randomValue >= range);
|
|
99
|
+
return randomValue % max;
|
|
193
100
|
}
|
|
194
101
|
function shuffleString(str) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
102
|
+
const arr = str.split("");
|
|
103
|
+
for (let i = arr.length - 1; i > 0; i--) {
|
|
104
|
+
const j = getRandomInt(i + 1);
|
|
105
|
+
[arr[i], arr[j]] = [arr[j], arr[i]];
|
|
106
|
+
}
|
|
107
|
+
return arr.join("");
|
|
201
108
|
}
|
|
202
109
|
function generatePassword(props = {}) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
activeCharsets.push(charsets.uppercase);
|
|
242
|
-
if (useLowercase && charsets.lowercase)
|
|
243
|
-
activeCharsets.push(charsets.lowercase);
|
|
244
|
-
if (useNumbers && charsets.numbers) activeCharsets.push(charsets.numbers);
|
|
245
|
-
if (useSymbols && charsets.symbols) activeCharsets.push(charsets.symbols);
|
|
246
|
-
const fullCharset = activeCharsets.join("");
|
|
247
|
-
if (fullCharset.length === 0) {
|
|
248
|
-
throw new Error("No valid characters to generate password.");
|
|
249
|
-
}
|
|
250
|
-
const generateSinglePassword = () => {
|
|
251
|
-
const passwordChars = [];
|
|
252
|
-
const addGuaranteed = (count2, set) => {
|
|
253
|
-
if (count2 > 0 && set.length > 0) {
|
|
254
|
-
for (let i = 0; i < count2; i++) {
|
|
255
|
-
passwordChars.push(set[getRandomInt(set.length)]);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
if (useUppercase) addGuaranteed(minUppercase, charsets.uppercase);
|
|
260
|
-
if (useLowercase) addGuaranteed(minLowercase, charsets.lowercase);
|
|
261
|
-
if (useNumbers) addGuaranteed(minNumbers, charsets.numbers);
|
|
262
|
-
if (useSymbols) addGuaranteed(minSymbols, charsets.symbols);
|
|
263
|
-
if (passwordChars.length > length) {
|
|
264
|
-
throw new Error(
|
|
265
|
-
"Minimum character requirements exceed requested password length."
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
const remainingLength = length - passwordChars.length;
|
|
269
|
-
for (let i = 0; i < remainingLength; i++) {
|
|
270
|
-
passwordChars.push(fullCharset[getRandomInt(fullCharset.length)]);
|
|
271
|
-
}
|
|
272
|
-
return shuffleString(passwordChars.join(""));
|
|
273
|
-
};
|
|
274
|
-
if (count === 1) return generateSinglePassword();
|
|
275
|
-
return Array.from({ length: count }, () => generateSinglePassword());
|
|
110
|
+
const { length = 12, useNumbers = true, useUppercase = true, useLowercase = true, useSymbols = false, excludeSimilarCharacters = false, exclude = "", count = 1, minUppercase = 0, minLowercase = 0, minNumbers = 0, minSymbols = 0, customUppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", customLowercase = "abcdefghijklmnopqrstuvwxyz", customNumbers = "0123456789", customSymbols = "@#$%^&*()_+=<>?/|" } = props;
|
|
111
|
+
generatePasswordPropValidation(props);
|
|
112
|
+
const similarChars = "il1Lo0O";
|
|
113
|
+
const filterCharset = (base) => {
|
|
114
|
+
let result = base;
|
|
115
|
+
if (excludeSimilarCharacters) result = result.split("").filter((char) => !similarChars.includes(char)).join("");
|
|
116
|
+
if (exclude) result = result.split("").filter((char) => !exclude.includes(char)).join("");
|
|
117
|
+
return result;
|
|
118
|
+
};
|
|
119
|
+
const charsets = {
|
|
120
|
+
uppercase: filterCharset(customUppercase),
|
|
121
|
+
lowercase: filterCharset(customLowercase),
|
|
122
|
+
numbers: filterCharset(customNumbers),
|
|
123
|
+
symbols: filterCharset(customSymbols)
|
|
124
|
+
};
|
|
125
|
+
const activeCharsets = [];
|
|
126
|
+
if (useUppercase && charsets.uppercase) activeCharsets.push(charsets.uppercase);
|
|
127
|
+
if (useLowercase && charsets.lowercase) activeCharsets.push(charsets.lowercase);
|
|
128
|
+
if (useNumbers && charsets.numbers) activeCharsets.push(charsets.numbers);
|
|
129
|
+
if (useSymbols && charsets.symbols) activeCharsets.push(charsets.symbols);
|
|
130
|
+
const fullCharset = activeCharsets.join("");
|
|
131
|
+
if (fullCharset.length === 0) throw new Error("No valid characters to generate password.");
|
|
132
|
+
const generateSinglePassword = () => {
|
|
133
|
+
const passwordChars = [];
|
|
134
|
+
const addGuaranteed = (count, set) => {
|
|
135
|
+
if (count > 0 && set.length > 0) for (let i = 0; i < count; i++) passwordChars.push(set[getRandomInt(set.length)]);
|
|
136
|
+
};
|
|
137
|
+
if (useUppercase) addGuaranteed(minUppercase, charsets.uppercase);
|
|
138
|
+
if (useLowercase) addGuaranteed(minLowercase, charsets.lowercase);
|
|
139
|
+
if (useNumbers) addGuaranteed(minNumbers, charsets.numbers);
|
|
140
|
+
if (useSymbols) addGuaranteed(minSymbols, charsets.symbols);
|
|
141
|
+
if (passwordChars.length > length) throw new Error("Minimum character requirements exceed requested password length.");
|
|
142
|
+
const remainingLength = length - passwordChars.length;
|
|
143
|
+
for (let i = 0; i < remainingLength; i++) passwordChars.push(fullCharset[getRandomInt(fullCharset.length)]);
|
|
144
|
+
return shuffleString(passwordChars.join(""));
|
|
145
|
+
};
|
|
146
|
+
if (count === 1) return generateSinglePassword();
|
|
147
|
+
return Array.from({ length: count }, () => generateSinglePassword());
|
|
276
148
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
useUppercaseError
|
|
292
|
-
});
|
|
149
|
+
//#endregion
|
|
150
|
+
exports.GeneratePasswordPropsEnum = GeneratePasswordPropsEnum;
|
|
151
|
+
exports.allOptionsFalseError = allOptionsFalseError;
|
|
152
|
+
exports.calculatePasswordEntropy = calculatePasswordEntropy;
|
|
153
|
+
exports.countError = countError;
|
|
154
|
+
exports.excludeError = excludeError;
|
|
155
|
+
exports.excludeSimilarCharactersError = excludeSimilarCharactersError;
|
|
156
|
+
exports.generatePassword = generatePassword;
|
|
157
|
+
exports.lengthError = lengthError;
|
|
158
|
+
exports.unwantedPropsError = unwantedPropsError;
|
|
159
|
+
exports.useLowercaseError = useLowercaseError;
|
|
160
|
+
exports.useNumbersError = useNumbersError;
|
|
161
|
+
exports.useSymbolsError = useSymbolsError;
|
|
162
|
+
exports.useUppercaseError = useUppercaseError;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,54 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
//#region src/enum/props.enum.d.ts
|
|
2
|
+
export declare enum GeneratePasswordPropsEnum {
|
|
3
|
+
LENGTH = "length",
|
|
4
|
+
USE_NUMBERS = "useNumbers",
|
|
5
|
+
USE_UPPERCASE = "useUppercase",
|
|
6
|
+
USE_LOWERCASE = "useLowercase",
|
|
7
|
+
USE_SYMBOLS = "useSymbols",
|
|
8
|
+
EXCLUDE_SIMILAR_CHARACTERS = "excludeSimilarCharacters",
|
|
9
|
+
EXCLUDE = "exclude",
|
|
10
|
+
COUNT = "count",
|
|
11
|
+
MIN_NUMBERS = "minNumbers",
|
|
12
|
+
MIN_UPPERCASE = "minUppercase",
|
|
13
|
+
MIN_LOWERCASE = "minLowercase",
|
|
14
|
+
MIN_SYMBOLS = "minSymbols",
|
|
15
|
+
CUSTOM_LOWERCASE = "customLowercase",
|
|
16
|
+
CUSTOM_UPPERCASE = "customUppercase",
|
|
17
|
+
CUSTOM_NUMBERS = "customNumbers",
|
|
18
|
+
CUSTOM_SYMBOLS = "customSymbols"
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
interface ExtendedGeneratePasswordFunctionProps extends GeneratePasswordFunctionProps {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/types/props.types.d.ts
|
|
22
|
+
export type GeneratePasswordFunctionProps = { [key in GeneratePasswordPropsEnum]?: key extends GeneratePasswordPropsEnum.LENGTH | GeneratePasswordPropsEnum.COUNT | GeneratePasswordPropsEnum.MIN_NUMBERS | GeneratePasswordPropsEnum.MIN_UPPERCASE | GeneratePasswordPropsEnum.MIN_LOWERCASE | GeneratePasswordPropsEnum.MIN_SYMBOLS ? number : key extends GeneratePasswordPropsEnum.EXCLUDE | GeneratePasswordPropsEnum.CUSTOM_LOWERCASE | GeneratePasswordPropsEnum.CUSTOM_UPPERCASE | GeneratePasswordPropsEnum.CUSTOM_NUMBERS | GeneratePasswordPropsEnum.CUSTOM_SYMBOLS ? string : key extends GeneratePasswordPropsEnum.USE_NUMBERS | GeneratePasswordPropsEnum.USE_UPPERCASE | GeneratePasswordPropsEnum.USE_LOWERCASE | GeneratePasswordPropsEnum.USE_SYMBOLS | GeneratePasswordPropsEnum.EXCLUDE_SIMILAR_CHARACTERS ? boolean : never; };
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/functions/generate.function.d.ts
|
|
25
|
+
export interface ExtendedGeneratePasswordFunctionProps extends GeneratePasswordFunctionProps {
|
|
26
|
+
minUppercase?: number;
|
|
27
|
+
minLowercase?: number;
|
|
28
|
+
minNumbers?: number;
|
|
29
|
+
minSymbols?: number;
|
|
30
|
+
customUppercase?: string;
|
|
31
|
+
customLowercase?: string;
|
|
32
|
+
customNumbers?: string;
|
|
33
|
+
customSymbols?: string;
|
|
33
34
|
}
|
|
34
|
-
declare function calculatePasswordEntropy(length: number, charsetSize: number): number;
|
|
35
|
-
declare function generatePassword(props?: ExtendedGeneratePasswordFunctionProps): string | string[];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
export declare function calculatePasswordEntropy(length: number, charsetSize: number): number;
|
|
36
|
+
export declare function generatePassword(props?: ExtendedGeneratePasswordFunctionProps): string | string[];
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/utils/error.message.d.ts
|
|
39
|
+
export declare const lengthError: {
|
|
40
|
+
invalidLength: string;
|
|
41
|
+
lengthTooLarge: string;
|
|
40
42
|
};
|
|
41
|
-
declare const useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
42
|
-
declare const useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
43
|
-
declare const useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
44
|
-
declare const useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
45
|
-
declare const excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
46
|
-
declare const excludeError = "Invalid exclude. It must be a string.";
|
|
47
|
-
declare const countError: {
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
export declare const useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
44
|
+
export declare const useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
45
|
+
export declare const useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
46
|
+
export declare const useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
47
|
+
export declare const excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
48
|
+
export declare const excludeError = "Invalid exclude. It must be a string.";
|
|
49
|
+
export declare const countError: {
|
|
50
|
+
invalidCount: string;
|
|
51
|
+
countTooLarge: string;
|
|
50
52
|
};
|
|
51
|
-
declare const unwantedPropsError: (unwantedProps: string[]) => string;
|
|
52
|
-
declare const allOptionsFalseError = "At least one of the options must be true.";
|
|
53
|
-
|
|
54
|
-
export { type ExtendedGeneratePasswordFunctionProps, type GeneratePasswordFunctionProps, GeneratePasswordPropsEnum, allOptionsFalseError, calculatePasswordEntropy, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
|
53
|
+
export declare const unwantedPropsError: (unwantedProps: string[]) => string;
|
|
54
|
+
export declare const allOptionsFalseError = "At least one of the options must be true.";
|
|
55
|
+
//#endregion
|
package/dist/index.d.ts
CHANGED
|
@@ -1,54 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
//#region src/enum/props.enum.d.ts
|
|
2
|
+
export declare enum GeneratePasswordPropsEnum {
|
|
3
|
+
LENGTH = "length",
|
|
4
|
+
USE_NUMBERS = "useNumbers",
|
|
5
|
+
USE_UPPERCASE = "useUppercase",
|
|
6
|
+
USE_LOWERCASE = "useLowercase",
|
|
7
|
+
USE_SYMBOLS = "useSymbols",
|
|
8
|
+
EXCLUDE_SIMILAR_CHARACTERS = "excludeSimilarCharacters",
|
|
9
|
+
EXCLUDE = "exclude",
|
|
10
|
+
COUNT = "count",
|
|
11
|
+
MIN_NUMBERS = "minNumbers",
|
|
12
|
+
MIN_UPPERCASE = "minUppercase",
|
|
13
|
+
MIN_LOWERCASE = "minLowercase",
|
|
14
|
+
MIN_SYMBOLS = "minSymbols",
|
|
15
|
+
CUSTOM_LOWERCASE = "customLowercase",
|
|
16
|
+
CUSTOM_UPPERCASE = "customUppercase",
|
|
17
|
+
CUSTOM_NUMBERS = "customNumbers",
|
|
18
|
+
CUSTOM_SYMBOLS = "customSymbols"
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
interface ExtendedGeneratePasswordFunctionProps extends GeneratePasswordFunctionProps {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/types/props.types.d.ts
|
|
22
|
+
export type GeneratePasswordFunctionProps = { [key in GeneratePasswordPropsEnum]?: key extends GeneratePasswordPropsEnum.LENGTH | GeneratePasswordPropsEnum.COUNT | GeneratePasswordPropsEnum.MIN_NUMBERS | GeneratePasswordPropsEnum.MIN_UPPERCASE | GeneratePasswordPropsEnum.MIN_LOWERCASE | GeneratePasswordPropsEnum.MIN_SYMBOLS ? number : key extends GeneratePasswordPropsEnum.EXCLUDE | GeneratePasswordPropsEnum.CUSTOM_LOWERCASE | GeneratePasswordPropsEnum.CUSTOM_UPPERCASE | GeneratePasswordPropsEnum.CUSTOM_NUMBERS | GeneratePasswordPropsEnum.CUSTOM_SYMBOLS ? string : key extends GeneratePasswordPropsEnum.USE_NUMBERS | GeneratePasswordPropsEnum.USE_UPPERCASE | GeneratePasswordPropsEnum.USE_LOWERCASE | GeneratePasswordPropsEnum.USE_SYMBOLS | GeneratePasswordPropsEnum.EXCLUDE_SIMILAR_CHARACTERS ? boolean : never; };
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/functions/generate.function.d.ts
|
|
25
|
+
export interface ExtendedGeneratePasswordFunctionProps extends GeneratePasswordFunctionProps {
|
|
26
|
+
minUppercase?: number;
|
|
27
|
+
minLowercase?: number;
|
|
28
|
+
minNumbers?: number;
|
|
29
|
+
minSymbols?: number;
|
|
30
|
+
customUppercase?: string;
|
|
31
|
+
customLowercase?: string;
|
|
32
|
+
customNumbers?: string;
|
|
33
|
+
customSymbols?: string;
|
|
33
34
|
}
|
|
34
|
-
declare function calculatePasswordEntropy(length: number, charsetSize: number): number;
|
|
35
|
-
declare function generatePassword(props?: ExtendedGeneratePasswordFunctionProps): string | string[];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
export declare function calculatePasswordEntropy(length: number, charsetSize: number): number;
|
|
36
|
+
export declare function generatePassword(props?: ExtendedGeneratePasswordFunctionProps): string | string[];
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/utils/error.message.d.ts
|
|
39
|
+
export declare const lengthError: {
|
|
40
|
+
invalidLength: string;
|
|
41
|
+
lengthTooLarge: string;
|
|
40
42
|
};
|
|
41
|
-
declare const useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
42
|
-
declare const useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
43
|
-
declare const useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
44
|
-
declare const useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
45
|
-
declare const excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
46
|
-
declare const excludeError = "Invalid exclude. It must be a string.";
|
|
47
|
-
declare const countError: {
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
export declare const useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
44
|
+
export declare const useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
45
|
+
export declare const useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
46
|
+
export declare const useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
47
|
+
export declare const excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
48
|
+
export declare const excludeError = "Invalid exclude. It must be a string.";
|
|
49
|
+
export declare const countError: {
|
|
50
|
+
invalidCount: string;
|
|
51
|
+
countTooLarge: string;
|
|
50
52
|
};
|
|
51
|
-
declare const unwantedPropsError: (unwantedProps: string[]) => string;
|
|
52
|
-
declare const allOptionsFalseError = "At least one of the options must be true.";
|
|
53
|
-
|
|
54
|
-
export { type ExtendedGeneratePasswordFunctionProps, type GeneratePasswordFunctionProps, GeneratePasswordPropsEnum, allOptionsFalseError, calculatePasswordEntropy, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
|
53
|
+
export declare const unwantedPropsError: (unwantedProps: string[]) => string;
|
|
54
|
+
export declare const allOptionsFalseError = "At least one of the options must be true.";
|
|
55
|
+
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -1,253 +1,149 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
//#region src/enum/props.enum.ts
|
|
2
|
+
let GeneratePasswordPropsEnum = /* @__PURE__ */ function(GeneratePasswordPropsEnum) {
|
|
3
|
+
GeneratePasswordPropsEnum["LENGTH"] = "length";
|
|
4
|
+
GeneratePasswordPropsEnum["USE_NUMBERS"] = "useNumbers";
|
|
5
|
+
GeneratePasswordPropsEnum["USE_UPPERCASE"] = "useUppercase";
|
|
6
|
+
GeneratePasswordPropsEnum["USE_LOWERCASE"] = "useLowercase";
|
|
7
|
+
GeneratePasswordPropsEnum["USE_SYMBOLS"] = "useSymbols";
|
|
8
|
+
GeneratePasswordPropsEnum["EXCLUDE_SIMILAR_CHARACTERS"] = "excludeSimilarCharacters";
|
|
9
|
+
GeneratePasswordPropsEnum["EXCLUDE"] = "exclude";
|
|
10
|
+
GeneratePasswordPropsEnum["COUNT"] = "count";
|
|
11
|
+
GeneratePasswordPropsEnum["MIN_NUMBERS"] = "minNumbers";
|
|
12
|
+
GeneratePasswordPropsEnum["MIN_UPPERCASE"] = "minUppercase";
|
|
13
|
+
GeneratePasswordPropsEnum["MIN_LOWERCASE"] = "minLowercase";
|
|
14
|
+
GeneratePasswordPropsEnum["MIN_SYMBOLS"] = "minSymbols";
|
|
15
|
+
GeneratePasswordPropsEnum["CUSTOM_LOWERCASE"] = "customLowercase";
|
|
16
|
+
GeneratePasswordPropsEnum["CUSTOM_UPPERCASE"] = "customUppercase";
|
|
17
|
+
GeneratePasswordPropsEnum["CUSTOM_NUMBERS"] = "customNumbers";
|
|
18
|
+
GeneratePasswordPropsEnum["CUSTOM_SYMBOLS"] = "customSymbols";
|
|
19
|
+
return GeneratePasswordPropsEnum;
|
|
20
|
+
}({});
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/utils/error.message.ts
|
|
23
|
+
const lengthError = {
|
|
24
|
+
invalidLength: "Invalid length. Length must be a positive number.",
|
|
25
|
+
lengthTooLarge: "Invalid length. Length must be less than or equal to 100."
|
|
26
26
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
const useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
28
|
+
const useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
29
|
+
const useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
30
|
+
const useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
31
|
+
const excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
32
|
+
const excludeError = "Invalid exclude. It must be a string.";
|
|
33
|
+
const countError = {
|
|
34
|
+
invalidCount: "Invalid count. Count must be a positive number.",
|
|
35
|
+
countTooLarge: "Invalid count. Count must be less than or equal to 10."
|
|
36
36
|
};
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const unwantedPropsError = (unwantedProps) => {
|
|
38
|
+
return `Invalid prop(s): ${unwantedProps.join(", ")}. Only the following options are allowed: length, useNumbers, useUppercase, useLowercase, useSymbols, excludeSimilarCharacters, exclude, count, minNumbers, minUppercase, minLowercase, minSymbols, customUppercase, customLowercase, customNumbers, customSymbols.`;
|
|
39
39
|
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
const allOptionsFalseError = "At least one of the options must be true.";
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/functions/validation.function.ts
|
|
43
|
+
const allValidProps = Object.values(GeneratePasswordPropsEnum);
|
|
44
44
|
function generatePasswordPropValidation(props) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
const checkMin = (val, name) => {
|
|
79
|
-
if (val !== void 0 && (typeof val !== "number" || val < 0)) {
|
|
80
|
-
throw new Error(`${name} must be a non-negative number.`);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
checkMin(minNumbers, "minNumbers");
|
|
84
|
-
checkMin(minUppercase, "minUppercase");
|
|
85
|
-
checkMin(minLowercase, "minLowercase");
|
|
86
|
-
checkMin(minSymbols, "minSymbols");
|
|
87
|
-
const totalMin = (minNumbers ?? 0) + (minUppercase ?? 0) + (minLowercase ?? 0) + (minSymbols ?? 0);
|
|
88
|
-
const len = length ?? 12;
|
|
89
|
-
if (totalMin > len) {
|
|
90
|
-
throw new Error(
|
|
91
|
-
"Total minimum character requirements exceed requested password length."
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
const checkString = (val, name) => {
|
|
95
|
-
if (val !== void 0 && typeof val !== "string") {
|
|
96
|
-
throw new Error(`${name} must be a string.`);
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
checkString(customNumbers, "customNumbers");
|
|
100
|
-
checkString(customUppercase, "customUppercase");
|
|
101
|
-
checkString(customLowercase, "customLowercase");
|
|
102
|
-
checkString(customSymbols, "customSymbols");
|
|
103
|
-
if (useNumbers !== void 0 && typeof useNumbers !== "boolean") {
|
|
104
|
-
throw new Error(useNumbersError);
|
|
105
|
-
}
|
|
106
|
-
if (useUppercase !== void 0 && typeof useUppercase !== "boolean") {
|
|
107
|
-
throw new Error(useUppercaseError);
|
|
108
|
-
}
|
|
109
|
-
if (useLowercase !== void 0 && typeof useLowercase !== "boolean") {
|
|
110
|
-
throw new Error(useLowercaseError);
|
|
111
|
-
}
|
|
112
|
-
if (useSymbols !== void 0 && typeof useSymbols !== "boolean") {
|
|
113
|
-
throw new Error(useSymbolsError);
|
|
114
|
-
}
|
|
115
|
-
if (excludeSimilarCharacters !== void 0 && typeof excludeSimilarCharacters !== "boolean") {
|
|
116
|
-
throw new Error(excludeSimilarCharactersError);
|
|
117
|
-
}
|
|
118
|
-
if (exclude !== void 0 && typeof exclude !== "string") {
|
|
119
|
-
throw new Error(excludeError);
|
|
120
|
-
}
|
|
121
|
-
if (count !== void 0 && (typeof count !== "number" || count < 1)) {
|
|
122
|
-
throw new Error(countError.invalidCount);
|
|
123
|
-
}
|
|
124
|
-
if (count !== void 0 && count > 10) {
|
|
125
|
-
throw new Error(countError.countTooLarge);
|
|
126
|
-
}
|
|
127
|
-
const uN = useNumbers ?? true;
|
|
128
|
-
const uU = useUppercase ?? true;
|
|
129
|
-
const uL = useLowercase ?? true;
|
|
130
|
-
const uS = useSymbols ?? false;
|
|
131
|
-
if (!uN && !uU && !uL && !uS) {
|
|
132
|
-
throw new Error(allOptionsFalseError);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// src/functions/generate.function.ts
|
|
137
|
-
var crypto = globalThis.crypto;
|
|
138
|
-
if (!crypto) {
|
|
139
|
-
throw new Error("Crypto not available. Requires Node 18+ or browser.");
|
|
45
|
+
const unwantedProps = Object.keys(props).filter((prop) => !allValidProps.includes(prop));
|
|
46
|
+
if (unwantedProps.length > 0) throw new Error(unwantedPropsError(unwantedProps));
|
|
47
|
+
const { length, useNumbers, useUppercase, useLowercase, useSymbols, excludeSimilarCharacters, exclude, count, minNumbers, minUppercase, minLowercase, minSymbols, customNumbers, customUppercase, customLowercase, customSymbols } = props;
|
|
48
|
+
if (length !== void 0) {
|
|
49
|
+
if (typeof length !== "number" || length < 1) throw new Error(lengthError.invalidLength);
|
|
50
|
+
if (length > 100) throw new Error(lengthError.lengthTooLarge);
|
|
51
|
+
}
|
|
52
|
+
const checkMin = (val, name) => {
|
|
53
|
+
if (val !== void 0 && (typeof val !== "number" || val < 0)) throw new Error(`${name} must be a non-negative number.`);
|
|
54
|
+
};
|
|
55
|
+
checkMin(minNumbers, "minNumbers");
|
|
56
|
+
checkMin(minUppercase, "minUppercase");
|
|
57
|
+
checkMin(minLowercase, "minLowercase");
|
|
58
|
+
checkMin(minSymbols, "minSymbols");
|
|
59
|
+
if ((minNumbers ?? 0) + (minUppercase ?? 0) + (minLowercase ?? 0) + (minSymbols ?? 0) > (length ?? 12)) throw new Error("Total minimum character requirements exceed requested password length.");
|
|
60
|
+
const checkString = (val, name) => {
|
|
61
|
+
if (val !== void 0 && typeof val !== "string") throw new Error(`${name} must be a string.`);
|
|
62
|
+
};
|
|
63
|
+
checkString(customNumbers, "customNumbers");
|
|
64
|
+
checkString(customUppercase, "customUppercase");
|
|
65
|
+
checkString(customLowercase, "customLowercase");
|
|
66
|
+
checkString(customSymbols, "customSymbols");
|
|
67
|
+
if (useNumbers !== void 0 && typeof useNumbers !== "boolean") throw new Error(useNumbersError);
|
|
68
|
+
if (useUppercase !== void 0 && typeof useUppercase !== "boolean") throw new Error(useUppercaseError);
|
|
69
|
+
if (useLowercase !== void 0 && typeof useLowercase !== "boolean") throw new Error(useLowercaseError);
|
|
70
|
+
if (useSymbols !== void 0 && typeof useSymbols !== "boolean") throw new Error(useSymbolsError);
|
|
71
|
+
if (excludeSimilarCharacters !== void 0 && typeof excludeSimilarCharacters !== "boolean") throw new Error(excludeSimilarCharactersError);
|
|
72
|
+
if (exclude !== void 0 && typeof exclude !== "string") throw new Error(excludeError);
|
|
73
|
+
if (count !== void 0 && (typeof count !== "number" || count < 1)) throw new Error(countError.invalidCount);
|
|
74
|
+
if (count !== void 0 && count > 10) throw new Error(countError.countTooLarge);
|
|
75
|
+
if (!(useNumbers ?? true) && !(useUppercase ?? true) && !(useLowercase ?? true) && !(useSymbols ?? false)) throw new Error(allOptionsFalseError);
|
|
140
76
|
}
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/functions/generate.function.ts
|
|
79
|
+
const crypto = globalThis.crypto;
|
|
80
|
+
if (!crypto) throw new Error("Crypto not available. Requires Node 18+ or browser.");
|
|
81
|
+
/**
|
|
82
|
+
* Calculates the theoretical entropy of a password based on its length and charset size.
|
|
83
|
+
* H = L * log2(N)
|
|
84
|
+
*/
|
|
141
85
|
function calculatePasswordEntropy(length, charsetSize) {
|
|
142
|
-
|
|
143
|
-
|
|
86
|
+
if (length <= 0 || charsetSize <= 0) return 0;
|
|
87
|
+
return length * Math.log2(charsetSize);
|
|
144
88
|
}
|
|
145
89
|
function getRandomInt(max) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
90
|
+
if (max <= 1) return 0;
|
|
91
|
+
const array = /* @__PURE__ */ new Uint32Array(1);
|
|
92
|
+
const range = Math.floor(4294967295 / max) * max;
|
|
93
|
+
let randomValue;
|
|
94
|
+
do {
|
|
95
|
+
crypto.getRandomValues(array);
|
|
96
|
+
randomValue = array[0];
|
|
97
|
+
} while (randomValue >= range);
|
|
98
|
+
return randomValue % max;
|
|
155
99
|
}
|
|
156
100
|
function shuffleString(str) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
101
|
+
const arr = str.split("");
|
|
102
|
+
for (let i = arr.length - 1; i > 0; i--) {
|
|
103
|
+
const j = getRandomInt(i + 1);
|
|
104
|
+
[arr[i], arr[j]] = [arr[j], arr[i]];
|
|
105
|
+
}
|
|
106
|
+
return arr.join("");
|
|
163
107
|
}
|
|
164
108
|
function generatePassword(props = {}) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
activeCharsets.push(charsets.uppercase);
|
|
204
|
-
if (useLowercase && charsets.lowercase)
|
|
205
|
-
activeCharsets.push(charsets.lowercase);
|
|
206
|
-
if (useNumbers && charsets.numbers) activeCharsets.push(charsets.numbers);
|
|
207
|
-
if (useSymbols && charsets.symbols) activeCharsets.push(charsets.symbols);
|
|
208
|
-
const fullCharset = activeCharsets.join("");
|
|
209
|
-
if (fullCharset.length === 0) {
|
|
210
|
-
throw new Error("No valid characters to generate password.");
|
|
211
|
-
}
|
|
212
|
-
const generateSinglePassword = () => {
|
|
213
|
-
const passwordChars = [];
|
|
214
|
-
const addGuaranteed = (count2, set) => {
|
|
215
|
-
if (count2 > 0 && set.length > 0) {
|
|
216
|
-
for (let i = 0; i < count2; i++) {
|
|
217
|
-
passwordChars.push(set[getRandomInt(set.length)]);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
if (useUppercase) addGuaranteed(minUppercase, charsets.uppercase);
|
|
222
|
-
if (useLowercase) addGuaranteed(minLowercase, charsets.lowercase);
|
|
223
|
-
if (useNumbers) addGuaranteed(minNumbers, charsets.numbers);
|
|
224
|
-
if (useSymbols) addGuaranteed(minSymbols, charsets.symbols);
|
|
225
|
-
if (passwordChars.length > length) {
|
|
226
|
-
throw new Error(
|
|
227
|
-
"Minimum character requirements exceed requested password length."
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
const remainingLength = length - passwordChars.length;
|
|
231
|
-
for (let i = 0; i < remainingLength; i++) {
|
|
232
|
-
passwordChars.push(fullCharset[getRandomInt(fullCharset.length)]);
|
|
233
|
-
}
|
|
234
|
-
return shuffleString(passwordChars.join(""));
|
|
235
|
-
};
|
|
236
|
-
if (count === 1) return generateSinglePassword();
|
|
237
|
-
return Array.from({ length: count }, () => generateSinglePassword());
|
|
109
|
+
const { length = 12, useNumbers = true, useUppercase = true, useLowercase = true, useSymbols = false, excludeSimilarCharacters = false, exclude = "", count = 1, minUppercase = 0, minLowercase = 0, minNumbers = 0, minSymbols = 0, customUppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", customLowercase = "abcdefghijklmnopqrstuvwxyz", customNumbers = "0123456789", customSymbols = "@#$%^&*()_+=<>?/|" } = props;
|
|
110
|
+
generatePasswordPropValidation(props);
|
|
111
|
+
const similarChars = "il1Lo0O";
|
|
112
|
+
const filterCharset = (base) => {
|
|
113
|
+
let result = base;
|
|
114
|
+
if (excludeSimilarCharacters) result = result.split("").filter((char) => !similarChars.includes(char)).join("");
|
|
115
|
+
if (exclude) result = result.split("").filter((char) => !exclude.includes(char)).join("");
|
|
116
|
+
return result;
|
|
117
|
+
};
|
|
118
|
+
const charsets = {
|
|
119
|
+
uppercase: filterCharset(customUppercase),
|
|
120
|
+
lowercase: filterCharset(customLowercase),
|
|
121
|
+
numbers: filterCharset(customNumbers),
|
|
122
|
+
symbols: filterCharset(customSymbols)
|
|
123
|
+
};
|
|
124
|
+
const activeCharsets = [];
|
|
125
|
+
if (useUppercase && charsets.uppercase) activeCharsets.push(charsets.uppercase);
|
|
126
|
+
if (useLowercase && charsets.lowercase) activeCharsets.push(charsets.lowercase);
|
|
127
|
+
if (useNumbers && charsets.numbers) activeCharsets.push(charsets.numbers);
|
|
128
|
+
if (useSymbols && charsets.symbols) activeCharsets.push(charsets.symbols);
|
|
129
|
+
const fullCharset = activeCharsets.join("");
|
|
130
|
+
if (fullCharset.length === 0) throw new Error("No valid characters to generate password.");
|
|
131
|
+
const generateSinglePassword = () => {
|
|
132
|
+
const passwordChars = [];
|
|
133
|
+
const addGuaranteed = (count, set) => {
|
|
134
|
+
if (count > 0 && set.length > 0) for (let i = 0; i < count; i++) passwordChars.push(set[getRandomInt(set.length)]);
|
|
135
|
+
};
|
|
136
|
+
if (useUppercase) addGuaranteed(minUppercase, charsets.uppercase);
|
|
137
|
+
if (useLowercase) addGuaranteed(minLowercase, charsets.lowercase);
|
|
138
|
+
if (useNumbers) addGuaranteed(minNumbers, charsets.numbers);
|
|
139
|
+
if (useSymbols) addGuaranteed(minSymbols, charsets.symbols);
|
|
140
|
+
if (passwordChars.length > length) throw new Error("Minimum character requirements exceed requested password length.");
|
|
141
|
+
const remainingLength = length - passwordChars.length;
|
|
142
|
+
for (let i = 0; i < remainingLength; i++) passwordChars.push(fullCharset[getRandomInt(fullCharset.length)]);
|
|
143
|
+
return shuffleString(passwordChars.join(""));
|
|
144
|
+
};
|
|
145
|
+
if (count === 1) return generateSinglePassword();
|
|
146
|
+
return Array.from({ length: count }, () => generateSinglePassword());
|
|
238
147
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
allOptionsFalseError,
|
|
242
|
-
calculatePasswordEntropy,
|
|
243
|
-
countError,
|
|
244
|
-
excludeError,
|
|
245
|
-
excludeSimilarCharactersError,
|
|
246
|
-
generatePassword,
|
|
247
|
-
lengthError,
|
|
248
|
-
unwantedPropsError,
|
|
249
|
-
useLowercaseError,
|
|
250
|
-
useNumbersError,
|
|
251
|
-
useSymbolsError,
|
|
252
|
-
useUppercaseError
|
|
253
|
-
};
|
|
148
|
+
//#endregion
|
|
149
|
+
export { GeneratePasswordPropsEnum, allOptionsFalseError, calculatePasswordEntropy, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemix/password",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -38,13 +38,14 @@
|
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"description": "A cryptographically secure password generator with customizable complexity. Part of the Systemix toolkit.",
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^
|
|
42
|
-
"eslint": "^10.0
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"@systemix/typescript": "0.
|
|
41
|
+
"@types/node": "^26.6.5",
|
|
42
|
+
"eslint": "^10.12.0",
|
|
43
|
+
"oxlint": "^1.87.0",
|
|
44
|
+
"oxlint-tsgolint": "^7.0.2004",
|
|
45
|
+
"tsdown": "^0.23.1",
|
|
46
|
+
"typescript": "~7.0.2",
|
|
47
|
+
"@systemix/typescript": "0.6.0",
|
|
48
|
+
"@systemix/runner": "0.3.1"
|
|
48
49
|
},
|
|
49
50
|
"directories": {
|
|
50
51
|
"test": "tests"
|
|
@@ -58,12 +59,13 @@
|
|
|
58
59
|
"README.md",
|
|
59
60
|
"package.json"
|
|
60
61
|
],
|
|
62
|
+
"tsconfig": null,
|
|
61
63
|
"scripts": {
|
|
62
|
-
"build": "
|
|
64
|
+
"build": "tsdown",
|
|
63
65
|
"test": "pnpm build && node tests/run.mjs",
|
|
64
66
|
"typecheck": "tsc --noEmit",
|
|
65
|
-
"lint": "
|
|
66
|
-
"lint:fix": "
|
|
67
|
+
"lint": "oxlint . --type-aware",
|
|
68
|
+
"lint:fix": "oxlint . --type-aware --fix",
|
|
67
69
|
"format": "prettier --check . --ignore-path .prettierignore",
|
|
68
70
|
"format:fix": "prettier --write . --ignore-path .prettierignore",
|
|
69
71
|
"clean": "rimraf dist node_modules",
|