@kumix/utils 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +111 -172
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +517 -401
- package/dist/index.js.map +1 -1
- package/dist/{logger-BOB35dQN.js → logger-qDWnDXis.js} +17 -14
- package/dist/logger-qDWnDXis.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5950 -26
- package/dist/server.js.map +1 -1
- package/package.json +7 -7
- package/dist/logger-BOB35dQN.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { a as NODE_ENV, c as isProduction, i as LOG_LEVEL, l as isStaging, n as API_PORT, o as PORT, r as DEBUG, s as isDevelopment, t as logger, u as
|
|
1
|
+
import { a as NODE_ENV, c as isProduction, d as getEnv, i as LOG_LEVEL, l as isStaging, n as API_PORT, o as PORT, r as DEBUG, s as isDevelopment, t as logger, u as isTest } from "./logger-qDWnDXis.js";
|
|
2
2
|
import slugify, { default as slugify$1 } from "@sindresorhus/slugify";
|
|
3
|
-
import baseX from "base-x";
|
|
4
3
|
import { createId, init } from "@paralleldrive/cuid2";
|
|
5
4
|
import { customAlphabet } from "nanoid";
|
|
6
5
|
import ms from "ms";
|
|
@@ -551,31 +550,30 @@ const EU_COUNTRY_CODES = [
|
|
|
551
550
|
"AT",
|
|
552
551
|
"BE",
|
|
553
552
|
"BG",
|
|
553
|
+
"HR",
|
|
554
554
|
"CY",
|
|
555
555
|
"CZ",
|
|
556
|
-
"DE",
|
|
557
556
|
"DK",
|
|
558
557
|
"EE",
|
|
559
|
-
"ES",
|
|
560
558
|
"FI",
|
|
561
559
|
"FR",
|
|
562
|
-
"
|
|
560
|
+
"DE",
|
|
563
561
|
"GR",
|
|
564
|
-
"HR",
|
|
565
562
|
"HU",
|
|
566
563
|
"IE",
|
|
567
564
|
"IT",
|
|
565
|
+
"LV",
|
|
568
566
|
"LT",
|
|
569
567
|
"LU",
|
|
570
|
-
"LV",
|
|
571
568
|
"MT",
|
|
572
569
|
"NL",
|
|
573
570
|
"PL",
|
|
574
571
|
"PT",
|
|
575
572
|
"RO",
|
|
576
|
-
"
|
|
573
|
+
"SK",
|
|
577
574
|
"SI",
|
|
578
|
-
"
|
|
575
|
+
"ES",
|
|
576
|
+
"SE"
|
|
579
577
|
];
|
|
580
578
|
//#endregion
|
|
581
579
|
//#region src/constants/country/country-phone-codes.ts
|
|
@@ -1149,7 +1147,7 @@ const REGIONS = {
|
|
|
1149
1147
|
"BY-VI": "Vitsyebskaya voblasts'",
|
|
1150
1148
|
"BE-BRU": "Brussels Hoofdstedelijk Gewest",
|
|
1151
1149
|
"BE-VLG": "Vlaams Gewest",
|
|
1152
|
-
"BE-WAL": "Waals Gewest
|
|
1150
|
+
"BE-WAL": "Waals Gewest",
|
|
1153
1151
|
"BZ-BZ": "Belize",
|
|
1154
1152
|
"BZ-CY": "Cayo",
|
|
1155
1153
|
"BZ-CZL": "Corozal",
|
|
@@ -1981,7 +1979,7 @@ const REGIONS = {
|
|
|
1981
1979
|
"IN-BR": "Bihār",
|
|
1982
1980
|
"IN-CH": "Chandīgarh",
|
|
1983
1981
|
"IN-CG": "Chhattīsgarh",
|
|
1984
|
-
"IN-DH": "Dādra and Nagar Haveli and Damān and Diu
|
|
1982
|
+
"IN-DH": "Dādra and Nagar Haveli and Damān and Diu",
|
|
1985
1983
|
"IN-DL": "Delhi",
|
|
1986
1984
|
"IN-GA": "Goa",
|
|
1987
1985
|
"IN-GJ": "Gujarāt",
|
|
@@ -2005,7 +2003,7 @@ const REGIONS = {
|
|
|
2005
2003
|
"IN-RJ": "Rājasthān",
|
|
2006
2004
|
"IN-SK": "Sikkim",
|
|
2007
2005
|
"IN-TN": "Tamil Nādu",
|
|
2008
|
-
"IN-TS": "Telangāna
|
|
2006
|
+
"IN-TS": "Telangāna",
|
|
2009
2007
|
"IN-TR": "Tripura",
|
|
2010
2008
|
"IN-UP": "Uttar Pradesh",
|
|
2011
2009
|
"IN-UK": "Uttarākhand",
|
|
@@ -2070,7 +2068,7 @@ const REGIONS = {
|
|
|
2070
2068
|
"IE-C": "Connaught",
|
|
2071
2069
|
"IE-L": "Leinster",
|
|
2072
2070
|
"IE-M": "Munster",
|
|
2073
|
-
"IE-U": "Ulster
|
|
2071
|
+
"IE-U": "Ulster",
|
|
2074
2072
|
"IL-D": "HaDarom",
|
|
2075
2073
|
"IL-M": "HaMerkaz",
|
|
2076
2074
|
"IL-Z": "HaTsafon",
|
|
@@ -3084,7 +3082,7 @@ const REGIONS = {
|
|
|
3084
3082
|
"PE-TAC": "Tacna",
|
|
3085
3083
|
"PE-TUM": "Tumbes",
|
|
3086
3084
|
"PE-UCA": "Ucayali",
|
|
3087
|
-
"PH-14": "Autonomous Region in Muslim Mindanao
|
|
3085
|
+
"PH-14": "Autonomous Region in Muslim Mindanao",
|
|
3088
3086
|
"PH-05": "Bicol",
|
|
3089
3087
|
"PH-02": "Cagayan Valley",
|
|
3090
3088
|
"PH-40": "Calabarzon",
|
|
@@ -4366,7 +4364,7 @@ const REGIONS = {
|
|
|
4366
4364
|
"ME-20": "Ulcinj",
|
|
4367
4365
|
"ME-21": "Žabljak",
|
|
4368
4366
|
"ME-25": "Zeta",
|
|
4369
|
-
"RS-KM": "Kosovo-Metohija
|
|
4367
|
+
"RS-KM": "Kosovo-Metohija",
|
|
4370
4368
|
"RS-VO": "Vojvodina",
|
|
4371
4369
|
"SS-EC": "Central Equatoria",
|
|
4372
4370
|
"SS-EE": "Eastern Equatoria",
|
|
@@ -4387,8 +4385,12 @@ const REGION_CODES = Object.keys(REGIONS);
|
|
|
4387
4385
|
* Provides a comprehensive set of all country-specific domain extensions
|
|
4388
4386
|
*/
|
|
4389
4387
|
/**
|
|
4390
|
-
* A Set containing
|
|
4391
|
-
*
|
|
4388
|
+
* A Set containing ISO 3166-1 alpha-2 country code top-level domains (ccTLDs),
|
|
4389
|
+
* plus a small set of commonly-recognized regional TLDs (`eu`, `eus`, `gal`,
|
|
4390
|
+
* `cat`, `asia`). De-duplicated and pruned of retired/withdrawn codes:
|
|
4391
|
+
* - `an` (Netherlands Antilles, retired 2010)
|
|
4392
|
+
* - `tp` (Timor-Leste, retired 2015 — use `tl`)
|
|
4393
|
+
* `gb` is included alongside `uk` per IANA reservation.
|
|
4392
4394
|
*
|
|
4393
4395
|
* @example
|
|
4394
4396
|
* ```ts
|
|
@@ -4401,286 +4403,261 @@ const REGION_CODES = Object.keys(REGIONS);
|
|
|
4401
4403
|
* const domain = 'example.co.uk';
|
|
4402
4404
|
* const tld = domain.split('.').pop();
|
|
4403
4405
|
* const isCountryDomain = tld ? ccTLDs.has(tld) : false; // true
|
|
4404
|
-
*
|
|
4405
|
-
* // Filter domains by ccTLD
|
|
4406
|
-
* const domains = ['example.com', 'example.co.uk', 'example.org'];
|
|
4407
|
-
* const countryDomains = domains.filter(domain => {
|
|
4408
|
-
* const tld = domain.split('.').pop();
|
|
4409
|
-
* return tld ? ccTLDs.has(tld) : false;
|
|
4410
|
-
* }); // ['example.co.uk']
|
|
4411
4406
|
* ```
|
|
4412
4407
|
*/
|
|
4413
4408
|
const ccTLDs = /* @__PURE__ */ new Set([
|
|
4409
|
+
"ac",
|
|
4410
|
+
"ad",
|
|
4411
|
+
"ae",
|
|
4414
4412
|
"af",
|
|
4415
|
-
"
|
|
4413
|
+
"ag",
|
|
4414
|
+
"ai",
|
|
4416
4415
|
"al",
|
|
4417
|
-
"
|
|
4418
|
-
"as",
|
|
4419
|
-
"ad",
|
|
4416
|
+
"am",
|
|
4420
4417
|
"ao",
|
|
4421
|
-
"ai",
|
|
4422
4418
|
"aq",
|
|
4423
|
-
"ag",
|
|
4424
4419
|
"ar",
|
|
4425
|
-
"
|
|
4426
|
-
"aw",
|
|
4427
|
-
"ac",
|
|
4428
|
-
"au",
|
|
4420
|
+
"as",
|
|
4429
4421
|
"at",
|
|
4422
|
+
"au",
|
|
4423
|
+
"aw",
|
|
4424
|
+
"ax",
|
|
4430
4425
|
"az",
|
|
4431
|
-
"
|
|
4432
|
-
"bh",
|
|
4433
|
-
"bd",
|
|
4426
|
+
"ba",
|
|
4434
4427
|
"bb",
|
|
4435
|
-
"
|
|
4436
|
-
"by",
|
|
4428
|
+
"bd",
|
|
4437
4429
|
"be",
|
|
4438
|
-
"
|
|
4430
|
+
"bf",
|
|
4431
|
+
"bg",
|
|
4432
|
+
"bh",
|
|
4433
|
+
"bi",
|
|
4439
4434
|
"bj",
|
|
4435
|
+
"bl",
|
|
4440
4436
|
"bm",
|
|
4441
|
-
"
|
|
4437
|
+
"bn",
|
|
4442
4438
|
"bo",
|
|
4443
4439
|
"bq",
|
|
4444
|
-
"an",
|
|
4445
|
-
"nl",
|
|
4446
|
-
"ba",
|
|
4447
|
-
"bw",
|
|
4448
|
-
"bv",
|
|
4449
4440
|
"br",
|
|
4450
|
-
"
|
|
4451
|
-
"
|
|
4452
|
-
"
|
|
4453
|
-
"
|
|
4454
|
-
"
|
|
4455
|
-
"
|
|
4456
|
-
"bi",
|
|
4457
|
-
"kh",
|
|
4458
|
-
"cm",
|
|
4441
|
+
"bs",
|
|
4442
|
+
"bt",
|
|
4443
|
+
"bv",
|
|
4444
|
+
"bw",
|
|
4445
|
+
"by",
|
|
4446
|
+
"bz",
|
|
4459
4447
|
"ca",
|
|
4460
|
-
"cv",
|
|
4461
4448
|
"cat",
|
|
4462
|
-
"ky",
|
|
4463
|
-
"cf",
|
|
4464
|
-
"td",
|
|
4465
|
-
"cl",
|
|
4466
|
-
"cn",
|
|
4467
|
-
"cx",
|
|
4468
4449
|
"cc",
|
|
4469
|
-
"co",
|
|
4470
|
-
"km",
|
|
4471
4450
|
"cd",
|
|
4451
|
+
"cf",
|
|
4472
4452
|
"cg",
|
|
4453
|
+
"ch",
|
|
4454
|
+
"ci",
|
|
4473
4455
|
"ck",
|
|
4456
|
+
"cl",
|
|
4457
|
+
"cm",
|
|
4458
|
+
"cn",
|
|
4459
|
+
"co",
|
|
4474
4460
|
"cr",
|
|
4475
|
-
"ci",
|
|
4476
|
-
"hr",
|
|
4477
4461
|
"cu",
|
|
4462
|
+
"cv",
|
|
4478
4463
|
"cw",
|
|
4464
|
+
"cx",
|
|
4479
4465
|
"cy",
|
|
4480
4466
|
"cz",
|
|
4481
|
-
"
|
|
4467
|
+
"de",
|
|
4482
4468
|
"dj",
|
|
4469
|
+
"dk",
|
|
4483
4470
|
"dm",
|
|
4484
4471
|
"do",
|
|
4485
|
-
"
|
|
4486
|
-
"tp",
|
|
4472
|
+
"dz",
|
|
4487
4473
|
"ec",
|
|
4474
|
+
"ee",
|
|
4488
4475
|
"eg",
|
|
4489
|
-
"
|
|
4490
|
-
"gq",
|
|
4476
|
+
"eh",
|
|
4491
4477
|
"er",
|
|
4492
|
-
"
|
|
4478
|
+
"es",
|
|
4493
4479
|
"et",
|
|
4494
4480
|
"eu",
|
|
4481
|
+
"eus",
|
|
4482
|
+
"fi",
|
|
4483
|
+
"fj",
|
|
4495
4484
|
"fk",
|
|
4496
|
-
"fo",
|
|
4497
4485
|
"fm",
|
|
4498
|
-
"
|
|
4499
|
-
"fi",
|
|
4486
|
+
"fo",
|
|
4500
4487
|
"fr",
|
|
4501
|
-
"gf",
|
|
4502
|
-
"pf",
|
|
4503
|
-
"tf",
|
|
4504
4488
|
"ga",
|
|
4505
4489
|
"gal",
|
|
4506
|
-
"
|
|
4507
|
-
"
|
|
4490
|
+
"gb",
|
|
4491
|
+
"gd",
|
|
4508
4492
|
"ge",
|
|
4509
|
-
"
|
|
4493
|
+
"gf",
|
|
4494
|
+
"gg",
|
|
4510
4495
|
"gh",
|
|
4511
4496
|
"gi",
|
|
4512
|
-
"gr",
|
|
4513
4497
|
"gl",
|
|
4514
|
-
"
|
|
4498
|
+
"gm",
|
|
4499
|
+
"gn",
|
|
4515
4500
|
"gp",
|
|
4516
|
-
"
|
|
4501
|
+
"gq",
|
|
4502
|
+
"gr",
|
|
4503
|
+
"gs",
|
|
4517
4504
|
"gt",
|
|
4518
|
-
"
|
|
4519
|
-
"gn",
|
|
4505
|
+
"gu",
|
|
4520
4506
|
"gw",
|
|
4521
4507
|
"gy",
|
|
4522
|
-
"
|
|
4508
|
+
"hk",
|
|
4523
4509
|
"hm",
|
|
4524
4510
|
"hn",
|
|
4525
|
-
"
|
|
4511
|
+
"hr",
|
|
4512
|
+
"ht",
|
|
4526
4513
|
"hu",
|
|
4527
|
-
"is",
|
|
4528
|
-
"in",
|
|
4529
4514
|
"id",
|
|
4530
|
-
"ir",
|
|
4531
|
-
"iq",
|
|
4532
4515
|
"ie",
|
|
4533
|
-
"im",
|
|
4534
4516
|
"il",
|
|
4517
|
+
"im",
|
|
4518
|
+
"in",
|
|
4519
|
+
"io",
|
|
4520
|
+
"iq",
|
|
4521
|
+
"ir",
|
|
4522
|
+
"is",
|
|
4535
4523
|
"it",
|
|
4536
|
-
"jm",
|
|
4537
|
-
"jp",
|
|
4538
4524
|
"je",
|
|
4525
|
+
"jm",
|
|
4539
4526
|
"jo",
|
|
4540
|
-
"
|
|
4527
|
+
"jp",
|
|
4541
4528
|
"ke",
|
|
4529
|
+
"kg",
|
|
4530
|
+
"kh",
|
|
4542
4531
|
"ki",
|
|
4532
|
+
"km",
|
|
4533
|
+
"kn",
|
|
4534
|
+
"kp",
|
|
4535
|
+
"kr",
|
|
4543
4536
|
"kw",
|
|
4544
|
-
"
|
|
4537
|
+
"ky",
|
|
4538
|
+
"kz",
|
|
4545
4539
|
"la",
|
|
4546
|
-
"lv",
|
|
4547
4540
|
"lb",
|
|
4548
|
-
"
|
|
4549
|
-
"lr",
|
|
4550
|
-
"ly",
|
|
4541
|
+
"lc",
|
|
4551
4542
|
"li",
|
|
4543
|
+
"lk",
|
|
4544
|
+
"lr",
|
|
4545
|
+
"ls",
|
|
4552
4546
|
"lt",
|
|
4553
4547
|
"lu",
|
|
4554
|
-
"
|
|
4555
|
-
"
|
|
4548
|
+
"lv",
|
|
4549
|
+
"ly",
|
|
4550
|
+
"ma",
|
|
4551
|
+
"mc",
|
|
4552
|
+
"md",
|
|
4553
|
+
"me",
|
|
4554
|
+
"mf",
|
|
4556
4555
|
"mg",
|
|
4557
|
-
"mw",
|
|
4558
|
-
"my",
|
|
4559
|
-
"mv",
|
|
4560
|
-
"ml",
|
|
4561
|
-
"mt",
|
|
4562
4556
|
"mh",
|
|
4557
|
+
"mk",
|
|
4558
|
+
"ml",
|
|
4559
|
+
"mm",
|
|
4560
|
+
"mn",
|
|
4561
|
+
"mo",
|
|
4562
|
+
"mp",
|
|
4563
4563
|
"mq",
|
|
4564
4564
|
"mr",
|
|
4565
|
+
"ms",
|
|
4566
|
+
"mt",
|
|
4565
4567
|
"mu",
|
|
4566
|
-
"
|
|
4568
|
+
"mv",
|
|
4569
|
+
"mw",
|
|
4567
4570
|
"mx",
|
|
4568
|
-
"
|
|
4569
|
-
"mc",
|
|
4570
|
-
"mn",
|
|
4571
|
-
"me",
|
|
4572
|
-
"ms",
|
|
4573
|
-
"ma",
|
|
4571
|
+
"my",
|
|
4574
4572
|
"mz",
|
|
4575
|
-
"mm",
|
|
4576
4573
|
"na",
|
|
4577
|
-
"nr",
|
|
4578
|
-
"np",
|
|
4579
|
-
"nl",
|
|
4580
4574
|
"nc",
|
|
4581
|
-
"nz",
|
|
4582
|
-
"ni",
|
|
4583
4575
|
"ne",
|
|
4584
|
-
"ng",
|
|
4585
|
-
"nu",
|
|
4586
4576
|
"nf",
|
|
4587
|
-
"
|
|
4588
|
-
"
|
|
4589
|
-
"
|
|
4590
|
-
"mp",
|
|
4577
|
+
"ng",
|
|
4578
|
+
"ni",
|
|
4579
|
+
"nl",
|
|
4591
4580
|
"no",
|
|
4581
|
+
"np",
|
|
4582
|
+
"nr",
|
|
4583
|
+
"nu",
|
|
4584
|
+
"nz",
|
|
4592
4585
|
"om",
|
|
4593
|
-
"pk",
|
|
4594
|
-
"pw",
|
|
4595
|
-
"ps",
|
|
4596
4586
|
"pa",
|
|
4597
|
-
"pg",
|
|
4598
|
-
"py",
|
|
4599
4587
|
"pe",
|
|
4588
|
+
"pf",
|
|
4589
|
+
"pg",
|
|
4600
4590
|
"ph",
|
|
4601
|
-
"
|
|
4591
|
+
"pk",
|
|
4602
4592
|
"pl",
|
|
4603
|
-
"
|
|
4593
|
+
"pm",
|
|
4594
|
+
"pn",
|
|
4604
4595
|
"pr",
|
|
4596
|
+
"ps",
|
|
4597
|
+
"pt",
|
|
4598
|
+
"pw",
|
|
4599
|
+
"py",
|
|
4605
4600
|
"qa",
|
|
4601
|
+
"re",
|
|
4606
4602
|
"ro",
|
|
4603
|
+
"rs",
|
|
4607
4604
|
"ru",
|
|
4608
4605
|
"rw",
|
|
4609
|
-
"re",
|
|
4610
|
-
"bq",
|
|
4611
|
-
"an",
|
|
4612
|
-
"bl",
|
|
4613
|
-
"gp",
|
|
4614
|
-
"fr",
|
|
4615
|
-
"sh",
|
|
4616
|
-
"kn",
|
|
4617
|
-
"lc",
|
|
4618
|
-
"mf",
|
|
4619
|
-
"gp",
|
|
4620
|
-
"fr",
|
|
4621
|
-
"pm",
|
|
4622
|
-
"vc",
|
|
4623
|
-
"ws",
|
|
4624
|
-
"sm",
|
|
4625
|
-
"st",
|
|
4626
4606
|
"sa",
|
|
4627
|
-
"
|
|
4628
|
-
"rs",
|
|
4607
|
+
"sb",
|
|
4629
4608
|
"sc",
|
|
4630
|
-
"
|
|
4609
|
+
"sd",
|
|
4610
|
+
"se",
|
|
4631
4611
|
"sg",
|
|
4632
|
-
"
|
|
4633
|
-
"an",
|
|
4634
|
-
"nl",
|
|
4635
|
-
"sx",
|
|
4636
|
-
"an",
|
|
4637
|
-
"sk",
|
|
4612
|
+
"sh",
|
|
4638
4613
|
"si",
|
|
4639
|
-
"
|
|
4640
|
-
"
|
|
4614
|
+
"sj",
|
|
4615
|
+
"sk",
|
|
4616
|
+
"sl",
|
|
4617
|
+
"sm",
|
|
4618
|
+
"sn",
|
|
4641
4619
|
"so",
|
|
4642
|
-
"za",
|
|
4643
|
-
"gs",
|
|
4644
|
-
"kr",
|
|
4645
|
-
"ss",
|
|
4646
|
-
"es",
|
|
4647
|
-
"lk",
|
|
4648
|
-
"sd",
|
|
4649
4620
|
"sr",
|
|
4650
|
-
"
|
|
4651
|
-
"
|
|
4652
|
-
"
|
|
4653
|
-
"
|
|
4621
|
+
"ss",
|
|
4622
|
+
"st",
|
|
4623
|
+
"sv",
|
|
4624
|
+
"sx",
|
|
4654
4625
|
"sy",
|
|
4655
|
-
"
|
|
4656
|
-
"
|
|
4657
|
-
"
|
|
4658
|
-
"
|
|
4626
|
+
"sz",
|
|
4627
|
+
"tc",
|
|
4628
|
+
"td",
|
|
4629
|
+
"tf",
|
|
4659
4630
|
"tg",
|
|
4631
|
+
"th",
|
|
4632
|
+
"tj",
|
|
4660
4633
|
"tk",
|
|
4661
|
-
"
|
|
4662
|
-
"
|
|
4634
|
+
"tl",
|
|
4635
|
+
"tm",
|
|
4663
4636
|
"tn",
|
|
4637
|
+
"to",
|
|
4664
4638
|
"tr",
|
|
4665
|
-
"
|
|
4666
|
-
"tc",
|
|
4639
|
+
"tt",
|
|
4667
4640
|
"tv",
|
|
4668
|
-
"
|
|
4641
|
+
"tw",
|
|
4642
|
+
"tz",
|
|
4669
4643
|
"ua",
|
|
4670
|
-
"
|
|
4644
|
+
"ug",
|
|
4671
4645
|
"uk",
|
|
4646
|
+
"um",
|
|
4672
4647
|
"us",
|
|
4673
|
-
"vi",
|
|
4674
4648
|
"uy",
|
|
4675
4649
|
"uz",
|
|
4676
|
-
"vu",
|
|
4677
4650
|
"va",
|
|
4651
|
+
"vc",
|
|
4678
4652
|
"ve",
|
|
4653
|
+
"vg",
|
|
4654
|
+
"vi",
|
|
4679
4655
|
"vn",
|
|
4656
|
+
"vu",
|
|
4680
4657
|
"wf",
|
|
4681
|
-
"
|
|
4682
|
-
"ma",
|
|
4658
|
+
"ws",
|
|
4683
4659
|
"ye",
|
|
4660
|
+
"za",
|
|
4684
4661
|
"zm",
|
|
4685
4662
|
"zw"
|
|
4686
4663
|
]);
|
|
@@ -4827,6 +4804,15 @@ const DEFAULT_THEME_MODE = THEME_MODES.SYSTEM;
|
|
|
4827
4804
|
*/
|
|
4828
4805
|
const NEXT_PUBLIC_RECAPTCHA_SITE_KEY = getEnv("NEXT_PUBLIC_RECAPTCHA_SITE_KEY");
|
|
4829
4806
|
/**
|
|
4807
|
+
* Recaptcha secret key for server-side token verification.
|
|
4808
|
+
* Used by verifyRecaptchaToken to call Google's siteverify endpoint.
|
|
4809
|
+
* Must NOT be exposed to the client (no NEXT_PUBLIC prefix).
|
|
4810
|
+
*
|
|
4811
|
+
* @example
|
|
4812
|
+
* const isValid = await verifyRecaptchaToken(token);
|
|
4813
|
+
*/
|
|
4814
|
+
const RECAPTCHA_SECRET_KEY = getEnv("RECAPTCHA_SECRET_KEY");
|
|
4815
|
+
/**
|
|
4830
4816
|
* Slack webhook URLs for different log types.
|
|
4831
4817
|
* Used for sending log messages to specific Slack channels based on log category.
|
|
4832
4818
|
*
|
|
@@ -4853,7 +4839,7 @@ const SLACK_WEBHOOKS = {
|
|
|
4853
4839
|
* @example
|
|
4854
4840
|
* <img src={OG_AVATAR_URL + userId} />
|
|
4855
4841
|
*/
|
|
4856
|
-
const OG_AVATAR_URL = "https://api.kumix.
|
|
4842
|
+
const OG_AVATAR_URL = "https://api.kumix.io/og/avatar/";
|
|
4857
4843
|
/**
|
|
4858
4844
|
* Default pagination limit for API responses and UI lists.
|
|
4859
4845
|
*
|
|
@@ -5063,7 +5049,7 @@ const LOCALHOST_GEO_DATA = {
|
|
|
5063
5049
|
* }
|
|
5064
5050
|
* ```
|
|
5065
5051
|
*/
|
|
5066
|
-
const LOCALHOST_IP = "
|
|
5052
|
+
const LOCALHOST_IP = "198.51.100.1";
|
|
5067
5053
|
//#endregion
|
|
5068
5054
|
//#region src/constants/reserved-slugs.ts
|
|
5069
5055
|
/**
|
|
@@ -5239,15 +5225,18 @@ const googleTrackEvent = ({ name, properties }) => {
|
|
|
5239
5225
|
}
|
|
5240
5226
|
};
|
|
5241
5227
|
/**
|
|
5242
|
-
* Helper function to safely get
|
|
5228
|
+
* Helper function to safely get the first path segment (component category)
|
|
5229
|
+
* from a component path. For "ui/buttons/Button" this returns "ui".
|
|
5243
5230
|
*
|
|
5244
5231
|
* @param componentPath - Component path string
|
|
5245
|
-
* @returns
|
|
5232
|
+
* @returns First segment of the path, or "unknown" if invalid
|
|
5246
5233
|
*/
|
|
5247
5234
|
const getComponentName = (componentPath) => {
|
|
5248
5235
|
if (!componentPath || typeof componentPath !== "string") return "unknown";
|
|
5249
|
-
const
|
|
5250
|
-
|
|
5236
|
+
const trimmed = componentPath.trim();
|
|
5237
|
+
if (!trimmed) return "unknown";
|
|
5238
|
+
const firstSlash = trimmed.indexOf("/");
|
|
5239
|
+
return firstSlash === -1 ? trimmed : trimmed.slice(0, firstSlash);
|
|
5251
5240
|
};
|
|
5252
5241
|
/**
|
|
5253
5242
|
* Tracks code copy events with validation.
|
|
@@ -5544,6 +5533,7 @@ const googleTrackItemRestore = (module, itemType, itemId) => {
|
|
|
5544
5533
|
* ```
|
|
5545
5534
|
*/
|
|
5546
5535
|
const chunk = (array, chunk_size) => {
|
|
5536
|
+
if (chunk_size <= 0) return [];
|
|
5547
5537
|
return array.reduce((resultArray, item, index) => {
|
|
5548
5538
|
const chunkIndex = Math.floor(index / chunk_size);
|
|
5549
5539
|
if (!resultArray[chunkIndex]) resultArray[chunkIndex] = [];
|
|
@@ -5648,15 +5638,17 @@ const stableSort = (arr, compare) => arr.map((item, index) => ({
|
|
|
5648
5638
|
* Asset URL builder utilities
|
|
5649
5639
|
* Provides helpers to construct absolute asset URLs against a configurable asset host.
|
|
5650
5640
|
*/
|
|
5651
|
-
const DEFAULT_ASSET_HOST = getEnv("NEXT_PUBLIC_ASSETS_URL") || getEnv("VITE_ASSETS_URL") || "https://assets.kumix.
|
|
5641
|
+
const DEFAULT_ASSET_HOST = getEnv("NEXT_PUBLIC_ASSETS_URL") || getEnv("VITE_ASSETS_URL") || "https://assets.kumix.io";
|
|
5652
5642
|
/**
|
|
5653
5643
|
* Builds an absolute URL for a given asset path using the provided asset host (CDN) base.
|
|
5654
5644
|
* Accepts relative paths (e.g., `logo/logo.png`, `/images/icon.svg`) and returns a fully-qualified URL.
|
|
5655
5645
|
* If an absolute URL is provided as `path`, it will be returned as-is (host is ignored).
|
|
5656
5646
|
*
|
|
5657
5647
|
* @param path - Asset path or absolute URL to resolve
|
|
5658
|
-
* @param host - Optional asset host (base URL). Defaults to `https://assets.kumix.
|
|
5659
|
-
* @returns A fully-qualified asset URL string
|
|
5648
|
+
* @param host - Optional asset host (base URL). Defaults to `https://assets.kumix.io`
|
|
5649
|
+
* @returns A fully-qualified asset URL string. On invalid input (empty path or
|
|
5650
|
+
* malformed base), falls back to the configured asset host rather than
|
|
5651
|
+
* throwing — call sites that need strict failure should validate inputs first.
|
|
5660
5652
|
*
|
|
5661
5653
|
* @example
|
|
5662
5654
|
* ```ts
|
|
@@ -5664,7 +5656,7 @@ const DEFAULT_ASSET_HOST = getEnv("NEXT_PUBLIC_ASSETS_URL") || getEnv("VITE_ASSE
|
|
|
5664
5656
|
*
|
|
5665
5657
|
* // Default host
|
|
5666
5658
|
* const u1 = assetsUrl('logo/logo.png');
|
|
5667
|
-
* // 'https://assets.kumix.
|
|
5659
|
+
* // 'https://assets.kumix.io/logo/logo.png'
|
|
5668
5660
|
*
|
|
5669
5661
|
* // Custom host (full URL)
|
|
5670
5662
|
* const u2 = assetsUrl('/images/icon.svg', 'https://cdn.example.com');
|
|
@@ -5678,16 +5670,16 @@ const DEFAULT_ASSET_HOST = getEnv("NEXT_PUBLIC_ASSETS_URL") || getEnv("VITE_ASSE
|
|
|
5678
5670
|
* const u4 = assetsUrl('https://other.com/a.png', 'https://cdn.example.com');
|
|
5679
5671
|
* // 'https://other.com/a.png'
|
|
5680
5672
|
*
|
|
5681
|
-
* // Edge cases
|
|
5673
|
+
* // Edge cases — falsy path or malformed base returns the configured asset host
|
|
5682
5674
|
* const u5 = assetsUrl('');
|
|
5683
|
-
* //
|
|
5675
|
+
* // 'https://assets.kumix.io' (the configured host)
|
|
5684
5676
|
*
|
|
5685
5677
|
* const u6 = assetsUrl('logo.png', '://bad-host');
|
|
5686
|
-
* //
|
|
5678
|
+
* // '://bad-host' (the supplied host — invalid, returned as-is)
|
|
5687
5679
|
* ```
|
|
5688
5680
|
*/
|
|
5689
5681
|
function assetsUrl(path, host = DEFAULT_ASSET_HOST) {
|
|
5690
|
-
const BASE_HOST =
|
|
5682
|
+
const BASE_HOST = host;
|
|
5691
5683
|
if (!path || typeof path !== "string") return BASE_HOST;
|
|
5692
5684
|
try {
|
|
5693
5685
|
const base = /^https?:\/\//i.test(BASE_HOST) ? BASE_HOST : `https://${BASE_HOST}`;
|
|
@@ -5711,17 +5703,18 @@ function assetsUrl(path, host = DEFAULT_ASSET_HOST) {
|
|
|
5711
5703
|
* import { getFlagUrl } from "@kumix/ui/utils/flag-url";
|
|
5712
5704
|
*
|
|
5713
5705
|
* const urlUs = getFlagUrl("US");
|
|
5714
|
-
* // "https://assets.kumix.
|
|
5706
|
+
* // "https://assets.kumix.io/media/flags/us.svg"
|
|
5715
5707
|
*
|
|
5716
5708
|
* const urlId = getFlagUrl("id");
|
|
5717
|
-
* // "https://assets.kumix.
|
|
5709
|
+
* // "https://assets.kumix.io/media/flags/id.svg"
|
|
5718
5710
|
*
|
|
5719
5711
|
* // Can be used directly in an <img /> or <Image /> component
|
|
5720
5712
|
* // <img src={getFlagUrl("GB")} alt="United Kingdom flag" />
|
|
5721
5713
|
* ```
|
|
5722
5714
|
*/
|
|
5723
5715
|
function getFlagUrl(flag) {
|
|
5724
|
-
|
|
5716
|
+
if (typeof flag !== "string" || !flag.trim()) return `${assetsUrl("media/flags")}/unknown.svg`;
|
|
5717
|
+
const flagCode = flag.trim().toLowerCase();
|
|
5725
5718
|
return `${assetsUrl("media/flags")}/${flagCode}.svg`;
|
|
5726
5719
|
}
|
|
5727
5720
|
//#endregion
|
|
@@ -5791,7 +5784,7 @@ function mapLocale(locale) {
|
|
|
5791
5784
|
* Supports Open Graph, Twitter cards, icons, canonical URLs, robots, manifest, and multi-language alternates.
|
|
5792
5785
|
*
|
|
5793
5786
|
* @param params - Metadata construction options
|
|
5794
|
-
* @param params.baseUrl - The base URL/domain for metadataBase (optional, e.g., 'https://kumix.
|
|
5787
|
+
* @param params.baseUrl - The base URL/domain for metadataBase (optional, e.g., 'https://kumix.io')
|
|
5795
5788
|
* @param params.title - The base title for the page (used in Open Graph and Twitter)
|
|
5796
5789
|
* @param params.fullTitle - The full title for the page (overrides title in the <title> tag)
|
|
5797
5790
|
* @param params.description - Description of the page (used in meta, Open Graph, Twitter)
|
|
@@ -5835,8 +5828,8 @@ function mapLocale(locale) {
|
|
|
5835
5828
|
* creator: '@lukmanaviccena',
|
|
5836
5829
|
* },
|
|
5837
5830
|
* alternateLanguages: {
|
|
5838
|
-
* en: 'https://kumix.
|
|
5839
|
-
* id: 'https://kumix.
|
|
5831
|
+
* en: 'https://kumix.io/en',
|
|
5832
|
+
* id: 'https://kumix.io/id',
|
|
5840
5833
|
* },
|
|
5841
5834
|
* icons: [
|
|
5842
5835
|
* { rel: 'icon', url: '/favicon.ico' },
|
|
@@ -5890,8 +5883,14 @@ function constructMetadata({ baseUrl, title, fullTitle, description, icons = [
|
|
|
5890
5883
|
type: "website",
|
|
5891
5884
|
locale: "en_US"
|
|
5892
5885
|
}, twitter = {}, canonicalUrl, alternateLanguages, noIndex = false, noArchive = false, noSnippet = false, manifest }) {
|
|
5886
|
+
let metadataBase;
|
|
5887
|
+
if (baseUrl) try {
|
|
5888
|
+
metadataBase = new URL(baseUrl);
|
|
5889
|
+
} catch {
|
|
5890
|
+
metadataBase = void 0;
|
|
5891
|
+
}
|
|
5893
5892
|
return {
|
|
5894
|
-
metadataBase
|
|
5893
|
+
metadataBase,
|
|
5895
5894
|
title: fullTitle || title,
|
|
5896
5895
|
description,
|
|
5897
5896
|
icons,
|
|
@@ -6507,7 +6506,6 @@ const resizeImage = (file, opts = {
|
|
|
6507
6506
|
const reader = new FileReader();
|
|
6508
6507
|
reader.onload = (e) => {
|
|
6509
6508
|
const img = new Image();
|
|
6510
|
-
img.src = e.target?.result;
|
|
6511
6509
|
img.onload = () => {
|
|
6512
6510
|
const targetWidth = opts.width;
|
|
6513
6511
|
const targetHeight = opts.height;
|
|
@@ -6537,6 +6535,7 @@ const resizeImage = (file, opts = {
|
|
|
6537
6535
|
resolve(canvas.toDataURL("image/jpeg", opts.quality));
|
|
6538
6536
|
};
|
|
6539
6537
|
img.onerror = (error) => reject(/* @__PURE__ */ new Error(`Image loading error: ${error}`));
|
|
6538
|
+
img.src = e.target?.result;
|
|
6540
6539
|
};
|
|
6541
6540
|
reader.onerror = (error) => reject(/* @__PURE__ */ new Error(`FileReader error: ${error}`));
|
|
6542
6541
|
reader.readAsDataURL(file);
|
|
@@ -6630,11 +6629,11 @@ async function loadImage(file) {
|
|
|
6630
6629
|
return new Promise((resolve, reject) => {
|
|
6631
6630
|
const image = new Image();
|
|
6632
6631
|
const reader = new FileReader();
|
|
6632
|
+
image.onload = () => resolve(image);
|
|
6633
|
+
image.onerror = (err) => reject(err);
|
|
6633
6634
|
reader.onload = (e) => {
|
|
6634
6635
|
image.src = e.target?.result;
|
|
6635
6636
|
};
|
|
6636
|
-
image.onload = () => resolve(image);
|
|
6637
|
-
image.onerror = (err) => reject(err);
|
|
6638
6637
|
reader.readAsDataURL(file);
|
|
6639
6638
|
});
|
|
6640
6639
|
}
|
|
@@ -6804,11 +6803,28 @@ const hasStorageItem = (key, storageType = "localStorage") => {
|
|
|
6804
6803
|
};
|
|
6805
6804
|
//#endregion
|
|
6806
6805
|
//#region src/functions/crypto/base-id.ts
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
*
|
|
6810
|
-
|
|
6811
|
-
|
|
6806
|
+
const CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
6807
|
+
/**
|
|
6808
|
+
* Encodes a 16-byte (128-bit) buffer into a fixed-length 26-character
|
|
6809
|
+
* Crockford base32 ULID string. Unlike big-number base encoders, this pads
|
|
6810
|
+
* the output to a constant length so IDs remain lexicographically sortable
|
|
6811
|
+
* regardless of leading zero bytes.
|
|
6812
|
+
*/
|
|
6813
|
+
function encodeULID(buf) {
|
|
6814
|
+
let bits = 0;
|
|
6815
|
+
let value = 0;
|
|
6816
|
+
let output = "";
|
|
6817
|
+
for (let i = 0; i < buf.length; i++) {
|
|
6818
|
+
value = value << 8 | buf[i];
|
|
6819
|
+
bits += 8;
|
|
6820
|
+
while (bits >= 5) {
|
|
6821
|
+
bits -= 5;
|
|
6822
|
+
output += CROCKFORD[value >>> bits & 31];
|
|
6823
|
+
}
|
|
6824
|
+
}
|
|
6825
|
+
if (bits > 0) output += CROCKFORD[value << 5 - bits & 31];
|
|
6826
|
+
return output;
|
|
6827
|
+
}
|
|
6812
6828
|
/**
|
|
6813
6829
|
* Creates a ULID-compatible buffer (48 bits timestamp + 80 bits randomness)
|
|
6814
6830
|
*
|
|
@@ -6848,8 +6864,7 @@ function createULIDBuffer() {
|
|
|
6848
6864
|
* ```
|
|
6849
6865
|
*/
|
|
6850
6866
|
const baseIdCustom = ({ prefix }) => {
|
|
6851
|
-
|
|
6852
|
-
return `${prefix}${base32.encode(buf)}`;
|
|
6867
|
+
return `${prefix}${encodeULID(createULIDBuffer())}`;
|
|
6853
6868
|
};
|
|
6854
6869
|
/**
|
|
6855
6870
|
* Creates a unique, time-sortable ID with a known prefix from the predefined set
|
|
@@ -6885,6 +6900,15 @@ const baseId = ({ prefix }) => baseIdCustom({ prefix });
|
|
|
6885
6900
|
* CUID (Collision-resistant Unique IDentifier) generation utilities
|
|
6886
6901
|
* Provides functions for generating unique identifiers using @paralleldrive/cuid2
|
|
6887
6902
|
*/
|
|
6903
|
+
const generatorCache = /* @__PURE__ */ new Map();
|
|
6904
|
+
function getGenerator(length) {
|
|
6905
|
+
let generator = generatorCache.get(length);
|
|
6906
|
+
if (!generator) {
|
|
6907
|
+
generator = init({ length });
|
|
6908
|
+
generatorCache.set(length, generator);
|
|
6909
|
+
}
|
|
6910
|
+
return generator;
|
|
6911
|
+
}
|
|
6888
6912
|
/**
|
|
6889
6913
|
* Generates a CUID (Collision-resistant Unique IDentifier)
|
|
6890
6914
|
* CUIDs are designed to be globally unique, even in distributed systems.
|
|
@@ -6921,10 +6945,8 @@ function cuid() {
|
|
|
6921
6945
|
return createId();
|
|
6922
6946
|
}
|
|
6923
6947
|
/**
|
|
6924
|
-
* Generates a custom ID with an optional prefix and configurable length
|
|
6925
|
-
*
|
|
6926
|
-
* with an optional prefix. Useful for creating IDs with specific patterns
|
|
6927
|
-
* like `user_abc123` or `order_987xyz`.
|
|
6948
|
+
* Generates a custom ID with an optional prefix and configurable length.
|
|
6949
|
+
* Uses `@paralleldrive/cuid2`'s cryptographically-secure RNG.
|
|
6928
6950
|
*
|
|
6929
6951
|
* @param prefix - Optional prefix to prepend to the ID
|
|
6930
6952
|
* @param length - The length of the generated ID (default is 12)
|
|
@@ -6932,40 +6954,25 @@ function cuid() {
|
|
|
6932
6954
|
*
|
|
6933
6955
|
* @example
|
|
6934
6956
|
* ```ts
|
|
6935
|
-
* import {
|
|
6957
|
+
* import { customId } from '@/utils/functions';
|
|
6936
6958
|
*
|
|
6937
6959
|
* // Generate ID with prefix
|
|
6938
|
-
* const userId =
|
|
6960
|
+
* const userId = customId('user_');
|
|
6939
6961
|
* // Returns: 'user_l5r8xn2gzqnb'
|
|
6940
6962
|
*
|
|
6941
6963
|
* // Generate ID with custom length
|
|
6942
|
-
* const orderId =
|
|
6943
|
-
* // Returns: 'order_l5r8xn2gzqnbf4r2'
|
|
6944
|
-
*
|
|
6945
|
-
* // Generate ID without prefix
|
|
6946
|
-
* const randomId = customeId();
|
|
6947
|
-
* // Returns: 'l5r8xn2gzqnb'
|
|
6948
|
-
*
|
|
6949
|
-
* // Use for different entity types
|
|
6950
|
-
* const productId = customeId('prod_', 8);
|
|
6951
|
-
* const invoiceId = customeId('inv_', 10);
|
|
6952
|
-
* const sessionId = customeId('sess_', 20);
|
|
6953
|
-
*
|
|
6954
|
-
* // Use in API responses
|
|
6955
|
-
* const apiResponse = {
|
|
6956
|
-
* id: customeId('api_'),
|
|
6957
|
-
* timestamp: Date.now(),
|
|
6958
|
-
* data: {...}
|
|
6959
|
-
* };
|
|
6964
|
+
* const orderId = customId('order_', 16);
|
|
6960
6965
|
* ```
|
|
6961
6966
|
*/
|
|
6962
|
-
function
|
|
6963
|
-
const generateId =
|
|
6964
|
-
random: Math.random,
|
|
6965
|
-
length
|
|
6966
|
-
});
|
|
6967
|
+
function customId(prefix, length = 12) {
|
|
6968
|
+
const generateId = getGenerator(length);
|
|
6967
6969
|
return `${prefix || ""}${generateId()}`;
|
|
6968
6970
|
}
|
|
6971
|
+
/**
|
|
6972
|
+
* @deprecated Use {@link customId} instead. This alias has a typo and is kept
|
|
6973
|
+
* only for backward compatibility; it will be removed in a future major.
|
|
6974
|
+
*/
|
|
6975
|
+
const customeId = customId;
|
|
6969
6976
|
//#endregion
|
|
6970
6977
|
//#region src/functions/crypto/hash-string.ts
|
|
6971
6978
|
/**
|
|
@@ -7011,6 +7018,8 @@ async function hashStringSHA256(str) {
|
|
|
7011
7018
|
* Utility function for generating unique IDs
|
|
7012
7019
|
* Provides a wrapper around nanoid for consistent ID generation
|
|
7013
7020
|
*/
|
|
7021
|
+
const DEFAULT_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
7022
|
+
const DEFAULT_SIZE = 7;
|
|
7014
7023
|
/**
|
|
7015
7024
|
* Generates a random alphanumeric ID of specified length
|
|
7016
7025
|
* Uses a custom alphabet of numbers and letters (both cases)
|
|
@@ -7036,7 +7045,7 @@ async function hashStringSHA256(str) {
|
|
|
7036
7045
|
* ```
|
|
7037
7046
|
*/
|
|
7038
7047
|
const nanoid = (chars) => {
|
|
7039
|
-
return customAlphabet(
|
|
7048
|
+
return customAlphabet(DEFAULT_ALPHABET, chars || DEFAULT_SIZE)();
|
|
7040
7049
|
};
|
|
7041
7050
|
/**
|
|
7042
7051
|
* Generates a unique identifier using the current timestamp and a random number
|
|
@@ -7067,7 +7076,8 @@ const nanoid = (chars) => {
|
|
|
7067
7076
|
* ```
|
|
7068
7077
|
*/
|
|
7069
7078
|
function uid() {
|
|
7070
|
-
|
|
7079
|
+
const random = Math.floor(Math.random() * 1e3).toString().padStart(3, "0");
|
|
7080
|
+
return `${Date.now()}${random}`;
|
|
7071
7081
|
}
|
|
7072
7082
|
//#endregion
|
|
7073
7083
|
//#region src/functions/datetime/billing-utils.ts
|
|
@@ -7216,8 +7226,9 @@ const getBillingStartDate = (billingCycleStart, referenceDate = /* @__PURE__ */
|
|
|
7216
7226
|
* ```
|
|
7217
7227
|
*/
|
|
7218
7228
|
const formatDate = (datetime, options, locale = "en-US") => {
|
|
7219
|
-
|
|
7220
|
-
|
|
7229
|
+
const date = new Date(datetime);
|
|
7230
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
7231
|
+
return date.toLocaleDateString(locale, {
|
|
7221
7232
|
day: "numeric",
|
|
7222
7233
|
month: "long",
|
|
7223
7234
|
year: "numeric",
|
|
@@ -7265,11 +7276,12 @@ const formatDate = (datetime, options, locale = "en-US") => {
|
|
|
7265
7276
|
*/
|
|
7266
7277
|
const formatDateTimeSmart = (datetime, options, locale = "en-US") => {
|
|
7267
7278
|
const date = new Date(datetime);
|
|
7279
|
+
if (Number.isNaN(date.getTime())) return "Invalid Date";
|
|
7268
7280
|
const now = /* @__PURE__ */ new Date();
|
|
7269
7281
|
return new Date(datetime).toLocaleDateString(locale, {
|
|
7270
7282
|
month: "short",
|
|
7271
7283
|
day: "numeric",
|
|
7272
|
-
...date.
|
|
7284
|
+
...date.getFullYear() !== now.getFullYear() ? { year: "numeric" } : {
|
|
7273
7285
|
hour: "numeric",
|
|
7274
7286
|
minute: "numeric",
|
|
7275
7287
|
hour12: true
|
|
@@ -7324,8 +7336,9 @@ const formatDateTimeSmart = (datetime, options, locale = "en-US") => {
|
|
|
7324
7336
|
* ```
|
|
7325
7337
|
*/
|
|
7326
7338
|
const formatDateTime = (datetime, options, locale = "en-US") => {
|
|
7327
|
-
|
|
7328
|
-
|
|
7339
|
+
const date = new Date(datetime);
|
|
7340
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
7341
|
+
return date.toLocaleString(locale, {
|
|
7329
7342
|
month: "short",
|
|
7330
7343
|
day: "numeric",
|
|
7331
7344
|
year: "numeric",
|
|
@@ -7561,18 +7574,26 @@ const getFirstAndLastDay = (day, referenceDate = /* @__PURE__ */ new Date()) =>
|
|
|
7561
7574
|
const currentDay = today.getDate();
|
|
7562
7575
|
const currentMonth = today.getMonth();
|
|
7563
7576
|
const currentYear = today.getFullYear();
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
const lastYear = currentMonth ===
|
|
7570
|
-
const
|
|
7577
|
+
const lastDayOfMonth = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
7578
|
+
const clamp = (year, month, requested) => Math.min(requested, lastDayOfMonth(year, month));
|
|
7579
|
+
if (currentDay >= day) {
|
|
7580
|
+
const firstDayClamped = clamp(currentYear, currentMonth, day);
|
|
7581
|
+
const lastMonth = currentMonth + 1;
|
|
7582
|
+
const lastYear = currentYear + (currentMonth === 11 ? 1 : 0);
|
|
7583
|
+
const lastDayClamped = clamp(lastMonth === 12 ? lastYear : currentYear, lastMonth % 12, Math.max(1, day - 1));
|
|
7571
7584
|
return {
|
|
7572
|
-
firstDay: new Date(
|
|
7573
|
-
lastDay: new Date(currentYear,
|
|
7585
|
+
firstDay: new Date(currentYear, currentMonth, firstDayClamped),
|
|
7586
|
+
lastDay: new Date(lastMonth === 12 ? lastYear : currentYear, lastMonth % 12, lastDayClamped)
|
|
7574
7587
|
};
|
|
7575
7588
|
}
|
|
7589
|
+
const lastYear = currentMonth === 0 ? currentYear - 1 : currentYear;
|
|
7590
|
+
const lastMonth = currentMonth === 0 ? 11 : currentMonth - 1;
|
|
7591
|
+
const firstDayClamped = clamp(lastYear, lastMonth, day);
|
|
7592
|
+
const lastDayClamped = clamp(currentYear, currentMonth, Math.max(1, day - 1));
|
|
7593
|
+
return {
|
|
7594
|
+
firstDay: new Date(lastYear, lastMonth, firstDayClamped),
|
|
7595
|
+
lastDay: new Date(currentYear, currentMonth, lastDayClamped)
|
|
7596
|
+
};
|
|
7576
7597
|
};
|
|
7577
7598
|
//#endregion
|
|
7578
7599
|
//#region src/functions/datetime/get-year.ts
|
|
@@ -7746,7 +7767,29 @@ const timeAgo = (timestamp, { withAgo, neverText = "Never", justNowText = "Just
|
|
|
7746
7767
|
* ```
|
|
7747
7768
|
*/
|
|
7748
7769
|
const getTimeZones = () => {
|
|
7749
|
-
|
|
7770
|
+
const safeSupported = () => {
|
|
7771
|
+
if (typeof Intl !== "undefined" && typeof Intl.supportedValuesOf === "function") try {
|
|
7772
|
+
return Intl.supportedValuesOf("timeZone");
|
|
7773
|
+
} catch {}
|
|
7774
|
+
return [
|
|
7775
|
+
"UTC",
|
|
7776
|
+
"America/New_York",
|
|
7777
|
+
"America/Los_Angeles",
|
|
7778
|
+
"Europe/London",
|
|
7779
|
+
"Europe/Paris",
|
|
7780
|
+
"Asia/Tokyo"
|
|
7781
|
+
];
|
|
7782
|
+
};
|
|
7783
|
+
const timezones = safeSupported();
|
|
7784
|
+
const parseOffsetMinutes = (offset) => {
|
|
7785
|
+
const match = offset.match(/GMT([+-])(\d{1,2})(?::(\d{2}))?/);
|
|
7786
|
+
if (!match) return 0;
|
|
7787
|
+
const sign = match[1] === "-" ? -1 : 1;
|
|
7788
|
+
const hours = Number.parseInt(match[2] ?? "0", 10);
|
|
7789
|
+
const minutes = Number.parseInt(match[3] ?? "0", 10);
|
|
7790
|
+
return sign * (hours * 60 + minutes);
|
|
7791
|
+
};
|
|
7792
|
+
return timezones.map((timezone) => {
|
|
7750
7793
|
const offset = new Intl.DateTimeFormat("en", {
|
|
7751
7794
|
timeZone: timezone,
|
|
7752
7795
|
timeZoneName: "shortOffset"
|
|
@@ -7755,7 +7798,7 @@ const getTimeZones = () => {
|
|
|
7755
7798
|
return {
|
|
7756
7799
|
value: timezone,
|
|
7757
7800
|
label: `(${formattedOffset}) ${timezone.replace(/_/g, " ")}`,
|
|
7758
|
-
numericOffset:
|
|
7801
|
+
numericOffset: parseOffsetMinutes(formattedOffset)
|
|
7759
7802
|
};
|
|
7760
7803
|
}).sort((a, b) => a.numericOffset - b.numericOffset);
|
|
7761
7804
|
};
|
|
@@ -7806,6 +7849,7 @@ const getTimeZones = () => {
|
|
|
7806
7849
|
*/
|
|
7807
7850
|
function formatFileSize(bytes, decimals = 2, base = 1024) {
|
|
7808
7851
|
if (bytes === 0) return "0 Bytes";
|
|
7852
|
+
if (bytes < 0) return `-${formatFileSize(-bytes, decimals, base)}`;
|
|
7809
7853
|
const k = base;
|
|
7810
7854
|
const sizes = [
|
|
7811
7855
|
"B",
|
|
@@ -7818,7 +7862,7 @@ function formatFileSize(bytes, decimals = 2, base = 1024) {
|
|
|
7818
7862
|
"ZB",
|
|
7819
7863
|
"YB"
|
|
7820
7864
|
];
|
|
7821
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
7865
|
+
const i = Math.min(Math.max(Math.floor(Math.log(bytes) / Math.log(k)), 0), sizes.length - 1);
|
|
7822
7866
|
return `${parseFloat((bytes / k ** i).toFixed(decimals))} ${sizes[i]}`;
|
|
7823
7867
|
}
|
|
7824
7868
|
//#endregion
|
|
@@ -7874,6 +7918,8 @@ function formatFileSize(bytes, decimals = 2, base = 1024) {
|
|
|
7874
7918
|
async function fetchWithRetry(input, init, options = {}) {
|
|
7875
7919
|
const { timeout = 5e3, maxRetries = 10, retryDelay = 1e3 } = options;
|
|
7876
7920
|
let lastError = null;
|
|
7921
|
+
let httpError = null;
|
|
7922
|
+
let lastStatus = 0;
|
|
7877
7923
|
for (let i = 0; i < maxRetries; i++) {
|
|
7878
7924
|
const controller = new AbortController();
|
|
7879
7925
|
const timeoutId = setTimeout(() => {
|
|
@@ -7886,21 +7932,25 @@ async function fetchWithRetry(input, init, options = {}) {
|
|
|
7886
7932
|
});
|
|
7887
7933
|
clearTimeout(timeoutId);
|
|
7888
7934
|
if (response.ok) return response;
|
|
7935
|
+
lastStatus = response.status;
|
|
7889
7936
|
if (response.status === 429 || response.status >= 500) {
|
|
7937
|
+
httpError = /* @__PURE__ */ new Error(`HTTP error ${response.status}`);
|
|
7890
7938
|
const delay = retryDelay + i ** 2 * 50;
|
|
7891
7939
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
7892
7940
|
continue;
|
|
7893
7941
|
}
|
|
7894
|
-
if (response.status ===
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
try {
|
|
7898
|
-
errorMessage = (await response.json()).error || `HTTP error ${response.status}`;
|
|
7899
|
-
} catch {
|
|
7900
|
-
errorMessage = `HTTP error ${response.status}`;
|
|
7901
|
-
}
|
|
7902
|
-
throw new Error(errorMessage);
|
|
7942
|
+
if (response.status === 401 || response.status === 403) {
|
|
7943
|
+
httpError = /* @__PURE__ */ new Error(response.status === 401 ? "Unauthorized" : "Forbidden");
|
|
7944
|
+
break;
|
|
7903
7945
|
}
|
|
7946
|
+
let errorMessage;
|
|
7947
|
+
try {
|
|
7948
|
+
errorMessage = (await response.json())?.error || `HTTP error ${response.status}`;
|
|
7949
|
+
} catch {
|
|
7950
|
+
errorMessage = `HTTP error ${response.status}`;
|
|
7951
|
+
}
|
|
7952
|
+
httpError = new Error(errorMessage);
|
|
7953
|
+
break;
|
|
7904
7954
|
} catch (error) {
|
|
7905
7955
|
clearTimeout(timeoutId);
|
|
7906
7956
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
@@ -7909,7 +7959,8 @@ async function fetchWithRetry(input, init, options = {}) {
|
|
|
7909
7959
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
7910
7960
|
}
|
|
7911
7961
|
}
|
|
7912
|
-
|
|
7962
|
+
if (httpError) throw httpError;
|
|
7963
|
+
throw new Error(`Failed after ${maxRetries} retries${lastStatus ? ` (last status: ${lastStatus})` : ""}`);
|
|
7913
7964
|
}
|
|
7914
7965
|
//#endregion
|
|
7915
7966
|
//#region src/functions/http/fetch-with-timeout.ts
|
|
@@ -8069,13 +8120,25 @@ async function fetcher(endpoint, method = "GET", body, options) {
|
|
|
8069
8120
|
if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
|
|
8070
8121
|
payload = JSON.stringify(body);
|
|
8071
8122
|
}
|
|
8072
|
-
const
|
|
8123
|
+
const res = await fetch(endpoint, {
|
|
8073
8124
|
method,
|
|
8074
8125
|
headers,
|
|
8075
8126
|
body: payload
|
|
8076
|
-
})
|
|
8077
|
-
|
|
8078
|
-
|
|
8127
|
+
});
|
|
8128
|
+
let data;
|
|
8129
|
+
try {
|
|
8130
|
+
data = await res.json();
|
|
8131
|
+
} catch {
|
|
8132
|
+
data = void 0;
|
|
8133
|
+
}
|
|
8134
|
+
if (options?.log && isDevelopment) logger.info(`[request] ${endpoint}`, data);
|
|
8135
|
+
if (!res.ok) {
|
|
8136
|
+
const message = (typeof data === "object" && data !== null && "error" in data ? String(data.error) : `HTTP error ${res.status}`) || `HTTP error ${res.status}`;
|
|
8137
|
+
const error = new Error(message);
|
|
8138
|
+
error.status = res.status;
|
|
8139
|
+
throw error;
|
|
8140
|
+
}
|
|
8141
|
+
return typeof data === "object" && data !== null && "data" in data ? data.data : data;
|
|
8079
8142
|
}
|
|
8080
8143
|
//#endregion
|
|
8081
8144
|
//#region src/functions/http/ip.ts
|
|
@@ -8177,7 +8240,7 @@ function getClientIP(request) {
|
|
|
8177
8240
|
*/
|
|
8178
8241
|
function isValidIP(ip) {
|
|
8179
8242
|
if (!ip || ip === "unknown") return false;
|
|
8180
|
-
return /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ip) || /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}
|
|
8243
|
+
return /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ip) || /^(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]+|::(?:ffff(?::0{1,4})?:)?(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$/.test(ip);
|
|
8181
8244
|
}
|
|
8182
8245
|
/**
|
|
8183
8246
|
* Gets user agent information from the request
|
|
@@ -8329,7 +8392,7 @@ async function getIPAddress() {
|
|
|
8329
8392
|
if (ip && typeof ip === "string") return ip;
|
|
8330
8393
|
}
|
|
8331
8394
|
} catch (serviceError) {
|
|
8332
|
-
|
|
8395
|
+
logger.warn(`IP service ${service} failed:`, serviceError);
|
|
8333
8396
|
}
|
|
8334
8397
|
return "unknown";
|
|
8335
8398
|
} catch (error) {
|
|
@@ -8386,7 +8449,7 @@ function normalizePath(input) {
|
|
|
8386
8449
|
* export function middleware(req: NextRequest) {
|
|
8387
8450
|
* const { domain, path, fullPath, key } = parse(req);
|
|
8388
8451
|
*
|
|
8389
|
-
* console.log(domain); // e.g., "api.kumix.
|
|
8452
|
+
* console.log(domain); // e.g., "api.kumix.io"
|
|
8390
8453
|
* console.log(path); // e.g., "/v1/users"
|
|
8391
8454
|
* console.log(fullPath); // e.g., "/v1/users?page=1"
|
|
8392
8455
|
* console.log(key); // e.g., "v1"
|
|
@@ -8410,22 +8473,26 @@ function normalizePath(input) {
|
|
|
8410
8473
|
* ```
|
|
8411
8474
|
*/
|
|
8412
8475
|
const parse = (req) => {
|
|
8413
|
-
|
|
8414
|
-
domain = domain.replace(/^www\./, "").toLowerCase();
|
|
8476
|
+
const domain = (req.headers.get("host") || "").replace(/^www\./, "").toLowerCase();
|
|
8415
8477
|
const path = req.nextUrl.pathname;
|
|
8416
8478
|
const searchParams = req.nextUrl.searchParams.toString();
|
|
8417
8479
|
const searchParamsObj = Object.fromEntries(req.nextUrl.searchParams);
|
|
8418
8480
|
const searchParamsString = searchParams.length > 0 ? `?${searchParams}` : "";
|
|
8419
8481
|
const fullPath = `${path}${searchParamsString}`;
|
|
8482
|
+
const safeDecode = (value) => {
|
|
8483
|
+
try {
|
|
8484
|
+
return decodeURIComponent(value);
|
|
8485
|
+
} catch {
|
|
8486
|
+
return value;
|
|
8487
|
+
}
|
|
8488
|
+
};
|
|
8420
8489
|
const pathSegments = path.split("/").filter(Boolean);
|
|
8421
|
-
const key = pathSegments.length > 0 ? decodeURIComponent(pathSegments[0]) : "";
|
|
8422
|
-
const fullKey = path.length > 1 ? decodeURIComponent(path.slice(1)) : "";
|
|
8423
8490
|
return {
|
|
8424
8491
|
domain,
|
|
8425
8492
|
path,
|
|
8426
8493
|
fullPath,
|
|
8427
|
-
key,
|
|
8428
|
-
fullKey,
|
|
8494
|
+
key: pathSegments.length > 0 ? safeDecode(pathSegments[0]) : "",
|
|
8495
|
+
fullKey: path.length > 1 ? safeDecode(path.slice(1)) : "",
|
|
8429
8496
|
searchParamsObj,
|
|
8430
8497
|
searchParamsString
|
|
8431
8498
|
};
|
|
@@ -8458,9 +8525,9 @@ const parse = (req) => {
|
|
|
8458
8525
|
*/
|
|
8459
8526
|
async function verifyRecaptchaToken(token) {
|
|
8460
8527
|
try {
|
|
8461
|
-
const secretKey =
|
|
8528
|
+
const secretKey = RECAPTCHA_SECRET_KEY;
|
|
8462
8529
|
if (!secretKey) {
|
|
8463
|
-
logger.error("
|
|
8530
|
+
logger.error("RECAPTCHA_SECRET_KEY is not set");
|
|
8464
8531
|
return false;
|
|
8465
8532
|
}
|
|
8466
8533
|
const data = await (await fetch("https://www.google.com/recaptcha/api/siteverify", {
|
|
@@ -8531,10 +8598,13 @@ const logTypeToEnv = {
|
|
|
8531
8598
|
* // In development, logs to console instead of Slack
|
|
8532
8599
|
* ```
|
|
8533
8600
|
*/
|
|
8534
|
-
const SlackLog = async ({ message, type, mention = false }) => {
|
|
8535
|
-
if (isDevelopment || !SLACK_WEBHOOKS.ALERTS || !SLACK_WEBHOOKS.CRON || !SLACK_WEBHOOKS.LINKS || !SLACK_WEBHOOKS.SUBSCRIBERS || !SLACK_WEBHOOKS.ERRORS) logger.log(message);
|
|
8601
|
+
const SlackLog = async ({ message, type, mention = false, mentionUserId }) => {
|
|
8536
8602
|
const HOOK = logTypeToEnv[type];
|
|
8537
|
-
if (!HOOK)
|
|
8603
|
+
if (isDevelopment || !HOOK) {
|
|
8604
|
+
logger.log(message);
|
|
8605
|
+
return;
|
|
8606
|
+
}
|
|
8607
|
+
const resolvedMentionId = mentionUserId || (typeof process !== "undefined" ? process.env.SLACK_MENTION_USER_ID : void 0);
|
|
8538
8608
|
try {
|
|
8539
8609
|
return await fetch(HOOK, {
|
|
8540
8610
|
method: "POST",
|
|
@@ -8543,7 +8613,7 @@ const SlackLog = async ({ message, type, mention = false }) => {
|
|
|
8543
8613
|
type: "section",
|
|
8544
8614
|
text: {
|
|
8545
8615
|
type: "mrkdwn",
|
|
8546
|
-
text: `${mention ?
|
|
8616
|
+
text: `${mention && resolvedMentionId ? `<@${resolvedMentionId}> ` : ""}${type === "alerts" || type === "errors" ? ":alert: " : ""}${message}`
|
|
8547
8617
|
}
|
|
8548
8618
|
}] })
|
|
8549
8619
|
});
|
|
@@ -8696,37 +8766,30 @@ function getUserName(user) {
|
|
|
8696
8766
|
//#region src/functions/string/camel-case.ts
|
|
8697
8767
|
/**
|
|
8698
8768
|
* Utility function for string case conversion
|
|
8699
|
-
* Provides conversion from
|
|
8769
|
+
* Provides conversion from various cases (snake, kebab, space, Pascal) to camelCase
|
|
8700
8770
|
*/
|
|
8701
8771
|
/**
|
|
8702
|
-
* Converts a string
|
|
8703
|
-
*
|
|
8772
|
+
* Converts a string to camelCase.
|
|
8773
|
+
* Handles snake_case, kebab-case, CONST_CASE, PascalCase, and space-separated words.
|
|
8704
8774
|
*
|
|
8705
8775
|
* @param str - The string to convert to camelCase
|
|
8706
8776
|
* @returns The camelCase version of the input string
|
|
8707
8777
|
*
|
|
8708
8778
|
* @example
|
|
8709
8779
|
* ```ts
|
|
8710
|
-
* //
|
|
8711
|
-
* toCamelCase('
|
|
8712
|
-
* //
|
|
8713
|
-
*
|
|
8714
|
-
* //
|
|
8715
|
-
* toCamelCase('userName')
|
|
8716
|
-
* // Returns "userName"
|
|
8717
|
-
*
|
|
8718
|
-
* // Multi-word snake_case strings
|
|
8719
|
-
* toCamelCase('first_name_last_name')
|
|
8720
|
-
* // Returns "firstNameLastName"
|
|
8721
|
-
*
|
|
8722
|
-
* // Handles single-word strings
|
|
8723
|
-
* toCamelCase('user')
|
|
8724
|
-
* // Returns "user"
|
|
8780
|
+
* toCamelCase('user_name') // "userName"
|
|
8781
|
+
* toCamelCase('user-name') // "userName"
|
|
8782
|
+
* toCamelCase('first name') // "firstName"
|
|
8783
|
+
* toCamelCase('PascalCase') // "pascalCase"
|
|
8784
|
+
* toCamelCase('first_name_last') // "firstNameLastName"
|
|
8725
8785
|
* ```
|
|
8726
8786
|
*/
|
|
8727
8787
|
const toCamelCase = (str) => {
|
|
8728
|
-
if (
|
|
8729
|
-
|
|
8788
|
+
if (!str) return "";
|
|
8789
|
+
const words = str.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
|
8790
|
+
if (words.length === 0) return "";
|
|
8791
|
+
const [first, ...rest] = words;
|
|
8792
|
+
return `${first.toLowerCase()}${rest.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("")}`;
|
|
8730
8793
|
};
|
|
8731
8794
|
//#endregion
|
|
8732
8795
|
//#region src/functions/string/capitalize.ts
|
|
@@ -8868,29 +8931,28 @@ const combineWords = (words) => {
|
|
|
8868
8931
|
* ```ts
|
|
8869
8932
|
* // Basic usage with defaults (USD)
|
|
8870
8933
|
* currencyFormatter(1000)
|
|
8871
|
-
* // Returns "$1,000"
|
|
8934
|
+
* // Returns "$1,000.00"
|
|
8872
8935
|
*
|
|
8873
8936
|
* // With custom currency
|
|
8874
8937
|
* currencyFormatter(1000, {}, 'en-US', 'EUR')
|
|
8875
|
-
* // Returns "€1,000"
|
|
8938
|
+
* // Returns "€1,000.00"
|
|
8876
8939
|
*
|
|
8877
8940
|
* // With custom locale
|
|
8878
8941
|
* currencyFormatter(1000, {}, 'de-DE', 'EUR')
|
|
8879
|
-
* // Returns "1.000 €"
|
|
8942
|
+
* // Returns "1.000,00 €"
|
|
8880
8943
|
*
|
|
8881
|
-
* // With custom options
|
|
8882
|
-
* currencyFormatter(1234.56, { maximumFractionDigits:
|
|
8883
|
-
* // Returns "$1,
|
|
8944
|
+
* // With custom options (no decimals)
|
|
8945
|
+
* currencyFormatter(1234.56, { maximumFractionDigits: 0 })
|
|
8946
|
+
* // Returns "$1,235"
|
|
8884
8947
|
*
|
|
8885
8948
|
* // Combining custom options, locale and currency
|
|
8886
|
-
* currencyFormatter(1234.56, { maximumFractionDigits:
|
|
8887
|
-
* // Returns "¥1,235"
|
|
8949
|
+
* currencyFormatter(1234.56, { maximumFractionDigits: 0 }, 'ja-JP', 'JPY')
|
|
8950
|
+
* // Returns "¥1,235"
|
|
8888
8951
|
* ```
|
|
8889
8952
|
*/
|
|
8890
8953
|
const currencyFormatter = (value, options, locale = "en-US", currencyCode = "USD") => Intl.NumberFormat(locale, {
|
|
8891
8954
|
style: "currency",
|
|
8892
8955
|
currency: currencyCode,
|
|
8893
|
-
maximumFractionDigits: 0,
|
|
8894
8956
|
...options
|
|
8895
8957
|
}).format(value);
|
|
8896
8958
|
//#endregion
|
|
@@ -9002,7 +9064,10 @@ function nFormatter(num, opts = { digits: 1 }, locale = "en-US") {
|
|
|
9002
9064
|
if (!num) return "0";
|
|
9003
9065
|
if (opts.full) return Intl.NumberFormat(locale).format(num);
|
|
9004
9066
|
const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
|
|
9005
|
-
|
|
9067
|
+
const digits = opts.digits ?? 1;
|
|
9068
|
+
const sign = num < 0 ? "-" : "";
|
|
9069
|
+
const abs = Math.abs(num);
|
|
9070
|
+
if (abs < 1) return `${sign}${abs.toFixed(digits).replace(rx, "$1")}`;
|
|
9006
9071
|
const item = [
|
|
9007
9072
|
{
|
|
9008
9073
|
value: 1,
|
|
@@ -9032,8 +9097,8 @@ function nFormatter(num, opts = { digits: 1 }, locale = "en-US") {
|
|
|
9032
9097
|
value: 0xde0b6b3a7640000,
|
|
9033
9098
|
symbol: "E"
|
|
9034
9099
|
}
|
|
9035
|
-
].slice().reverse().find((item) =>
|
|
9036
|
-
return item ? (
|
|
9100
|
+
].slice().reverse().find((item) => abs >= item.value);
|
|
9101
|
+
return item ? `${sign}${(abs / item.value).toFixed(digits).replace(rx, "$1")}${item.symbol}` : "0";
|
|
9037
9102
|
}
|
|
9038
9103
|
//#endregion
|
|
9039
9104
|
//#region src/functions/string/normalize-string.ts
|
|
@@ -9076,14 +9141,11 @@ function nFormatter(num, opts = { digits: 1 }, locale = "en-US") {
|
|
|
9076
9141
|
const normalizeString = (key) => {
|
|
9077
9142
|
if (!key) return "";
|
|
9078
9143
|
const original = key;
|
|
9079
|
-
const normalized = key.replace(/^\uFEFF/, "").replace(/^\uFFFE/, "").replace(
|
|
9144
|
+
const normalized = key.replace(/^\uFEFF/, "").replace(/^\uFFFE/, "").replace(/^[\u00EF\u00BB\u00BF]+/, "").replace(/^[\u0000\uFEFF]{2}/, "").replace(/^[\uFFFE\u0000]{2}/, "").replace(/^\u2028/, "").replace(/^\u2029/, "").replace(/./g, (char) => {
|
|
9080
9145
|
const code = char.charCodeAt(0);
|
|
9081
9146
|
return code <= 31 || code >= 127 && code <= 159 ? "" : char;
|
|
9082
9147
|
}).replace(/\s+/g, " ").trim().toLowerCase();
|
|
9083
|
-
if (isDevelopment && original !== normalized) {
|
|
9084
|
-
logger.log(`Normalized key: "${original}" -> "${normalized}"`);
|
|
9085
|
-
logger.log("Original char codes:", Array.from(original).map((c) => c.charCodeAt(0)));
|
|
9086
|
-
}
|
|
9148
|
+
if (isDevelopment && typeof process !== "undefined" && process.env?.KUMIX_DEBUG_NORMALIZE && original !== normalized) logger.log(`normalizeString: input changed (length ${original.length} -> ${normalized.length})`);
|
|
9087
9149
|
return normalized;
|
|
9088
9150
|
};
|
|
9089
9151
|
//#endregion
|
|
@@ -9212,8 +9274,11 @@ function regexEscape(str) {
|
|
|
9212
9274
|
* ```
|
|
9213
9275
|
*/
|
|
9214
9276
|
const truncate = (str, length) => {
|
|
9215
|
-
if (!str
|
|
9216
|
-
|
|
9277
|
+
if (!str) return null;
|
|
9278
|
+
if (str.length <= length) return str;
|
|
9279
|
+
const ELLIPSIS = "...";
|
|
9280
|
+
if (length <= 3) return str.slice(0, length);
|
|
9281
|
+
return `${str.slice(0, length - 3)}${ELLIPSIS}`;
|
|
9217
9282
|
};
|
|
9218
9283
|
//#endregion
|
|
9219
9284
|
//#region src/functions/string/smart-truncate.ts
|
|
@@ -9270,9 +9335,16 @@ const truncateDomain = (domain, maxLength) => {
|
|
|
9270
9335
|
* ```
|
|
9271
9336
|
*/
|
|
9272
9337
|
const smartTruncate = (link, maxLength) => {
|
|
9338
|
+
if (!link) return "";
|
|
9339
|
+
if (maxLength <= 0) return "";
|
|
9273
9340
|
if (link.length <= maxLength) return link;
|
|
9274
9341
|
const [domain, ...pathParts] = link.split("/");
|
|
9275
|
-
const
|
|
9342
|
+
const path = pathParts.join("/");
|
|
9343
|
+
const minDomainLength = 8;
|
|
9344
|
+
if (maxLength < minDomainLength) return link.slice(0, maxLength);
|
|
9345
|
+
const maxPathLength = maxLength - minDomainLength;
|
|
9346
|
+
const truncatedPath = path ? truncate(path, maxPathLength) : null;
|
|
9347
|
+
if (!truncatedPath) return truncateDomain(domain, maxLength);
|
|
9276
9348
|
return `${truncateDomain(domain, maxLength - truncatedPath.length)}/${truncatedPath}`;
|
|
9277
9349
|
};
|
|
9278
9350
|
//#endregion
|
|
@@ -9319,10 +9391,17 @@ const trim = (u) => typeof u === "string" ? u.trim() : u;
|
|
|
9319
9391
|
* Provides functions for validating URL strings and checking URL validity
|
|
9320
9392
|
*/
|
|
9321
9393
|
/**
|
|
9322
|
-
* Checks if a string is a valid URL
|
|
9323
|
-
*
|
|
9394
|
+
* Checks if a string is a valid URL.
|
|
9395
|
+
*
|
|
9396
|
+
* By default rejects non-fetchable schemes (`javascript:`, `data:`, `file:`,
|
|
9397
|
+
* `vbscript:`) to avoid XSS via redirect/href validation. Set `allowAnyScheme`
|
|
9398
|
+
* to accept any scheme the URL parser accepts.
|
|
9399
|
+
*
|
|
9400
|
+
* Uses the URL constructor for validation.
|
|
9324
9401
|
*
|
|
9325
9402
|
* @param url - The string to check
|
|
9403
|
+
* @param options - Validation options
|
|
9404
|
+
* @param options.allowAnyScheme - When true, accept any scheme (defaults to false)
|
|
9326
9405
|
* @returns True if the string is a valid URL, false otherwise
|
|
9327
9406
|
*
|
|
9328
9407
|
* @example
|
|
@@ -9334,11 +9413,9 @@ const trim = (u) => typeof u === "string" ? u.trim() : u;
|
|
|
9334
9413
|
* isValidUrl('http://localhost:3000'); // true
|
|
9335
9414
|
* isValidUrl('ftp://files.example.com'); // true
|
|
9336
9415
|
*
|
|
9337
|
-
* // Invalid URLs
|
|
9416
|
+
* // Invalid / unsafe URLs (rejected by default)
|
|
9417
|
+
* isValidUrl('javascript:alert(1)'); // false
|
|
9338
9418
|
* isValidUrl('example.com'); // false (missing protocol)
|
|
9339
|
-
* isValidUrl('not a url'); // false
|
|
9340
|
-
* isValidUrl(''); // false
|
|
9341
|
-
* isValidUrl('https://'); // false (incomplete)
|
|
9342
9419
|
*
|
|
9343
9420
|
* // Use in form validation
|
|
9344
9421
|
* function validateUrlInput(input: string) {
|
|
@@ -9347,14 +9424,21 @@ const trim = (u) => typeof u === "string" ? u.trim() : u;
|
|
|
9347
9424
|
* }
|
|
9348
9425
|
* return null;
|
|
9349
9426
|
* }
|
|
9350
|
-
*
|
|
9351
|
-
* // Use in data processing
|
|
9352
|
-
* const validUrls = urls.filter(isValidUrl);
|
|
9353
9427
|
* ```
|
|
9354
9428
|
*/
|
|
9355
|
-
const isValidUrl = (url) => {
|
|
9429
|
+
const isValidUrl = (url, options = {}) => {
|
|
9430
|
+
if (!url || typeof url !== "string") return false;
|
|
9356
9431
|
try {
|
|
9357
|
-
new URL(url);
|
|
9432
|
+
const parsed = new URL(url);
|
|
9433
|
+
if (options.allowAnyScheme) return true;
|
|
9434
|
+
const blocked = [
|
|
9435
|
+
"javascript:",
|
|
9436
|
+
"data:",
|
|
9437
|
+
"vbscript:",
|
|
9438
|
+
"file:"
|
|
9439
|
+
];
|
|
9440
|
+
const scheme = parsed.protocol.toLowerCase();
|
|
9441
|
+
if (blocked.some((b) => scheme === b)) return false;
|
|
9358
9442
|
return true;
|
|
9359
9443
|
} catch (_) {
|
|
9360
9444
|
return false;
|
|
@@ -9386,9 +9470,11 @@ const isValidUrl = (url) => {
|
|
|
9386
9470
|
* generateDomainFromName('My Cool Project', 'com')
|
|
9387
9471
|
* // Returns "mycoolproject.com"
|
|
9388
9472
|
*
|
|
9389
|
-
* //
|
|
9473
|
+
* // ccTLD fallback only applies when the trailing 2 chars form a known ccTLD;
|
|
9474
|
+
* // for "Canada" the trailing 2 chars are "da" (not a ccTLD), so the default
|
|
9475
|
+
* // extension is used.
|
|
9390
9476
|
* generateDomainFromName('Canada')
|
|
9391
|
-
* // Returns "
|
|
9477
|
+
* // Returns "canada.link"
|
|
9392
9478
|
*
|
|
9393
9479
|
* // With vowels removed if needed
|
|
9394
9480
|
* generateDomainFromName('Digital', 'io')
|
|
@@ -9676,9 +9762,11 @@ function linkConstructorSimple({ domain, key }) {
|
|
|
9676
9762
|
*/
|
|
9677
9763
|
const getSearchParams = (url) => {
|
|
9678
9764
|
const params = {};
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9765
|
+
try {
|
|
9766
|
+
new URL(url).searchParams.forEach((val, key) => {
|
|
9767
|
+
params[key] = val;
|
|
9768
|
+
});
|
|
9769
|
+
} catch {}
|
|
9682
9770
|
return params;
|
|
9683
9771
|
};
|
|
9684
9772
|
/**
|
|
@@ -9720,13 +9808,15 @@ const getSearchParams = (url) => {
|
|
|
9720
9808
|
*/
|
|
9721
9809
|
const getSearchParamsWithArray = (url) => {
|
|
9722
9810
|
const params = {};
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
|
|
9811
|
+
try {
|
|
9812
|
+
new URL(url).searchParams.forEach((val, key) => {
|
|
9813
|
+
if (key in params) {
|
|
9814
|
+
const param = params[key];
|
|
9815
|
+
if (Array.isArray(param)) param.push(val);
|
|
9816
|
+
else params[key] = [param, val];
|
|
9817
|
+
} else params[key] = val;
|
|
9818
|
+
});
|
|
9819
|
+
} catch {}
|
|
9730
9820
|
return params;
|
|
9731
9821
|
};
|
|
9732
9822
|
/**
|
|
@@ -9964,7 +10054,7 @@ const getUrlFromStringIfValid = (str) => {
|
|
|
9964
10054
|
*/
|
|
9965
10055
|
const getPrettyUrl = (url) => {
|
|
9966
10056
|
if (!url) return "";
|
|
9967
|
-
return url.replace(/(^\w+:|^)\/\//, "").replace(
|
|
10057
|
+
return url.replace(/(^\w+:|^)\/\//, "").replace(/^www\./, "").replace(/\/$/, "");
|
|
9968
10058
|
};
|
|
9969
10059
|
/**
|
|
9970
10060
|
* Generates a URL-friendly slug from a given title
|
|
@@ -10166,7 +10256,7 @@ const constructURLFromUTMParams = (url, utmParams) => {
|
|
|
10166
10256
|
try {
|
|
10167
10257
|
const newURL = new URL(url);
|
|
10168
10258
|
for (const [key, value] of Object.entries(utmParams)) if (value === "") newURL.searchParams.delete(key);
|
|
10169
|
-
else newURL.searchParams.set(key, value.replace(
|
|
10259
|
+
else newURL.searchParams.set(key, value.replace(/\+/g, " "));
|
|
10170
10260
|
return newURL.toString();
|
|
10171
10261
|
} catch (_) {
|
|
10172
10262
|
return "";
|
|
@@ -10211,9 +10301,7 @@ const constructURLFromUTMParams = (url, utmParams) => {
|
|
|
10211
10301
|
const getUrlWithoutUTMParams = (url) => {
|
|
10212
10302
|
try {
|
|
10213
10303
|
const newURL = new URL(url);
|
|
10214
|
-
|
|
10215
|
-
newURL.searchParams.delete(param.key);
|
|
10216
|
-
});
|
|
10304
|
+
for (const key of UTMTags) newURL.searchParams.delete(key);
|
|
10217
10305
|
return newURL.toString();
|
|
10218
10306
|
} catch (_) {
|
|
10219
10307
|
return url;
|
|
@@ -10321,6 +10409,34 @@ const createHref = (href, domain, utmParams) => {
|
|
|
10321
10409
|
const deepEqual = (obj1, obj2) => {
|
|
10322
10410
|
if (obj1 === obj2) return true;
|
|
10323
10411
|
if (typeof obj1 !== "object" || typeof obj2 !== "object" || obj1 === null || obj2 === null) return false;
|
|
10412
|
+
if (Object.prototype.toString.call(obj1) !== Object.prototype.toString.call(obj2)) return false;
|
|
10413
|
+
if (obj1 instanceof Date && obj2 instanceof Date) return obj1.getTime() === obj2.getTime();
|
|
10414
|
+
if (obj1 instanceof RegExp && obj2 instanceof RegExp) return obj1.source === obj2.source && obj1.flags === obj2.flags;
|
|
10415
|
+
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
|
10416
|
+
if (obj1.length !== obj2.length) return false;
|
|
10417
|
+
for (let i = 0; i < obj1.length; i++) if (!deepEqual(obj1[i], obj2[i])) return false;
|
|
10418
|
+
return true;
|
|
10419
|
+
}
|
|
10420
|
+
if (obj1 instanceof Map && obj2 instanceof Map) {
|
|
10421
|
+
if (obj1.size !== obj2.size) return false;
|
|
10422
|
+
for (const [key, value] of obj1) {
|
|
10423
|
+
if (!obj2.has(key)) return false;
|
|
10424
|
+
if (!deepEqual(value, obj2.get(key))) return false;
|
|
10425
|
+
}
|
|
10426
|
+
return true;
|
|
10427
|
+
}
|
|
10428
|
+
if (obj1 instanceof Set && obj2 instanceof Set) {
|
|
10429
|
+
if (obj1.size !== obj2.size) return false;
|
|
10430
|
+
for (const value of obj1) {
|
|
10431
|
+
let found = false;
|
|
10432
|
+
for (const other of obj2) if (deepEqual(value, other)) {
|
|
10433
|
+
found = true;
|
|
10434
|
+
break;
|
|
10435
|
+
}
|
|
10436
|
+
if (!found) return false;
|
|
10437
|
+
}
|
|
10438
|
+
return true;
|
|
10439
|
+
}
|
|
10324
10440
|
const keys1 = Object.keys(obj1);
|
|
10325
10441
|
const keys2 = Object.keys(obj2);
|
|
10326
10442
|
if (keys1.length !== keys2.length) return false;
|
|
@@ -10617,64 +10733,64 @@ function getEmailDomain(email) {
|
|
|
10617
10733
|
* Checks if a URL can be embedded in an iframe based on security headers
|
|
10618
10734
|
*/
|
|
10619
10735
|
/**
|
|
10620
|
-
* Determines if a URL can be displayed in an iframe by checking security headers
|
|
10621
|
-
* Examines Content-Security-Policy and X-Frame-Options headers
|
|
10736
|
+
* Determines if a URL can be displayed in an iframe by checking security headers.
|
|
10737
|
+
* Examines Content-Security-Policy `frame-ancestors` and `X-Frame-Options` headers.
|
|
10738
|
+
*
|
|
10739
|
+
* A URL is considered embeddable only when:
|
|
10740
|
+
* - `frame-ancestors` is absent OR explicitly allows `*` / `self` (same origin) /
|
|
10741
|
+
* a wildcard/origin that matches `requestDomain`, AND
|
|
10742
|
+
* - `X-Frame-Options` is not `DENY` or `SAMEORIGIN` (when origin differs).
|
|
10622
10743
|
*
|
|
10623
10744
|
* @param options - The options for the check
|
|
10624
10745
|
* @param options.url - The URL to check for iframe embedding capability
|
|
10625
|
-
* @param options.requestDomain - The
|
|
10626
|
-
*
|
|
10746
|
+
* @param options.requestDomain - The origin that will be embedding the iframe
|
|
10747
|
+
* (e.g. `https://myapp.com`). Compared against CSP source expressions.
|
|
10748
|
+
* @returns A Promise that resolves to true if the URL can be embedded, false otherwise.
|
|
10627
10749
|
*
|
|
10628
10750
|
* @example
|
|
10629
10751
|
* ```ts
|
|
10630
10752
|
* import { isIframeable } from '@/utils/functions';
|
|
10631
10753
|
*
|
|
10632
|
-
* // Check if a URL can be embedded in an iframe
|
|
10633
10754
|
* const canEmbed = await isIframeable({
|
|
10634
10755
|
* url: 'https://example.com',
|
|
10635
10756
|
* requestDomain: 'https://myapp.com'
|
|
10636
10757
|
* });
|
|
10637
|
-
*
|
|
10638
|
-
* if (canEmbed) {
|
|
10639
|
-
* console.log('URL can be embedded in an iframe');
|
|
10640
|
-
* } else {
|
|
10641
|
-
* console.log('URL cannot be embedded due to security restrictions');
|
|
10642
|
-
* }
|
|
10643
|
-
*
|
|
10644
|
-
* // In a React component
|
|
10645
|
-
* function EmbedPreview({ url }) {
|
|
10646
|
-
* const [canEmbed, setCanEmbed] = useState<boolean | null>(null);
|
|
10647
|
-
*
|
|
10648
|
-
* useEffect(() => {
|
|
10649
|
-
* async function checkEmbedding() {
|
|
10650
|
-
* const result = await isIframeable({
|
|
10651
|
-
* url,
|
|
10652
|
-
* requestDomain: window.location.origin
|
|
10653
|
-
* });
|
|
10654
|
-
* setCanEmbed(result);
|
|
10655
|
-
* }
|
|
10656
|
-
* checkEmbedding();
|
|
10657
|
-
* }, [url]);
|
|
10658
|
-
*
|
|
10659
|
-
* if (canEmbed === null) return <div>Checking...</div>;
|
|
10660
|
-
* if (canEmbed === false) return <div>Cannot embed this URL</div>;
|
|
10661
|
-
*
|
|
10662
|
-
* return <iframe src={url} />;
|
|
10663
|
-
* }
|
|
10664
10758
|
* ```
|
|
10665
10759
|
*/
|
|
10666
10760
|
const isIframeable = async ({ url, requestDomain }) => {
|
|
10667
10761
|
const res = await fetch(url);
|
|
10762
|
+
const normalizeOrigin = (value) => value.trim().replace(/\/$/, "").toLowerCase();
|
|
10763
|
+
const requestedOrigin = normalizeOrigin(requestDomain);
|
|
10668
10764
|
const cspHeader = res.headers.get("content-security-policy");
|
|
10669
10765
|
if (cspHeader) {
|
|
10670
10766
|
const frameAncestorsMatch = cspHeader.match(/frame-ancestors\s+([\s\S]+?)(?=;|$)/i);
|
|
10671
|
-
if (frameAncestorsMatch) {
|
|
10672
|
-
|
|
10673
|
-
if (
|
|
10674
|
-
|
|
10767
|
+
if (frameAncestorsMatch) return frameAncestorsMatch[1].trim().split(/\s+/).filter(Boolean).some((source) => {
|
|
10768
|
+
const s = source.toLowerCase();
|
|
10769
|
+
if (s === "'none'") return false;
|
|
10770
|
+
if (s === "*" || s === "https:*" || s === "http:*") return true;
|
|
10771
|
+
if (s === "'self'") try {
|
|
10772
|
+
return normalizeOrigin(new URL(res.url).origin) === requestedOrigin;
|
|
10773
|
+
} catch {
|
|
10774
|
+
return false;
|
|
10775
|
+
}
|
|
10776
|
+
if (s.includes("*")) {
|
|
10777
|
+
const pattern = s.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
10778
|
+
return new RegExp(`^${pattern}$`).test(requestedOrigin);
|
|
10779
|
+
}
|
|
10780
|
+
return normalizeOrigin(s) === requestedOrigin;
|
|
10781
|
+
});
|
|
10675
10782
|
}
|
|
10676
10783
|
const xFrameOptions = res.headers.get("X-Frame-Options");
|
|
10677
|
-
if (xFrameOptions
|
|
10784
|
+
if (xFrameOptions) {
|
|
10785
|
+
const value = xFrameOptions.trim().toUpperCase();
|
|
10786
|
+
if (value === "DENY") return false;
|
|
10787
|
+
if (value === "SAMEORIGIN") try {
|
|
10788
|
+
return normalizeOrigin(new URL(res.url).origin) === requestedOrigin;
|
|
10789
|
+
} catch {
|
|
10790
|
+
return false;
|
|
10791
|
+
}
|
|
10792
|
+
if (value.startsWith("ALLOW-FROM")) return false;
|
|
10793
|
+
}
|
|
10678
10794
|
return true;
|
|
10679
10795
|
};
|
|
10680
10796
|
//#endregion
|
|
@@ -10758,6 +10874,6 @@ const isReservedKeyGlobal = (key) => {
|
|
|
10758
10874
|
].includes(key);
|
|
10759
10875
|
};
|
|
10760
10876
|
//#endregion
|
|
10761
|
-
export { API_PORT, CONNECT_SUPPORTED_COUNTRIES, CONTINENTS, CONTINENT_CODES, COUNTRIES, COUNTRY_CODES, COUNTRY_PHONE_CODES, DEBUG, DEFAULT_THEME_MODE, EU_COUNTRY_CODES, FRAMER_MOTION_LIST_ITEM_VARIANTS, INFINITY_NUMBER, LAST_VISITED_WORKSPACE, LOCALHOST_GEO_DATA, LOCALHOST_IP, LOG_LEVEL, META_THEME_COLORS, NEXT_PUBLIC_RECAPTCHA_SITE_KEY, NODE_ENV, OG_AVATAR_URL, PAGINATION_LIMIT, PORT, REDIRECT_QUERY_PARAM, REGIONS, REGION_CODES, RESERVED_SLUGS, SECOND_LEVEL_DOMAINS, SLACK_WEBHOOKS, SPECIAL_APEX_DOMAINS, STAGGER_CHILD_VARIANTS, SlackLog, TAB_ITEM_ANIMATION_SETTINGS, THEME_MODES, THE_BEGINNING_OF_TIME, TWO_WEEKS_IN_SECONDS, UTMTags, assetsUrl, baseId, baseIdCustom, capitalize, ccTLDs, chunk, clearAllCookies, clearStorage, cn, combineWords, constructMetadata, constructURLFromUTMParams, createHref, createId, cuid, currencyFormatter, customeId, debounce, deepEqual, fetchWithRetry, fetchWithTimeout, fetcher, fetcherSWR, fileToBase64, formatDate, formatDateTime, formatDateTimeSmart, formatFileSize, formatPeriod, formatTime, generateDomainFromName, getAdjustedBillingCycleStart, getAllCookies, getApexDomain, getBillingStartDate, getClientIP, getClientIPFromHeaders, getCookie, getCurrentYear, getDateTimeLocal, getDaysDifference, getDomainWithoutWWW, getEmailDomain, getEnv, getFirstAndLastDay, getFlagUrl, getHeight, getIPAddress, getInitials, getLastDayOfMonth, getParamsFromURL, getPrettyUrl, getRequestOrigin, getSearchParams, getSearchParamsWithArray, getSizeAvatar, getSlug, getStorageItem, getSubdomain, getTimeZones, getUrlFromString, getUrlFromStringIfValid, getUrlObjFromString, getUrlWithoutUTMParams, getUserAgent, getUserAgentFromHeaders, getUserName, googleTrackCodeCopy, googleTrackDirectionChange, googleTrackEvent, googleTrackItemCreate, googleTrackItemDelete, googleTrackItemRestore, googleTrackItemUpdate, googleTrackItemView, googleTrackThemeChange, googleTrackViewChange, hasCookie, hasStorageItem, hashStringSHA256, init as initCuid, isBusinessEmail, isDevelopment, isDisposableEmail, isIframeable, isProduction, isReservedKeyGlobal, isStaging, isUnsupportedKey, isValidIP, isValidUrl, linkConstructor, linkConstructorSimple, loadImage, logger, mapLocale, nFormatter, nanoid, normalizeEmail, normalizePath, normalizeString, paramsMetadata, parse, pluralize, randomValue, regexEscape, removeCookie, removeStorageItem, resizeAndCropImage, resizeImage, setCookie, setStorageItem, slugify, smartTruncate, stableSort, throttle, timeAgo, toCamelCase, trim, truncate, uid, validDomainRegex, validKeyRegex, validSlugRegex, validateEmail, verifyRecaptchaToken };
|
|
10877
|
+
export { API_PORT, CONNECT_SUPPORTED_COUNTRIES, CONTINENTS, CONTINENT_CODES, COUNTRIES, COUNTRY_CODES, COUNTRY_PHONE_CODES, DEBUG, DEFAULT_THEME_MODE, EU_COUNTRY_CODES, FRAMER_MOTION_LIST_ITEM_VARIANTS, INFINITY_NUMBER, LAST_VISITED_WORKSPACE, LOCALHOST_GEO_DATA, LOCALHOST_IP, LOG_LEVEL, META_THEME_COLORS, NEXT_PUBLIC_RECAPTCHA_SITE_KEY, NODE_ENV, OG_AVATAR_URL, PAGINATION_LIMIT, PORT, RECAPTCHA_SECRET_KEY, REDIRECT_QUERY_PARAM, REGIONS, REGION_CODES, RESERVED_SLUGS, SECOND_LEVEL_DOMAINS, SLACK_WEBHOOKS, SPECIAL_APEX_DOMAINS, STAGGER_CHILD_VARIANTS, SlackLog, TAB_ITEM_ANIMATION_SETTINGS, THEME_MODES, THE_BEGINNING_OF_TIME, TWO_WEEKS_IN_SECONDS, UTMTags, assetsUrl, baseId, baseIdCustom, capitalize, ccTLDs, chunk, clearAllCookies, clearStorage, cn, combineWords, constructMetadata, constructURLFromUTMParams, createHref, createId, cuid, currencyFormatter, customId, customeId, debounce, deepEqual, fetchWithRetry, fetchWithTimeout, fetcher, fetcherSWR, fileToBase64, formatDate, formatDateTime, formatDateTimeSmart, formatFileSize, formatPeriod, formatTime, generateDomainFromName, getAdjustedBillingCycleStart, getAllCookies, getApexDomain, getBillingStartDate, getClientIP, getClientIPFromHeaders, getCookie, getCurrentYear, getDateTimeLocal, getDaysDifference, getDomainWithoutWWW, getEmailDomain, getEnv, getFirstAndLastDay, getFlagUrl, getHeight, getIPAddress, getInitials, getLastDayOfMonth, getParamsFromURL, getPrettyUrl, getRequestOrigin, getSearchParams, getSearchParamsWithArray, getSizeAvatar, getSlug, getStorageItem, getSubdomain, getTimeZones, getUrlFromString, getUrlFromStringIfValid, getUrlObjFromString, getUrlWithoutUTMParams, getUserAgent, getUserAgentFromHeaders, getUserName, googleTrackCodeCopy, googleTrackDirectionChange, googleTrackEvent, googleTrackItemCreate, googleTrackItemDelete, googleTrackItemRestore, googleTrackItemUpdate, googleTrackItemView, googleTrackThemeChange, googleTrackViewChange, hasCookie, hasStorageItem, hashStringSHA256, init as initCuid, isBusinessEmail, isDevelopment, isDisposableEmail, isIframeable, isProduction, isReservedKeyGlobal, isStaging, isTest, isUnsupportedKey, isValidIP, isValidUrl, linkConstructor, linkConstructorSimple, loadImage, logger, mapLocale, nFormatter, nanoid, normalizeEmail, normalizePath, normalizeString, paramsMetadata, parse, pluralize, randomValue, regexEscape, removeCookie, removeStorageItem, resizeAndCropImage, resizeImage, setCookie, setStorageItem, slugify, smartTruncate, stableSort, throttle, timeAgo, toCamelCase, trim, truncate, uid, validDomainRegex, validKeyRegex, validSlugRegex, validateEmail, verifyRecaptchaToken };
|
|
10762
10878
|
|
|
10763
10879
|
//# sourceMappingURL=index.js.map
|