@catbee/utils 2.0.2 → 2.0.4

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/crypto/index.mjs CHANGED
@@ -22,7 +22,7 @@
22
22
  * SOFTWARE.
23
23
  */
24
24
 
25
- import { pbkdf2, scrypt, createHmac, createHash, randomBytes, timingSafeEqual, createCipheriv, createDecipheriv } from 'crypto';
25
+ import { pbkdf2, scrypt, webcrypto, createHmac, createHash, randomBytes, timingSafeEqual, createCipheriv, createDecipheriv } from 'crypto';
26
26
  import { promisify } from 'util';
27
27
  import { uuid } from '@catbee/utils/id';
28
28
 
@@ -54,6 +54,287 @@ function md5(input) {
54
54
  return hash("md5", input);
55
55
  }
56
56
  __name(md5, "md5");
57
+ var DEFAULT_SIGNATURE_ENCODING = "base64url";
58
+ var subtle = globalThis.crypto?.subtle ?? webcrypto.subtle;
59
+ function getDigestLength(hash2) {
60
+ switch (hash2) {
61
+ case "SHA-256":
62
+ return 32;
63
+ case "SHA-384":
64
+ return 48;
65
+ case "SHA-512":
66
+ return 64;
67
+ default:
68
+ return 32;
69
+ }
70
+ }
71
+ __name(getDigestLength, "getDigestLength");
72
+ function resolveKeyAlgorithm({ type = "RSA-PSS", modulusLength = 2048, hash: hash2 = "SHA-256", namedCurve = "P-256" }) {
73
+ switch (type) {
74
+ case "RSA":
75
+ if (!Number.isInteger(modulusLength) || modulusLength < 2048) {
76
+ throw new Error("RSA modulusLength must be an integer greater than or equal to 2048");
77
+ }
78
+ return {
79
+ name: "RSASSA-PKCS1-v1_5",
80
+ modulusLength,
81
+ publicExponent: new Uint8Array([
82
+ 1,
83
+ 0,
84
+ 1
85
+ ]),
86
+ hash: hash2
87
+ };
88
+ case "RSA-PSS":
89
+ if (!Number.isInteger(modulusLength) || modulusLength < 2048) {
90
+ throw new Error("RSA-PSS modulusLength must be an integer greater than or equal to 2048");
91
+ }
92
+ return {
93
+ name: "RSA-PSS",
94
+ modulusLength,
95
+ publicExponent: new Uint8Array([
96
+ 1,
97
+ 0,
98
+ 1
99
+ ]),
100
+ hash: hash2
101
+ };
102
+ case "ECDSA":
103
+ return {
104
+ name: "ECDSA",
105
+ namedCurve
106
+ };
107
+ case "Ed25519":
108
+ return {
109
+ name: "Ed25519"
110
+ };
111
+ default:
112
+ throw new Error(`Unsupported key type: ${type}. Supported types: RSA, RSA-PSS, ECDSA, Ed25519`);
113
+ }
114
+ }
115
+ __name(resolveKeyAlgorithm, "resolveKeyAlgorithm");
116
+ function toBase64(buffer) {
117
+ if (typeof Buffer !== "undefined") {
118
+ return Buffer.from(buffer).toString("base64");
119
+ }
120
+ let binary = "";
121
+ const bytes = new Uint8Array(buffer);
122
+ const chunkSize = 32768;
123
+ for (let i = 0; i < bytes.length; i += chunkSize) {
124
+ binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
125
+ }
126
+ return btoa(binary);
127
+ }
128
+ __name(toBase64, "toBase64");
129
+ function toPEM(base64, type, formatPemLines, addPrefixSuffix) {
130
+ const formattedBase64 = formatPemLines ? base64.match(/.{1,64}/g)?.join("\n") ?? base64 : base64;
131
+ if (!addPrefixSuffix) {
132
+ return formattedBase64;
133
+ }
134
+ const prefix = `-----BEGIN ${type}-----`;
135
+ const suffix = `-----END ${type}-----`;
136
+ return `${prefix}
137
+ ${formattedBase64}
138
+ ${suffix}`;
139
+ }
140
+ __name(toPEM, "toPEM");
141
+ function fromPEM(pem) {
142
+ const trimmedPem = pem.trim();
143
+ const format = trimmedPem.includes("BEGIN PRIVATE KEY") ? "pkcs8" : trimmedPem.includes("BEGIN PUBLIC KEY") ? "spki" : void 0;
144
+ if (!format) {
145
+ throw new Error("Unsupported PEM format. Expected PUBLIC KEY or PRIVATE KEY PEM block");
146
+ }
147
+ const base64 = trimmedPem.replace(/-----BEGIN [A-Z ]+-----/g, "").replace(/-----END [A-Z ]+-----/g, "").replace(/\s+/g, "");
148
+ return {
149
+ format,
150
+ binary: toArrayBuffer(Buffer.from(base64, "base64"))
151
+ };
152
+ }
153
+ __name(fromPEM, "fromPEM");
154
+ function toBinary(data, encoding = "utf8") {
155
+ if (typeof data === "string") {
156
+ return Uint8Array.from(Buffer.from(data, encoding));
157
+ }
158
+ if (Buffer.isBuffer(data)) {
159
+ return Uint8Array.from(data);
160
+ }
161
+ return data;
162
+ }
163
+ __name(toBinary, "toBinary");
164
+ function toArrayBuffer(data) {
165
+ const byteView = data instanceof Uint8Array ? data : Uint8Array.from(data);
166
+ const copy = new Uint8Array(byteView.byteLength);
167
+ copy.set(byteView);
168
+ return copy.buffer;
169
+ }
170
+ __name(toArrayBuffer, "toArrayBuffer");
171
+ function inferKeyTypeFromJwk(jwk, fallback) {
172
+ if (fallback) {
173
+ return fallback;
174
+ }
175
+ const keyType = typeof jwk.kty === "string" ? jwk.kty : void 0;
176
+ const curve = typeof jwk.crv === "string" ? jwk.crv : void 0;
177
+ const algorithm = typeof jwk.alg === "string" ? jwk.alg : void 0;
178
+ if (keyType === "OKP" && curve === "Ed25519") {
179
+ return "Ed25519";
180
+ }
181
+ if (keyType === "EC") {
182
+ return "ECDSA";
183
+ }
184
+ if (keyType === "RSA") {
185
+ return algorithm?.startsWith("PS") ? "RSA-PSS" : "RSA";
186
+ }
187
+ throw new Error("Unable to infer key type from JWK. Provide import options with an explicit type");
188
+ }
189
+ __name(inferKeyTypeFromJwk, "inferKeyTypeFromJwk");
190
+ function resolveDefaultUsages(format, usages) {
191
+ return usages ?? (format === "pkcs8" ? [
192
+ "sign"
193
+ ] : [
194
+ "verify"
195
+ ]);
196
+ }
197
+ __name(resolveDefaultUsages, "resolveDefaultUsages");
198
+ function inferJwkUsages(jwk, usages) {
199
+ if (usages) {
200
+ return usages;
201
+ }
202
+ if (Array.isArray(jwk.key_ops)) {
203
+ const inferredFromKeyOps = jwk.key_ops.filter((usage) => usage === "sign" || usage === "verify");
204
+ if (inferredFromKeyOps.length === 0) {
205
+ throw new Error("JWK key_ops must include at least one of sign or verify when provided");
206
+ }
207
+ return inferredFromKeyOps;
208
+ }
209
+ if (typeof jwk.d === "string" && jwk.d.length > 0) {
210
+ return [
211
+ "sign"
212
+ ];
213
+ }
214
+ return [
215
+ "verify"
216
+ ];
217
+ }
218
+ __name(inferJwkUsages, "inferJwkUsages");
219
+ function resolveSignAlgorithm(key, options = {}) {
220
+ const hash2 = options.hash ?? "SHA-256";
221
+ switch (key.algorithm.name) {
222
+ case "RSASSA-PKCS1-v1_5":
223
+ return "RSASSA-PKCS1-v1_5";
224
+ case "RSA-PSS": {
225
+ const keyAlgorithm = key.algorithm;
226
+ const pssHash = options.hash ?? keyAlgorithm.hash.name;
227
+ return {
228
+ name: "RSA-PSS",
229
+ saltLength: options.saltLength ?? getDigestLength(pssHash)
230
+ };
231
+ }
232
+ case "ECDSA":
233
+ return {
234
+ name: "ECDSA",
235
+ hash: hash2
236
+ };
237
+ case "Ed25519":
238
+ return "Ed25519";
239
+ default:
240
+ throw new Error(`Unsupported signing key algorithm: ${key.algorithm.name}`);
241
+ }
242
+ }
243
+ __name(resolveSignAlgorithm, "resolveSignAlgorithm");
244
+ function arrayBufferToBuffer(buffer) {
245
+ return Buffer.from(buffer);
246
+ }
247
+ __name(arrayBufferToBuffer, "arrayBufferToBuffer");
248
+ async function generateKeys(options = {}) {
249
+ const { type = "RSA-PSS", modulusLength = 2048, hash: hash2 = "SHA-256", namedCurve = "P-256", extractable = false, includeCryptoKeys = false, formatPemLines = true, addPrefixSuffix = true } = options;
250
+ const algorithm = resolveKeyAlgorithm({
251
+ type,
252
+ modulusLength,
253
+ hash: hash2,
254
+ namedCurve
255
+ });
256
+ const usages = [
257
+ "sign",
258
+ "verify"
259
+ ];
260
+ const keyPair = await subtle.generateKey(algorithm, extractable, usages);
261
+ const [publicKeyBuf, privateKeyBuf] = await Promise.all([
262
+ subtle.exportKey("spki", keyPair.publicKey),
263
+ extractable ? subtle.exportKey("pkcs8", keyPair.privateKey) : Promise.resolve(void 0)
264
+ ]);
265
+ const publicKeyBase64 = toBase64(publicKeyBuf);
266
+ const privateKeyBase64 = privateKeyBuf ? toBase64(privateKeyBuf) : void 0;
267
+ const result = {
268
+ type,
269
+ publicKey: toPEM(publicKeyBase64, "PUBLIC KEY", formatPemLines, addPrefixSuffix),
270
+ publicKeyBuffer: publicKeyBuf
271
+ };
272
+ if (privateKeyBase64 && privateKeyBuf) {
273
+ result.privateKey = toPEM(privateKeyBase64, "PRIVATE KEY", formatPemLines, addPrefixSuffix);
274
+ result.privateKeyBuffer = privateKeyBuf;
275
+ }
276
+ if (includeCryptoKeys) {
277
+ result.privateKeyCrypto = keyPair.privateKey;
278
+ result.publicKeyCrypto = keyPair.publicKey;
279
+ }
280
+ return result;
281
+ }
282
+ __name(generateKeys, "generateKeys");
283
+ async function sign(data, privateKeyCrypto, options = {}) {
284
+ const algorithm = resolveSignAlgorithm(privateKeyCrypto, options);
285
+ const signature = await subtle.sign(algorithm, privateKeyCrypto, toArrayBuffer(toBinary(data, options.inputEncoding)));
286
+ return arrayBufferToBuffer(signature).toString(options.outputEncoding ?? DEFAULT_SIGNATURE_ENCODING);
287
+ }
288
+ __name(sign, "sign");
289
+ async function verify(data, signature, publicKeyCrypto, options = {}) {
290
+ const algorithm = resolveSignAlgorithm(publicKeyCrypto, options);
291
+ const signatureBytes = typeof signature === "string" ? Uint8Array.from(Buffer.from(signature, options.signatureEncoding ?? DEFAULT_SIGNATURE_ENCODING)) : toBinary(signature);
292
+ return subtle.verify(algorithm, publicKeyCrypto, toArrayBuffer(signatureBytes), toArrayBuffer(toBinary(data, options.inputEncoding)));
293
+ }
294
+ __name(verify, "verify");
295
+ async function importKey(key, options = {}) {
296
+ const extractable = options.extractable ?? false;
297
+ if (typeof key === "string") {
298
+ if (!options.type) {
299
+ throw new Error("Key type is required when importing PEM keys");
300
+ }
301
+ const { format, binary } = fromPEM(key);
302
+ const algorithm2 = resolveKeyAlgorithm({
303
+ type: options.type,
304
+ hash: options.hash,
305
+ namedCurve: options.namedCurve
306
+ });
307
+ return subtle.importKey(format, binary, algorithm2, extractable, resolveDefaultUsages(format, options.usages));
308
+ }
309
+ const keyType = inferKeyTypeFromJwk(key, options.type);
310
+ const algorithm = resolveKeyAlgorithm({
311
+ type: keyType,
312
+ hash: options.hash,
313
+ namedCurve: options.namedCurve
314
+ });
315
+ return subtle.importKey("jwk", key, algorithm, extractable, inferJwkUsages(key, options.usages));
316
+ }
317
+ __name(importKey, "importKey");
318
+ async function exportKey(key, format = "jwk", options = {}) {
319
+ if (format === "jwk") {
320
+ return subtle.exportKey("jwk", key);
321
+ }
322
+ const binary = key.type === "private" ? await subtle.exportKey("pkcs8", key) : await subtle.exportKey("spki", key);
323
+ return toPEM(toBase64(binary), key.type === "private" ? "PRIVATE KEY" : "PUBLIC KEY", options.formatPemLines ?? true, options.addPrefixSuffix ?? true);
324
+ }
325
+ __name(exportKey, "exportKey");
326
+ async function fingerprint(publicKey, encoding = "base64url") {
327
+ if (publicKey.type !== "public") {
328
+ throw new Error("fingerprint requires a public key");
329
+ }
330
+ const spki = await subtle.exportKey("spki", publicKey);
331
+ return createHash("sha256").update(arrayBufferToBuffer(spki)).digest(encoding);
332
+ }
333
+ __name(fingerprint, "fingerprint");
334
+ async function getKeyId(publicKey) {
335
+ return fingerprint(publicKey, "base64url");
336
+ }
337
+ __name(getKeyId, "getKeyId");
57
338
  function randomString() {
58
339
  return sha256(uuid());
59
340
  }
@@ -174,8 +455,16 @@ function generateNonce(byteLength = 16, encoding = "hex") {
174
455
  }
175
456
  __name(generateNonce, "generateNonce");
176
457
  function secureRandomInt(min, max) {
177
- if (min > max) throw new Error("min must be less than or equal to max");
458
+ if (!Number.isSafeInteger(min) || !Number.isSafeInteger(max)) {
459
+ throw new TypeError("min and max must be safe integers");
460
+ }
461
+ if (min > max) {
462
+ throw new RangeError("min must be less than or equal to max");
463
+ }
178
464
  const range = max - min + 1;
465
+ if (!Number.isSafeInteger(range) || range <= 0) {
466
+ throw new RangeError("Range is too large");
467
+ }
179
468
  const bytesNeeded = Math.ceil(Math.log2(range) / 8);
180
469
  const maxValid = Math.floor(256 ** bytesNeeded / range) * range;
181
470
  let randomValue;
@@ -208,4 +497,4 @@ async function verifyPassword(password, hash2) {
208
497
  }
209
498
  __name(verifyPassword, "verifyPassword");
210
499
 
211
- export { createSignedToken, decrypt, encrypt, generateApiKey, generateNonce, generateRandomBytes, generateRandomBytesAsString, hash, hashPassword, hmac, md5, pbkdf2Hash, randomString, safeCompare, secureRandomInt, sha1, sha256, sha256Hmac, verifyPassword, verifySignedToken };
500
+ export { createSignedToken, decrypt, encrypt, exportKey, fingerprint, generateApiKey, generateKeys, generateNonce, generateRandomBytes, generateRandomBytesAsString, getKeyId, hash, hashPassword, hmac, importKey, md5, pbkdf2Hash, randomString, safeCompare, secureRandomInt, sha1, sha256, sha256Hmac, sign, verify, verifyPassword, verifySignedToken };
package/date/index.cjs CHANGED
@@ -575,6 +575,278 @@ function getTimeZoneParts(date, timeZone) {
575
575
  };
576
576
  }
577
577
  __name(getTimeZoneParts, "getTimeZoneParts");
578
+ var COUNTRY_CODES = [
579
+ "AD",
580
+ "AE",
581
+ "AF",
582
+ "AG",
583
+ "AI",
584
+ "AL",
585
+ "AM",
586
+ "AO",
587
+ "AQ",
588
+ "AR",
589
+ "AS",
590
+ "AT",
591
+ "AU",
592
+ "AW",
593
+ "AX",
594
+ "AZ",
595
+ "BA",
596
+ "BB",
597
+ "BD",
598
+ "BE",
599
+ "BF",
600
+ "BG",
601
+ "BH",
602
+ "BI",
603
+ "BJ",
604
+ "BL",
605
+ "BM",
606
+ "BN",
607
+ "BO",
608
+ "BQ",
609
+ "BR",
610
+ "BS",
611
+ "BT",
612
+ "BV",
613
+ "BW",
614
+ "BY",
615
+ "BZ",
616
+ "CA",
617
+ "CC",
618
+ "CD",
619
+ "CF",
620
+ "CG",
621
+ "CH",
622
+ "CI",
623
+ "CK",
624
+ "CL",
625
+ "CM",
626
+ "CN",
627
+ "CO",
628
+ "CR",
629
+ "CU",
630
+ "CV",
631
+ "CW",
632
+ "CX",
633
+ "CY",
634
+ "CZ",
635
+ "DE",
636
+ "DJ",
637
+ "DK",
638
+ "DM",
639
+ "DO",
640
+ "DZ",
641
+ "EC",
642
+ "EE",
643
+ "EG",
644
+ "EH",
645
+ "ER",
646
+ "ES",
647
+ "ET",
648
+ "FI",
649
+ "FJ",
650
+ "FK",
651
+ "FM",
652
+ "FO",
653
+ "FR",
654
+ "GA",
655
+ "GB",
656
+ "GD",
657
+ "GE",
658
+ "GF",
659
+ "GG",
660
+ "GH",
661
+ "GI",
662
+ "GL",
663
+ "GM",
664
+ "GN",
665
+ "GP",
666
+ "GQ",
667
+ "GR",
668
+ "GS",
669
+ "GT",
670
+ "GU",
671
+ "GW",
672
+ "GY",
673
+ "HK",
674
+ "HM",
675
+ "HN",
676
+ "HR",
677
+ "HT",
678
+ "HU",
679
+ "ID",
680
+ "IE",
681
+ "IL",
682
+ "IM",
683
+ "IN",
684
+ "IO",
685
+ "IQ",
686
+ "IR",
687
+ "IS",
688
+ "IT",
689
+ "JE",
690
+ "JM",
691
+ "JO",
692
+ "JP",
693
+ "KE",
694
+ "KG",
695
+ "KH",
696
+ "KI",
697
+ "KM",
698
+ "KN",
699
+ "KP",
700
+ "KR",
701
+ "KW",
702
+ "KY",
703
+ "KZ",
704
+ "LA",
705
+ "LB",
706
+ "LC",
707
+ "LI",
708
+ "LK",
709
+ "LR",
710
+ "LS",
711
+ "LT",
712
+ "LU",
713
+ "LV",
714
+ "LY",
715
+ "MA",
716
+ "MC",
717
+ "MD",
718
+ "ME",
719
+ "MF",
720
+ "MG",
721
+ "MH",
722
+ "MK",
723
+ "ML",
724
+ "MM",
725
+ "MN",
726
+ "MO",
727
+ "MP",
728
+ "MQ",
729
+ "MR",
730
+ "MS",
731
+ "MT",
732
+ "MU",
733
+ "MV",
734
+ "MW",
735
+ "MX",
736
+ "MY",
737
+ "MZ",
738
+ "NA",
739
+ "NC",
740
+ "NE",
741
+ "NF",
742
+ "NG",
743
+ "NI",
744
+ "NL",
745
+ "NO",
746
+ "NP",
747
+ "NR",
748
+ "NU",
749
+ "NZ",
750
+ "OM",
751
+ "PA",
752
+ "PE",
753
+ "PF",
754
+ "PG",
755
+ "PH",
756
+ "PK",
757
+ "PL",
758
+ "PM",
759
+ "PN",
760
+ "PR",
761
+ "PS",
762
+ "PT",
763
+ "PW",
764
+ "PY",
765
+ "QA",
766
+ "RE",
767
+ "RO",
768
+ "RS",
769
+ "RU",
770
+ "RW",
771
+ "SA",
772
+ "SB",
773
+ "SC",
774
+ "SD",
775
+ "SE",
776
+ "SG",
777
+ "SH",
778
+ "SI",
779
+ "SJ",
780
+ "SK",
781
+ "SL",
782
+ "SM",
783
+ "SN",
784
+ "SO",
785
+ "SR",
786
+ "SS",
787
+ "ST",
788
+ "SV",
789
+ "SX",
790
+ "SY",
791
+ "SZ",
792
+ "TC",
793
+ "TD",
794
+ "TF",
795
+ "TG",
796
+ "TH",
797
+ "TJ",
798
+ "TK",
799
+ "TL",
800
+ "TM",
801
+ "TN",
802
+ "TO",
803
+ "TR",
804
+ "TT",
805
+ "TV",
806
+ "TW",
807
+ "TZ",
808
+ "UA",
809
+ "UG",
810
+ "UM",
811
+ "US",
812
+ "UY",
813
+ "UZ",
814
+ "VA",
815
+ "VC",
816
+ "VE",
817
+ "VG",
818
+ "VI",
819
+ "VN",
820
+ "VU",
821
+ "WF",
822
+ "WS",
823
+ "YE",
824
+ "YT",
825
+ "ZA",
826
+ "ZM",
827
+ "ZW"
828
+ ];
829
+ function getCountries(locale = "en") {
830
+ const regionNames = new Intl.DisplayNames([
831
+ locale
832
+ ], {
833
+ type: "region"
834
+ });
835
+ return COUNTRY_CODES.map((code) => ({
836
+ code,
837
+ name: regionNames.of(code)
838
+ }));
839
+ }
840
+ __name(getCountries, "getCountries");
841
+ var SUPPORTED_TIMEZONE_NAMES = Intl.supportedValuesOf("timeZone");
842
+ var TIMEZONE_NAMES = SUPPORTED_TIMEZONE_NAMES.includes("UTC") ? SUPPORTED_TIMEZONE_NAMES : [
843
+ ...SUPPORTED_TIMEZONE_NAMES,
844
+ "UTC"
845
+ ].sort((a, b) => a.localeCompare(b));
846
+ function getTimezones() {
847
+ return TIMEZONE_NAMES;
848
+ }
849
+ __name(getTimezones, "getTimezones");
578
850
 
579
851
  // src/date/date.builder.ts
580
852
  var DateBuilder = class _DateBuilder {
@@ -1179,7 +1451,9 @@ var DateBuilder = class _DateBuilder {
1179
1451
  }
1180
1452
  };
1181
1453
 
1454
+ exports.COUNTRY_CODES = COUNTRY_CODES;
1182
1455
  exports.DateBuilder = DateBuilder;
1456
+ exports.TIMEZONE_NAMES = TIMEZONE_NAMES;
1183
1457
  exports.addDays = addDays;
1184
1458
  exports.addMonths = addMonths;
1185
1459
  exports.addToDate = addToDate;
@@ -1192,9 +1466,11 @@ exports.formatDate = formatDate;
1192
1466
  exports.formatDateInTimeZone = formatDateInTimeZone;
1193
1467
  exports.formatDuration = formatDuration;
1194
1468
  exports.formatRelativeTime = formatRelativeTime;
1469
+ exports.getCountries = getCountries;
1195
1470
  exports.getDateFromDuration = getDateFromDuration;
1196
1471
  exports.getTimezoneAbbreviation = getTimezoneAbbreviation;
1197
1472
  exports.getTimezoneOffset = getTimezoneOffset;
1473
+ exports.getTimezones = getTimezones;
1198
1474
  exports.isBetween = isBetween;
1199
1475
  exports.isDST = isDST;
1200
1476
  exports.isFuture = isFuture;
package/date/index.d.ts CHANGED
@@ -441,6 +441,49 @@ declare function isDST(timeZone: string, date?: Date | number): boolean;
441
441
  * ```
442
442
  */
443
443
  declare function getTimezoneAbbreviation(timeZone: string, date?: Date | number, locale?: string): string;
444
+ /**
445
+ * List of ISO 3166-1 alpha-2 country codes for use in timezone utilities.
446
+ * This list is used to generate country names and filter timezones by country.
447
+ */
448
+ declare const COUNTRY_CODES: string[];
449
+ type Country = {
450
+ code: string;
451
+ name: string;
452
+ };
453
+ /**
454
+ * Get a list of countries with their ISO codes and localized names.
455
+ * Uses Intl.DisplayNames to get the country names based on the provided locale.
456
+ *
457
+ * @param locale - Locale code for country names (default: 'en')
458
+ * @returns Array of country objects with code and name
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * getCountries('en');
463
+ * // [ { code: 'US', name: 'United States' }, { code: 'DE', name: 'Germany' }, ... ]
464
+ *
465
+ * getCountries('fr');
466
+ * // [ { code: 'US', name: 'États-Unis' }, { code: 'DE', name: 'Allemagne' }, ... ]
467
+ * ```
468
+ */
469
+ declare function getCountries(locale?: string): Country[];
470
+ /**
471
+ * List of all IANA timezone identifiers supported by the environment.
472
+ * This can be used to populate dropdowns or validate timezone inputs.
473
+ */
474
+ declare const TIMEZONE_NAMES: string[];
475
+ /**
476
+ * Get a list of all IANA timezone identifiers supported by the environment.
477
+ * This can be used to populate dropdowns or validate timezone inputs.
478
+ *
479
+ * @returns Array of timezone identifiers (e.g., 'America/New_York', 'Europe/Berlin')
480
+ * @example
481
+ * ```typescript
482
+ * getTimezones();
483
+ * // [ 'Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', ... ]
484
+ * ```
485
+ */
486
+ declare function getTimezones(): string[];
444
487
 
445
488
  /**
446
489
  * DateBuilder class for fluent date manipulation and building.
@@ -867,5 +910,5 @@ declare class DateBuilder {
867
910
  getTimezoneAbbreviation(timeZone: string): string;
868
911
  }
869
912
 
870
- export { DateBuilder, addDays, addMonths, addToDate, addYears, dateDiff, dateDiffDaysTZ, daysInMonth, endOf, formatDate, formatDateInTimeZone, formatDuration, formatRelativeTime, getDateFromDuration, getTimezoneAbbreviation, getTimezoneOffset, isBetween, isDST, isFuture, isLeapYear, isPast, isToday, isWeekend, parseDate, parseDuration, quarterOf, startOf, toTimeZone, weekOfYear };
913
+ export { COUNTRY_CODES, DateBuilder, TIMEZONE_NAMES, addDays, addMonths, addToDate, addYears, dateDiff, dateDiffDaysTZ, daysInMonth, endOf, formatDate, formatDateInTimeZone, formatDuration, formatRelativeTime, getCountries, getDateFromDuration, getTimezoneAbbreviation, getTimezoneOffset, getTimezones, isBetween, isDST, isFuture, isLeapYear, isPast, isToday, isWeekend, parseDate, parseDuration, quarterOf, startOf, toTimeZone, weekOfYear };
871
914
  export type { DateFormatOptions, DateFormatPreset };