@systemix/password 0.0.1 → 0.0.2
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 +43 -21
- package/dist/index.cjs +125 -42
- package/dist/index.d.cts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +124 -42
- package/package.json +26 -20
- package/dist/index.d.mts +0 -35
- package/dist/index.mjs +0 -158
package/README.md
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Secure**: Uses `crypto.getRandomValues()`
|
|
7
|
+
- **Secure**: Uses `crypto.getRandomValues()` with bias-free distribution for maximum security.
|
|
8
|
+
- **Character Guarantees**: Ensure a minimum number of uppercase, lowercase, numbers, or symbols.
|
|
9
|
+
- **Custom Charsets**: Pass your own character sets for generation.
|
|
10
|
+
- **Entropy Calculation**: Built-in utility to calculate technical password entropy.
|
|
8
11
|
- **Zero Dependencies**: Purely built with Node.js built-ins.
|
|
9
12
|
- **TypeScript Ready**: Full type definitions included.
|
|
10
|
-
- **Customizable**: Control length, character sets (numbers, symbols, uppercase, lowercase), and exclude similar characters.
|
|
11
|
-
- **Validation**: Built-in strict validation for generation options.
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
14
15
|
|
|
@@ -33,37 +34,58 @@ const password = generatePassword({
|
|
|
33
34
|
length: 16,
|
|
34
35
|
useNumbers: true,
|
|
35
36
|
useSymbols: true,
|
|
36
|
-
useUppercase: true,
|
|
37
|
-
useLowercase: true,
|
|
38
37
|
});
|
|
39
38
|
|
|
40
39
|
console.log(password); // Example: "Z#kM@4p*J!h2X&b7"
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
###
|
|
42
|
+
### Guarantees and Character Sets
|
|
44
43
|
|
|
45
44
|
```typescript
|
|
46
|
-
const
|
|
45
|
+
const securePass = generatePassword({
|
|
47
46
|
length: 12,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
minNumbers: 2,
|
|
48
|
+
minSymbols: 2,
|
|
49
|
+
useUppercase: true,
|
|
50
|
+
customSymbols: '!@#$%^&*', // Use specific symbols only
|
|
51
51
|
});
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
### Entropy Calculation
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { calculatePasswordEntropy } from '@systemix/password';
|
|
58
|
+
|
|
59
|
+
const entropy = calculatePasswordEntropy(12, 62); // length, charset size
|
|
60
|
+
console.log(`Entropy: ${entropy} bits`);
|
|
61
|
+
```
|
|
62
|
+
|
|
54
63
|
## API Reference
|
|
55
64
|
|
|
56
|
-
### `generatePassword(props?: PasswordProps): string`
|
|
57
|
-
|
|
58
|
-
| Property | Type | Default
|
|
59
|
-
| :------------------------- | :-------- |
|
|
60
|
-
| `length` | `number` | `
|
|
61
|
-
| `useNumbers` | `boolean` | `true`
|
|
62
|
-
| `useUppercase` | `boolean` | `true`
|
|
63
|
-
| `useLowercase` | `boolean` | `true`
|
|
64
|
-
| `useSymbols` | `boolean` | `false`
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
65
|
+
### `generatePassword(props?: PasswordProps): string | string[]`
|
|
66
|
+
|
|
67
|
+
| Property | Type | Default | Description |
|
|
68
|
+
| :------------------------- | :-------- | :-------- | :------------------------------------ |
|
|
69
|
+
| `length` | `number` | `12` | Password length (1 to 100). |
|
|
70
|
+
| `useNumbers` | `boolean` | `true` | Include 0-9. |
|
|
71
|
+
| `useUppercase` | `boolean` | `true` | Include A-Z. |
|
|
72
|
+
| `useLowercase` | `boolean` | `true` | Include a-z. |
|
|
73
|
+
| `useSymbols` | `boolean` | `false` | Include special characters. |
|
|
74
|
+
| `minNumbers` | `number` | `0` | Minimum numbers to include. |
|
|
75
|
+
| `minUppercase` | `number` | `0` | Minimum uppercase letters to include. |
|
|
76
|
+
| `minLowercase` | `number` | `0` | Minimum lowercase letters to include. |
|
|
77
|
+
| `minSymbols` | `number` | `0` | Minimum symbols to include. |
|
|
78
|
+
| `customNumbers` | `string` | _0-9_ | Custom number set. |
|
|
79
|
+
| `customUppercase` | `string` | _A-Z_ | Custom uppercase set. |
|
|
80
|
+
| `customLowercase` | `string` | _a-z_ | Custom lowercase set. |
|
|
81
|
+
| `customSymbols` | `string` | _Special_ | Custom symbol set. |
|
|
82
|
+
| `excludeSimilarCharacters` | `boolean` | `false` | Exclude visually similar characters. |
|
|
83
|
+
| `exclude` | `string` | `""` | Specific characters to exclude. |
|
|
84
|
+
| `count` | `number` | `1` | Number of passwords to generate. |
|
|
85
|
+
|
|
86
|
+
### `calculatePasswordEntropy(length: number, charsetSize: number): number`
|
|
87
|
+
|
|
88
|
+
Calculates the theoretical entropy of a password (H = L \* log2(N)).
|
|
67
89
|
|
|
68
90
|
## License
|
|
69
91
|
|
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
GeneratePasswordPropsEnum: () => GeneratePasswordPropsEnum,
|
|
24
24
|
allOptionsFalseError: () => allOptionsFalseError,
|
|
25
|
+
calculatePasswordEntropy: () => calculatePasswordEntropy,
|
|
25
26
|
countError: () => countError,
|
|
26
27
|
excludeError: () => excludeError,
|
|
27
28
|
excludeSimilarCharactersError: () => excludeSimilarCharactersError,
|
|
@@ -45,6 +46,14 @@ var GeneratePasswordPropsEnum = /* @__PURE__ */ ((GeneratePasswordPropsEnum2) =>
|
|
|
45
46
|
GeneratePasswordPropsEnum2["EXCLUDE_SIMILAR_CHARACTERS"] = "excludeSimilarCharacters";
|
|
46
47
|
GeneratePasswordPropsEnum2["EXCLUDE"] = "exclude";
|
|
47
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";
|
|
48
57
|
return GeneratePasswordPropsEnum2;
|
|
49
58
|
})(GeneratePasswordPropsEnum || {});
|
|
50
59
|
|
|
@@ -89,14 +98,46 @@ function generatePasswordPropValidation(props) {
|
|
|
89
98
|
useSymbols,
|
|
90
99
|
excludeSimilarCharacters,
|
|
91
100
|
exclude,
|
|
92
|
-
count
|
|
101
|
+
count,
|
|
102
|
+
minNumbers,
|
|
103
|
+
minUppercase,
|
|
104
|
+
minLowercase,
|
|
105
|
+
minSymbols,
|
|
106
|
+
customNumbers,
|
|
107
|
+
customUppercase,
|
|
108
|
+
customLowercase,
|
|
109
|
+
customSymbols
|
|
93
110
|
} = props;
|
|
94
111
|
if (typeof length !== "number" || length < 1) {
|
|
95
112
|
throw new Error(lengthError.invalidLength);
|
|
96
113
|
}
|
|
97
|
-
if (length >
|
|
114
|
+
if (length > 100) {
|
|
98
115
|
throw new Error(lengthError.lengthTooLarge);
|
|
99
116
|
}
|
|
117
|
+
const checkMin = (val, name) => {
|
|
118
|
+
if (val !== void 0 && (typeof val !== "number" || val < 0)) {
|
|
119
|
+
throw new Error(`${name} must be a non-negative number.`);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
checkMin(minNumbers, "minNumbers");
|
|
123
|
+
checkMin(minUppercase, "minUppercase");
|
|
124
|
+
checkMin(minLowercase, "minLowercase");
|
|
125
|
+
checkMin(minSymbols, "minSymbols");
|
|
126
|
+
const totalMin = (minNumbers ?? 0) + (minUppercase ?? 0) + (minLowercase ?? 0) + (minSymbols ?? 0);
|
|
127
|
+
if (totalMin > length) {
|
|
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");
|
|
100
141
|
if (typeof useNumbers !== "boolean") {
|
|
101
142
|
throw new Error(useNumbersError);
|
|
102
143
|
}
|
|
@@ -127,9 +168,32 @@ function generatePasswordPropValidation(props) {
|
|
|
127
168
|
}
|
|
128
169
|
|
|
129
170
|
// src/functions/generate.function.ts
|
|
171
|
+
function calculatePasswordEntropy(length, charsetSize) {
|
|
172
|
+
if (length <= 0 || charsetSize <= 0) return 0;
|
|
173
|
+
return length * Math.log2(charsetSize);
|
|
174
|
+
}
|
|
175
|
+
function getRandomInt(max) {
|
|
176
|
+
if (max <= 1) return 0;
|
|
177
|
+
const array = new Uint32Array(1);
|
|
178
|
+
const range = Math.floor(4294967295 / max) * max;
|
|
179
|
+
let randomValue;
|
|
180
|
+
do {
|
|
181
|
+
import_node_crypto.webcrypto.getRandomValues(array);
|
|
182
|
+
randomValue = array[0];
|
|
183
|
+
} while (randomValue >= range);
|
|
184
|
+
return randomValue % max;
|
|
185
|
+
}
|
|
186
|
+
function shuffleString(str) {
|
|
187
|
+
const arr = str.split("");
|
|
188
|
+
for (let i = arr.length - 1; i > 0; i--) {
|
|
189
|
+
const j = getRandomInt(i + 1);
|
|
190
|
+
[arr[i], arr[j]] = [arr[j], arr[i]];
|
|
191
|
+
}
|
|
192
|
+
return arr.join("");
|
|
193
|
+
}
|
|
130
194
|
function generatePassword(props = {}) {
|
|
131
195
|
const {
|
|
132
|
-
length =
|
|
196
|
+
length = 12,
|
|
133
197
|
useNumbers = true,
|
|
134
198
|
useUppercase = true,
|
|
135
199
|
useLowercase = true,
|
|
@@ -137,57 +201,76 @@ function generatePassword(props = {}) {
|
|
|
137
201
|
excludeSimilarCharacters = false,
|
|
138
202
|
exclude = "",
|
|
139
203
|
count = 1,
|
|
140
|
-
|
|
204
|
+
minUppercase = 0,
|
|
205
|
+
minLowercase = 0,
|
|
206
|
+
minNumbers = 0,
|
|
207
|
+
minSymbols = 0,
|
|
208
|
+
customUppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
209
|
+
customLowercase = "abcdefghijklmnopqrstuvwxyz",
|
|
210
|
+
customNumbers = "0123456789",
|
|
211
|
+
customSymbols = "@#$%^&*()_+=<>?/|"
|
|
141
212
|
} = props;
|
|
142
|
-
|
|
143
|
-
length,
|
|
144
|
-
useNumbers,
|
|
145
|
-
useUppercase,
|
|
146
|
-
useLowercase,
|
|
147
|
-
useSymbols,
|
|
148
|
-
excludeSimilarCharacters,
|
|
149
|
-
exclude,
|
|
150
|
-
count,
|
|
151
|
-
...extraProps
|
|
152
|
-
};
|
|
153
|
-
generatePasswordPropValidation(allProps);
|
|
154
|
-
const lowercaseChars = "abcdefghijklmnopqrstuvwxyz";
|
|
155
|
-
const uppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
156
|
-
const numberChars = "0123456789";
|
|
157
|
-
const symbolChars = "@#$%^&*()_+=<>?/|";
|
|
213
|
+
generatePasswordPropValidation(props);
|
|
158
214
|
const similarChars = "il1Lo0O";
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
215
|
+
const filterCharset = (base) => {
|
|
216
|
+
let result = base;
|
|
217
|
+
if (excludeSimilarCharacters) {
|
|
218
|
+
result = result.split("").filter((char) => !similarChars.includes(char)).join("");
|
|
219
|
+
}
|
|
220
|
+
if (exclude) {
|
|
221
|
+
result = result.split("").filter((char) => !exclude.includes(char)).join("");
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
};
|
|
225
|
+
const charsets = {
|
|
226
|
+
uppercase: filterCharset(customUppercase),
|
|
227
|
+
lowercase: filterCharset(customLowercase),
|
|
228
|
+
numbers: filterCharset(customNumbers),
|
|
229
|
+
symbols: filterCharset(customSymbols)
|
|
230
|
+
};
|
|
231
|
+
const activeCharsets = [];
|
|
232
|
+
if (useUppercase && charsets.uppercase)
|
|
233
|
+
activeCharsets.push(charsets.uppercase);
|
|
234
|
+
if (useLowercase && charsets.lowercase)
|
|
235
|
+
activeCharsets.push(charsets.lowercase);
|
|
236
|
+
if (useNumbers && charsets.numbers) activeCharsets.push(charsets.numbers);
|
|
237
|
+
if (useSymbols && charsets.symbols) activeCharsets.push(charsets.symbols);
|
|
238
|
+
const fullCharset = activeCharsets.join("");
|
|
239
|
+
if (fullCharset.length === 0) {
|
|
176
240
|
throw new Error("No valid characters to generate password.");
|
|
177
241
|
}
|
|
178
242
|
const generateSinglePassword = () => {
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
243
|
+
const passwordChars = [];
|
|
244
|
+
const addGuaranteed = (count2, set) => {
|
|
245
|
+
if (count2 > 0 && set.length > 0) {
|
|
246
|
+
for (let i = 0; i < count2; i++) {
|
|
247
|
+
passwordChars.push(set[getRandomInt(set.length)]);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
if (useUppercase) addGuaranteed(minUppercase, charsets.uppercase);
|
|
252
|
+
if (useLowercase) addGuaranteed(minLowercase, charsets.lowercase);
|
|
253
|
+
if (useNumbers) addGuaranteed(minNumbers, charsets.numbers);
|
|
254
|
+
if (useSymbols) addGuaranteed(minSymbols, charsets.symbols);
|
|
255
|
+
if (passwordChars.length > length) {
|
|
256
|
+
throw new Error(
|
|
257
|
+
"Minimum character requirements exceed requested password length."
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
const remainingLength = length - passwordChars.length;
|
|
261
|
+
for (let i = 0; i < remainingLength; i++) {
|
|
262
|
+
passwordChars.push(fullCharset[getRandomInt(fullCharset.length)]);
|
|
263
|
+
}
|
|
264
|
+
return shuffleString(passwordChars.join(""));
|
|
183
265
|
};
|
|
184
266
|
if (count === 1) return generateSinglePassword();
|
|
185
|
-
return Array.from({ length: count }, generateSinglePassword);
|
|
267
|
+
return Array.from({ length: count }, () => generateSinglePassword());
|
|
186
268
|
}
|
|
187
269
|
// Annotate the CommonJS export names for ESM import in node:
|
|
188
270
|
0 && (module.exports = {
|
|
189
271
|
GeneratePasswordPropsEnum,
|
|
190
272
|
allOptionsFalseError,
|
|
273
|
+
calculatePasswordEntropy,
|
|
191
274
|
countError,
|
|
192
275
|
excludeError,
|
|
193
276
|
excludeSimilarCharactersError,
|
package/dist/index.d.cts
CHANGED
|
@@ -6,14 +6,33 @@ declare enum GeneratePasswordPropsEnum {
|
|
|
6
6
|
USE_SYMBOLS = "useSymbols",
|
|
7
7
|
EXCLUDE_SIMILAR_CHARACTERS = "excludeSimilarCharacters",
|
|
8
8
|
EXCLUDE = "exclude",
|
|
9
|
-
COUNT = "count"
|
|
9
|
+
COUNT = "count",
|
|
10
|
+
MIN_NUMBERS = "minNumbers",
|
|
11
|
+
MIN_UPPERCASE = "minUppercase",
|
|
12
|
+
MIN_LOWERCASE = "minLowercase",
|
|
13
|
+
MIN_SYMBOLS = "minSymbols",
|
|
14
|
+
CUSTOM_LOWERCASE = "customLowercase",
|
|
15
|
+
CUSTOM_UPPERCASE = "customUppercase",
|
|
16
|
+
CUSTOM_NUMBERS = "customNumbers",
|
|
17
|
+
CUSTOM_SYMBOLS = "customSymbols"
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
type GeneratePasswordFunctionProps = {
|
|
13
|
-
[key in GeneratePasswordPropsEnum]?: key extends GeneratePasswordPropsEnum.LENGTH | GeneratePasswordPropsEnum.COUNT ? number : key extends GeneratePasswordPropsEnum.EXCLUDE ? string : key extends GeneratePasswordPropsEnum.USE_NUMBERS | GeneratePasswordPropsEnum.USE_UPPERCASE | GeneratePasswordPropsEnum.USE_LOWERCASE | GeneratePasswordPropsEnum.USE_SYMBOLS | GeneratePasswordPropsEnum.EXCLUDE_SIMILAR_CHARACTERS ? boolean : never;
|
|
21
|
+
[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;
|
|
14
22
|
};
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
interface ExtendedGeneratePasswordFunctionProps extends GeneratePasswordFunctionProps {
|
|
25
|
+
minUppercase?: number;
|
|
26
|
+
minLowercase?: number;
|
|
27
|
+
minNumbers?: number;
|
|
28
|
+
minSymbols?: number;
|
|
29
|
+
customUppercase?: string;
|
|
30
|
+
customLowercase?: string;
|
|
31
|
+
customNumbers?: string;
|
|
32
|
+
customSymbols?: string;
|
|
33
|
+
}
|
|
34
|
+
declare function calculatePasswordEntropy(length: number, charsetSize: number): number;
|
|
35
|
+
declare function generatePassword(props?: ExtendedGeneratePasswordFunctionProps): string | string[];
|
|
17
36
|
|
|
18
37
|
declare const lengthError: {
|
|
19
38
|
invalidLength: string;
|
|
@@ -32,4 +51,4 @@ declare const countError: {
|
|
|
32
51
|
declare const unwantedPropsError: (unwantedProps: string[]) => string;
|
|
33
52
|
declare const allOptionsFalseError = "At least one of the options must be true.";
|
|
34
53
|
|
|
35
|
-
export { type GeneratePasswordFunctionProps, GeneratePasswordPropsEnum, allOptionsFalseError, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
|
54
|
+
export { type ExtendedGeneratePasswordFunctionProps, type GeneratePasswordFunctionProps, GeneratePasswordPropsEnum, allOptionsFalseError, calculatePasswordEntropy, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,14 +6,33 @@ declare enum GeneratePasswordPropsEnum {
|
|
|
6
6
|
USE_SYMBOLS = "useSymbols",
|
|
7
7
|
EXCLUDE_SIMILAR_CHARACTERS = "excludeSimilarCharacters",
|
|
8
8
|
EXCLUDE = "exclude",
|
|
9
|
-
COUNT = "count"
|
|
9
|
+
COUNT = "count",
|
|
10
|
+
MIN_NUMBERS = "minNumbers",
|
|
11
|
+
MIN_UPPERCASE = "minUppercase",
|
|
12
|
+
MIN_LOWERCASE = "minLowercase",
|
|
13
|
+
MIN_SYMBOLS = "minSymbols",
|
|
14
|
+
CUSTOM_LOWERCASE = "customLowercase",
|
|
15
|
+
CUSTOM_UPPERCASE = "customUppercase",
|
|
16
|
+
CUSTOM_NUMBERS = "customNumbers",
|
|
17
|
+
CUSTOM_SYMBOLS = "customSymbols"
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
type GeneratePasswordFunctionProps = {
|
|
13
|
-
[key in GeneratePasswordPropsEnum]?: key extends GeneratePasswordPropsEnum.LENGTH | GeneratePasswordPropsEnum.COUNT ? number : key extends GeneratePasswordPropsEnum.EXCLUDE ? string : key extends GeneratePasswordPropsEnum.USE_NUMBERS | GeneratePasswordPropsEnum.USE_UPPERCASE | GeneratePasswordPropsEnum.USE_LOWERCASE | GeneratePasswordPropsEnum.USE_SYMBOLS | GeneratePasswordPropsEnum.EXCLUDE_SIMILAR_CHARACTERS ? boolean : never;
|
|
21
|
+
[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;
|
|
14
22
|
};
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
interface ExtendedGeneratePasswordFunctionProps extends GeneratePasswordFunctionProps {
|
|
25
|
+
minUppercase?: number;
|
|
26
|
+
minLowercase?: number;
|
|
27
|
+
minNumbers?: number;
|
|
28
|
+
minSymbols?: number;
|
|
29
|
+
customUppercase?: string;
|
|
30
|
+
customLowercase?: string;
|
|
31
|
+
customNumbers?: string;
|
|
32
|
+
customSymbols?: string;
|
|
33
|
+
}
|
|
34
|
+
declare function calculatePasswordEntropy(length: number, charsetSize: number): number;
|
|
35
|
+
declare function generatePassword(props?: ExtendedGeneratePasswordFunctionProps): string | string[];
|
|
17
36
|
|
|
18
37
|
declare const lengthError: {
|
|
19
38
|
invalidLength: string;
|
|
@@ -32,4 +51,4 @@ declare const countError: {
|
|
|
32
51
|
declare const unwantedPropsError: (unwantedProps: string[]) => string;
|
|
33
52
|
declare const allOptionsFalseError = "At least one of the options must be true.";
|
|
34
53
|
|
|
35
|
-
export { type GeneratePasswordFunctionProps, GeneratePasswordPropsEnum, allOptionsFalseError, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
|
54
|
+
export { type ExtendedGeneratePasswordFunctionProps, type GeneratePasswordFunctionProps, GeneratePasswordPropsEnum, allOptionsFalseError, calculatePasswordEntropy, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,14 @@ var GeneratePasswordPropsEnum = /* @__PURE__ */ ((GeneratePasswordPropsEnum2) =>
|
|
|
8
8
|
GeneratePasswordPropsEnum2["EXCLUDE_SIMILAR_CHARACTERS"] = "excludeSimilarCharacters";
|
|
9
9
|
GeneratePasswordPropsEnum2["EXCLUDE"] = "exclude";
|
|
10
10
|
GeneratePasswordPropsEnum2["COUNT"] = "count";
|
|
11
|
+
GeneratePasswordPropsEnum2["MIN_NUMBERS"] = "minNumbers";
|
|
12
|
+
GeneratePasswordPropsEnum2["MIN_UPPERCASE"] = "minUppercase";
|
|
13
|
+
GeneratePasswordPropsEnum2["MIN_LOWERCASE"] = "minLowercase";
|
|
14
|
+
GeneratePasswordPropsEnum2["MIN_SYMBOLS"] = "minSymbols";
|
|
15
|
+
GeneratePasswordPropsEnum2["CUSTOM_LOWERCASE"] = "customLowercase";
|
|
16
|
+
GeneratePasswordPropsEnum2["CUSTOM_UPPERCASE"] = "customUppercase";
|
|
17
|
+
GeneratePasswordPropsEnum2["CUSTOM_NUMBERS"] = "customNumbers";
|
|
18
|
+
GeneratePasswordPropsEnum2["CUSTOM_SYMBOLS"] = "customSymbols";
|
|
11
19
|
return GeneratePasswordPropsEnum2;
|
|
12
20
|
})(GeneratePasswordPropsEnum || {});
|
|
13
21
|
|
|
@@ -52,14 +60,46 @@ function generatePasswordPropValidation(props) {
|
|
|
52
60
|
useSymbols,
|
|
53
61
|
excludeSimilarCharacters,
|
|
54
62
|
exclude,
|
|
55
|
-
count
|
|
63
|
+
count,
|
|
64
|
+
minNumbers,
|
|
65
|
+
minUppercase,
|
|
66
|
+
minLowercase,
|
|
67
|
+
minSymbols,
|
|
68
|
+
customNumbers,
|
|
69
|
+
customUppercase,
|
|
70
|
+
customLowercase,
|
|
71
|
+
customSymbols
|
|
56
72
|
} = props;
|
|
57
73
|
if (typeof length !== "number" || length < 1) {
|
|
58
74
|
throw new Error(lengthError.invalidLength);
|
|
59
75
|
}
|
|
60
|
-
if (length >
|
|
76
|
+
if (length > 100) {
|
|
61
77
|
throw new Error(lengthError.lengthTooLarge);
|
|
62
78
|
}
|
|
79
|
+
const checkMin = (val, name) => {
|
|
80
|
+
if (val !== void 0 && (typeof val !== "number" || val < 0)) {
|
|
81
|
+
throw new Error(`${name} must be a non-negative number.`);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
checkMin(minNumbers, "minNumbers");
|
|
85
|
+
checkMin(minUppercase, "minUppercase");
|
|
86
|
+
checkMin(minLowercase, "minLowercase");
|
|
87
|
+
checkMin(minSymbols, "minSymbols");
|
|
88
|
+
const totalMin = (minNumbers ?? 0) + (minUppercase ?? 0) + (minLowercase ?? 0) + (minSymbols ?? 0);
|
|
89
|
+
if (totalMin > length) {
|
|
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");
|
|
63
103
|
if (typeof useNumbers !== "boolean") {
|
|
64
104
|
throw new Error(useNumbersError);
|
|
65
105
|
}
|
|
@@ -90,9 +130,32 @@ function generatePasswordPropValidation(props) {
|
|
|
90
130
|
}
|
|
91
131
|
|
|
92
132
|
// src/functions/generate.function.ts
|
|
133
|
+
function calculatePasswordEntropy(length, charsetSize) {
|
|
134
|
+
if (length <= 0 || charsetSize <= 0) return 0;
|
|
135
|
+
return length * Math.log2(charsetSize);
|
|
136
|
+
}
|
|
137
|
+
function getRandomInt(max) {
|
|
138
|
+
if (max <= 1) return 0;
|
|
139
|
+
const array = new Uint32Array(1);
|
|
140
|
+
const range = Math.floor(4294967295 / max) * max;
|
|
141
|
+
let randomValue;
|
|
142
|
+
do {
|
|
143
|
+
crypto.getRandomValues(array);
|
|
144
|
+
randomValue = array[0];
|
|
145
|
+
} while (randomValue >= range);
|
|
146
|
+
return randomValue % max;
|
|
147
|
+
}
|
|
148
|
+
function shuffleString(str) {
|
|
149
|
+
const arr = str.split("");
|
|
150
|
+
for (let i = arr.length - 1; i > 0; i--) {
|
|
151
|
+
const j = getRandomInt(i + 1);
|
|
152
|
+
[arr[i], arr[j]] = [arr[j], arr[i]];
|
|
153
|
+
}
|
|
154
|
+
return arr.join("");
|
|
155
|
+
}
|
|
93
156
|
function generatePassword(props = {}) {
|
|
94
157
|
const {
|
|
95
|
-
length =
|
|
158
|
+
length = 12,
|
|
96
159
|
useNumbers = true,
|
|
97
160
|
useUppercase = true,
|
|
98
161
|
useLowercase = true,
|
|
@@ -100,56 +163,75 @@ function generatePassword(props = {}) {
|
|
|
100
163
|
excludeSimilarCharacters = false,
|
|
101
164
|
exclude = "",
|
|
102
165
|
count = 1,
|
|
103
|
-
|
|
166
|
+
minUppercase = 0,
|
|
167
|
+
minLowercase = 0,
|
|
168
|
+
minNumbers = 0,
|
|
169
|
+
minSymbols = 0,
|
|
170
|
+
customUppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
171
|
+
customLowercase = "abcdefghijklmnopqrstuvwxyz",
|
|
172
|
+
customNumbers = "0123456789",
|
|
173
|
+
customSymbols = "@#$%^&*()_+=<>?/|"
|
|
104
174
|
} = props;
|
|
105
|
-
|
|
106
|
-
length,
|
|
107
|
-
useNumbers,
|
|
108
|
-
useUppercase,
|
|
109
|
-
useLowercase,
|
|
110
|
-
useSymbols,
|
|
111
|
-
excludeSimilarCharacters,
|
|
112
|
-
exclude,
|
|
113
|
-
count,
|
|
114
|
-
...extraProps
|
|
115
|
-
};
|
|
116
|
-
generatePasswordPropValidation(allProps);
|
|
117
|
-
const lowercaseChars = "abcdefghijklmnopqrstuvwxyz";
|
|
118
|
-
const uppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
119
|
-
const numberChars = "0123456789";
|
|
120
|
-
const symbolChars = "@#$%^&*()_+=<>?/|";
|
|
175
|
+
generatePasswordPropValidation(props);
|
|
121
176
|
const similarChars = "il1Lo0O";
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
177
|
+
const filterCharset = (base) => {
|
|
178
|
+
let result = base;
|
|
179
|
+
if (excludeSimilarCharacters) {
|
|
180
|
+
result = result.split("").filter((char) => !similarChars.includes(char)).join("");
|
|
181
|
+
}
|
|
182
|
+
if (exclude) {
|
|
183
|
+
result = result.split("").filter((char) => !exclude.includes(char)).join("");
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
};
|
|
187
|
+
const charsets = {
|
|
188
|
+
uppercase: filterCharset(customUppercase),
|
|
189
|
+
lowercase: filterCharset(customLowercase),
|
|
190
|
+
numbers: filterCharset(customNumbers),
|
|
191
|
+
symbols: filterCharset(customSymbols)
|
|
192
|
+
};
|
|
193
|
+
const activeCharsets = [];
|
|
194
|
+
if (useUppercase && charsets.uppercase)
|
|
195
|
+
activeCharsets.push(charsets.uppercase);
|
|
196
|
+
if (useLowercase && charsets.lowercase)
|
|
197
|
+
activeCharsets.push(charsets.lowercase);
|
|
198
|
+
if (useNumbers && charsets.numbers) activeCharsets.push(charsets.numbers);
|
|
199
|
+
if (useSymbols && charsets.symbols) activeCharsets.push(charsets.symbols);
|
|
200
|
+
const fullCharset = activeCharsets.join("");
|
|
201
|
+
if (fullCharset.length === 0) {
|
|
139
202
|
throw new Error("No valid characters to generate password.");
|
|
140
203
|
}
|
|
141
204
|
const generateSinglePassword = () => {
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
205
|
+
const passwordChars = [];
|
|
206
|
+
const addGuaranteed = (count2, set) => {
|
|
207
|
+
if (count2 > 0 && set.length > 0) {
|
|
208
|
+
for (let i = 0; i < count2; i++) {
|
|
209
|
+
passwordChars.push(set[getRandomInt(set.length)]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
if (useUppercase) addGuaranteed(minUppercase, charsets.uppercase);
|
|
214
|
+
if (useLowercase) addGuaranteed(minLowercase, charsets.lowercase);
|
|
215
|
+
if (useNumbers) addGuaranteed(minNumbers, charsets.numbers);
|
|
216
|
+
if (useSymbols) addGuaranteed(minSymbols, charsets.symbols);
|
|
217
|
+
if (passwordChars.length > length) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
"Minimum character requirements exceed requested password length."
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
const remainingLength = length - passwordChars.length;
|
|
223
|
+
for (let i = 0; i < remainingLength; i++) {
|
|
224
|
+
passwordChars.push(fullCharset[getRandomInt(fullCharset.length)]);
|
|
225
|
+
}
|
|
226
|
+
return shuffleString(passwordChars.join(""));
|
|
146
227
|
};
|
|
147
228
|
if (count === 1) return generateSinglePassword();
|
|
148
|
-
return Array.from({ length: count }, generateSinglePassword);
|
|
229
|
+
return Array.from({ length: count }, () => generateSinglePassword());
|
|
149
230
|
}
|
|
150
231
|
export {
|
|
151
232
|
GeneratePasswordPropsEnum,
|
|
152
233
|
allOptionsFalseError,
|
|
234
|
+
calculatePasswordEntropy,
|
|
153
235
|
countError,
|
|
154
236
|
excludeError,
|
|
155
237
|
excludeSimilarCharactersError,
|
package/package.json
CHANGED
|
@@ -1,31 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemix/password",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"private": false,
|
|
8
8
|
"type": "module",
|
|
9
|
-
"main": "./dist/index.
|
|
10
|
-
"module": "./dist/index.
|
|
9
|
+
"main": "./dist/index.cjs",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
"repository": {
|
|
13
20
|
"type": "git",
|
|
14
21
|
"url": "git+https://github.com/shahadathhs/systemix.git",
|
|
15
22
|
"directory": "packages/password"
|
|
16
23
|
},
|
|
17
24
|
"homepage": "https://github.com/shahadathhs/systemix/tree/main/packages/password#readme",
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
20
|
-
"typecheck": "tsc --noEmit",
|
|
21
|
-
"lint": "eslint .",
|
|
22
|
-
"lint:fix": "eslint . --fix",
|
|
23
|
-
"format": "prettier --check . --ignore-path .prettierignore",
|
|
24
|
-
"format:fix": "prettier --write . --ignore-path .prettierignore",
|
|
25
|
-
"clean": "rimraf dist node_modules",
|
|
26
|
-
"clean:turbo": "rimraf .turbo dist node_modules",
|
|
27
|
-
"prepublishOnly": "pnpm build"
|
|
28
|
-
},
|
|
29
25
|
"keywords": [
|
|
30
26
|
"systemix",
|
|
31
27
|
"password",
|
|
@@ -38,16 +34,16 @@
|
|
|
38
34
|
"node",
|
|
39
35
|
"utility"
|
|
40
36
|
],
|
|
41
|
-
"author": "Shahadath
|
|
37
|
+
"author": "Shahadath Hossen Sajib <shahadathhossensajib732@gmail.com> (https://github.com/shahadathhs)",
|
|
42
38
|
"license": "MIT",
|
|
43
39
|
"description": "A cryptographically secure password generator with customizable complexity. Part of the Systemix toolkit.",
|
|
44
40
|
"devDependencies": {
|
|
45
|
-
"@systemix/eslint": "workspace:*",
|
|
46
|
-
"@systemix/typescript": "workspace:*",
|
|
47
41
|
"@types/node": "^25.2.3",
|
|
48
42
|
"eslint": "^10.0.0",
|
|
49
43
|
"tsup": "^8.5.1",
|
|
50
|
-
"typescript": "^5.9.3"
|
|
44
|
+
"typescript": "^5.9.3",
|
|
45
|
+
"@systemix/eslint": "0.0.1",
|
|
46
|
+
"@systemix/typescript": "0.0.1"
|
|
51
47
|
},
|
|
52
48
|
"directories": {
|
|
53
49
|
"test": "tests"
|
|
@@ -63,5 +59,15 @@
|
|
|
63
59
|
"dist",
|
|
64
60
|
"README.md",
|
|
65
61
|
"package.json"
|
|
66
|
-
]
|
|
67
|
-
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"lint": "eslint .",
|
|
67
|
+
"lint:fix": "eslint . --fix",
|
|
68
|
+
"format": "prettier --check . --ignore-path .prettierignore",
|
|
69
|
+
"format:fix": "prettier --write . --ignore-path .prettierignore",
|
|
70
|
+
"clean": "rimraf dist node_modules",
|
|
71
|
+
"clean:turbo": "rimraf .turbo dist node_modules"
|
|
72
|
+
}
|
|
73
|
+
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
declare enum GeneratePasswordPropsEnum {
|
|
2
|
-
LENGTH = "length",
|
|
3
|
-
USE_NUMBERS = "useNumbers",
|
|
4
|
-
USE_UPPERCASE = "useUppercase",
|
|
5
|
-
USE_LOWERCASE = "useLowercase",
|
|
6
|
-
USE_SYMBOLS = "useSymbols",
|
|
7
|
-
EXCLUDE_SIMILAR_CHARACTERS = "excludeSimilarCharacters",
|
|
8
|
-
EXCLUDE = "exclude",
|
|
9
|
-
COUNT = "count"
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type GeneratePasswordFunctionProps = {
|
|
13
|
-
[key in GeneratePasswordPropsEnum]?: key extends GeneratePasswordPropsEnum.LENGTH | GeneratePasswordPropsEnum.COUNT ? number : key extends GeneratePasswordPropsEnum.EXCLUDE ? string : key extends GeneratePasswordPropsEnum.USE_NUMBERS | GeneratePasswordPropsEnum.USE_UPPERCASE | GeneratePasswordPropsEnum.USE_LOWERCASE | GeneratePasswordPropsEnum.USE_SYMBOLS | GeneratePasswordPropsEnum.EXCLUDE_SIMILAR_CHARACTERS ? boolean : never;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
declare function generatePassword(props?: GeneratePasswordFunctionProps): string | string[];
|
|
17
|
-
|
|
18
|
-
declare const lengthError: {
|
|
19
|
-
invalidLength: string;
|
|
20
|
-
lengthTooLarge: string;
|
|
21
|
-
};
|
|
22
|
-
declare const useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
23
|
-
declare const useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
24
|
-
declare const useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
25
|
-
declare const useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
26
|
-
declare const excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
27
|
-
declare const excludeError = "Invalid exclude. It must be a string.";
|
|
28
|
-
declare const countError: {
|
|
29
|
-
invalidCount: string;
|
|
30
|
-
countTooLarge: string;
|
|
31
|
-
};
|
|
32
|
-
declare const unwantedPropsError: (unwantedProps: string[]) => string;
|
|
33
|
-
declare const allOptionsFalseError = "At least one of the options must be true.";
|
|
34
|
-
|
|
35
|
-
export { type GeneratePasswordFunctionProps, GeneratePasswordPropsEnum, allOptionsFalseError, countError, excludeError, excludeSimilarCharactersError, generatePassword, lengthError, unwantedPropsError, useLowercaseError, useNumbersError, useSymbolsError, useUppercaseError };
|
package/dist/index.mjs
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
// src/enum/props.enum.ts
|
|
2
|
-
var GeneratePasswordPropsEnum = /* @__PURE__ */ ((GeneratePasswordPropsEnum2) => {
|
|
3
|
-
GeneratePasswordPropsEnum2["LENGTH"] = "length";
|
|
4
|
-
GeneratePasswordPropsEnum2["USE_NUMBERS"] = "useNumbers";
|
|
5
|
-
GeneratePasswordPropsEnum2["USE_UPPERCASE"] = "useUppercase";
|
|
6
|
-
GeneratePasswordPropsEnum2["USE_LOWERCASE"] = "useLowercase";
|
|
7
|
-
GeneratePasswordPropsEnum2["USE_SYMBOLS"] = "useSymbols";
|
|
8
|
-
GeneratePasswordPropsEnum2["EXCLUDE_SIMILAR_CHARACTERS"] = "excludeSimilarCharacters";
|
|
9
|
-
GeneratePasswordPropsEnum2["EXCLUDE"] = "exclude";
|
|
10
|
-
GeneratePasswordPropsEnum2["COUNT"] = "count";
|
|
11
|
-
return GeneratePasswordPropsEnum2;
|
|
12
|
-
})(GeneratePasswordPropsEnum || {});
|
|
13
|
-
|
|
14
|
-
// src/utils/error.message.ts
|
|
15
|
-
var lengthError = {
|
|
16
|
-
invalidLength: "Invalid length. Length must be a positive number.",
|
|
17
|
-
lengthTooLarge: "Invalid length. Length must be less than or equal to 50."
|
|
18
|
-
};
|
|
19
|
-
var useNumbersError = "Invalid useNumbers. It must be a boolean value.";
|
|
20
|
-
var useUppercaseError = "Invalid useUppercase. It must be a boolean value.";
|
|
21
|
-
var useLowercaseError = "Invalid useLowercase. It must be a boolean value.";
|
|
22
|
-
var useSymbolsError = "Invalid useSymbols. It must be a boolean value.";
|
|
23
|
-
var excludeSimilarCharactersError = "Invalid excludeSimilarCharacters. It must be a boolean value.";
|
|
24
|
-
var excludeError = "Invalid exclude. It must be a string.";
|
|
25
|
-
var countError = {
|
|
26
|
-
invalidCount: "Invalid count. Count must be a positive number.",
|
|
27
|
-
countTooLarge: "Invalid count. Count must be less than or equal to 10."
|
|
28
|
-
};
|
|
29
|
-
var unwantedPropsError = (unwantedProps) => {
|
|
30
|
-
return `Invalid prop(s): ${unwantedProps.join(", ")}. Only the following options are allowed: length, useNumbers, useUppercase, useLowercase, useSymbols, excludeSimilarCharacters, exclude, count.`;
|
|
31
|
-
};
|
|
32
|
-
var allOptionsFalseError = "At least one of the options must be true.";
|
|
33
|
-
|
|
34
|
-
// src/functions/validation.function.ts
|
|
35
|
-
var allValidProps = Object.values(GeneratePasswordPropsEnum);
|
|
36
|
-
function generatePasswordPropValidation(props) {
|
|
37
|
-
const propsValue = Object.keys(props);
|
|
38
|
-
const unwantedProps = propsValue.filter((prop) => !allValidProps.includes(prop));
|
|
39
|
-
if (unwantedProps.length > 0) {
|
|
40
|
-
throw new Error(unwantedPropsError(unwantedProps));
|
|
41
|
-
}
|
|
42
|
-
const {
|
|
43
|
-
length,
|
|
44
|
-
useNumbers,
|
|
45
|
-
useUppercase,
|
|
46
|
-
useLowercase,
|
|
47
|
-
useSymbols,
|
|
48
|
-
excludeSimilarCharacters,
|
|
49
|
-
exclude,
|
|
50
|
-
count
|
|
51
|
-
} = props;
|
|
52
|
-
if (typeof length !== "number" || length < 1) {
|
|
53
|
-
throw new Error(lengthError.invalidLength);
|
|
54
|
-
}
|
|
55
|
-
if (length > 50) {
|
|
56
|
-
throw new Error(lengthError.lengthTooLarge);
|
|
57
|
-
}
|
|
58
|
-
if (typeof useNumbers !== "boolean") {
|
|
59
|
-
throw new Error(useNumbersError);
|
|
60
|
-
}
|
|
61
|
-
if (typeof useUppercase !== "boolean") {
|
|
62
|
-
throw new Error(useUppercaseError);
|
|
63
|
-
}
|
|
64
|
-
if (typeof useLowercase !== "boolean") {
|
|
65
|
-
throw new Error(useLowercaseError);
|
|
66
|
-
}
|
|
67
|
-
if (typeof useSymbols !== "boolean") {
|
|
68
|
-
throw new Error(useSymbolsError);
|
|
69
|
-
}
|
|
70
|
-
if (typeof excludeSimilarCharacters !== "boolean") {
|
|
71
|
-
throw new Error(excludeSimilarCharactersError);
|
|
72
|
-
}
|
|
73
|
-
if (typeof exclude !== "string") {
|
|
74
|
-
throw new Error(excludeError);
|
|
75
|
-
}
|
|
76
|
-
if (typeof count !== "number" || count < 1) {
|
|
77
|
-
throw new Error(countError.invalidCount);
|
|
78
|
-
}
|
|
79
|
-
if (count > 10) {
|
|
80
|
-
throw new Error(countError.countTooLarge);
|
|
81
|
-
}
|
|
82
|
-
if (!useNumbers && !useUppercase && !useLowercase && !useSymbols) {
|
|
83
|
-
throw new Error(allOptionsFalseError);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// src/functions/generate.function.ts
|
|
88
|
-
function generatePassword(props = {}) {
|
|
89
|
-
const {
|
|
90
|
-
length = 8,
|
|
91
|
-
useNumbers = true,
|
|
92
|
-
useUppercase = true,
|
|
93
|
-
useLowercase = true,
|
|
94
|
-
useSymbols = false,
|
|
95
|
-
excludeSimilarCharacters = false,
|
|
96
|
-
exclude = "",
|
|
97
|
-
count = 1,
|
|
98
|
-
...extraProps
|
|
99
|
-
} = props;
|
|
100
|
-
const allProps = {
|
|
101
|
-
length,
|
|
102
|
-
useNumbers,
|
|
103
|
-
useUppercase,
|
|
104
|
-
useLowercase,
|
|
105
|
-
useSymbols,
|
|
106
|
-
excludeSimilarCharacters,
|
|
107
|
-
exclude,
|
|
108
|
-
count,
|
|
109
|
-
...extraProps
|
|
110
|
-
};
|
|
111
|
-
generatePasswordPropValidation(allProps);
|
|
112
|
-
const lowercaseChars = "abcdefghijklmnopqrstuvwxyz";
|
|
113
|
-
const uppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
114
|
-
const numberChars = "0123456789";
|
|
115
|
-
const symbolChars = "@#$%^&*()_+=<>?/|";
|
|
116
|
-
const similarChars = "il1Lo0O";
|
|
117
|
-
let charset = "";
|
|
118
|
-
const charsetOptions = [
|
|
119
|
-
{ condition: useLowercase, value: lowercaseChars },
|
|
120
|
-
{ condition: useUppercase, value: uppercaseChars },
|
|
121
|
-
{ condition: useNumbers, value: numberChars },
|
|
122
|
-
{ condition: useSymbols, value: symbolChars }
|
|
123
|
-
];
|
|
124
|
-
charset = charsetOptions.reduce((acc, { condition, value }) => {
|
|
125
|
-
return condition ? acc + value : acc;
|
|
126
|
-
}, "");
|
|
127
|
-
if (excludeSimilarCharacters) {
|
|
128
|
-
charset = charset.split("").filter((char) => !similarChars.includes(char)).join("");
|
|
129
|
-
}
|
|
130
|
-
if (exclude) {
|
|
131
|
-
charset = charset.split("").filter((char) => !exclude.includes(char)).join("");
|
|
132
|
-
}
|
|
133
|
-
if (charset.length === 0) {
|
|
134
|
-
throw new Error("No valid characters to generate password.");
|
|
135
|
-
}
|
|
136
|
-
const generateSinglePassword = () => {
|
|
137
|
-
const randomIndices = new Uint32Array(length);
|
|
138
|
-
crypto.getRandomValues(randomIndices);
|
|
139
|
-
const password = Array.from(randomIndices).map((index) => charset[index % charset.length]).join("");
|
|
140
|
-
return password;
|
|
141
|
-
};
|
|
142
|
-
if (count === 1) return generateSinglePassword();
|
|
143
|
-
return Array.from({ length: count }, generateSinglePassword);
|
|
144
|
-
}
|
|
145
|
-
export {
|
|
146
|
-
GeneratePasswordPropsEnum,
|
|
147
|
-
allOptionsFalseError,
|
|
148
|
-
countError,
|
|
149
|
-
excludeError,
|
|
150
|
-
excludeSimilarCharactersError,
|
|
151
|
-
generatePassword,
|
|
152
|
-
lengthError,
|
|
153
|
-
unwantedPropsError,
|
|
154
|
-
useLowercaseError,
|
|
155
|
-
useNumbersError,
|
|
156
|
-
useSymbolsError,
|
|
157
|
-
useUppercaseError
|
|
158
|
-
};
|