@guren/server 0.2.0-alpha.7 → 1.0.0-rc.9

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.
Files changed (54) hide show
  1. package/dist/Application-DtWDHXr1.d.ts +2110 -0
  2. package/dist/BroadcastManager-AkIWUGJo.d.ts +466 -0
  3. package/dist/CacheManager-BkvHEOZX.d.ts +244 -0
  4. package/dist/ConsoleKernel-CqCVrdZs.d.ts +207 -0
  5. package/dist/EventManager-CmIoLt7r.d.ts +207 -0
  6. package/dist/Gate-CNkBYf8m.d.ts +268 -0
  7. package/dist/HealthManager-DUyMIzsZ.d.ts +141 -0
  8. package/dist/I18nManager-Dtgzsf5n.d.ts +270 -0
  9. package/dist/LogManager-7mxnkaPM.d.ts +256 -0
  10. package/dist/MailManager-DpMvYiP9.d.ts +292 -0
  11. package/dist/Scheduler-BstvSca7.d.ts +469 -0
  12. package/dist/StorageManager-oZTHqaza.d.ts +337 -0
  13. package/dist/api-token-JOif2CtG.d.ts +1792 -0
  14. package/dist/app-key-CsBfRC_Q.d.ts +214 -0
  15. package/dist/auth/index.d.ts +418 -0
  16. package/dist/auth/index.js +6742 -0
  17. package/dist/authorization/index.d.ts +129 -0
  18. package/dist/authorization/index.js +621 -0
  19. package/dist/broadcasting/index.d.ts +233 -0
  20. package/dist/broadcasting/index.js +907 -0
  21. package/dist/cache/index.d.ts +233 -0
  22. package/dist/cache/index.js +817 -0
  23. package/dist/encryption/index.d.ts +222 -0
  24. package/dist/encryption/index.js +602 -0
  25. package/dist/events/index.d.ts +155 -0
  26. package/dist/events/index.js +330 -0
  27. package/dist/health/index.d.ts +185 -0
  28. package/dist/health/index.js +379 -0
  29. package/dist/i18n/index.d.ts +101 -0
  30. package/dist/i18n/index.js +597 -0
  31. package/dist/index-9_Jzj5jo.d.ts +7 -0
  32. package/dist/index.d.ts +2628 -619
  33. package/dist/index.js +22229 -3116
  34. package/dist/lambda/index.d.ts +156 -0
  35. package/dist/lambda/index.js +91 -0
  36. package/dist/logging/index.d.ts +50 -0
  37. package/dist/logging/index.js +557 -0
  38. package/dist/mail/index.d.ts +288 -0
  39. package/dist/mail/index.js +695 -0
  40. package/dist/mcp/index.d.ts +139 -0
  41. package/dist/mcp/index.js +382 -0
  42. package/dist/notifications/index.d.ts +271 -0
  43. package/dist/notifications/index.js +741 -0
  44. package/dist/queue/index.d.ts +423 -0
  45. package/dist/queue/index.js +958 -0
  46. package/dist/runtime/index.d.ts +93 -0
  47. package/dist/runtime/index.js +834 -0
  48. package/dist/scheduling/index.d.ts +41 -0
  49. package/dist/scheduling/index.js +836 -0
  50. package/dist/storage/index.d.ts +196 -0
  51. package/dist/storage/index.js +832 -0
  52. package/dist/vite/index.js +203 -3
  53. package/package.json +93 -6
  54. package/dist/chunk-FK2XQSBF.js +0 -160
@@ -0,0 +1,602 @@
1
+ // src/encryption/Encrypter.ts
2
+ import { createCipheriv, createDecipheriv, randomBytes as randomBytes2, createHmac } from "crypto";
3
+
4
+ // src/encryption/app-key.ts
5
+ import { hkdfSync, randomBytes } from "crypto";
6
+ var APP_KEY_PREFIX = "base64:";
7
+ var APP_KEY_BYTES = 32;
8
+ function decodeAppKey(rawKey, envName) {
9
+ const trimmed = rawKey.trim();
10
+ if (!trimmed) {
11
+ throw new Error(`${envName} is required and must be a base64-encoded 32-byte key.`);
12
+ }
13
+ const encoded = trimmed.startsWith(APP_KEY_PREFIX) ? trimmed.slice(APP_KEY_PREFIX.length) : trimmed;
14
+ const decoded = Buffer.from(encoded, "base64");
15
+ if (decoded.length !== APP_KEY_BYTES || decoded.toString("base64") !== encoded.replace(/\s+/gu, "")) {
16
+ throw new Error(`${envName} must be a base64-encoded 32-byte key.`);
17
+ }
18
+ return decoded;
19
+ }
20
+ function normalizeAppKey(rawKey, envName = "APP_KEY") {
21
+ return `${APP_KEY_PREFIX}${decodeAppKey(rawKey, envName).toString("base64")}`;
22
+ }
23
+ function parseAppKey(rawKey, envName = "APP_KEY") {
24
+ return decodeAppKey(rawKey, envName);
25
+ }
26
+ function parsePreviousAppKeys(rawKeys, envName = "APP_PREVIOUS_KEYS") {
27
+ if (!rawKeys) {
28
+ return [];
29
+ }
30
+ return rawKeys.split(",").map((value) => value.trim()).filter(Boolean).map((value, index) => decodeAppKey(value, `${envName}[${index}]`));
31
+ }
32
+ function getAppKeyringFromEnv(env = process.env) {
33
+ return {
34
+ current: parseAppKey(env.APP_KEY ?? "", "APP_KEY"),
35
+ previous: parsePreviousAppKeys(env.APP_PREVIOUS_KEYS)
36
+ };
37
+ }
38
+ function deriveAppKey(rootKey, purpose) {
39
+ return Buffer.from(
40
+ hkdfSync("sha256", rootKey, Buffer.alloc(0), Buffer.from(`guren:${purpose}`, "utf8"), APP_KEY_BYTES)
41
+ );
42
+ }
43
+ function deriveAppKeyring(keyring, purpose) {
44
+ return {
45
+ current: deriveAppKey(keyring.current, purpose),
46
+ previous: keyring.previous.map((key) => deriveAppKey(key, purpose))
47
+ };
48
+ }
49
+ function encodeDerivedKey(key) {
50
+ return `${APP_KEY_PREFIX}${key.toString("base64")}`;
51
+ }
52
+ function generateAppKey() {
53
+ return `${APP_KEY_PREFIX}${randomBytes(APP_KEY_BYTES).toString("base64")}`;
54
+ }
55
+
56
+ // src/encryption/Encrypter.ts
57
+ var Encrypter = class {
58
+ /**
59
+ * Encryption key.
60
+ */
61
+ key;
62
+ previousKeys;
63
+ /**
64
+ * Cipher algorithm.
65
+ */
66
+ cipher;
67
+ constructor(config) {
68
+ this.key = Buffer.from(normalizeAppKey(config.key).slice("base64:".length), "base64");
69
+ this.previousKeys = (config.previousKeys ?? []).map(
70
+ (key) => Buffer.from(normalizeAppKey(key).slice("base64:".length), "base64")
71
+ );
72
+ this.cipher = config.cipher ?? "aes-256-gcm";
73
+ }
74
+ /**
75
+ * Encrypt a value.
76
+ */
77
+ encrypt(value, options = {}) {
78
+ const serialize = options.serialize !== false;
79
+ const data = serialize ? JSON.stringify(value) : String(value);
80
+ if (this.cipher === "aes-256-gcm") {
81
+ return this.encryptGcm(data);
82
+ }
83
+ return this.encryptCbc(data);
84
+ }
85
+ /**
86
+ * Decrypt a value.
87
+ */
88
+ decrypt(payload, options = {}) {
89
+ const deserialize = options.deserialize !== false;
90
+ let parsed;
91
+ try {
92
+ parsed = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
93
+ } catch {
94
+ throw new Error("Invalid encrypted payload.");
95
+ }
96
+ let decrypted;
97
+ if (parsed.tag) {
98
+ decrypted = this.decryptGcm(parsed);
99
+ } else if (parsed.mac) {
100
+ decrypted = this.decryptCbc(parsed);
101
+ } else {
102
+ throw new Error("Invalid encrypted payload format.");
103
+ }
104
+ if (deserialize) {
105
+ try {
106
+ return JSON.parse(decrypted);
107
+ } catch {
108
+ return decrypted;
109
+ }
110
+ }
111
+ return decrypted;
112
+ }
113
+ /**
114
+ * Encrypt a string (no serialization).
115
+ */
116
+ encryptString(value) {
117
+ return this.encrypt(value, { serialize: false });
118
+ }
119
+ /**
120
+ * Decrypt a string (no deserialization).
121
+ */
122
+ decryptString(payload) {
123
+ return this.decrypt(payload, { deserialize: false });
124
+ }
125
+ /**
126
+ * Encrypt using AES-256-GCM.
127
+ */
128
+ encryptGcm(data) {
129
+ const iv = randomBytes2(12);
130
+ const cipher = createCipheriv("aes-256-gcm", this.key, iv);
131
+ const encrypted = Buffer.concat([
132
+ cipher.update(data, "utf8"),
133
+ cipher.final()
134
+ ]);
135
+ const tag = cipher.getAuthTag();
136
+ const payload = {
137
+ iv: iv.toString("base64"),
138
+ value: encrypted.toString("base64"),
139
+ tag: tag.toString("base64")
140
+ };
141
+ return Buffer.from(JSON.stringify(payload)).toString("base64");
142
+ }
143
+ /**
144
+ * Decrypt using AES-256-GCM.
145
+ */
146
+ decryptGcm(payload) {
147
+ return this.tryDecryptWithKeys((key) => {
148
+ const iv = Buffer.from(payload.iv, "base64");
149
+ const encrypted = Buffer.from(payload.value, "base64");
150
+ const tag = Buffer.from(payload.tag, "base64");
151
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
152
+ decipher.setAuthTag(tag);
153
+ const decrypted = Buffer.concat([
154
+ decipher.update(encrypted),
155
+ decipher.final()
156
+ ]);
157
+ return decrypted.toString("utf8");
158
+ });
159
+ }
160
+ /**
161
+ * Encrypt using AES-256-CBC with HMAC.
162
+ */
163
+ encryptCbc(data) {
164
+ const iv = randomBytes2(16);
165
+ const cipher = createCipheriv("aes-256-cbc", this.key, iv);
166
+ const encrypted = Buffer.concat([
167
+ cipher.update(data, "utf8"),
168
+ cipher.final()
169
+ ]);
170
+ const mac = this.createMac(iv, encrypted);
171
+ const payload = {
172
+ iv: iv.toString("base64"),
173
+ value: encrypted.toString("base64"),
174
+ mac
175
+ };
176
+ return Buffer.from(JSON.stringify(payload)).toString("base64");
177
+ }
178
+ /**
179
+ * Decrypt using AES-256-CBC with HMAC verification.
180
+ */
181
+ decryptCbc(payload) {
182
+ return this.tryDecryptWithKeys((key) => {
183
+ const iv = Buffer.from(payload.iv, "base64");
184
+ const encrypted = Buffer.from(payload.value, "base64");
185
+ const expectedMac = this.createMac(iv, encrypted, key);
186
+ if (!this.secureCompare(payload.mac, expectedMac)) {
187
+ throw new Error("MAC verification failed.");
188
+ }
189
+ const decipher = createDecipheriv("aes-256-cbc", key, iv);
190
+ const decrypted = Buffer.concat([
191
+ decipher.update(encrypted),
192
+ decipher.final()
193
+ ]);
194
+ return decrypted.toString("utf8");
195
+ });
196
+ }
197
+ /**
198
+ * Create HMAC for CBC mode.
199
+ */
200
+ createMac(iv, encrypted, key = this.key) {
201
+ const hmac2 = createHmac("sha256", key);
202
+ hmac2.update(iv);
203
+ hmac2.update(encrypted);
204
+ return hmac2.digest("hex");
205
+ }
206
+ /**
207
+ * Constant-time string comparison.
208
+ */
209
+ secureCompare(a, b) {
210
+ if (a.length !== b.length) {
211
+ return false;
212
+ }
213
+ let result = 0;
214
+ for (let i = 0; i < a.length; i++) {
215
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
216
+ }
217
+ return result === 0;
218
+ }
219
+ /**
220
+ * Get the encryption key (base64).
221
+ */
222
+ getKey() {
223
+ return this.key.toString("base64");
224
+ }
225
+ tryDecryptWithKeys(run) {
226
+ const keys = [this.key, ...this.previousKeys];
227
+ let lastError;
228
+ for (const key of keys) {
229
+ try {
230
+ return run(key);
231
+ } catch (error) {
232
+ lastError = error;
233
+ }
234
+ }
235
+ throw lastError ?? new Error("Failed to decrypt payload.");
236
+ }
237
+ };
238
+ function generateKey() {
239
+ return generateAppKey();
240
+ }
241
+ var globalEncrypter = null;
242
+ function createEncrypter(config) {
243
+ return new Encrypter(config);
244
+ }
245
+ function setEncrypter(encrypter) {
246
+ globalEncrypter = encrypter;
247
+ }
248
+ function getEncrypter() {
249
+ if (!globalEncrypter) {
250
+ throw new Error("Encrypter not initialized. Call setEncrypter() first.");
251
+ }
252
+ return globalEncrypter;
253
+ }
254
+ function encrypt(value, options) {
255
+ return getEncrypter().encrypt(value, options);
256
+ }
257
+ function decrypt(payload, options) {
258
+ return getEncrypter().decrypt(payload, options);
259
+ }
260
+
261
+ // src/encryption/MessageSigner.ts
262
+ import { createHmac as createHmac2, timingSafeEqual } from "crypto";
263
+ function encodeBase64Url(value) {
264
+ return Buffer.from(value).toString("base64url");
265
+ }
266
+ function decodeBase64Url(value) {
267
+ return Buffer.from(value, "base64url").toString("utf8");
268
+ }
269
+ function createSignature(input, key) {
270
+ return encodeBase64Url(createHmac2("sha256", key).update(input).digest());
271
+ }
272
+ function signaturesMatch(actual, expected) {
273
+ const actualBuffer = Buffer.from(actual, "utf8");
274
+ const expectedBuffer = Buffer.from(expected, "utf8");
275
+ if (actualBuffer.length !== expectedBuffer.length) {
276
+ return false;
277
+ }
278
+ return timingSafeEqual(actualBuffer, expectedBuffer);
279
+ }
280
+ var MessageSigner = class {
281
+ constructor(keyring) {
282
+ this.keyring = keyring;
283
+ }
284
+ sign(payload, options = {}) {
285
+ const now = Date.now();
286
+ const claims = {
287
+ ...payload,
288
+ iat: Math.floor(now / 1e3),
289
+ ...options.purpose ? { purpose: options.purpose } : {},
290
+ ...typeof options.expiresIn === "number" ? { exp: Math.floor((now + options.expiresIn) / 1e3) } : {}
291
+ };
292
+ const encodedPayload = encodeBase64Url(JSON.stringify(claims));
293
+ const signature = createSignature(encodedPayload, this.keyring.current);
294
+ return `${encodedPayload}.${signature}`;
295
+ }
296
+ verify(token, options = {}) {
297
+ const [encodedPayload, signature, extra] = token.split(".");
298
+ if (!encodedPayload || !signature || extra) {
299
+ return null;
300
+ }
301
+ const verified = [this.keyring.current, ...this.keyring.previous].some(
302
+ (key) => signaturesMatch(signature, createSignature(encodedPayload, key))
303
+ );
304
+ if (!verified) {
305
+ return null;
306
+ }
307
+ let payload;
308
+ try {
309
+ payload = JSON.parse(decodeBase64Url(encodedPayload));
310
+ } catch {
311
+ return null;
312
+ }
313
+ if (options.purpose && payload.purpose !== options.purpose) {
314
+ return null;
315
+ }
316
+ if (typeof payload.exp === "number" && Math.floor(Date.now() / 1e3) > payload.exp && options.allowExpired !== true) {
317
+ return null;
318
+ }
319
+ return payload;
320
+ }
321
+ };
322
+
323
+ // src/encryption/signed-url.ts
324
+ var PURPOSE = "signed-url";
325
+ var SIGNATURE_PARAM = "signature";
326
+ var EXPIRES_PARAM = "expires";
327
+ function canonicalizeUrl(value) {
328
+ const url = new URL(value);
329
+ url.searchParams.delete(SIGNATURE_PARAM);
330
+ const params = Array.from(url.searchParams.entries()).sort(([left], [right]) => left.localeCompare(right));
331
+ url.search = "";
332
+ for (const [key, paramValue] of params) {
333
+ url.searchParams.append(key, paramValue);
334
+ }
335
+ return { canonical: `${url.pathname}${url.search}`, url };
336
+ }
337
+ function signUrl(value, keyring, options = {}) {
338
+ const url = new URL(value);
339
+ if (typeof options.expiresIn === "number") {
340
+ url.searchParams.set(EXPIRES_PARAM, String(Math.floor((Date.now() + options.expiresIn) / 1e3)));
341
+ }
342
+ const { canonical } = canonicalizeUrl(url.toString());
343
+ const signer = new MessageSigner(keyring);
344
+ const signature = signer.sign({ url: canonical }, { purpose: PURPOSE });
345
+ url.searchParams.set(SIGNATURE_PARAM, signature);
346
+ return url.toString();
347
+ }
348
+ function verifySignedUrl(value, keyring, options = {}) {
349
+ const url = new URL(value);
350
+ const signature = url.searchParams.get(SIGNATURE_PARAM);
351
+ if (!signature) {
352
+ return false;
353
+ }
354
+ const expires = url.searchParams.get(EXPIRES_PARAM);
355
+ if (options.requireExpiration && !expires) {
356
+ return false;
357
+ }
358
+ if (expires && Number(expires) < Math.floor(Date.now() / 1e3)) {
359
+ return false;
360
+ }
361
+ const { canonical } = canonicalizeUrl(value);
362
+ const signer = new MessageSigner(keyring);
363
+ const payload = signer.verify(signature, { purpose: PURPOSE });
364
+ return payload?.url === canonical;
365
+ }
366
+
367
+ // src/encryption/Hash.ts
368
+ import {
369
+ createHash,
370
+ createHmac as createHmac3,
371
+ randomBytes as randomBytes3,
372
+ scrypt,
373
+ timingSafeEqual as timingSafeEqual2
374
+ } from "crypto";
375
+ import { promisify } from "util";
376
+ var scryptAsync = promisify(scrypt);
377
+ function hash(value, algorithm = "sha256", encoding = "hex") {
378
+ return createHash(algorithm).update(value).digest(encoding);
379
+ }
380
+ function hmac(value, key, options = {}) {
381
+ const { algorithm = "sha256", encoding = "hex" } = options;
382
+ return createHmac3(algorithm, key).update(value).digest(encoding);
383
+ }
384
+ function verifyHmac(value, signature, key, options = {}) {
385
+ const expected = hmac(value, key, options);
386
+ return secureCompare(signature, expected);
387
+ }
388
+ function sha256(value) {
389
+ return hash(value, "sha256");
390
+ }
391
+ function sha512(value) {
392
+ return hash(value, "sha512");
393
+ }
394
+ function md5(value) {
395
+ return hash(value, "md5");
396
+ }
397
+ async function hashPassword(password, options = {}) {
398
+ const {
399
+ cost = 16384,
400
+ // N
401
+ memory = 8,
402
+ // r (block size)
403
+ saltLength = 16,
404
+ keyLength = 64
405
+ } = options;
406
+ const salt = randomBytes3(saltLength);
407
+ const derived = await scryptAsync(password, salt, keyLength, {
408
+ N: cost,
409
+ r: memory,
410
+ p: 1
411
+ });
412
+ const params = `N=${cost},r=${memory},p=1`;
413
+ return `$scrypt$${params}$${salt.toString("base64")}$${derived.toString("base64")}`;
414
+ }
415
+ async function verifyPassword(password, hash2) {
416
+ if (!hash2.startsWith("$scrypt$")) {
417
+ throw new Error("Invalid password hash format.");
418
+ }
419
+ const parts = hash2.split("$");
420
+ if (parts.length !== 5) {
421
+ throw new Error("Invalid password hash format.");
422
+ }
423
+ const [, , paramsStr, saltB64, hashB64] = parts;
424
+ const params = {};
425
+ for (const param of paramsStr.split(",")) {
426
+ const [key, value] = param.split("=");
427
+ params[key] = parseInt(value, 10);
428
+ }
429
+ const salt = Buffer.from(saltB64, "base64");
430
+ const expectedHash = Buffer.from(hashB64, "base64");
431
+ const derived = await scryptAsync(password, salt, expectedHash.length, {
432
+ N: params.N,
433
+ r: params.r,
434
+ p: params.p ?? 1
435
+ });
436
+ return timingSafeEqual2(derived, expectedHash);
437
+ }
438
+ function needsRehash(hash2, options = {}) {
439
+ const { cost = 16384, memory = 8 } = options;
440
+ if (!hash2.startsWith("$scrypt$")) {
441
+ return true;
442
+ }
443
+ const parts = hash2.split("$");
444
+ if (parts.length !== 5) {
445
+ return true;
446
+ }
447
+ const paramsStr = parts[2];
448
+ const params = {};
449
+ for (const param of paramsStr.split(",")) {
450
+ const [key, value] = param.split("=");
451
+ params[key] = parseInt(value, 10);
452
+ }
453
+ return params.N !== cost || params.r !== memory;
454
+ }
455
+ function secureCompare(a, b) {
456
+ if (a.length !== b.length) {
457
+ return false;
458
+ }
459
+ const bufA = Buffer.from(a);
460
+ const bufB = Buffer.from(b);
461
+ return timingSafeEqual2(bufA, bufB);
462
+ }
463
+ function check(value, hash2, algorithm = "sha256") {
464
+ const computed = createHash(algorithm).update(value).digest("hex");
465
+ return secureCompare(computed, hash2);
466
+ }
467
+
468
+ // src/encryption/Random.ts
469
+ import { randomBytes as randomBytes4, randomUUID, randomInt as cryptoRandomInt } from "crypto";
470
+ var CHARSETS = {
471
+ alphanumeric: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
472
+ alphabetic: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
473
+ numeric: "0123456789",
474
+ hex: "0123456789abcdef",
475
+ "base64": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
476
+ "url-safe": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
477
+ };
478
+ function randomString(length, options = {}) {
479
+ const { charset = "alphanumeric" } = options;
480
+ const chars = CHARSETS[charset];
481
+ const bytes = randomBytes4(length);
482
+ let result = "";
483
+ for (let i = 0; i < length; i++) {
484
+ result += chars[bytes[i] % chars.length];
485
+ }
486
+ return result;
487
+ }
488
+ function random(length) {
489
+ return randomBytes4(length);
490
+ }
491
+ function randomHex(length) {
492
+ return randomBytes4(length).toString("hex");
493
+ }
494
+ function randomBase64(length) {
495
+ return randomBytes4(length).toString("base64");
496
+ }
497
+ function randomBase64Url(length) {
498
+ return randomBytes4(length).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
499
+ }
500
+ function uuid() {
501
+ return randomUUID();
502
+ }
503
+ function randomInt(min, max) {
504
+ return cryptoRandomInt(min, max + 1);
505
+ }
506
+ function urlSafeToken(length = 32) {
507
+ return randomBase64Url(Math.ceil(length * 0.75)).slice(0, length);
508
+ }
509
+ function generatePassword(length = 16, options = {}) {
510
+ const {
511
+ uppercase = true,
512
+ lowercase = true,
513
+ numbers = true,
514
+ symbols = true
515
+ } = options;
516
+ let chars = "";
517
+ if (uppercase) chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
518
+ if (lowercase) chars += "abcdefghijklmnopqrstuvwxyz";
519
+ if (numbers) chars += "0123456789";
520
+ if (symbols) chars += "!@#$%^&*()-_=+[]{}|;:,.<>?";
521
+ if (chars.length === 0) {
522
+ chars = CHARSETS.alphanumeric;
523
+ }
524
+ const bytes = randomBytes4(length);
525
+ let result = "";
526
+ for (let i = 0; i < length; i++) {
527
+ result += chars[bytes[i] % chars.length];
528
+ }
529
+ return result;
530
+ }
531
+ function generateOtp(length = 6) {
532
+ return randomString(length, { charset: "numeric" });
533
+ }
534
+ function generateSlug(length = 10) {
535
+ return randomString(length, { charset: "hex" });
536
+ }
537
+ function shuffle(array) {
538
+ const result = [...array];
539
+ for (let i = result.length - 1; i > 0; i--) {
540
+ const j = randomInt(0, i);
541
+ [result[i], result[j]] = [result[j], result[i]];
542
+ }
543
+ return result;
544
+ }
545
+ function pick(array) {
546
+ if (array.length === 0) {
547
+ throw new Error("Cannot pick from empty array.");
548
+ }
549
+ return array[randomInt(0, array.length - 1)];
550
+ }
551
+ function sample(array, count) {
552
+ if (count > array.length) {
553
+ throw new Error("Sample count exceeds array length.");
554
+ }
555
+ const shuffled = shuffle(array);
556
+ return shuffled.slice(0, count);
557
+ }
558
+ export {
559
+ Encrypter,
560
+ MessageSigner,
561
+ check,
562
+ createEncrypter,
563
+ decrypt,
564
+ deriveAppKey,
565
+ deriveAppKeyring,
566
+ encodeDerivedKey,
567
+ encrypt,
568
+ generateAppKey,
569
+ generateKey,
570
+ generateOtp,
571
+ generatePassword,
572
+ generateSlug,
573
+ getAppKeyringFromEnv,
574
+ getEncrypter,
575
+ hash,
576
+ hashPassword,
577
+ hmac,
578
+ md5,
579
+ needsRehash,
580
+ normalizeAppKey,
581
+ parseAppKey,
582
+ parsePreviousAppKeys,
583
+ pick,
584
+ random,
585
+ randomBase64,
586
+ randomBase64Url,
587
+ randomHex,
588
+ randomInt,
589
+ randomString,
590
+ sample,
591
+ secureCompare,
592
+ setEncrypter,
593
+ sha256,
594
+ sha512,
595
+ shuffle,
596
+ signUrl,
597
+ urlSafeToken,
598
+ uuid,
599
+ verifyHmac,
600
+ verifyPassword,
601
+ verifySignedUrl
602
+ };