utilitify-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +338 -0
- package/dist/async.cjs +25 -0
- package/dist/async.cjs.map +1 -0
- package/dist/async.d.cts +104 -0
- package/dist/async.d.ts +104 -0
- package/dist/async.js +4 -0
- package/dist/async.js.map +1 -0
- package/dist/chunk-2ICNRTSN.cjs +346 -0
- package/dist/chunk-2ICNRTSN.cjs.map +1 -0
- package/dist/chunk-3DPF72DY.js +170 -0
- package/dist/chunk-3DPF72DY.js.map +1 -0
- package/dist/chunk-4CV4JOE5.js +24 -0
- package/dist/chunk-4CV4JOE5.js.map +1 -0
- package/dist/chunk-4SLYNSLH.cjs +783 -0
- package/dist/chunk-4SLYNSLH.cjs.map +1 -0
- package/dist/chunk-5WP7DWCG.js +1285 -0
- package/dist/chunk-5WP7DWCG.js.map +1 -0
- package/dist/chunk-BMQ6YPKV.js +876 -0
- package/dist/chunk-BMQ6YPKV.js.map +1 -0
- package/dist/chunk-BZCMWUKS.cjs +479 -0
- package/dist/chunk-BZCMWUKS.cjs.map +1 -0
- package/dist/chunk-C5R744DY.cjs +173 -0
- package/dist/chunk-C5R744DY.cjs.map +1 -0
- package/dist/chunk-C75J62CV.cjs +913 -0
- package/dist/chunk-C75J62CV.cjs.map +1 -0
- package/dist/chunk-CZLDE2OZ.cjs +28 -0
- package/dist/chunk-CZLDE2OZ.cjs.map +1 -0
- package/dist/chunk-DSMB6AF6.cjs +193 -0
- package/dist/chunk-DSMB6AF6.cjs.map +1 -0
- package/dist/chunk-ETWGPOPY.js +426 -0
- package/dist/chunk-ETWGPOPY.js.map +1 -0
- package/dist/chunk-FQBPVN63.cjs +403 -0
- package/dist/chunk-FQBPVN63.cjs.map +1 -0
- package/dist/chunk-G4GYQGTW.cjs +178 -0
- package/dist/chunk-G4GYQGTW.cjs.map +1 -0
- package/dist/chunk-GFDMZDMI.js +486 -0
- package/dist/chunk-GFDMZDMI.js.map +1 -0
- package/dist/chunk-HOTOYIPB.js +171 -0
- package/dist/chunk-HOTOYIPB.js.map +1 -0
- package/dist/chunk-HYADH4ZX.js +176 -0
- package/dist/chunk-HYADH4ZX.js.map +1 -0
- package/dist/chunk-JBN7C5WE.js +255 -0
- package/dist/chunk-JBN7C5WE.js.map +1 -0
- package/dist/chunk-JNCTPFTD.cjs +25 -0
- package/dist/chunk-JNCTPFTD.cjs.map +1 -0
- package/dist/chunk-N3BH3BV7.js +21 -0
- package/dist/chunk-N3BH3BV7.js.map +1 -0
- package/dist/chunk-NFPGAVRQ.js +749 -0
- package/dist/chunk-NFPGAVRQ.js.map +1 -0
- package/dist/chunk-OFFRGRBN.cjs +1332 -0
- package/dist/chunk-OFFRGRBN.cjs.map +1 -0
- package/dist/chunk-OZLKYIZL.cjs +490 -0
- package/dist/chunk-OZLKYIZL.cjs.map +1 -0
- package/dist/chunk-P3NUK46X.js +145 -0
- package/dist/chunk-P3NUK46X.js.map +1 -0
- package/dist/chunk-P7P2B7ZI.cjs +429 -0
- package/dist/chunk-P7P2B7ZI.cjs.map +1 -0
- package/dist/chunk-PB6SKSJN.cjs +150 -0
- package/dist/chunk-PB6SKSJN.cjs.map +1 -0
- package/dist/chunk-R3IXCJR7.js +378 -0
- package/dist/chunk-R3IXCJR7.js.map +1 -0
- package/dist/chunk-SD6P3WEJ.js +324 -0
- package/dist/chunk-SD6P3WEJ.js.map +1 -0
- package/dist/chunk-YSCHP26P.js +451 -0
- package/dist/chunk-YSCHP26P.js.map +1 -0
- package/dist/chunk-ZLMPRPCY.cjs +274 -0
- package/dist/chunk-ZLMPRPCY.cjs.map +1 -0
- package/dist/common-CBDYNJeh.d.cts +48 -0
- package/dist/common-CBDYNJeh.d.ts +48 -0
- package/dist/constants.cjs +42 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +60 -0
- package/dist/constants.d.ts +60 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/country/index.cjs +154 -0
- package/dist/country/index.cjs.map +1 -0
- package/dist/country/index.d.cts +1 -0
- package/dist/country/index.d.ts +1 -0
- package/dist/country/index.js +5 -0
- package/dist/country/index.js.map +1 -0
- package/dist/date/index.cjs +117 -0
- package/dist/date/index.cjs.map +1 -0
- package/dist/date/index.d.cts +283 -0
- package/dist/date/index.d.ts +283 -0
- package/dist/date/index.js +4 -0
- package/dist/date/index.js.map +1 -0
- package/dist/environment/index.cjs +73 -0
- package/dist/environment/index.cjs.map +1 -0
- package/dist/environment/index.d.cts +127 -0
- package/dist/environment/index.d.ts +127 -0
- package/dist/environment/index.js +4 -0
- package/dist/environment/index.js.map +1 -0
- package/dist/form/index.cjs +81 -0
- package/dist/form/index.cjs.map +1 -0
- package/dist/form/index.d.cts +227 -0
- package/dist/form/index.d.ts +227 -0
- package/dist/form/index.js +4 -0
- package/dist/form/index.js.map +1 -0
- package/dist/i18n.cjs +37 -0
- package/dist/i18n.cjs.map +1 -0
- package/dist/i18n.d.cts +102 -0
- package/dist/i18n.d.ts +102 -0
- package/dist/i18n.js +4 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index-BXBmBHyL.d.ts +718 -0
- package/dist/index-BYsUCP3u.d.cts +718 -0
- package/dist/index-Cl26FrAZ.d.cts +362 -0
- package/dist/index-Cl26FrAZ.d.ts +362 -0
- package/dist/index.cjs +1265 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +205 -0
- package/dist/index.d.ts +205 -0
- package/dist/index.js +277 -0
- package/dist/index.js.map +1 -0
- package/dist/schema.cjs +13 -0
- package/dist/schema.cjs.map +1 -0
- package/dist/schema.d.cts +84 -0
- package/dist/schema.d.ts +84 -0
- package/dist/schema.js +4 -0
- package/dist/schema.js.map +1 -0
- package/dist/security/index.cjs +94 -0
- package/dist/security/index.cjs.map +1 -0
- package/dist/security/index.d.cts +216 -0
- package/dist/security/index.d.ts +216 -0
- package/dist/security/index.js +5 -0
- package/dist/security/index.js.map +1 -0
- package/dist/string/index.cjs +153 -0
- package/dist/string/index.cjs.map +1 -0
- package/dist/string/index.d.cts +471 -0
- package/dist/string/index.d.ts +471 -0
- package/dist/string/index.js +4 -0
- package/dist/string/index.js.map +1 -0
- package/dist/transform/index.cjs +105 -0
- package/dist/transform/index.cjs.map +1 -0
- package/dist/transform/index.d.cts +271 -0
- package/dist/transform/index.d.ts +271 -0
- package/dist/transform/index.js +4 -0
- package/dist/transform/index.js.map +1 -0
- package/dist/validators/index.cjs +195 -0
- package/dist/validators/index.cjs.map +1 -0
- package/dist/validators/index.d.cts +2 -0
- package/dist/validators/index.d.ts +2 -0
- package/dist/validators/index.js +6 -0
- package/dist/validators/index.js.map +1 -0
- package/package.json +229 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkP7P2B7ZI_cjs = require('./chunk-P7P2B7ZI.cjs');
|
|
4
|
+
|
|
5
|
+
// src/security/password.ts
|
|
6
|
+
chunkP7P2B7ZI_cjs.init_constants();
|
|
7
|
+
var DEFAULT_OPTIONS = {
|
|
8
|
+
minLength: 8,
|
|
9
|
+
requireUppercase: true,
|
|
10
|
+
requireLowercase: true,
|
|
11
|
+
requireNumber: true,
|
|
12
|
+
requireSymbol: false
|
|
13
|
+
};
|
|
14
|
+
function checkPasswordStrength(password, options = {}) {
|
|
15
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
16
|
+
const suggestions = [];
|
|
17
|
+
const requirements = {
|
|
18
|
+
minLength: password.length >= (opts.minLength || 8),
|
|
19
|
+
hasUppercase: /[A-Z]/.test(password),
|
|
20
|
+
hasLowercase: /[a-z]/.test(password),
|
|
21
|
+
hasNumber: /[0-9]/.test(password),
|
|
22
|
+
hasSymbol: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password),
|
|
23
|
+
noCommonPatterns: !chunkP7P2B7ZI_cjs.COMMON_PASSWORD_PATTERNS.some((pattern) => pattern.test(password))
|
|
24
|
+
};
|
|
25
|
+
if (!requirements.minLength) {
|
|
26
|
+
suggestions.push(`Use at least ${opts.minLength} characters`);
|
|
27
|
+
}
|
|
28
|
+
if (!requirements.hasUppercase && opts.requireUppercase) {
|
|
29
|
+
suggestions.push("Add uppercase letters");
|
|
30
|
+
}
|
|
31
|
+
if (!requirements.hasLowercase && opts.requireLowercase) {
|
|
32
|
+
suggestions.push("Add lowercase letters");
|
|
33
|
+
}
|
|
34
|
+
if (!requirements.hasNumber && opts.requireNumber) {
|
|
35
|
+
suggestions.push("Add numbers");
|
|
36
|
+
}
|
|
37
|
+
if (!requirements.hasSymbol) {
|
|
38
|
+
suggestions.push("Add special characters (!@#$%^&*)");
|
|
39
|
+
}
|
|
40
|
+
if (!requirements.noCommonPatterns) {
|
|
41
|
+
suggestions.push("Avoid common password patterns");
|
|
42
|
+
}
|
|
43
|
+
let rawScore = 0;
|
|
44
|
+
if (password.length >= 8) rawScore += 1;
|
|
45
|
+
if (password.length >= 12) rawScore += 1;
|
|
46
|
+
if (password.length >= 16) rawScore += 1;
|
|
47
|
+
const varietyScore = (requirements.hasUppercase ? 1 : 0) + (requirements.hasLowercase ? 1 : 0) + (requirements.hasNumber ? 1 : 0) + (requirements.hasSymbol ? 1 : 0);
|
|
48
|
+
if (varietyScore >= 3) rawScore += 1;
|
|
49
|
+
if (varietyScore >= 4) rawScore += 1;
|
|
50
|
+
if (!requirements.noCommonPatterns) {
|
|
51
|
+
rawScore = Math.max(0, rawScore - 2);
|
|
52
|
+
}
|
|
53
|
+
const score = Math.min(4, Math.max(0, rawScore));
|
|
54
|
+
const entropy = calculatePasswordEntropy(password);
|
|
55
|
+
const labels = {
|
|
56
|
+
0: "very-weak",
|
|
57
|
+
1: "weak",
|
|
58
|
+
2: "fair",
|
|
59
|
+
3: "strong",
|
|
60
|
+
4: "very-strong"
|
|
61
|
+
};
|
|
62
|
+
const crackTime = estimateCrackTime(entropy);
|
|
63
|
+
return {
|
|
64
|
+
score,
|
|
65
|
+
label: labels[score],
|
|
66
|
+
suggestions,
|
|
67
|
+
requirements,
|
|
68
|
+
crackTime
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function calculatePasswordEntropy(password) {
|
|
72
|
+
if (!password) return 0;
|
|
73
|
+
let charsetSize = 0;
|
|
74
|
+
if (/[a-z]/.test(password)) charsetSize += 26;
|
|
75
|
+
if (/[A-Z]/.test(password)) charsetSize += 26;
|
|
76
|
+
if (/[0-9]/.test(password)) charsetSize += 10;
|
|
77
|
+
if (/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)) charsetSize += 32;
|
|
78
|
+
if (/[^\x00-\x7F]/.test(password)) charsetSize += 100;
|
|
79
|
+
if (charsetSize === 0) return 0;
|
|
80
|
+
return password.length * Math.log2(charsetSize);
|
|
81
|
+
}
|
|
82
|
+
function estimateCrackTime(entropy) {
|
|
83
|
+
if (entropy <= 0) return "Instantly";
|
|
84
|
+
const guessesPerSecondLog2 = 33.22;
|
|
85
|
+
const secondsLog2 = entropy - guessesPerSecondLog2;
|
|
86
|
+
if (secondsLog2 < 0) return "Instantly";
|
|
87
|
+
if (secondsLog2 < 6) return "Less than a minute";
|
|
88
|
+
if (secondsLog2 < 10) return "Minutes";
|
|
89
|
+
if (secondsLog2 < 14) return "Hours";
|
|
90
|
+
if (secondsLog2 < 17) return "Days";
|
|
91
|
+
if (secondsLog2 < 20) return "Weeks";
|
|
92
|
+
if (secondsLog2 < 22) return "Months";
|
|
93
|
+
if (secondsLog2 < 25) return "Years";
|
|
94
|
+
if (secondsLog2 < 35) return "Decades";
|
|
95
|
+
if (secondsLog2 < 45) return "Centuries";
|
|
96
|
+
return "Millennia+";
|
|
97
|
+
}
|
|
98
|
+
function meetsRequirements(password, requirements) {
|
|
99
|
+
const result = checkPasswordStrength(password, requirements);
|
|
100
|
+
if (requirements.minLength && !result.requirements.minLength) return false;
|
|
101
|
+
if (requirements.requireUppercase && !result.requirements.hasUppercase) return false;
|
|
102
|
+
if (requirements.requireLowercase && !result.requirements.hasLowercase) return false;
|
|
103
|
+
if (requirements.requireNumber && !result.requirements.hasNumber) return false;
|
|
104
|
+
if (requirements.requireSymbol && !result.requirements.hasSymbol) return false;
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
function isStrongPassword(password, minScore = 3) {
|
|
108
|
+
const result = checkPasswordStrength(password);
|
|
109
|
+
return result.score >= minScore;
|
|
110
|
+
}
|
|
111
|
+
function getPasswordFeedback(password) {
|
|
112
|
+
const result = checkPasswordStrength(password);
|
|
113
|
+
if (result.score === 0) {
|
|
114
|
+
return "This password is very weak and can be cracked instantly.";
|
|
115
|
+
}
|
|
116
|
+
if (result.score === 1) {
|
|
117
|
+
return "This password is weak. " + result.suggestions.slice(0, 2).join(". ") + ".";
|
|
118
|
+
}
|
|
119
|
+
if (result.score === 2) {
|
|
120
|
+
return "This password is fair but could be stronger. " + result.suggestions[0] + ".";
|
|
121
|
+
}
|
|
122
|
+
if (result.score === 3) {
|
|
123
|
+
return "This password is strong.";
|
|
124
|
+
}
|
|
125
|
+
return "This password is very strong!";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/security/hash.ts
|
|
129
|
+
async function hashSHA256(data) {
|
|
130
|
+
if (typeof globalThis.crypto?.subtle !== "undefined") {
|
|
131
|
+
const encoder = new TextEncoder();
|
|
132
|
+
const dataBuffer = encoder.encode(data);
|
|
133
|
+
const hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", dataBuffer);
|
|
134
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
135
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const crypto = await import('crypto');
|
|
139
|
+
return crypto.createHash("sha256").update(data).digest("hex");
|
|
140
|
+
} catch {
|
|
141
|
+
throw new Error("SHA-256 hashing is not available in this environment");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function hashSHA512(data) {
|
|
145
|
+
if (typeof globalThis.crypto?.subtle !== "undefined") {
|
|
146
|
+
const encoder = new TextEncoder();
|
|
147
|
+
const dataBuffer = encoder.encode(data);
|
|
148
|
+
const hashBuffer = await globalThis.crypto.subtle.digest("SHA-512", dataBuffer);
|
|
149
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
150
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const crypto = await import('crypto');
|
|
154
|
+
return crypto.createHash("sha512").update(data).digest("hex");
|
|
155
|
+
} catch {
|
|
156
|
+
throw new Error("SHA-512 hashing is not available in this environment");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function hashMD5(data) {
|
|
160
|
+
console.warn(
|
|
161
|
+
"[utilitify] MD5 is cryptographically broken and should not be used for security purposes. Use hashSHA256() instead. MD5 should only be used for checksums or legacy compatibility."
|
|
162
|
+
);
|
|
163
|
+
try {
|
|
164
|
+
const crypto = await import('crypto');
|
|
165
|
+
return crypto.createHash("md5").update(data).digest("hex");
|
|
166
|
+
} catch {
|
|
167
|
+
throw new Error("MD5 hashing is not available in this environment");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async function hashBcrypt(password, rounds = 10) {
|
|
171
|
+
try {
|
|
172
|
+
const bcrypt = await import('bcryptjs');
|
|
173
|
+
const salt = await bcrypt.genSalt(rounds);
|
|
174
|
+
return bcrypt.hash(password, salt);
|
|
175
|
+
} catch {
|
|
176
|
+
throw new Error(
|
|
177
|
+
"bcryptjs is not installed. Install it with: npm install bcryptjs"
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async function verifyBcrypt(password, hash) {
|
|
182
|
+
try {
|
|
183
|
+
const bcrypt = await import('bcryptjs');
|
|
184
|
+
return bcrypt.compare(password, hash);
|
|
185
|
+
} catch {
|
|
186
|
+
throw new Error(
|
|
187
|
+
"bcryptjs is not installed. Install it with: npm install bcryptjs"
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function hmacSHA256(data, key) {
|
|
192
|
+
if (typeof globalThis.crypto?.subtle !== "undefined") {
|
|
193
|
+
const encoder = new TextEncoder();
|
|
194
|
+
const keyData = encoder.encode(key);
|
|
195
|
+
const dataBuffer = encoder.encode(data);
|
|
196
|
+
const cryptoKey = await globalThis.crypto.subtle.importKey(
|
|
197
|
+
"raw",
|
|
198
|
+
keyData,
|
|
199
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
200
|
+
false,
|
|
201
|
+
["sign"]
|
|
202
|
+
);
|
|
203
|
+
const signature = await globalThis.crypto.subtle.sign("HMAC", cryptoKey, dataBuffer);
|
|
204
|
+
const hashArray = Array.from(new Uint8Array(signature));
|
|
205
|
+
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
const crypto = await import('crypto');
|
|
209
|
+
return crypto.createHmac("sha256", key).update(data).digest("hex");
|
|
210
|
+
} catch {
|
|
211
|
+
throw new Error("HMAC-SHA256 is not available in this environment");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function timingSafeCompare(a, b) {
|
|
215
|
+
const maxLength = Math.max(a.length, b.length);
|
|
216
|
+
const paddedA = a.padEnd(maxLength, "\0");
|
|
217
|
+
const paddedB = b.padEnd(maxLength, "\0");
|
|
218
|
+
let result = 0;
|
|
219
|
+
for (let i = 0; i < maxLength; i++) {
|
|
220
|
+
result |= paddedA.charCodeAt(i) ^ paddedB.charCodeAt(i);
|
|
221
|
+
}
|
|
222
|
+
result |= a.length ^ b.length;
|
|
223
|
+
return result === 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/security/token.ts
|
|
227
|
+
function generateUUID() {
|
|
228
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
229
|
+
return globalThis.crypto.randomUUID();
|
|
230
|
+
}
|
|
231
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
232
|
+
const bytes = new Uint8Array(16);
|
|
233
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
234
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
235
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
236
|
+
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
237
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
238
|
+
}
|
|
239
|
+
throw new Error(
|
|
240
|
+
"Crypto API not available. UUID generation requires a secure random source. Ensure you are running in a modern browser or Node.js 15.0.0+."
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
function generateUUIDv7() {
|
|
244
|
+
const now = Date.now();
|
|
245
|
+
const timestampHex = now.toString(16).padStart(12, "0");
|
|
246
|
+
const randomHex = generateRandomHex(20);
|
|
247
|
+
const variantIndex = parseInt(randomHex.charAt(0), 16) % 4;
|
|
248
|
+
const variants = ["8", "9", "a", "b"];
|
|
249
|
+
return timestampHex.slice(0, 8) + "-" + timestampHex.slice(8, 12) + "-7" + randomHex.slice(0, 3) + "-" + variants[variantIndex] + randomHex.slice(3, 6) + "-" + randomHex.slice(6, 18);
|
|
250
|
+
}
|
|
251
|
+
function generateToken(length = 32) {
|
|
252
|
+
return generateRandomHex(length * 2);
|
|
253
|
+
}
|
|
254
|
+
function generateSecureToken(length = 32) {
|
|
255
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
256
|
+
const bytes = new Uint8Array(length);
|
|
257
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
258
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
259
|
+
}
|
|
260
|
+
return generateRandomHex(length * 2);
|
|
261
|
+
}
|
|
262
|
+
function generateBase64Token(length = 32) {
|
|
263
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
264
|
+
const bytes = new Uint8Array(length);
|
|
265
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
266
|
+
if (typeof btoa === "function") {
|
|
267
|
+
return btoa(String.fromCharCode(...bytes));
|
|
268
|
+
}
|
|
269
|
+
return Buffer.from(bytes).toString("base64");
|
|
270
|
+
}
|
|
271
|
+
const hex = generateRandomHex(length * 2);
|
|
272
|
+
if (typeof btoa === "function") {
|
|
273
|
+
return btoa(
|
|
274
|
+
hex.match(/.{2}/g).map((byte) => String.fromCharCode(parseInt(byte, 16))).join("")
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
return Buffer.from(hex, "hex").toString("base64");
|
|
278
|
+
}
|
|
279
|
+
function generateUrlSafeToken(length = 32) {
|
|
280
|
+
const base64 = generateBase64Token(length);
|
|
281
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
282
|
+
}
|
|
283
|
+
function isValidUUID(uuid) {
|
|
284
|
+
if (!uuid || typeof uuid !== "string") return false;
|
|
285
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
286
|
+
return uuidRegex.test(uuid);
|
|
287
|
+
}
|
|
288
|
+
function getUUIDv7Timestamp(uuid) {
|
|
289
|
+
if (!isValidUUID(uuid)) return null;
|
|
290
|
+
if (uuid[14] !== "7") return null;
|
|
291
|
+
try {
|
|
292
|
+
const timestampHex = uuid.replace(/-/g, "").slice(0, 12);
|
|
293
|
+
const timestamp = parseInt(timestampHex, 16);
|
|
294
|
+
return new Date(timestamp);
|
|
295
|
+
} catch {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
function generateShortId() {
|
|
300
|
+
return generateRandomHex(8);
|
|
301
|
+
}
|
|
302
|
+
function generateNanoId(length = 21) {
|
|
303
|
+
const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
|
|
304
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
305
|
+
const bytes = new Uint8Array(length);
|
|
306
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
307
|
+
return Array.from(bytes).map((b) => alphabet[b % alphabet.length]).join("");
|
|
308
|
+
}
|
|
309
|
+
throw new Error(
|
|
310
|
+
"Crypto API not available. NanoID generation requires a secure random source. Ensure you are running in a modern browser or Node.js 15.0.0+."
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
function generateRandomHex(length) {
|
|
314
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
315
|
+
const bytes = new Uint8Array(Math.ceil(length / 2));
|
|
316
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
317
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, length);
|
|
318
|
+
}
|
|
319
|
+
throw new Error(
|
|
320
|
+
"Crypto API not available. Secure random generation requires crypto.getRandomValues. Ensure you are running in a modern browser or Node.js 15.0.0+."
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
exports.checkPasswordStrength = checkPasswordStrength;
|
|
325
|
+
exports.generateBase64Token = generateBase64Token;
|
|
326
|
+
exports.generateNanoId = generateNanoId;
|
|
327
|
+
exports.generateSecureToken = generateSecureToken;
|
|
328
|
+
exports.generateShortId = generateShortId;
|
|
329
|
+
exports.generateToken = generateToken;
|
|
330
|
+
exports.generateUUID = generateUUID;
|
|
331
|
+
exports.generateUUIDv7 = generateUUIDv7;
|
|
332
|
+
exports.generateUrlSafeToken = generateUrlSafeToken;
|
|
333
|
+
exports.getPasswordFeedback = getPasswordFeedback;
|
|
334
|
+
exports.getUUIDv7Timestamp = getUUIDv7Timestamp;
|
|
335
|
+
exports.hashBcrypt = hashBcrypt;
|
|
336
|
+
exports.hashMD5 = hashMD5;
|
|
337
|
+
exports.hashSHA256 = hashSHA256;
|
|
338
|
+
exports.hashSHA512 = hashSHA512;
|
|
339
|
+
exports.hmacSHA256 = hmacSHA256;
|
|
340
|
+
exports.isStrongPassword = isStrongPassword;
|
|
341
|
+
exports.isValidUUID = isValidUUID;
|
|
342
|
+
exports.meetsRequirements = meetsRequirements;
|
|
343
|
+
exports.timingSafeCompare = timingSafeCompare;
|
|
344
|
+
exports.verifyBcrypt = verifyBcrypt;
|
|
345
|
+
//# sourceMappingURL=chunk-2ICNRTSN.cjs.map
|
|
346
|
+
//# sourceMappingURL=chunk-2ICNRTSN.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/security/password.ts","../src/security/hash.ts","../src/security/token.ts"],"names":["init_constants","COMMON_PASSWORD_PATTERNS"],"mappings":"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","file":"chunk-2ICNRTSN.cjs","sourcesContent":["import { COMMON_PASSWORD_PATTERNS } from '../utils/constants';\r\n\r\n/**\r\n * Password strength result\r\n */\r\nexport interface PasswordStrength {\r\n /** Score from 0-4 (0 = very weak, 4 = very strong) */\r\n score: 0 | 1 | 2 | 3 | 4;\r\n /** Human-readable strength label */\r\n label: 'very-weak' | 'weak' | 'fair' | 'strong' | 'very-strong';\r\n /** Improvement suggestions */\r\n suggestions: string[];\r\n /** Requirements met */\r\n requirements: {\r\n minLength: boolean;\r\n hasUppercase: boolean;\r\n hasLowercase: boolean;\r\n hasNumber: boolean;\r\n hasSymbol: boolean;\r\n noCommonPatterns: boolean;\r\n };\r\n /** Estimated crack time description */\r\n crackTime: string;\r\n}\r\n\r\n/**\r\n * Password strength options\r\n */\r\nexport interface PasswordStrengthOptions {\r\n /** Minimum length (default: 8) */\r\n minLength?: number;\r\n /** Require uppercase (default: true) */\r\n requireUppercase?: boolean;\r\n /** Require lowercase (default: true) */\r\n requireLowercase?: boolean;\r\n /** Require number (default: true) */\r\n requireNumber?: boolean;\r\n /** Require symbol (default: false) */\r\n requireSymbol?: boolean;\r\n}\r\n\r\n/**\r\n * Default options\r\n */\r\nconst DEFAULT_OPTIONS: PasswordStrengthOptions = {\r\n minLength: 8,\r\n requireUppercase: true,\r\n requireLowercase: true,\r\n requireNumber: true,\r\n requireSymbol: false,\r\n};\r\n\r\n/**\r\n * Check password strength\r\n *\r\n * @param password - Password to check\r\n * @param options - Strength options\r\n * @returns Password strength result\r\n * @since 1.0.0\r\n *\r\n * @example\r\n * ```typescript\r\n * const result = checkPasswordStrength('MyP@ssw0rd!');\r\n * console.log(result.score); // 4\r\n * console.log(result.label); // 'very-strong'\r\n * ```\r\n */\r\nexport function checkPasswordStrength(\r\n password: string,\r\n options: PasswordStrengthOptions = {}\r\n): PasswordStrength {\r\n const opts = { ...DEFAULT_OPTIONS, ...options };\r\n const suggestions: string[] = [];\r\n\r\n // Check requirements\r\n const requirements = {\r\n minLength: password.length >= (opts.minLength || 8),\r\n hasUppercase: /[A-Z]/.test(password),\r\n hasLowercase: /[a-z]/.test(password),\r\n hasNumber: /[0-9]/.test(password),\r\n hasSymbol: /[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]/.test(password),\r\n noCommonPatterns: !COMMON_PASSWORD_PATTERNS.some(pattern => pattern.test(password)),\r\n };\r\n\r\n // Build suggestions\r\n if (!requirements.minLength) {\r\n suggestions.push(`Use at least ${opts.minLength} characters`);\r\n }\r\n if (!requirements.hasUppercase && opts.requireUppercase) {\r\n suggestions.push('Add uppercase letters');\r\n }\r\n if (!requirements.hasLowercase && opts.requireLowercase) {\r\n suggestions.push('Add lowercase letters');\r\n }\r\n if (!requirements.hasNumber && opts.requireNumber) {\r\n suggestions.push('Add numbers');\r\n }\r\n if (!requirements.hasSymbol) {\r\n suggestions.push('Add special characters (!@#$%^&*)');\r\n }\r\n if (!requirements.noCommonPatterns) {\r\n suggestions.push('Avoid common password patterns');\r\n }\r\n\r\n // Calculate score\r\n let rawScore = 0;\r\n\r\n // Length scoring\r\n if (password.length >= 8) rawScore += 1;\r\n if (password.length >= 12) rawScore += 1;\r\n if (password.length >= 16) rawScore += 1;\r\n\r\n // Character variety scoring\r\n const varietyScore =\r\n (requirements.hasUppercase ? 1 : 0) +\r\n (requirements.hasLowercase ? 1 : 0) +\r\n (requirements.hasNumber ? 1 : 0) +\r\n (requirements.hasSymbol ? 1 : 0);\r\n\r\n if (varietyScore >= 3) rawScore += 1;\r\n if (varietyScore >= 4) rawScore += 1;\r\n\r\n // Penalty for common patterns\r\n if (!requirements.noCommonPatterns) {\r\n rawScore = Math.max(0, rawScore - 2);\r\n }\r\n\r\n // Ensure score is in range and cast to proper type\r\n const score = Math.min(4, Math.max(0, rawScore)) as 0 | 1 | 2 | 3 | 4;\r\n\r\n // Calculate entropy for more accurate strength assessment\r\n const entropy = calculatePasswordEntropy(password);\r\n\r\n // Determine label based on entropy\r\n const labels: Record<number, PasswordStrength['label']> = {\r\n 0: 'very-weak',\r\n 1: 'weak',\r\n 2: 'fair',\r\n 3: 'strong',\r\n 4: 'very-strong',\r\n };\r\n\r\n // Calculate crack time based on entropy\r\n // Assuming 10 billion guesses per second (modern GPU cracking)\r\n const crackTime = estimateCrackTime(entropy);\r\n\r\n return {\r\n score,\r\n label: labels[score],\r\n suggestions,\r\n requirements,\r\n crackTime,\r\n };\r\n}\r\n\r\n/**\r\n * Calculate password entropy in bits\r\n * \r\n * @param password - Password to analyze\r\n * @returns Entropy in bits\r\n */\r\nfunction calculatePasswordEntropy(password: string): number {\r\n if (!password) return 0;\r\n\r\n let charsetSize = 0;\r\n\r\n // Calculate character set size\r\n if (/[a-z]/.test(password)) charsetSize += 26;\r\n if (/[A-Z]/.test(password)) charsetSize += 26;\r\n if (/[0-9]/.test(password)) charsetSize += 10;\r\n if (/[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]/.test(password)) charsetSize += 32;\r\n if (/[^\\x00-\\x7F]/.test(password)) charsetSize += 100; // Unicode characters\r\n\r\n // Entropy = log2(charsetSize^length) = length * log2(charsetSize)\r\n if (charsetSize === 0) return 0;\r\n\r\n return password.length * Math.log2(charsetSize);\r\n}\r\n\r\n/**\r\n * Estimate crack time based on entropy\r\n * Assumes 10 billion guesses per second (modern GPU)\r\n * \r\n * @param entropy - Entropy in bits\r\n * @returns Human-readable crack time\r\n */\r\nfunction estimateCrackTime(entropy: number): string {\r\n if (entropy <= 0) return 'Instantly';\r\n\r\n // 2^entropy = number of possible combinations\r\n // Time = combinations / guesses_per_second\r\n // Using log to avoid overflow: log2(seconds) = entropy - log2(guesses_per_second)\r\n const guessesPerSecondLog2 = 33.22; // log2(10 billion) ≈ 33.22\r\n const secondsLog2 = entropy - guessesPerSecondLog2;\r\n\r\n if (secondsLog2 < 0) return 'Instantly';\r\n if (secondsLog2 < 6) return 'Less than a minute';\r\n if (secondsLog2 < 10) return 'Minutes';\r\n if (secondsLog2 < 14) return 'Hours';\r\n if (secondsLog2 < 17) return 'Days';\r\n if (secondsLog2 < 20) return 'Weeks';\r\n if (secondsLog2 < 22) return 'Months';\r\n if (secondsLog2 < 25) return 'Years';\r\n if (secondsLog2 < 35) return 'Decades';\r\n if (secondsLog2 < 45) return 'Centuries';\r\n return 'Millennia+';\r\n}\r\n\r\n/**\r\n * Check if password meets requirements\r\n *\r\n * @param password - Password to check\r\n * @param requirements - Requirements to check\r\n * @returns true if all requirements met\r\n */\r\nexport function meetsRequirements(\r\n password: string,\r\n requirements: Partial<PasswordStrengthOptions>\r\n): boolean {\r\n const result = checkPasswordStrength(password, requirements);\r\n\r\n if (requirements.minLength && !result.requirements.minLength) return false;\r\n if (requirements.requireUppercase && !result.requirements.hasUppercase) return false;\r\n if (requirements.requireLowercase && !result.requirements.hasLowercase) return false;\r\n if (requirements.requireNumber && !result.requirements.hasNumber) return false;\r\n if (requirements.requireSymbol && !result.requirements.hasSymbol) return false;\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Check if password is strong enough\r\n *\r\n * @param password - Password to check\r\n * @param minScore - Minimum score (default: 3)\r\n * @returns true if strong enough\r\n */\r\nexport function isStrongPassword(password: string, minScore: number = 3): boolean {\r\n const result = checkPasswordStrength(password);\r\n return result.score >= minScore;\r\n}\r\n\r\n/**\r\n * Get password feedback message\r\n *\r\n * @param password - Password to check\r\n * @returns Feedback message\r\n */\r\nexport function getPasswordFeedback(password: string): string {\r\n const result = checkPasswordStrength(password);\r\n\r\n if (result.score === 0) {\r\n return 'This password is very weak and can be cracked instantly.';\r\n }\r\n if (result.score === 1) {\r\n return 'This password is weak. ' + result.suggestions.slice(0, 2).join('. ') + '.';\r\n }\r\n if (result.score === 2) {\r\n return 'This password is fair but could be stronger. ' + result.suggestions[0] + '.';\r\n }\r\n if (result.score === 3) {\r\n return 'This password is strong.';\r\n }\r\n return 'This password is very strong!';\r\n}\r\n","/**\r\n * Hash a string using SHA-256\r\n * Uses Web Crypto API for browser compatibility\r\n *\r\n * @param data - String to hash\r\n * @returns SHA-256 hash as hex string\r\n *\r\n * @example\r\n * ```typescript\r\n * const hash = await hashSHA256('hello world');\r\n * // 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'\r\n * ```\r\n */\r\nexport async function hashSHA256(data: string): Promise<string> {\r\n // Node.js environment\r\n if (typeof globalThis.crypto?.subtle !== 'undefined') {\r\n const encoder = new TextEncoder();\r\n const dataBuffer = encoder.encode(data);\r\n const hashBuffer = await globalThis.crypto.subtle.digest('SHA-256', dataBuffer);\r\n const hashArray = Array.from(new Uint8Array(hashBuffer));\r\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n // Fallback for Node.js without Web Crypto\r\n try {\r\n const crypto = await import('crypto');\r\n return crypto.createHash('sha256').update(data).digest('hex');\r\n } catch {\r\n throw new Error('SHA-256 hashing is not available in this environment');\r\n }\r\n}\r\n\r\n/**\r\n * Hash a string using SHA-512\r\n *\r\n * @param data - String to hash\r\n * @returns SHA-512 hash as hex string\r\n */\r\nexport async function hashSHA512(data: string): Promise<string> {\r\n if (typeof globalThis.crypto?.subtle !== 'undefined') {\r\n const encoder = new TextEncoder();\r\n const dataBuffer = encoder.encode(data);\r\n const hashBuffer = await globalThis.crypto.subtle.digest('SHA-512', dataBuffer);\r\n const hashArray = Array.from(new Uint8Array(hashBuffer));\r\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n try {\r\n const crypto = await import('crypto');\r\n return crypto.createHash('sha512').update(data).digest('hex');\r\n } catch {\r\n throw new Error('SHA-512 hashing is not available in this environment');\r\n }\r\n}\r\n\r\n/**\r\n * Hash a string using MD5 (NOT SECURE - use for checksums only)\r\n *\r\n * @deprecated MD5 is cryptographically broken. Use SHA-256 for security-sensitive hashing.\r\n * @param data - String to hash\r\n * @returns MD5 hash as hex string\r\n */\r\nexport async function hashMD5(data: string): Promise<string> {\r\n console.warn(\r\n '[utilitify] MD5 is cryptographically broken and should not be used for security purposes. ' +\r\n 'Use hashSHA256() instead. MD5 should only be used for checksums or legacy compatibility.'\r\n );\r\n try {\r\n const crypto = await import('crypto');\r\n return crypto.createHash('md5').update(data).digest('hex');\r\n } catch {\r\n throw new Error('MD5 hashing is not available in this environment');\r\n }\r\n}\r\n\r\n/**\r\n * Hash password using bcrypt (requires bcryptjs)\r\n *\r\n * @param password - Password to hash\r\n * @param rounds - Salt rounds (default: 10)\r\n * @returns Bcrypt hash\r\n */\r\nexport async function hashBcrypt(password: string, rounds: number = 10): Promise<string> {\r\n try {\r\n const bcrypt = await import('bcryptjs');\r\n const salt = await bcrypt.genSalt(rounds);\r\n return bcrypt.hash(password, salt);\r\n } catch {\r\n throw new Error(\r\n 'bcryptjs is not installed. Install it with: npm install bcryptjs'\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Verify password against bcrypt hash\r\n *\r\n * @param password - Password to verify\r\n * @param hash - Bcrypt hash\r\n * @returns true if password matches\r\n */\r\nexport async function verifyBcrypt(password: string, hash: string): Promise<boolean> {\r\n try {\r\n const bcrypt = await import('bcryptjs');\r\n return bcrypt.compare(password, hash);\r\n } catch {\r\n throw new Error(\r\n 'bcryptjs is not installed. Install it with: npm install bcryptjs'\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Hash with HMAC-SHA256\r\n *\r\n * @param data - Data to hash\r\n * @param key - Secret key\r\n * @returns HMAC hash\r\n */\r\nexport async function hmacSHA256(data: string, key: string): Promise<string> {\r\n if (typeof globalThis.crypto?.subtle !== 'undefined') {\r\n const encoder = new TextEncoder();\r\n const keyData = encoder.encode(key);\r\n const dataBuffer = encoder.encode(data);\r\n\r\n const cryptoKey = await globalThis.crypto.subtle.importKey(\r\n 'raw',\r\n keyData,\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n false,\r\n ['sign']\r\n );\r\n\r\n const signature = await globalThis.crypto.subtle.sign('HMAC', cryptoKey, dataBuffer);\r\n const hashArray = Array.from(new Uint8Array(signature));\r\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n try {\r\n const crypto = await import('crypto');\r\n return crypto.createHmac('sha256', key).update(data).digest('hex');\r\n } catch {\r\n throw new Error('HMAC-SHA256 is not available in this environment');\r\n }\r\n}\r\n\r\n/**\r\n * Compare two strings in constant time (timing-safe)\r\n * This prevents timing attacks that could leak information about the string contents.\r\n *\r\n * @param a - First string\r\n * @param b - Second string\r\n * @returns true if equal\r\n */\r\nexport function timingSafeCompare(a: string, b: string): boolean {\r\n // Use the longer length to ensure constant-time comparison\r\n const maxLength = Math.max(a.length, b.length);\r\n\r\n // Pad both strings to the same length to prevent length-based timing attacks\r\n const paddedA = a.padEnd(maxLength, '\\0');\r\n const paddedB = b.padEnd(maxLength, '\\0');\r\n\r\n let result = 0;\r\n\r\n // XOR all characters - this takes constant time regardless of differences\r\n for (let i = 0; i < maxLength; i++) {\r\n result |= paddedA.charCodeAt(i) ^ paddedB.charCodeAt(i);\r\n }\r\n\r\n // Also check if lengths match (constant time)\r\n result |= a.length ^ b.length;\r\n\r\n return result === 0;\r\n}\r\n","/**\r\n * Generate UUID v4 (random)\r\n *\r\n * @returns UUID v4 string\r\n * @throws Error if crypto API is not available\r\n *\r\n * @example\r\n * ```typescript\r\n * generateUUID(); // '550e8400-e29b-41d4-a716-446655440000'\r\n * ```\r\n */\r\nexport function generateUUID(): string {\r\n // Use crypto.randomUUID if available (best option)\r\n if (typeof globalThis.crypto?.randomUUID === 'function') {\r\n return globalThis.crypto.randomUUID();\r\n }\r\n\r\n // Fallback using getRandomValues (still secure)\r\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\r\n const bytes = new Uint8Array(16);\r\n globalThis.crypto.getRandomValues(bytes);\r\n // Set version (4) and variant (RFC 4122)\r\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\r\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\r\n\r\n const hex = Array.from(bytes)\r\n .map(b => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n\r\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\r\n }\r\n\r\n throw new Error(\r\n 'Crypto API not available. UUID generation requires a secure random source. ' +\r\n 'Ensure you are running in a modern browser or Node.js 15.0.0+.'\r\n );\r\n}\r\n\r\n/**\r\n * Generate UUID v7 (time-sortable)\r\n * Based on Unix Epoch timestamp\r\n *\r\n * @returns UUID v7 string\r\n */\r\nexport function generateUUIDv7(): string {\r\n const now = Date.now();\r\n\r\n // Convert timestamp to hex (48 bits = 12 hex chars)\r\n const timestampHex = now.toString(16).padStart(12, '0');\r\n\r\n // Generate random bytes for the rest\r\n const randomHex = generateRandomHex(20);\r\n\r\n // Format: tttttttt-tttt-7xxx-yxxx-xxxxxxxxxxxx\r\n // t = timestamp, 7 = version, y = variant (8, 9, a, or b)\r\n // Use first byte of random for variant selection\r\n const variantIndex = parseInt(randomHex.charAt(0), 16) % 4;\r\n const variants = ['8', '9', 'a', 'b'];\r\n\r\n return (\r\n timestampHex.slice(0, 8) +\r\n '-' +\r\n timestampHex.slice(8, 12) +\r\n '-7' +\r\n randomHex.slice(0, 3) +\r\n '-' +\r\n variants[variantIndex] +\r\n randomHex.slice(3, 6) +\r\n '-' +\r\n randomHex.slice(6, 18)\r\n );\r\n}\r\n\r\n/**\r\n * Generate a secure random token\r\n *\r\n * @param length - Token length in bytes (default: 32)\r\n * @returns Hex-encoded token\r\n */\r\nexport function generateToken(length: number = 32): string {\r\n return generateRandomHex(length * 2);\r\n}\r\n\r\n/**\r\n * Generate a cryptographically secure token\r\n *\r\n * @param length - Token length in bytes\r\n * @returns Hex-encoded secure token\r\n */\r\nexport function generateSecureToken(length: number = 32): string {\r\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\r\n const bytes = new Uint8Array(length);\r\n globalThis.crypto.getRandomValues(bytes);\r\n return Array.from(bytes)\r\n .map(b => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n }\r\n\r\n // Fallback to less secure method\r\n return generateRandomHex(length * 2);\r\n}\r\n\r\n/**\r\n * Generate a Base64 encoded token\r\n *\r\n * @param length - Token length in bytes\r\n * @returns Base64-encoded token\r\n */\r\nexport function generateBase64Token(length: number = 32): string {\r\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\r\n const bytes = new Uint8Array(length);\r\n globalThis.crypto.getRandomValues(bytes);\r\n\r\n // Convert to base64\r\n if (typeof btoa === 'function') {\r\n return btoa(String.fromCharCode(...bytes));\r\n }\r\n\r\n // Node.js fallback\r\n return Buffer.from(bytes).toString('base64');\r\n }\r\n\r\n // Fallback\r\n const hex = generateRandomHex(length * 2);\r\n if (typeof btoa === 'function') {\r\n return btoa(\r\n hex\r\n .match(/.{2}/g)!\r\n .map(byte => String.fromCharCode(parseInt(byte, 16)))\r\n .join('')\r\n );\r\n }\r\n return Buffer.from(hex, 'hex').toString('base64');\r\n}\r\n\r\n/**\r\n * Generate URL-safe token\r\n *\r\n * @param length - Token length\r\n * @returns URL-safe token\r\n */\r\nexport function generateUrlSafeToken(length: number = 32): string {\r\n const base64 = generateBase64Token(length);\r\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\r\n}\r\n\r\n/**\r\n * Validate UUID format\r\n *\r\n * @param uuid - String to validate\r\n * @returns true if valid UUID\r\n */\r\nexport function isValidUUID(uuid: string): boolean {\r\n if (!uuid || typeof uuid !== 'string') return false;\r\n const uuidRegex =\r\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\r\n return uuidRegex.test(uuid);\r\n}\r\n\r\n/**\r\n * Extract timestamp from UUID v7\r\n *\r\n * @param uuid - UUID v7 string\r\n * @returns Date or null\r\n */\r\nexport function getUUIDv7Timestamp(uuid: string): Date | null {\r\n if (!isValidUUID(uuid)) return null;\r\n\r\n // Check if it's v7\r\n if (uuid[14] !== '7') return null;\r\n\r\n try {\r\n const timestampHex = uuid.replace(/-/g, '').slice(0, 12);\r\n const timestamp = parseInt(timestampHex, 16);\r\n return new Date(timestamp);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Generate short ID (8 characters)\r\n *\r\n * @returns Short ID\r\n */\r\nexport function generateShortId(): string {\r\n return generateRandomHex(8);\r\n}\r\n\r\n/**\r\n * Generate nano ID style token\r\n *\r\n * @param length - Length (default: 21)\r\n * @returns NanoID-style token\r\n */\r\nexport function generateNanoId(length: number = 21): string {\r\n const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_';\r\n\r\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\r\n const bytes = new Uint8Array(length);\r\n globalThis.crypto.getRandomValues(bytes);\r\n return Array.from(bytes)\r\n .map(b => alphabet[b % alphabet.length])\r\n .join('');\r\n }\r\n\r\n throw new Error(\r\n 'Crypto API not available. NanoID generation requires a secure random source. ' +\r\n 'Ensure you are running in a modern browser or Node.js 15.0.0+.'\r\n );\r\n}\r\n\r\n/**\r\n * Generate random hex string\r\n */\r\nfunction generateRandomHex(length: number): string {\r\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\r\n const bytes = new Uint8Array(Math.ceil(length / 2));\r\n globalThis.crypto.getRandomValues(bytes);\r\n return Array.from(bytes)\r\n .map(b => b.toString(16).padStart(2, '0'))\r\n .join('')\r\n .slice(0, length);\r\n }\r\n\r\n throw new Error(\r\n 'Crypto API not available. Secure random generation requires crypto.getRandomValues. ' +\r\n 'Ensure you are running in a modern browser or Node.js 15.0.0+.'\r\n );\r\n}\r\n"]}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// src/i18n.ts
|
|
2
|
+
var EN_MESSAGES = {
|
|
3
|
+
required: "This field is required",
|
|
4
|
+
invalid: "This field is invalid",
|
|
5
|
+
tooShort: "Must be at least {min} characters",
|
|
6
|
+
tooLong: "Must not exceed {max} characters",
|
|
7
|
+
emailInvalid: "Please enter a valid email address",
|
|
8
|
+
emailDisposable: "Disposable email addresses are not allowed",
|
|
9
|
+
emailDomainBlocked: "This email domain is not allowed",
|
|
10
|
+
phoneInvalid: "Please enter a valid phone number",
|
|
11
|
+
phoneTooShort: "Phone number is too short",
|
|
12
|
+
phoneTooLong: "Phone number is too long",
|
|
13
|
+
phoneMobileOnly: "Only mobile numbers are allowed",
|
|
14
|
+
passwordTooWeak: "Password is too weak",
|
|
15
|
+
passwordNoUppercase: "Password must contain uppercase letters",
|
|
16
|
+
passwordNoLowercase: "Password must contain lowercase letters",
|
|
17
|
+
passwordNoNumber: "Password must contain numbers",
|
|
18
|
+
passwordNoSymbol: "Password must contain special characters",
|
|
19
|
+
passwordCommonPattern: "Password is too common",
|
|
20
|
+
nameInvalid: "Please enter a valid name",
|
|
21
|
+
nameContainsNumbers: "Name cannot contain numbers",
|
|
22
|
+
usernameReserved: "This username is reserved",
|
|
23
|
+
usernameInvalidChars: "Username contains invalid characters",
|
|
24
|
+
urlInvalid: "Please enter a valid URL",
|
|
25
|
+
urlDangerous: "This URL is not allowed for security reasons",
|
|
26
|
+
cardInvalid: "Please enter a valid card number",
|
|
27
|
+
cardExpired: "This card has expired",
|
|
28
|
+
cardCvvInvalid: "Please enter a valid CVV"
|
|
29
|
+
};
|
|
30
|
+
var ES_MESSAGES = {
|
|
31
|
+
required: "Este campo es obligatorio",
|
|
32
|
+
invalid: "Este campo no es válido",
|
|
33
|
+
tooShort: "Debe tener al menos {min} caracteres",
|
|
34
|
+
tooLong: "No debe exceder {max} caracteres",
|
|
35
|
+
emailInvalid: "Por favor ingrese un correo electrónico válido",
|
|
36
|
+
emailDisposable: "No se permiten correos electrónicos temporales",
|
|
37
|
+
emailDomainBlocked: "Este dominio de correo no está permitido",
|
|
38
|
+
phoneInvalid: "Por favor ingrese un número de teléfono válido",
|
|
39
|
+
phoneTooShort: "El número de teléfono es muy corto",
|
|
40
|
+
phoneTooLong: "El número de teléfono es muy largo",
|
|
41
|
+
phoneMobileOnly: "Solo se permiten números móviles",
|
|
42
|
+
passwordTooWeak: "La contraseña es muy débil",
|
|
43
|
+
passwordNoUppercase: "La contraseña debe contener mayúsculas",
|
|
44
|
+
passwordNoLowercase: "La contraseña debe contener minúsculas",
|
|
45
|
+
passwordNoNumber: "La contraseña debe contener números",
|
|
46
|
+
passwordNoSymbol: "La contraseña debe contener caracteres especiales",
|
|
47
|
+
passwordCommonPattern: "La contraseña es muy común",
|
|
48
|
+
nameInvalid: "Por favor ingrese un nombre válido",
|
|
49
|
+
nameContainsNumbers: "El nombre no puede contener números",
|
|
50
|
+
usernameReserved: "Este nombre de usuario está reservado",
|
|
51
|
+
usernameInvalidChars: "El nombre de usuario contiene caracteres no válidos",
|
|
52
|
+
urlInvalid: "Por favor ingrese una URL válida",
|
|
53
|
+
urlDangerous: "Esta URL no está permitida por razones de seguridad",
|
|
54
|
+
cardInvalid: "Por favor ingrese un número de tarjeta válido",
|
|
55
|
+
cardExpired: "Esta tarjeta ha expirado",
|
|
56
|
+
cardCvvInvalid: "Por favor ingrese un CVV válido"
|
|
57
|
+
};
|
|
58
|
+
var UR_MESSAGES = {
|
|
59
|
+
required: "یہ فیلڈ ضروری ہے",
|
|
60
|
+
invalid: "یہ فیلڈ درست نہیں ہے",
|
|
61
|
+
tooShort: "کم از کم {min} حروف ہونے چاہئیں",
|
|
62
|
+
tooLong: "{max} حروف سے زیادہ نہیں ہونے چاہئیں",
|
|
63
|
+
emailInvalid: "براہ کرم درست ای میل درج کریں",
|
|
64
|
+
emailDisposable: "عارضی ای میل کی اجازت نہیں ہے",
|
|
65
|
+
emailDomainBlocked: "یہ ای میل ڈومین کی اجازت نہیں ہے",
|
|
66
|
+
phoneInvalid: "براہ کرم درست فون نمبر درج کریں",
|
|
67
|
+
phoneTooShort: "فون نمبر بہت چھوٹا ہے",
|
|
68
|
+
phoneTooLong: "فون نمبر بہت لمبا ہے",
|
|
69
|
+
phoneMobileOnly: "صرف موبائل نمبر کی اجازت ہے",
|
|
70
|
+
passwordTooWeak: "پاس ورڈ بہت کمزور ہے",
|
|
71
|
+
passwordNoUppercase: "پاس ورڈ میں بڑے حروف ہونے چاہئیں",
|
|
72
|
+
passwordNoLowercase: "پاس ورڈ میں چھوٹے حروف ہونے چاہئیں",
|
|
73
|
+
passwordNoNumber: "پاس ورڈ میں نمبر ہونے چاہئیں",
|
|
74
|
+
passwordNoSymbol: "پاس ورڈ میں خاص حروف ہونے چاہئیں",
|
|
75
|
+
passwordCommonPattern: "پاس ورڈ بہت عام ہے",
|
|
76
|
+
nameInvalid: "براہ کرم درست نام درج کریں",
|
|
77
|
+
nameContainsNumbers: "نام میں نمبر نہیں ہو سکتے",
|
|
78
|
+
usernameReserved: "یہ صارف نام محفوظ ہے",
|
|
79
|
+
usernameInvalidChars: "صارف نام میں غیر درست حروف ہیں",
|
|
80
|
+
urlInvalid: "براہ کرم درست URL درج کریں",
|
|
81
|
+
urlDangerous: "سیکیورٹی وجوہات کی بنا پر یہ URL کی اجازت نہیں ہے",
|
|
82
|
+
cardInvalid: "براہ کرم درست کارڈ نمبر درج کریں",
|
|
83
|
+
cardExpired: "یہ کارڈ ختم ہو چکا ہے",
|
|
84
|
+
cardCvvInvalid: "براہ کرم درست CVV درج کریں"
|
|
85
|
+
};
|
|
86
|
+
var AR_MESSAGES = {
|
|
87
|
+
required: "هذا الحقل مطلوب",
|
|
88
|
+
invalid: "هذا الحقل غير صالح",
|
|
89
|
+
tooShort: "يجب أن يكون على الأقل {min} أحرف",
|
|
90
|
+
tooLong: "يجب ألا يتجاوز {max} أحرف",
|
|
91
|
+
emailInvalid: "يرجى إدخال بريد إلكتروني صالح",
|
|
92
|
+
emailDisposable: "البريد الإلكتروني المؤقت غير مسموح به",
|
|
93
|
+
emailDomainBlocked: "نطاق البريد الإلكتروني هذا غير مسموح به",
|
|
94
|
+
phoneInvalid: "يرجى إدخال رقم هاتف صالح",
|
|
95
|
+
phoneTooShort: "رقم الهاتف قصير جداً",
|
|
96
|
+
phoneTooLong: "رقم الهاتف طويل جداً",
|
|
97
|
+
phoneMobileOnly: "يسمح فقط بأرقام الجوال",
|
|
98
|
+
passwordTooWeak: "كلمة المرور ضعيفة جداً",
|
|
99
|
+
passwordNoUppercase: "يجب أن تحتوي كلمة المرور على أحرف كبيرة",
|
|
100
|
+
passwordNoLowercase: "يجب أن تحتوي كلمة المرور على أحرف صغيرة",
|
|
101
|
+
passwordNoNumber: "يجب أن تحتوي كلمة المرور على أرقام",
|
|
102
|
+
passwordNoSymbol: "يجب أن تحتوي كلمة المرور على رموز خاصة",
|
|
103
|
+
passwordCommonPattern: "كلمة المرور شائعة جداً",
|
|
104
|
+
nameInvalid: "يرجى إدخال اسم صالح",
|
|
105
|
+
nameContainsNumbers: "لا يمكن أن يحتوي الاسم على أرقام",
|
|
106
|
+
usernameReserved: "اسم المستخدم هذا محجوز",
|
|
107
|
+
usernameInvalidChars: "اسم المستخدم يحتوي على أحرف غير صالحة",
|
|
108
|
+
urlInvalid: "يرجى إدخال رابط صالح",
|
|
109
|
+
urlDangerous: "هذا الرابط غير مسموح به لأسباب أمنية",
|
|
110
|
+
cardInvalid: "يرجى إدخال رقم بطاقة صالح",
|
|
111
|
+
cardExpired: "انتهت صلاحية هذه البطاقة",
|
|
112
|
+
cardCvvInvalid: "يرجى إدخال CVV صالح"
|
|
113
|
+
};
|
|
114
|
+
var MESSAGES = {
|
|
115
|
+
en: EN_MESSAGES,
|
|
116
|
+
es: ES_MESSAGES,
|
|
117
|
+
fr: EN_MESSAGES,
|
|
118
|
+
// Fallback to English
|
|
119
|
+
de: EN_MESSAGES,
|
|
120
|
+
// Fallback to English
|
|
121
|
+
ar: AR_MESSAGES,
|
|
122
|
+
zh: EN_MESSAGES,
|
|
123
|
+
// Fallback to English
|
|
124
|
+
ur: UR_MESSAGES,
|
|
125
|
+
hi: EN_MESSAGES
|
|
126
|
+
// Fallback to English
|
|
127
|
+
};
|
|
128
|
+
var currentLocale = "en";
|
|
129
|
+
var customMessages = {};
|
|
130
|
+
function setLocale(locale) {
|
|
131
|
+
currentLocale = locale;
|
|
132
|
+
}
|
|
133
|
+
function getLocale() {
|
|
134
|
+
return currentLocale;
|
|
135
|
+
}
|
|
136
|
+
function getMessage(key, params) {
|
|
137
|
+
let message = customMessages[key] || MESSAGES[currentLocale]?.[key] || MESSAGES.en[key];
|
|
138
|
+
if (params) {
|
|
139
|
+
Object.entries(params).forEach(([k, v]) => {
|
|
140
|
+
message = message.replace(new RegExp(`\\{${k}\\}`, "g"), String(v));
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return message;
|
|
144
|
+
}
|
|
145
|
+
function setCustomMessages(messages) {
|
|
146
|
+
customMessages = { ...customMessages, ...messages };
|
|
147
|
+
}
|
|
148
|
+
function addLocale(locale, messages) {
|
|
149
|
+
MESSAGES[locale] = messages;
|
|
150
|
+
}
|
|
151
|
+
function getAvailableLocales() {
|
|
152
|
+
return Object.keys(MESSAGES);
|
|
153
|
+
}
|
|
154
|
+
function withLocalization(validator) {
|
|
155
|
+
return ((...args) => {
|
|
156
|
+
const result = validator(...args);
|
|
157
|
+
const localizedErrors = result.errors.map((error) => ({
|
|
158
|
+
...error,
|
|
159
|
+
message: getMessage(error.code.toLowerCase()) || error.message
|
|
160
|
+
}));
|
|
161
|
+
return {
|
|
162
|
+
...result,
|
|
163
|
+
errors: localizedErrors
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { addLocale, getAvailableLocales, getLocale, getMessage, setCustomMessages, setLocale, withLocalization };
|
|
169
|
+
//# sourceMappingURL=chunk-3DPF72DY.js.map
|
|
170
|
+
//# sourceMappingURL=chunk-3DPF72DY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/i18n.ts"],"names":[],"mappings":"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","file":"chunk-3DPF72DY.js","sourcesContent":["/**\r\n * Internationalization (i18n) module for Utilitify\r\n * Provides multi-language error message support\r\n *\r\n * @packageDocumentation\r\n * @since 1.0.0\r\n */\r\n\r\n/**\r\n * Supported locales\r\n */\r\nexport type Locale = 'en' | 'es' | 'fr' | 'de' | 'ar' | 'zh' | 'ur' | 'hi';\r\n\r\n/**\r\n * Error message templates\r\n */\r\nexport interface MessageTemplates {\r\n // Common\r\n required: string;\r\n invalid: string;\r\n tooShort: string;\r\n tooLong: string;\r\n\r\n // Email\r\n emailInvalid: string;\r\n emailDisposable: string;\r\n emailDomainBlocked: string;\r\n\r\n // Phone\r\n phoneInvalid: string;\r\n phoneTooShort: string;\r\n phoneTooLong: string;\r\n phoneMobileOnly: string;\r\n\r\n // Password\r\n passwordTooWeak: string;\r\n passwordNoUppercase: string;\r\n passwordNoLowercase: string;\r\n passwordNoNumber: string;\r\n passwordNoSymbol: string;\r\n passwordCommonPattern: string;\r\n\r\n // Name\r\n nameInvalid: string;\r\n nameContainsNumbers: string;\r\n\r\n // Username\r\n usernameReserved: string;\r\n usernameInvalidChars: string;\r\n\r\n // URL\r\n urlInvalid: string;\r\n urlDangerous: string;\r\n\r\n // Credit Card\r\n cardInvalid: string;\r\n cardExpired: string;\r\n cardCvvInvalid: string;\r\n}\r\n\r\n/**\r\n * Default English messages\r\n */\r\nconst EN_MESSAGES: MessageTemplates = {\r\n required: 'This field is required',\r\n invalid: 'This field is invalid',\r\n tooShort: 'Must be at least {min} characters',\r\n tooLong: 'Must not exceed {max} characters',\r\n\r\n emailInvalid: 'Please enter a valid email address',\r\n emailDisposable: 'Disposable email addresses are not allowed',\r\n emailDomainBlocked: 'This email domain is not allowed',\r\n\r\n phoneInvalid: 'Please enter a valid phone number',\r\n phoneTooShort: 'Phone number is too short',\r\n phoneTooLong: 'Phone number is too long',\r\n phoneMobileOnly: 'Only mobile numbers are allowed',\r\n\r\n passwordTooWeak: 'Password is too weak',\r\n passwordNoUppercase: 'Password must contain uppercase letters',\r\n passwordNoLowercase: 'Password must contain lowercase letters',\r\n passwordNoNumber: 'Password must contain numbers',\r\n passwordNoSymbol: 'Password must contain special characters',\r\n passwordCommonPattern: 'Password is too common',\r\n\r\n nameInvalid: 'Please enter a valid name',\r\n nameContainsNumbers: 'Name cannot contain numbers',\r\n\r\n usernameReserved: 'This username is reserved',\r\n usernameInvalidChars: 'Username contains invalid characters',\r\n\r\n urlInvalid: 'Please enter a valid URL',\r\n urlDangerous: 'This URL is not allowed for security reasons',\r\n\r\n cardInvalid: 'Please enter a valid card number',\r\n cardExpired: 'This card has expired',\r\n cardCvvInvalid: 'Please enter a valid CVV',\r\n};\r\n\r\n/**\r\n * Spanish messages\r\n */\r\nconst ES_MESSAGES: MessageTemplates = {\r\n required: 'Este campo es obligatorio',\r\n invalid: 'Este campo no es válido',\r\n tooShort: 'Debe tener al menos {min} caracteres',\r\n tooLong: 'No debe exceder {max} caracteres',\r\n\r\n emailInvalid: 'Por favor ingrese un correo electrónico válido',\r\n emailDisposable: 'No se permiten correos electrónicos temporales',\r\n emailDomainBlocked: 'Este dominio de correo no está permitido',\r\n\r\n phoneInvalid: 'Por favor ingrese un número de teléfono válido',\r\n phoneTooShort: 'El número de teléfono es muy corto',\r\n phoneTooLong: 'El número de teléfono es muy largo',\r\n phoneMobileOnly: 'Solo se permiten números móviles',\r\n\r\n passwordTooWeak: 'La contraseña es muy débil',\r\n passwordNoUppercase: 'La contraseña debe contener mayúsculas',\r\n passwordNoLowercase: 'La contraseña debe contener minúsculas',\r\n passwordNoNumber: 'La contraseña debe contener números',\r\n passwordNoSymbol: 'La contraseña debe contener caracteres especiales',\r\n passwordCommonPattern: 'La contraseña es muy común',\r\n\r\n nameInvalid: 'Por favor ingrese un nombre válido',\r\n nameContainsNumbers: 'El nombre no puede contener números',\r\n\r\n usernameReserved: 'Este nombre de usuario está reservado',\r\n usernameInvalidChars: 'El nombre de usuario contiene caracteres no válidos',\r\n\r\n urlInvalid: 'Por favor ingrese una URL válida',\r\n urlDangerous: 'Esta URL no está permitida por razones de seguridad',\r\n\r\n cardInvalid: 'Por favor ingrese un número de tarjeta válido',\r\n cardExpired: 'Esta tarjeta ha expirado',\r\n cardCvvInvalid: 'Por favor ingrese un CVV válido',\r\n};\r\n\r\n/**\r\n * Urdu messages\r\n */\r\nconst UR_MESSAGES: MessageTemplates = {\r\n required: 'یہ فیلڈ ضروری ہے',\r\n invalid: 'یہ فیلڈ درست نہیں ہے',\r\n tooShort: 'کم از کم {min} حروف ہونے چاہئیں',\r\n tooLong: '{max} حروف سے زیادہ نہیں ہونے چاہئیں',\r\n\r\n emailInvalid: 'براہ کرم درست ای میل درج کریں',\r\n emailDisposable: 'عارضی ای میل کی اجازت نہیں ہے',\r\n emailDomainBlocked: 'یہ ای میل ڈومین کی اجازت نہیں ہے',\r\n\r\n phoneInvalid: 'براہ کرم درست فون نمبر درج کریں',\r\n phoneTooShort: 'فون نمبر بہت چھوٹا ہے',\r\n phoneTooLong: 'فون نمبر بہت لمبا ہے',\r\n phoneMobileOnly: 'صرف موبائل نمبر کی اجازت ہے',\r\n\r\n passwordTooWeak: 'پاس ورڈ بہت کمزور ہے',\r\n passwordNoUppercase: 'پاس ورڈ میں بڑے حروف ہونے چاہئیں',\r\n passwordNoLowercase: 'پاس ورڈ میں چھوٹے حروف ہونے چاہئیں',\r\n passwordNoNumber: 'پاس ورڈ میں نمبر ہونے چاہئیں',\r\n passwordNoSymbol: 'پاس ورڈ میں خاص حروف ہونے چاہئیں',\r\n passwordCommonPattern: 'پاس ورڈ بہت عام ہے',\r\n\r\n nameInvalid: 'براہ کرم درست نام درج کریں',\r\n nameContainsNumbers: 'نام میں نمبر نہیں ہو سکتے',\r\n\r\n usernameReserved: 'یہ صارف نام محفوظ ہے',\r\n usernameInvalidChars: 'صارف نام میں غیر درست حروف ہیں',\r\n\r\n urlInvalid: 'براہ کرم درست URL درج کریں',\r\n urlDangerous: 'سیکیورٹی وجوہات کی بنا پر یہ URL کی اجازت نہیں ہے',\r\n\r\n cardInvalid: 'براہ کرم درست کارڈ نمبر درج کریں',\r\n cardExpired: 'یہ کارڈ ختم ہو چکا ہے',\r\n cardCvvInvalid: 'براہ کرم درست CVV درج کریں',\r\n};\r\n\r\n/**\r\n * Arabic messages\r\n */\r\nconst AR_MESSAGES: MessageTemplates = {\r\n required: 'هذا الحقل مطلوب',\r\n invalid: 'هذا الحقل غير صالح',\r\n tooShort: 'يجب أن يكون على الأقل {min} أحرف',\r\n tooLong: 'يجب ألا يتجاوز {max} أحرف',\r\n\r\n emailInvalid: 'يرجى إدخال بريد إلكتروني صالح',\r\n emailDisposable: 'البريد الإلكتروني المؤقت غير مسموح به',\r\n emailDomainBlocked: 'نطاق البريد الإلكتروني هذا غير مسموح به',\r\n\r\n phoneInvalid: 'يرجى إدخال رقم هاتف صالح',\r\n phoneTooShort: 'رقم الهاتف قصير جداً',\r\n phoneTooLong: 'رقم الهاتف طويل جداً',\r\n phoneMobileOnly: 'يسمح فقط بأرقام الجوال',\r\n\r\n passwordTooWeak: 'كلمة المرور ضعيفة جداً',\r\n passwordNoUppercase: 'يجب أن تحتوي كلمة المرور على أحرف كبيرة',\r\n passwordNoLowercase: 'يجب أن تحتوي كلمة المرور على أحرف صغيرة',\r\n passwordNoNumber: 'يجب أن تحتوي كلمة المرور على أرقام',\r\n passwordNoSymbol: 'يجب أن تحتوي كلمة المرور على رموز خاصة',\r\n passwordCommonPattern: 'كلمة المرور شائعة جداً',\r\n\r\n nameInvalid: 'يرجى إدخال اسم صالح',\r\n nameContainsNumbers: 'لا يمكن أن يحتوي الاسم على أرقام',\r\n\r\n usernameReserved: 'اسم المستخدم هذا محجوز',\r\n usernameInvalidChars: 'اسم المستخدم يحتوي على أحرف غير صالحة',\r\n\r\n urlInvalid: 'يرجى إدخال رابط صالح',\r\n urlDangerous: 'هذا الرابط غير مسموح به لأسباب أمنية',\r\n\r\n cardInvalid: 'يرجى إدخال رقم بطاقة صالح',\r\n cardExpired: 'انتهت صلاحية هذه البطاقة',\r\n cardCvvInvalid: 'يرجى إدخال CVV صالح',\r\n};\r\n\r\n/**\r\n * All available message sets\r\n */\r\nconst MESSAGES: Record<Locale, MessageTemplates> = {\r\n en: EN_MESSAGES,\r\n es: ES_MESSAGES,\r\n fr: EN_MESSAGES, // Fallback to English\r\n de: EN_MESSAGES, // Fallback to English\r\n ar: AR_MESSAGES,\r\n zh: EN_MESSAGES, // Fallback to English\r\n ur: UR_MESSAGES,\r\n hi: EN_MESSAGES, // Fallback to English\r\n};\r\n\r\n/**\r\n * Current locale\r\n */\r\nlet currentLocale: Locale = 'en';\r\n\r\n/**\r\n * Custom message overrides\r\n */\r\nlet customMessages: Partial<MessageTemplates> = {};\r\n\r\n/**\r\n * Set the current locale\r\n *\r\n * @param locale - Locale to set\r\n * @since 1.0.0\r\n *\r\n * @example\r\n * ```typescript\r\n * import { setLocale } from 'utilitify/i18n';\r\n * setLocale('es'); // Switch to Spanish\r\n * ```\r\n */\r\nexport function setLocale(locale: Locale): void {\r\n currentLocale = locale;\r\n}\r\n\r\n/**\r\n * Get the current locale\r\n */\r\nexport function getLocale(): Locale {\r\n return currentLocale;\r\n}\r\n\r\n/**\r\n * Get a translated message\r\n *\r\n * @param key - Message key\r\n * @param params - Parameters to interpolate\r\n * @returns Translated message\r\n * @since 1.0.0\r\n */\r\nexport function getMessage(\r\n key: keyof MessageTemplates,\r\n params?: Record<string, string | number>\r\n): string {\r\n // Check custom messages first\r\n let message = customMessages[key] || MESSAGES[currentLocale]?.[key] || MESSAGES.en[key];\r\n\r\n // Interpolate parameters\r\n if (params) {\r\n Object.entries(params).forEach(([k, v]) => {\r\n message = message.replace(new RegExp(`\\\\{${k}\\\\}`, 'g'), String(v));\r\n });\r\n }\r\n\r\n return message;\r\n}\r\n\r\n/**\r\n * Set custom messages\r\n *\r\n * @param messages - Custom message overrides\r\n * @since 1.0.0\r\n */\r\nexport function setCustomMessages(messages: Partial<MessageTemplates>): void {\r\n customMessages = { ...customMessages, ...messages };\r\n}\r\n\r\n/**\r\n * Add a new locale\r\n *\r\n * @param locale - Locale code\r\n * @param messages - Message templates\r\n * @since 1.0.0\r\n */\r\nexport function addLocale(locale: string, messages: MessageTemplates): void {\r\n (MESSAGES as Record<string, MessageTemplates>)[locale] = messages;\r\n}\r\n\r\n/**\r\n * Get all available locales\r\n */\r\nexport function getAvailableLocales(): Locale[] {\r\n return Object.keys(MESSAGES) as Locale[];\r\n}\r\n\r\n/**\r\n * Create a localized validator wrapper\r\n *\r\n * @param validator - Original validator function\r\n * @returns Localized validator\r\n * @since 1.0.0\r\n */\r\nexport function withLocalization<T extends (...args: unknown[]) => { errors: Array<{ code: string; message: string }> }>(\r\n validator: T\r\n): T {\r\n return ((...args: Parameters<T>) => {\r\n const result = validator(...args);\r\n\r\n // Map error codes to localized messages\r\n const localizedErrors = result.errors.map(error => ({\r\n ...error,\r\n message: getMessage(error.code.toLowerCase() as keyof MessageTemplates) || error.message,\r\n }));\r\n\r\n return {\r\n ...result,\r\n errors: localizedErrors,\r\n };\r\n }) as T;\r\n}\r\n"]}
|