@salespark/toolkit 2.1.19 → 2.1.21

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.d.cts CHANGED
@@ -1027,8 +1027,83 @@ declare const decodeBase36Code: (code: string, config: EncodeDecodeConfig) => Sa
1027
1027
  identifier: string;
1028
1028
  }>;
1029
1029
 
1030
+ /******************************************************
1031
+ * ##: Password Generator (sync + async modes)
1032
+ * Generates random passwords with optional memorable and pattern-based modes.
1033
+ * Supports deterministic entropy and passphrase words in async mode.
1034
+ * History:
1035
+ * 14-03-2026: Created
1036
+ ****************************************************/
1037
+ type GenerateOptions = {
1038
+ length?: number;
1039
+ memorable?: boolean;
1040
+ pattern?: RegExp;
1041
+ prefix?: string;
1042
+ ignoreSecurityRecommendations?: boolean;
1043
+ entropy?: Uint8Array | string;
1044
+ words?: number;
1045
+ };
1046
+ /******************************************************
1047
+ * ##: Generate Password
1048
+ * Default sync implementation; returns a Promise when async options are used.
1049
+ * @param {Number} length - Password length
1050
+ * @param {Boolean} memorable - Alternates consonants and vowels
1051
+ * @param {RegExp} pattern - Pattern applied to each character
1052
+ * @param {String} prefix - Prefix appended to the password
1053
+ * History:
1054
+ * 14-03-2026: Created
1055
+ ****************************************************/
1056
+ declare function generatePassword(length?: number, memorable?: boolean, pattern?: RegExp, prefix?: string): string;
1057
+ declare function generatePassword(options?: GenerateOptions): string | Promise<string>;
1058
+ /******************************************************
1059
+ * ##: Generate Password (options wrapper)
1060
+ * Full options support including async features (words, entropy).
1061
+ * History:
1062
+ * 14-03-2026: Created
1063
+ ****************************************************/
1064
+ declare const generatePasswordWithOptions: (options?: GenerateOptions) => string | Promise<string>;
1065
+
1066
+ /******************************************************
1067
+ * ##: SMS Length Calculator
1068
+ * Calculates SMS length, segmentation, and encoding based on GSM rules.
1069
+ * Reference: 3GPP TS 23.038 (GSM 03.38)
1070
+ * History:
1071
+ * 14-03-2026: Created
1072
+ ****************************************************/
1073
+ type SmsEncoding = "GSM_7BIT" | "GSM_7BIT_EXT" | "UTF16";
1074
+ declare const GSM_7BIT_REGEXP: RegExp;
1075
+ declare const GSM_7BIT_EXT_REGEXP: RegExp;
1076
+ /******************************************************
1077
+ * Extended GSM characters that consume 2 septets each.
1078
+ * Per 3GPP TS 23.038 Table 3 (Basic Character Set Extension):
1079
+ * ^ { } \ [ ] ~ | €
1080
+ ****************************************************/
1081
+ declare const GSM_7BIT_EXT_CHAR_REGEXP: RegExp;
1082
+ type SmsLengthResult = {
1083
+ encoding: SmsEncoding;
1084
+ length: number;
1085
+ characterPerMessage: number;
1086
+ inCurrentMessage: number;
1087
+ remaining: number;
1088
+ messages: number;
1089
+ };
1090
+ /******************************************************
1091
+ * ##: SMS Length
1092
+ * Calculates encoding, length, and segmentation for an SMS message.
1093
+ * Extended GSM characters (^{}\\[]~|€) each count as 2 septets.
1094
+ * Supports optional per-encoding length overrides for carrier-specific limits.
1095
+ * @param {string} text - SMS message text
1096
+ * @param {Partial<Record<SmsEncoding, number>>} [singleOverrides] - Override
1097
+ * single-segment lengths per encoding
1098
+ * @param {Partial<Record<SmsEncoding, number>>} [multiOverrides] - Override
1099
+ * multi-segment lengths per encoding
1100
+ * History:
1101
+ * 14-03-2026: Created
1102
+ ****************************************************/
1103
+ declare const smsLength: (text: string, singleOverrides?: Partial<Record<SmsEncoding, number>>, multiOverrides?: Partial<Record<SmsEncoding, number>>) => SmsLengthResult;
1104
+
1030
1105
  /** Environment helpers (runtime-agnostic checks) */
1031
1106
  declare const isBrowser: boolean;
1032
1107
  declare const isNode: boolean;
1033
1108
 
1034
- export { type CapitalizeFirstOptions, type CapitalizeWordsOptions, type DeferFn, type EncodeDecodeConfig, type FormatCurrencyProOptions, type HttpResponseLike, type SecurityCheckResult, type SecurityRisk, type SentenceCaseOptions, addSpaceBetweenNumbers, addThousandsSpace, areArraysDeepEqualUnordered, areArraysEqual, assessSecurityRisks, basicSanitize, capitalizeFirst, capitalizeWords, checkMarkdownSecurity, chunk, clamp, cleanObject, compact, currencyToSymbol, debounce, deburr, decodeBase36Code, decodeObject, decodeString, deferAfterResponse, deferAfterResponseNonCritical, deferNonCritical, deferPostReturn, delay, difference, encodeBase36Code, encodeObject, encodeString, fill, flatten, flattenDepth, flattenDepthBase, flattenOnce, formatBytes, formatCurrency, formatCurrencyPro, formatDecimalNumber, getStringSimilarity, groupBy, hasNilOrEmpty, humanFileSize, intersection, isBrowser, isFlattenable, isNil, isNilEmptyOrEmptyObject, isNilEmptyOrZeroLen, isNilEmptyOrZeroLength, isNilOrEmpty, isNilOrNaN, isNilOrZeroLen, isNilOrZeroLength, isNilText, isNilTextOrEmpty, isNode, isNullOrUndefined, isNullOrUndefinedEmptyOrZero, isNullOrUndefinedInArray, isNullOrUndefinedOrNaN, isNullOrUndefinedTextInc, isNullUndefinedOrEmpty, isNullUndefinedOrEmptyEnforced, isNullUndefinedOrZero, isPTTaxId, isValidIBAN, isValidPTTaxId, numbersEqual, objectToString, omit, otp, parseName, parseToBool, parseToNumber, pick, pluck, pushAll, randomDigits, removeDiacritics, round, safeAdd, safeDivide, safeJSONParse, safeMultiply, safeParseFloat, safeParseInt, safeSubtract, sanitize, sanitizeMarkdown, sentenceCase, shuffle, slugify, sortBy, stringSimilarity, symbolToCurrency, throttle, toBool, toInteger, toNumber, uniq, uniqBy };
1109
+ export { type CapitalizeFirstOptions, type CapitalizeWordsOptions, type DeferFn, type EncodeDecodeConfig, type FormatCurrencyProOptions, GSM_7BIT_EXT_CHAR_REGEXP, GSM_7BIT_EXT_REGEXP, GSM_7BIT_REGEXP, type GenerateOptions, type HttpResponseLike, type SecurityCheckResult, type SecurityRisk, type SentenceCaseOptions, type SmsEncoding, type SmsLengthResult, addSpaceBetweenNumbers, addThousandsSpace, areArraysDeepEqualUnordered, areArraysEqual, assessSecurityRisks, basicSanitize, capitalizeFirst, capitalizeWords, checkMarkdownSecurity, chunk, clamp, cleanObject, compact, currencyToSymbol, debounce, deburr, decodeBase36Code, decodeObject, decodeString, deferAfterResponse, deferAfterResponseNonCritical, deferNonCritical, deferPostReturn, delay, difference, encodeBase36Code, encodeObject, encodeString, fill, flatten, flattenDepth, flattenDepthBase, flattenOnce, formatBytes, formatCurrency, formatCurrencyPro, formatDecimalNumber, generatePassword, generatePasswordWithOptions, getStringSimilarity, groupBy, hasNilOrEmpty, humanFileSize, intersection, isBrowser, isFlattenable, isNil, isNilEmptyOrEmptyObject, isNilEmptyOrZeroLen, isNilEmptyOrZeroLength, isNilOrEmpty, isNilOrNaN, isNilOrZeroLen, isNilOrZeroLength, isNilText, isNilTextOrEmpty, isNode, isNullOrUndefined, isNullOrUndefinedEmptyOrZero, isNullOrUndefinedInArray, isNullOrUndefinedOrNaN, isNullOrUndefinedTextInc, isNullUndefinedOrEmpty, isNullUndefinedOrEmptyEnforced, isNullUndefinedOrZero, isPTTaxId, isValidIBAN, isValidPTTaxId, numbersEqual, objectToString, omit, otp, parseName, parseToBool, parseToNumber, pick, pluck, pushAll, randomDigits, removeDiacritics, round, safeAdd, safeDivide, safeJSONParse, safeMultiply, safeParseFloat, safeParseInt, safeSubtract, sanitize, sanitizeMarkdown, sentenceCase, shuffle, slugify, smsLength, sortBy, stringSimilarity, symbolToCurrency, throttle, toBool, toInteger, toNumber, uniq, uniqBy };
package/dist/index.d.ts CHANGED
@@ -1027,8 +1027,83 @@ declare const decodeBase36Code: (code: string, config: EncodeDecodeConfig) => Sa
1027
1027
  identifier: string;
1028
1028
  }>;
1029
1029
 
1030
+ /******************************************************
1031
+ * ##: Password Generator (sync + async modes)
1032
+ * Generates random passwords with optional memorable and pattern-based modes.
1033
+ * Supports deterministic entropy and passphrase words in async mode.
1034
+ * History:
1035
+ * 14-03-2026: Created
1036
+ ****************************************************/
1037
+ type GenerateOptions = {
1038
+ length?: number;
1039
+ memorable?: boolean;
1040
+ pattern?: RegExp;
1041
+ prefix?: string;
1042
+ ignoreSecurityRecommendations?: boolean;
1043
+ entropy?: Uint8Array | string;
1044
+ words?: number;
1045
+ };
1046
+ /******************************************************
1047
+ * ##: Generate Password
1048
+ * Default sync implementation; returns a Promise when async options are used.
1049
+ * @param {Number} length - Password length
1050
+ * @param {Boolean} memorable - Alternates consonants and vowels
1051
+ * @param {RegExp} pattern - Pattern applied to each character
1052
+ * @param {String} prefix - Prefix appended to the password
1053
+ * History:
1054
+ * 14-03-2026: Created
1055
+ ****************************************************/
1056
+ declare function generatePassword(length?: number, memorable?: boolean, pattern?: RegExp, prefix?: string): string;
1057
+ declare function generatePassword(options?: GenerateOptions): string | Promise<string>;
1058
+ /******************************************************
1059
+ * ##: Generate Password (options wrapper)
1060
+ * Full options support including async features (words, entropy).
1061
+ * History:
1062
+ * 14-03-2026: Created
1063
+ ****************************************************/
1064
+ declare const generatePasswordWithOptions: (options?: GenerateOptions) => string | Promise<string>;
1065
+
1066
+ /******************************************************
1067
+ * ##: SMS Length Calculator
1068
+ * Calculates SMS length, segmentation, and encoding based on GSM rules.
1069
+ * Reference: 3GPP TS 23.038 (GSM 03.38)
1070
+ * History:
1071
+ * 14-03-2026: Created
1072
+ ****************************************************/
1073
+ type SmsEncoding = "GSM_7BIT" | "GSM_7BIT_EXT" | "UTF16";
1074
+ declare const GSM_7BIT_REGEXP: RegExp;
1075
+ declare const GSM_7BIT_EXT_REGEXP: RegExp;
1076
+ /******************************************************
1077
+ * Extended GSM characters that consume 2 septets each.
1078
+ * Per 3GPP TS 23.038 Table 3 (Basic Character Set Extension):
1079
+ * ^ { } \ [ ] ~ | €
1080
+ ****************************************************/
1081
+ declare const GSM_7BIT_EXT_CHAR_REGEXP: RegExp;
1082
+ type SmsLengthResult = {
1083
+ encoding: SmsEncoding;
1084
+ length: number;
1085
+ characterPerMessage: number;
1086
+ inCurrentMessage: number;
1087
+ remaining: number;
1088
+ messages: number;
1089
+ };
1090
+ /******************************************************
1091
+ * ##: SMS Length
1092
+ * Calculates encoding, length, and segmentation for an SMS message.
1093
+ * Extended GSM characters (^{}\\[]~|€) each count as 2 septets.
1094
+ * Supports optional per-encoding length overrides for carrier-specific limits.
1095
+ * @param {string} text - SMS message text
1096
+ * @param {Partial<Record<SmsEncoding, number>>} [singleOverrides] - Override
1097
+ * single-segment lengths per encoding
1098
+ * @param {Partial<Record<SmsEncoding, number>>} [multiOverrides] - Override
1099
+ * multi-segment lengths per encoding
1100
+ * History:
1101
+ * 14-03-2026: Created
1102
+ ****************************************************/
1103
+ declare const smsLength: (text: string, singleOverrides?: Partial<Record<SmsEncoding, number>>, multiOverrides?: Partial<Record<SmsEncoding, number>>) => SmsLengthResult;
1104
+
1030
1105
  /** Environment helpers (runtime-agnostic checks) */
1031
1106
  declare const isBrowser: boolean;
1032
1107
  declare const isNode: boolean;
1033
1108
 
1034
- export { type CapitalizeFirstOptions, type CapitalizeWordsOptions, type DeferFn, type EncodeDecodeConfig, type FormatCurrencyProOptions, type HttpResponseLike, type SecurityCheckResult, type SecurityRisk, type SentenceCaseOptions, addSpaceBetweenNumbers, addThousandsSpace, areArraysDeepEqualUnordered, areArraysEqual, assessSecurityRisks, basicSanitize, capitalizeFirst, capitalizeWords, checkMarkdownSecurity, chunk, clamp, cleanObject, compact, currencyToSymbol, debounce, deburr, decodeBase36Code, decodeObject, decodeString, deferAfterResponse, deferAfterResponseNonCritical, deferNonCritical, deferPostReturn, delay, difference, encodeBase36Code, encodeObject, encodeString, fill, flatten, flattenDepth, flattenDepthBase, flattenOnce, formatBytes, formatCurrency, formatCurrencyPro, formatDecimalNumber, getStringSimilarity, groupBy, hasNilOrEmpty, humanFileSize, intersection, isBrowser, isFlattenable, isNil, isNilEmptyOrEmptyObject, isNilEmptyOrZeroLen, isNilEmptyOrZeroLength, isNilOrEmpty, isNilOrNaN, isNilOrZeroLen, isNilOrZeroLength, isNilText, isNilTextOrEmpty, isNode, isNullOrUndefined, isNullOrUndefinedEmptyOrZero, isNullOrUndefinedInArray, isNullOrUndefinedOrNaN, isNullOrUndefinedTextInc, isNullUndefinedOrEmpty, isNullUndefinedOrEmptyEnforced, isNullUndefinedOrZero, isPTTaxId, isValidIBAN, isValidPTTaxId, numbersEqual, objectToString, omit, otp, parseName, parseToBool, parseToNumber, pick, pluck, pushAll, randomDigits, removeDiacritics, round, safeAdd, safeDivide, safeJSONParse, safeMultiply, safeParseFloat, safeParseInt, safeSubtract, sanitize, sanitizeMarkdown, sentenceCase, shuffle, slugify, sortBy, stringSimilarity, symbolToCurrency, throttle, toBool, toInteger, toNumber, uniq, uniqBy };
1109
+ export { type CapitalizeFirstOptions, type CapitalizeWordsOptions, type DeferFn, type EncodeDecodeConfig, type FormatCurrencyProOptions, GSM_7BIT_EXT_CHAR_REGEXP, GSM_7BIT_EXT_REGEXP, GSM_7BIT_REGEXP, type GenerateOptions, type HttpResponseLike, type SecurityCheckResult, type SecurityRisk, type SentenceCaseOptions, type SmsEncoding, type SmsLengthResult, addSpaceBetweenNumbers, addThousandsSpace, areArraysDeepEqualUnordered, areArraysEqual, assessSecurityRisks, basicSanitize, capitalizeFirst, capitalizeWords, checkMarkdownSecurity, chunk, clamp, cleanObject, compact, currencyToSymbol, debounce, deburr, decodeBase36Code, decodeObject, decodeString, deferAfterResponse, deferAfterResponseNonCritical, deferNonCritical, deferPostReturn, delay, difference, encodeBase36Code, encodeObject, encodeString, fill, flatten, flattenDepth, flattenDepthBase, flattenOnce, formatBytes, formatCurrency, formatCurrencyPro, formatDecimalNumber, generatePassword, generatePasswordWithOptions, getStringSimilarity, groupBy, hasNilOrEmpty, humanFileSize, intersection, isBrowser, isFlattenable, isNil, isNilEmptyOrEmptyObject, isNilEmptyOrZeroLen, isNilEmptyOrZeroLength, isNilOrEmpty, isNilOrNaN, isNilOrZeroLen, isNilOrZeroLength, isNilText, isNilTextOrEmpty, isNode, isNullOrUndefined, isNullOrUndefinedEmptyOrZero, isNullOrUndefinedInArray, isNullOrUndefinedOrNaN, isNullOrUndefinedTextInc, isNullUndefinedOrEmpty, isNullUndefinedOrEmptyEnforced, isNullUndefinedOrZero, isPTTaxId, isValidIBAN, isValidPTTaxId, numbersEqual, objectToString, omit, otp, parseName, parseToBool, parseToNumber, pick, pluck, pushAll, randomDigits, removeDiacritics, round, safeAdd, safeDivide, safeJSONParse, safeMultiply, safeParseFloat, safeParseInt, safeSubtract, sanitize, sanitizeMarkdown, sentenceCase, shuffle, slugify, smsLength, sortBy, stringSimilarity, symbolToCurrency, throttle, toBool, toInteger, toNumber, uniq, uniqBy };
package/dist/index.js CHANGED
@@ -2220,10 +2220,464 @@ var decodeBase36Code = (code, config) => {
2220
2220
  }
2221
2221
  };
2222
2222
 
2223
+ // src/utils/password.ts
2224
+ var hasCrypto = typeof globalThis !== "undefined" && typeof globalThis.crypto !== "undefined";
2225
+ var cryptoSource = hasCrypto ? globalThis.crypto : void 0;
2226
+ var textEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
2227
+ var MAX_RANDOM_BYTES = 65536;
2228
+ var VOWELS = "aeiou";
2229
+ var CONSONANTS = "bcdfghjklmnpqrstvwxyz";
2230
+ var CONSONANT = new RegExp(`[${CONSONANTS}]$`, "i");
2231
+ var DEFAULT_PATTERN = /\w/;
2232
+ var DEFAULT_LENGTH = 12;
2233
+ var MIN_ENTROPY_BITS = 64;
2234
+ var MIN_WORD_LENGTH = 3;
2235
+ var MAX_WORD_LENGTH = 7;
2236
+ var MIN_MEMORABLE_LENGTH = (() => {
2237
+ let bits = 0;
2238
+ let len = 0;
2239
+ let vowel = false;
2240
+ while (bits < MIN_ENTROPY_BITS) {
2241
+ bits += Math.log2(vowel ? VOWELS.length : CONSONANTS.length);
2242
+ vowel = !vowel;
2243
+ len += 1;
2244
+ }
2245
+ return len;
2246
+ })();
2247
+ var ensureCrypto = () => {
2248
+ if (!cryptoSource) {
2249
+ throw new Error("WebCrypto is required for password generation");
2250
+ }
2251
+ return cryptoSource;
2252
+ };
2253
+ var getRandomBytesSync = (length) => {
2254
+ if (!Number.isFinite(length) || length < 0) {
2255
+ throw new RangeError("length must be a non-negative finite number");
2256
+ }
2257
+ const crypto = ensureCrypto();
2258
+ const buffer = new Uint8Array(length);
2259
+ for (let offset = 0; offset < length; offset += MAX_RANDOM_BYTES) {
2260
+ const end = Math.min(offset + MAX_RANDOM_BYTES, length);
2261
+ crypto.getRandomValues(buffer.subarray(offset, end));
2262
+ }
2263
+ return buffer;
2264
+ };
2265
+ var getRandomBytes = async (length) => getRandomBytesSync(length);
2266
+ var createDeterministicRandomBytes = async (entropy, source = ensureCrypto()) => {
2267
+ if (entropy.length === 0) {
2268
+ throw new RangeError("entropy must not be empty");
2269
+ }
2270
+ if (!source.subtle) {
2271
+ throw new Error("WebCrypto subtle is required for deterministic entropy");
2272
+ }
2273
+ const keyData = new Uint8Array(entropy).buffer;
2274
+ const key = await source.subtle.importKey(
2275
+ "raw",
2276
+ keyData,
2277
+ { name: "HMAC", hash: "SHA-256" },
2278
+ false,
2279
+ ["sign"]
2280
+ );
2281
+ let counter = 0n;
2282
+ const counterBytes = new Uint8Array(8);
2283
+ const counterView = new DataView(counterBytes.buffer);
2284
+ const deterministicRandomBytes = async (length) => {
2285
+ if (!Number.isFinite(length) || length < 0) {
2286
+ throw new RangeError("length must be a non-negative finite number");
2287
+ }
2288
+ const buffer = new Uint8Array(length);
2289
+ let offset = 0;
2290
+ while (offset < length) {
2291
+ counterView.setBigUint64(0, counter, false);
2292
+ counter += 1n;
2293
+ const block = new Uint8Array(
2294
+ await source.subtle.sign("HMAC", key, counterBytes)
2295
+ );
2296
+ const take = Math.min(block.length, length - offset);
2297
+ buffer.set(block.subarray(0, take), offset);
2298
+ offset += take;
2299
+ }
2300
+ return buffer;
2301
+ };
2302
+ return deterministicRandomBytes;
2303
+ };
2304
+ var randomIntSync = (min, max, randomBytes = getRandomBytesSync) => {
2305
+ if (!Number.isFinite(min) || !Number.isFinite(max)) {
2306
+ throw new RangeError("min and max must be finite numbers");
2307
+ }
2308
+ if (max <= min) {
2309
+ throw new RangeError("max must be greater than min");
2310
+ }
2311
+ const range = max - min;
2312
+ if (range === 1) {
2313
+ return min;
2314
+ }
2315
+ const bytesNeeded = Math.ceil(Math.log2(range) / 8);
2316
+ const maxValue = 256 ** bytesNeeded;
2317
+ const limit = maxValue - maxValue % range;
2318
+ let value = limit;
2319
+ while (value >= limit) {
2320
+ const bytes = randomBytes(bytesNeeded);
2321
+ value = 0;
2322
+ for (const byte of bytes) {
2323
+ value = value * 256 + byte;
2324
+ }
2325
+ }
2326
+ return min + value % range;
2327
+ };
2328
+ var randomInt = async (min, max, randomBytes = getRandomBytes) => {
2329
+ if (!Number.isFinite(min) || !Number.isFinite(max)) {
2330
+ throw new RangeError("min and max must be finite numbers");
2331
+ }
2332
+ if (max <= min) {
2333
+ throw new RangeError("max must be greater than min");
2334
+ }
2335
+ const range = max - min;
2336
+ if (range === 1) {
2337
+ return min;
2338
+ }
2339
+ const bytesNeeded = Math.ceil(Math.log2(range) / 8);
2340
+ const maxValue = 256 ** bytesNeeded;
2341
+ const limit = maxValue - maxValue % range;
2342
+ let value = limit;
2343
+ while (value >= limit) {
2344
+ const bytes = await randomBytes(bytesNeeded);
2345
+ value = 0;
2346
+ for (const byte of bytes) {
2347
+ value = value * 256 + byte;
2348
+ }
2349
+ }
2350
+ return min + value % range;
2351
+ };
2352
+ var buildValidChars = (pattern) => {
2353
+ const chars = [];
2354
+ for (let i = 33; i <= 126; i += 1) {
2355
+ const char = String.fromCharCode(i);
2356
+ if (pattern.test(char)) {
2357
+ chars.push(char);
2358
+ }
2359
+ }
2360
+ if (chars.length === 0) {
2361
+ throw new Error(
2362
+ `Could not find characters that match the password pattern ${pattern}. Patterns must match individual characters, not the password as a whole.`
2363
+ );
2364
+ }
2365
+ return chars;
2366
+ };
2367
+ var estimatePatternEntropy = (alphabetSize, length, prefixLength) => {
2368
+ const bitsPerChar = alphabetSize > 1 ? Math.log2(alphabetSize) : 0;
2369
+ return {
2370
+ entropyBits: bitsPerChar * Math.max(0, length - prefixLength),
2371
+ recommendedLength: bitsPerChar > 0 ? prefixLength + Math.ceil(MIN_ENTROPY_BITS / bitsPerChar) : null
2372
+ };
2373
+ };
2374
+ var estimateMemorableEntropy = (length, prefix) => {
2375
+ const effectiveLength = Math.max(0, length - prefix.length);
2376
+ let entropyBits = 0;
2377
+ let expectsVowel = CONSONANT.test(prefix);
2378
+ for (let i = 0; i < effectiveLength; i += 1) {
2379
+ entropyBits += Math.log2(expectsVowel ? VOWELS.length : CONSONANTS.length);
2380
+ expectsVowel = !expectsVowel;
2381
+ }
2382
+ let recommendedLength = prefix.length;
2383
+ let bits = 0;
2384
+ expectsVowel = CONSONANT.test(prefix);
2385
+ while (bits < MIN_ENTROPY_BITS) {
2386
+ bits += Math.log2(expectsVowel ? VOWELS.length : CONSONANTS.length);
2387
+ expectsVowel = !expectsVowel;
2388
+ recommendedLength += 1;
2389
+ }
2390
+ return { entropyBits, recommendedLength };
2391
+ };
2392
+ var buildMemorableSync = (length, startsWithVowel, nextInt) => {
2393
+ let expectsVowel = startsWithVowel;
2394
+ let result = "";
2395
+ for (let i = 0; i < length; i += 1) {
2396
+ const alphabet = expectsVowel ? VOWELS : CONSONANTS;
2397
+ result += alphabet[nextInt(0, alphabet.length)];
2398
+ expectsVowel = !expectsVowel;
2399
+ }
2400
+ return result;
2401
+ };
2402
+ var buildMemorable = async (length, startsWithVowel, nextInt) => {
2403
+ let expectsVowel = startsWithVowel;
2404
+ let result = "";
2405
+ for (let i = 0; i < length; i += 1) {
2406
+ const alphabet = expectsVowel ? VOWELS : CONSONANTS;
2407
+ result += alphabet[await nextInt(0, alphabet.length)];
2408
+ expectsVowel = !expectsVowel;
2409
+ }
2410
+ return result;
2411
+ };
2412
+ var buildWordLengths = async (count, nextInt, targetLength) => {
2413
+ const lengths = [];
2414
+ let total = 0;
2415
+ for (let i = 0; i < count; i += 1) {
2416
+ const len = await nextInt(MIN_WORD_LENGTH, MAX_WORD_LENGTH + 1);
2417
+ lengths.push(len);
2418
+ total += len;
2419
+ }
2420
+ if (targetLength !== void 0 && total < targetLength) {
2421
+ const adjustable = [];
2422
+ for (let i = 0; i < count; i += 1) {
2423
+ if (lengths[i] < MAX_WORD_LENGTH) adjustable.push(i);
2424
+ }
2425
+ let remaining = targetLength - total;
2426
+ while (remaining > 0 && adjustable.length > 0) {
2427
+ const pick2 = await nextInt(0, adjustable.length);
2428
+ const wordIdx = adjustable[pick2];
2429
+ lengths[wordIdx] = lengths[wordIdx] + 1;
2430
+ remaining -= 1;
2431
+ if (lengths[wordIdx] >= MAX_WORD_LENGTH) {
2432
+ adjustable.splice(pick2, 1);
2433
+ }
2434
+ }
2435
+ }
2436
+ return lengths;
2437
+ };
2438
+ var parseEntropy = (entropy) => {
2439
+ if (typeof entropy === "string") {
2440
+ if (textEncoder) return textEncoder.encode(entropy);
2441
+ if (typeof Buffer !== "undefined") return Buffer.from(entropy, "utf8");
2442
+ throw new Error("TextEncoder is required for entropy strings");
2443
+ }
2444
+ if (entropy instanceof Uint8Array) {
2445
+ return entropy;
2446
+ }
2447
+ throw new TypeError("entropy must be a Uint8Array or string");
2448
+ };
2449
+ var validateOptions = (options) => {
2450
+ const length = options?.length ?? DEFAULT_LENGTH;
2451
+ const memorable = options?.memorable ?? false;
2452
+ const pattern = options?.pattern ?? DEFAULT_PATTERN;
2453
+ const prefix = String(options?.prefix ?? "");
2454
+ const ignoreSecurityRecommendations = options?.ignoreSecurityRecommendations ?? false;
2455
+ const words = options?.words;
2456
+ if (!Number.isSafeInteger(length)) {
2457
+ throw new RangeError("length must be a safe integer");
2458
+ }
2459
+ if (length < 0) {
2460
+ throw new RangeError("length must be a non-negative integer");
2461
+ }
2462
+ if (!(pattern instanceof RegExp)) {
2463
+ throw new TypeError("pattern must be a RegExp");
2464
+ }
2465
+ if (words !== void 0) {
2466
+ if (!Number.isSafeInteger(words)) {
2467
+ throw new RangeError("words must be a safe integer");
2468
+ }
2469
+ if (words <= 0) {
2470
+ throw new RangeError("words must be a positive integer");
2471
+ }
2472
+ }
2473
+ if (words !== void 0 && prefix !== "") {
2474
+ throw new Error("prefix is not supported when words are enabled");
2475
+ }
2476
+ return {
2477
+ length,
2478
+ memorable,
2479
+ pattern,
2480
+ prefix,
2481
+ ignoreSecurityRecommendations,
2482
+ words
2483
+ };
2484
+ };
2485
+ var generatePasswordSync = (options) => {
2486
+ const {
2487
+ length,
2488
+ memorable,
2489
+ pattern,
2490
+ prefix,
2491
+ ignoreSecurityRecommendations,
2492
+ words
2493
+ } = validateOptions(options);
2494
+ if (words !== void 0) {
2495
+ throw new Error("words requires async password generation");
2496
+ }
2497
+ const nextInt = (min, max) => randomIntSync(min, max, getRandomBytesSync);
2498
+ if (memorable) {
2499
+ if (!ignoreSecurityRecommendations) {
2500
+ const estimate = estimateMemorableEntropy(length, prefix);
2501
+ if (estimate.entropyBits < MIN_ENTROPY_BITS) {
2502
+ throw new Error(
2503
+ `Security recommendation: estimated entropy ${estimate.entropyBits.toFixed(
2504
+ 1
2505
+ )} bits is below ${MIN_ENTROPY_BITS} bits. Use length >= ${estimate.recommendedLength} or set memorable: false. To override, pass { ignoreSecurityRecommendations: true }.`
2506
+ );
2507
+ }
2508
+ }
2509
+ const charCount = Math.max(0, length - prefix.length);
2510
+ return prefix + buildMemorableSync(charCount, CONSONANT.test(prefix), nextInt);
2511
+ }
2512
+ const validChars = buildValidChars(pattern);
2513
+ if (!ignoreSecurityRecommendations) {
2514
+ const estimate = estimatePatternEntropy(
2515
+ validChars.length,
2516
+ length,
2517
+ prefix.length
2518
+ );
2519
+ if (estimate.entropyBits < MIN_ENTROPY_BITS) {
2520
+ const recommendation = estimate.recommendedLength === null ? "Use a broader pattern to increase the character set." : `Use length >= ${estimate.recommendedLength} or broaden the pattern.`;
2521
+ throw new Error(
2522
+ `Security recommendation: estimated entropy ${estimate.entropyBits.toFixed(
2523
+ 1
2524
+ )} bits is below ${MIN_ENTROPY_BITS} bits. ${recommendation} To override, pass { ignoreSecurityRecommendations: true }.`
2525
+ );
2526
+ }
2527
+ }
2528
+ let result = prefix;
2529
+ while (result.length < length) {
2530
+ result += validChars[nextInt(0, validChars.length)];
2531
+ }
2532
+ return result;
2533
+ };
2534
+ var generatePasswordAsync = async (options) => {
2535
+ const {
2536
+ length,
2537
+ memorable,
2538
+ pattern,
2539
+ prefix,
2540
+ ignoreSecurityRecommendations,
2541
+ words
2542
+ } = validateOptions(options);
2543
+ const entropy = options?.entropy;
2544
+ let entropyBytes;
2545
+ if (entropy !== void 0) {
2546
+ entropyBytes = parseEntropy(entropy);
2547
+ }
2548
+ const randomBytes = entropyBytes ? await createDeterministicRandomBytes(entropyBytes) : getRandomBytes;
2549
+ const nextInt = (min, max) => randomInt(min, max, randomBytes);
2550
+ if (words !== void 0) {
2551
+ if (!ignoreSecurityRecommendations && words * MAX_WORD_LENGTH < MIN_MEMORABLE_LENGTH) {
2552
+ const recommendedWords = Math.ceil(
2553
+ MIN_MEMORABLE_LENGTH / MAX_WORD_LENGTH
2554
+ );
2555
+ throw new Error(
2556
+ `Security recommendation: word count ${words} cannot reach ${MIN_ENTROPY_BITS} bits with ${MIN_WORD_LENGTH}-${MAX_WORD_LENGTH} letter words. Use words >= ${recommendedWords}. To override, pass { ignoreSecurityRecommendations: true }.`
2557
+ );
2558
+ }
2559
+ const targetLength = ignoreSecurityRecommendations ? void 0 : MIN_MEMORABLE_LENGTH;
2560
+ const lengths = await buildWordLengths(words, nextInt, targetLength);
2561
+ const wordsList = [];
2562
+ for (const wordLength of lengths) {
2563
+ wordsList.push(await buildMemorable(wordLength, false, nextInt));
2564
+ }
2565
+ return wordsList.join(" ");
2566
+ }
2567
+ if (memorable) {
2568
+ if (!ignoreSecurityRecommendations) {
2569
+ const estimate = estimateMemorableEntropy(length, prefix);
2570
+ if (estimate.entropyBits < MIN_ENTROPY_BITS) {
2571
+ throw new Error(
2572
+ `Security recommendation: estimated entropy ${estimate.entropyBits.toFixed(
2573
+ 1
2574
+ )} bits is below ${MIN_ENTROPY_BITS} bits. Use length >= ${estimate.recommendedLength} or set memorable: false. To override, pass { ignoreSecurityRecommendations: true }.`
2575
+ );
2576
+ }
2577
+ }
2578
+ const charCount = Math.max(0, length - prefix.length);
2579
+ return prefix + await buildMemorable(charCount, CONSONANT.test(prefix), nextInt);
2580
+ }
2581
+ const validChars = buildValidChars(pattern);
2582
+ if (!ignoreSecurityRecommendations) {
2583
+ const estimate = estimatePatternEntropy(
2584
+ validChars.length,
2585
+ length,
2586
+ prefix.length
2587
+ );
2588
+ if (estimate.entropyBits < MIN_ENTROPY_BITS) {
2589
+ const recommendation = estimate.recommendedLength === null ? "Use a broader pattern to increase the character set." : `Use length >= ${estimate.recommendedLength} or broaden the pattern.`;
2590
+ throw new Error(
2591
+ `Security recommendation: estimated entropy ${estimate.entropyBits.toFixed(
2592
+ 1
2593
+ )} bits is below ${MIN_ENTROPY_BITS} bits. ${recommendation} To override, pass { ignoreSecurityRecommendations: true }.`
2594
+ );
2595
+ }
2596
+ }
2597
+ let result = prefix;
2598
+ while (result.length < length) {
2599
+ result += validChars[await nextInt(0, validChars.length)];
2600
+ }
2601
+ return result;
2602
+ };
2603
+ function generatePassword(lengthOrOptions, memorable, pattern, prefix) {
2604
+ if (typeof lengthOrOptions === "object") {
2605
+ const options2 = lengthOrOptions;
2606
+ const requiresAsync = options2.words !== void 0 || options2.entropy !== void 0;
2607
+ return requiresAsync ? generatePasswordAsync(options2) : generatePasswordSync(options2);
2608
+ }
2609
+ const options = {};
2610
+ if (lengthOrOptions !== void 0) options.length = lengthOrOptions;
2611
+ if (memorable !== void 0) options.memorable = memorable;
2612
+ if (pattern !== void 0) options.pattern = pattern;
2613
+ if (prefix !== void 0) options.prefix = prefix;
2614
+ return generatePasswordSync(options);
2615
+ }
2616
+ var generatePasswordWithOptions = (options) => {
2617
+ const requiresAsync = options?.words !== void 0 || options?.entropy !== void 0;
2618
+ return requiresAsync ? generatePasswordAsync(options) : generatePasswordSync(options);
2619
+ };
2620
+
2621
+ // src/utils/sms.ts
2622
+ var GSM_7BIT_REGEXP = /^[@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"#¤%&'()*+,\-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà]*$/;
2623
+ var GSM_7BIT_EXT_REGEXP = /^[@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !"#¤%&'()*+,\-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà\^{}\\\[\]~|€]*$/;
2624
+ var GSM_7BIT_EXT_CHAR_REGEXP = /[\^{}\\\[\]~|€]/g;
2625
+ var messageLength = {
2626
+ GSM_7BIT: 160,
2627
+ GSM_7BIT_EXT: 160,
2628
+ UTF16: 70
2629
+ };
2630
+ var multiMessageLength = {
2631
+ GSM_7BIT: 153,
2632
+ GSM_7BIT_EXT: 153,
2633
+ UTF16: 67
2634
+ };
2635
+ var detectEncoding = (text) => {
2636
+ if (GSM_7BIT_REGEXP.test(text)) {
2637
+ return "GSM_7BIT";
2638
+ }
2639
+ if (GSM_7BIT_EXT_REGEXP.test(text)) {
2640
+ return "GSM_7BIT_EXT";
2641
+ }
2642
+ return "UTF16";
2643
+ };
2644
+ var smsLength = (text, singleOverrides, multiOverrides) => {
2645
+ const singleLengths = { ...messageLength, ...singleOverrides };
2646
+ const multiLengths = { ...multiMessageLength, ...multiOverrides };
2647
+ if (text.length === 0) {
2648
+ return {
2649
+ encoding: "GSM_7BIT",
2650
+ length: 0,
2651
+ characterPerMessage: singleLengths.GSM_7BIT,
2652
+ inCurrentMessage: 0,
2653
+ remaining: singleLengths.GSM_7BIT,
2654
+ messages: 0
2655
+ };
2656
+ }
2657
+ const encoding = detectEncoding(text);
2658
+ const extCharCount = encoding === "GSM_7BIT_EXT" ? (text.match(GSM_7BIT_EXT_CHAR_REGEXP) ?? []).length : 0;
2659
+ const length = text.length + extCharCount;
2660
+ let characterPerMessage = singleLengths[encoding];
2661
+ if (length > characterPerMessage) {
2662
+ characterPerMessage = multiLengths[encoding];
2663
+ }
2664
+ const messages = Math.ceil(length / characterPerMessage);
2665
+ const inCurrentMessage = length - characterPerMessage * (messages - 1);
2666
+ const remaining = characterPerMessage * messages - length;
2667
+ return {
2668
+ encoding,
2669
+ length,
2670
+ characterPerMessage,
2671
+ inCurrentMessage,
2672
+ remaining,
2673
+ messages
2674
+ };
2675
+ };
2676
+
2223
2677
  // src/index.ts
2224
2678
  var isBrowser = typeof globalThis !== "undefined" && typeof globalThis.document !== "undefined";
2225
2679
  var isNode = typeof process !== "undefined" && !!process.versions?.node;
2226
2680
 
2227
- export { addSpaceBetweenNumbers, addThousandsSpace, areArraysDeepEqualUnordered, areArraysEqual, assessSecurityRisks, basicSanitize, capitalizeFirst, capitalizeWords, checkMarkdownSecurity, chunk, clamp, cleanObject, compact, currencyToSymbol, debounce, deburr, decodeBase36Code, decodeObject, decodeString, deferAfterResponse, deferAfterResponseNonCritical, deferNonCritical, deferPostReturn, delay, difference, encodeBase36Code, encodeObject, encodeString, fill, flatten, flattenDepth, flattenDepthBase, flattenOnce, formatBytes, formatCurrency, formatCurrencyPro, formatDecimalNumber, getStringSimilarity, groupBy, hasNilOrEmpty, humanFileSize, intersection, isBrowser, isFlattenable, isNil, isNilEmptyOrEmptyObject, isNilEmptyOrZeroLen, isNilEmptyOrZeroLength, isNilOrEmpty, isNilOrNaN, isNilOrZeroLen, isNilOrZeroLength, isNilText, isNilTextOrEmpty, isNode, isNullOrUndefined, isNullOrUndefinedEmptyOrZero, isNullOrUndefinedInArray, isNullOrUndefinedOrNaN, isNullOrUndefinedTextInc, isNullUndefinedOrEmpty, isNullUndefinedOrEmptyEnforced, isNullUndefinedOrZero, isPTTaxId, isValidIBAN, isValidPTTaxId, numbersEqual, objectToString, omit, otp, parseName, parseToBool, parseToNumber, pick, pluck, pushAll, randomDigits, removeDiacritics, round, safeAdd, safeDivide, safeJSONParse, safeMultiply, safeParseFloat, safeParseInt, safeSubtract, sanitize, sanitizeMarkdown, sentenceCase, shuffle, slugify, sortBy, stringSimilarity, symbolToCurrency, throttle, toBool, toInteger, toNumber, uniq, uniqBy };
2681
+ export { GSM_7BIT_EXT_CHAR_REGEXP, GSM_7BIT_EXT_REGEXP, GSM_7BIT_REGEXP, addSpaceBetweenNumbers, addThousandsSpace, areArraysDeepEqualUnordered, areArraysEqual, assessSecurityRisks, basicSanitize, capitalizeFirst, capitalizeWords, checkMarkdownSecurity, chunk, clamp, cleanObject, compact, currencyToSymbol, debounce, deburr, decodeBase36Code, decodeObject, decodeString, deferAfterResponse, deferAfterResponseNonCritical, deferNonCritical, deferPostReturn, delay, difference, encodeBase36Code, encodeObject, encodeString, fill, flatten, flattenDepth, flattenDepthBase, flattenOnce, formatBytes, formatCurrency, formatCurrencyPro, formatDecimalNumber, generatePassword, generatePasswordWithOptions, getStringSimilarity, groupBy, hasNilOrEmpty, humanFileSize, intersection, isBrowser, isFlattenable, isNil, isNilEmptyOrEmptyObject, isNilEmptyOrZeroLen, isNilEmptyOrZeroLength, isNilOrEmpty, isNilOrNaN, isNilOrZeroLen, isNilOrZeroLength, isNilText, isNilTextOrEmpty, isNode, isNullOrUndefined, isNullOrUndefinedEmptyOrZero, isNullOrUndefinedInArray, isNullOrUndefinedOrNaN, isNullOrUndefinedTextInc, isNullUndefinedOrEmpty, isNullUndefinedOrEmptyEnforced, isNullUndefinedOrZero, isPTTaxId, isValidIBAN, isValidPTTaxId, numbersEqual, objectToString, omit, otp, parseName, parseToBool, parseToNumber, pick, pluck, pushAll, randomDigits, removeDiacritics, round, safeAdd, safeDivide, safeJSONParse, safeMultiply, safeParseFloat, safeParseInt, safeSubtract, sanitize, sanitizeMarkdown, sentenceCase, shuffle, slugify, smsLength, sortBy, stringSimilarity, symbolToCurrency, throttle, toBool, toInteger, toNumber, uniq, uniqBy };
2228
2682
  //# sourceMappingURL=index.js.map
2229
2683
  //# sourceMappingURL=index.js.map