@xeno-js/core 0.1.1 → 0.1.3
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/README.md +2 -2
- package/dist/index.cjs +671 -306
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +153 -4
- package/dist/index.d.ts +153 -4
- package/dist/index.js +521 -156
- package/dist/index.js.map +1 -1
- package/package.json +160 -160
package/dist/index.js
CHANGED
|
@@ -1365,8 +1365,7 @@ var init_sentry_logger_factory = __esm({
|
|
|
1365
1365
|
dsn: sentryConfig.dsn,
|
|
1366
1366
|
environment: env,
|
|
1367
1367
|
tracesSampleRate: env === "production" ? 0.1 : 1,
|
|
1368
|
-
|
|
1369
|
-
integrations: [new Sentry.Integrations.Http({ tracing: true })],
|
|
1368
|
+
integrations: [Sentry.httpIntegration()],
|
|
1370
1369
|
beforeSend(event, hint) {
|
|
1371
1370
|
const error = hint.originalException;
|
|
1372
1371
|
if (error instanceof Error && error.name === "ZodError") {
|
|
@@ -1509,15 +1508,15 @@ var init_logger_utils = __esm({
|
|
|
1509
1508
|
*/
|
|
1510
1509
|
async addLogger(container, opts) {
|
|
1511
1510
|
const loggerDependencies = [];
|
|
1512
|
-
const { Guards:
|
|
1513
|
-
if (!
|
|
1511
|
+
const { Guards: Guards45, LOG_LEVEL: LOG_LEVEL7, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
|
|
1512
|
+
if (!Guards45.isDefined(opts) || opts.console) {
|
|
1514
1513
|
const { ConsoleLogger: ConsoleLogger2 } = await Promise.resolve().then(() => (init_console_logger(), console_logger_exports));
|
|
1515
1514
|
container.addSingleton(TOKENS4.CONSOLE_LOGGER, () => new ConsoleLogger2(opts?.level));
|
|
1516
1515
|
loggerDependencies.push(TOKENS4.CONSOLE_LOGGER);
|
|
1517
1516
|
}
|
|
1518
1517
|
const customLoggerFactories = [];
|
|
1519
|
-
if (
|
|
1520
|
-
if (
|
|
1518
|
+
if (Guards45.isDefined(opts)) {
|
|
1519
|
+
if (Guards45.isDefined(opts.sentry.config)) {
|
|
1521
1520
|
const { SentryLoggerFactory: SentryLoggerFactory2 } = await Promise.resolve().then(() => (init_sentry_logger_factory(), sentry_logger_factory_exports));
|
|
1522
1521
|
container.addSingleton(TOKENS4.SENTRY_LOGGER, () => {
|
|
1523
1522
|
const factory = new SentryLoggerFactory2();
|
|
@@ -1525,7 +1524,7 @@ var init_logger_utils = __esm({
|
|
|
1525
1524
|
});
|
|
1526
1525
|
loggerDependencies.push(TOKENS4.SENTRY_LOGGER);
|
|
1527
1526
|
}
|
|
1528
|
-
if (
|
|
1527
|
+
if (Guards45.isDefined(opts.pino.config)) {
|
|
1529
1528
|
const { PinoLoggerFactory: PinoLoggerFactory2 } = await Promise.resolve().then(() => (init_pino_logger_factory(), pino_logger_factory_exports));
|
|
1530
1529
|
container.addSingleton(TOKENS4.PINO_LOGGER, () => {
|
|
1531
1530
|
const factory = new PinoLoggerFactory2();
|
|
@@ -1533,10 +1532,10 @@ var init_logger_utils = __esm({
|
|
|
1533
1532
|
});
|
|
1534
1533
|
loggerDependencies.push(TOKENS4.PINO_LOGGER);
|
|
1535
1534
|
}
|
|
1536
|
-
if (!
|
|
1535
|
+
if (!Guards45.isNullOrEmpty(opts.customLoggers)) {
|
|
1537
1536
|
const customLoggers = opts.customLoggers;
|
|
1538
1537
|
customLoggers.forEach((f) => {
|
|
1539
|
-
if (
|
|
1538
|
+
if (Guards45.isDefined(f)) {
|
|
1540
1539
|
customLoggerFactories.push(f);
|
|
1541
1540
|
}
|
|
1542
1541
|
});
|
|
@@ -1556,8 +1555,30 @@ var init_logger_utils = __esm({
|
|
|
1556
1555
|
}
|
|
1557
1556
|
});
|
|
1558
1557
|
|
|
1558
|
+
// src/infrastructure/cache/inmemory.cache.ts
|
|
1559
|
+
var inmemory_cache_exports = {};
|
|
1560
|
+
__export(inmemory_cache_exports, {
|
|
1561
|
+
InMemoryCacheExtended: () => InMemoryCacheExtended
|
|
1562
|
+
});
|
|
1563
|
+
import { Guards as Guards19, InMemoryCache } from "@xeno-js/shared";
|
|
1564
|
+
var InMemoryCacheExtended;
|
|
1565
|
+
var init_inmemory_cache = __esm({
|
|
1566
|
+
"src/infrastructure/cache/inmemory.cache.ts"() {
|
|
1567
|
+
"use strict";
|
|
1568
|
+
InMemoryCacheExtended = class extends InMemoryCache {
|
|
1569
|
+
async increment(key, ttlSeconds) {
|
|
1570
|
+
const current = await this.get(key) ?? 0;
|
|
1571
|
+
const next = Number(current) + 1;
|
|
1572
|
+
const ttl = Guards19.isDefined(ttlSeconds) ? Number(ttlSeconds) : 60;
|
|
1573
|
+
await this.set(key, next, ttl);
|
|
1574
|
+
return next;
|
|
1575
|
+
}
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1578
|
+
});
|
|
1579
|
+
|
|
1559
1580
|
// src/infrastructure/cache/redis.cache.ts
|
|
1560
|
-
import { Guards as
|
|
1581
|
+
import { Guards as Guards20, StringHelper } from "@xeno-js/shared";
|
|
1561
1582
|
var RedisCache;
|
|
1562
1583
|
var init_redis_cache = __esm({
|
|
1563
1584
|
"src/infrastructure/cache/redis.cache.ts"() {
|
|
@@ -1577,21 +1598,28 @@ var init_redis_cache = __esm({
|
|
|
1577
1598
|
this._redisClient = _redisClient;
|
|
1578
1599
|
}
|
|
1579
1600
|
_redisClient;
|
|
1601
|
+
async increment(key, ttlSeconds) {
|
|
1602
|
+
const multi = this._redisClient.multi();
|
|
1603
|
+
multi.incr(key);
|
|
1604
|
+
multi.expire(key, ttlSeconds ?? 60);
|
|
1605
|
+
const results = await multi.exec();
|
|
1606
|
+
return results?.[0]?.[1] ?? 1;
|
|
1607
|
+
}
|
|
1580
1608
|
async get(key) {
|
|
1581
1609
|
const value = await this._redisClient.get(key);
|
|
1582
|
-
if (!
|
|
1610
|
+
if (!Guards20.isDefined(value)) {
|
|
1583
1611
|
return void 0;
|
|
1584
1612
|
}
|
|
1585
1613
|
return JSON.parse(value);
|
|
1586
1614
|
}
|
|
1587
1615
|
async set(key, value, ttl) {
|
|
1588
1616
|
const stringValue = StringHelper.safeStringify(value);
|
|
1589
|
-
const ttlOption =
|
|
1617
|
+
const ttlOption = Guards20.isDefined(ttl) ? ttl : 86400;
|
|
1590
1618
|
await this._redisClient.set(key, stringValue, "EX", ttlOption);
|
|
1591
1619
|
}
|
|
1592
1620
|
async setIfAbsent(key, value, ttl) {
|
|
1593
1621
|
const stringValue = StringHelper.safeStringify(value);
|
|
1594
|
-
const ttlOption =
|
|
1622
|
+
const ttlOption = Guards20.isDefined(ttl) ? ttl : 300;
|
|
1595
1623
|
const result = await this._redisClient.set(key, stringValue, "EX", ttlOption, "NX");
|
|
1596
1624
|
return result === "OK";
|
|
1597
1625
|
}
|
|
@@ -1614,7 +1642,7 @@ var redis_cache_factory_exports = {};
|
|
|
1614
1642
|
__export(redis_cache_factory_exports, {
|
|
1615
1643
|
RedisCacheFactory: () => RedisCacheFactory
|
|
1616
1644
|
});
|
|
1617
|
-
import { Guards as
|
|
1645
|
+
import { Guards as Guards21 } from "@xeno-js/shared";
|
|
1618
1646
|
import { Redis } from "ioredis";
|
|
1619
1647
|
var RedisCacheFactory;
|
|
1620
1648
|
var init_redis_cache_factory = __esm({
|
|
@@ -1639,10 +1667,10 @@ var init_redis_cache_factory = __esm({
|
|
|
1639
1667
|
return delay;
|
|
1640
1668
|
}
|
|
1641
1669
|
};
|
|
1642
|
-
if (
|
|
1670
|
+
if (Guards21.isDefined(password)) {
|
|
1643
1671
|
redisOptions.password = password;
|
|
1644
1672
|
}
|
|
1645
|
-
if (
|
|
1673
|
+
if (Guards21.isDefined(username)) {
|
|
1646
1674
|
redisOptions.username = username;
|
|
1647
1675
|
}
|
|
1648
1676
|
if (useTls) {
|
|
@@ -1680,8 +1708,8 @@ var init_cache_utils = __esm({
|
|
|
1680
1708
|
* @link https://github.com/xeno-js/xeno-js
|
|
1681
1709
|
*/
|
|
1682
1710
|
async addCache(container, opts) {
|
|
1683
|
-
const { Guards:
|
|
1684
|
-
if (!opts.inMemory && !
|
|
1711
|
+
const { Guards: Guards45, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
|
|
1712
|
+
if (!opts.inMemory && !Guards45.isDefined(opts.redis)) {
|
|
1685
1713
|
throw new Error(
|
|
1686
1714
|
"No cache strategies are configured. Please provide at least one cache strategy."
|
|
1687
1715
|
);
|
|
@@ -1691,12 +1719,12 @@ var init_cache_utils = __esm({
|
|
|
1691
1719
|
TOKENS4.CACHE_KEY_BUILDER,
|
|
1692
1720
|
(c) => new CacheKeyBuilder(c.resolve(TOKENS4.IDENTITY_ACCESSOR))
|
|
1693
1721
|
);
|
|
1694
|
-
if (opts.inMemory || !
|
|
1695
|
-
const {
|
|
1696
|
-
container.addSingleton(TOKENS4.CACHE, () => new
|
|
1722
|
+
if (opts.inMemory || !Guards45.isDefined(opts.redis)) {
|
|
1723
|
+
const { InMemoryCacheExtended: InMemoryCacheExtended2 } = await Promise.resolve().then(() => (init_inmemory_cache(), inmemory_cache_exports));
|
|
1724
|
+
container.addSingleton(TOKENS4.CACHE, () => new InMemoryCacheExtended2());
|
|
1697
1725
|
return;
|
|
1698
1726
|
}
|
|
1699
|
-
if (
|
|
1727
|
+
if (Guards45.isDefined(opts.redis)) {
|
|
1700
1728
|
const { RedisCacheFactory: RedisCacheFactory2 } = await Promise.resolve().then(() => (init_redis_cache_factory(), redis_cache_factory_exports));
|
|
1701
1729
|
container.addSingleton(TOKENS4.CACHE, () => {
|
|
1702
1730
|
const config = opts.redis;
|
|
@@ -1709,7 +1737,7 @@ var init_cache_utils = __esm({
|
|
|
1709
1737
|
});
|
|
1710
1738
|
|
|
1711
1739
|
// src/infrastructure/services/allow_methods/allow-method.service.ts
|
|
1712
|
-
import { Guards as
|
|
1740
|
+
import { Guards as Guards22 } from "@xeno-js/shared";
|
|
1713
1741
|
var AllowMethodRegistry;
|
|
1714
1742
|
var init_allow_method_service = __esm({
|
|
1715
1743
|
"src/infrastructure/services/allow_methods/allow-method.service.ts"() {
|
|
@@ -1729,7 +1757,7 @@ var init_allow_method_service = __esm({
|
|
|
1729
1757
|
check(path, method) {
|
|
1730
1758
|
const cleanPath = this.normalizePath(path.split("?")[0].split("#")[0]);
|
|
1731
1759
|
const staticMethods = this._staticRoutes.get(cleanPath);
|
|
1732
|
-
if (
|
|
1760
|
+
if (Guards22.isDefined(staticMethods)) return staticMethods.includes(method);
|
|
1733
1761
|
for (const route of this._dynamicRoutes) {
|
|
1734
1762
|
if (route.pattern.test(cleanPath)) return route.methods.includes(method);
|
|
1735
1763
|
}
|
|
@@ -1766,7 +1794,7 @@ var init_allow_methods = __esm({
|
|
|
1766
1794
|
});
|
|
1767
1795
|
|
|
1768
1796
|
// src/infrastructure/services/allow_origins/allow-origin.http.ts
|
|
1769
|
-
import { Guards as
|
|
1797
|
+
import { Guards as Guards23 } from "@xeno-js/shared";
|
|
1770
1798
|
var AllowOrigin;
|
|
1771
1799
|
var init_allow_origin_http = __esm({
|
|
1772
1800
|
"src/infrastructure/services/allow_origins/allow-origin.http.ts"() {
|
|
@@ -1777,7 +1805,7 @@ var init_allow_origin_http = __esm({
|
|
|
1777
1805
|
}
|
|
1778
1806
|
_list;
|
|
1779
1807
|
isAllowed(origin) {
|
|
1780
|
-
if (
|
|
1808
|
+
if (Guards23.isNullOrEmpty(origin)) return true;
|
|
1781
1809
|
const cleanOrigin = origin.trim().toLowerCase();
|
|
1782
1810
|
for (const pattern of this._list) {
|
|
1783
1811
|
const cleanPattern = pattern.trim().toLowerCase();
|
|
@@ -1787,7 +1815,7 @@ var init_allow_origin_http = __esm({
|
|
|
1787
1815
|
const domainSuffix = cleanPattern.substring(1);
|
|
1788
1816
|
if (cleanOrigin.endsWith(domainSuffix)) {
|
|
1789
1817
|
const prefix = cleanOrigin.slice(0, cleanOrigin.length - domainSuffix.length);
|
|
1790
|
-
if (!
|
|
1818
|
+
if (!Guards23.isNullOrEmpty(prefix) && !prefix.includes(".")) return true;
|
|
1791
1819
|
}
|
|
1792
1820
|
}
|
|
1793
1821
|
}
|
|
@@ -1833,8 +1861,108 @@ var init_concurrency = __esm({
|
|
|
1833
1861
|
}
|
|
1834
1862
|
});
|
|
1835
1863
|
|
|
1864
|
+
// src/infrastructure/services/crypto/crypto.service.ts
|
|
1865
|
+
var EdgeCryptoService;
|
|
1866
|
+
var init_crypto_service = __esm({
|
|
1867
|
+
"src/infrastructure/services/crypto/crypto.service.ts"() {
|
|
1868
|
+
"use strict";
|
|
1869
|
+
EdgeCryptoService = class {
|
|
1870
|
+
randomBytes(size) {
|
|
1871
|
+
const buffer = new Uint8Array(size);
|
|
1872
|
+
crypto.getRandomValues(buffer);
|
|
1873
|
+
return buffer;
|
|
1874
|
+
}
|
|
1875
|
+
async hmacSha256(secret, data) {
|
|
1876
|
+
const encoder = new TextEncoder();
|
|
1877
|
+
const keyData = encoder.encode(secret);
|
|
1878
|
+
const messageData = encoder.encode(data);
|
|
1879
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
1880
|
+
"raw",
|
|
1881
|
+
keyData,
|
|
1882
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
1883
|
+
false,
|
|
1884
|
+
["sign"]
|
|
1885
|
+
);
|
|
1886
|
+
const signature = await crypto.subtle.sign("HMAC", cryptoKey, messageData);
|
|
1887
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
1888
|
+
}
|
|
1889
|
+
timingSafeEqual(a, b) {
|
|
1890
|
+
if (a.length !== b.length) {
|
|
1891
|
+
return false;
|
|
1892
|
+
}
|
|
1893
|
+
let mismatch = 0;
|
|
1894
|
+
for (let i = 0; i < a.length; i++) {
|
|
1895
|
+
mismatch |= a[i] ^ b[i];
|
|
1896
|
+
}
|
|
1897
|
+
return mismatch === 0;
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
});
|
|
1902
|
+
|
|
1903
|
+
// src/infrastructure/services/crypto/index.ts
|
|
1904
|
+
var init_crypto = __esm({
|
|
1905
|
+
"src/infrastructure/services/crypto/index.ts"() {
|
|
1906
|
+
"use strict";
|
|
1907
|
+
init_crypto_service();
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1911
|
+
// src/infrastructure/services/csrf/csrf-token.service.ts
|
|
1912
|
+
import { Guards as Guards24 } from "@xeno-js/shared";
|
|
1913
|
+
var CsrfTokenService;
|
|
1914
|
+
var init_csrf_token_service = __esm({
|
|
1915
|
+
"src/infrastructure/services/csrf/csrf-token.service.ts"() {
|
|
1916
|
+
"use strict";
|
|
1917
|
+
CsrfTokenService = class {
|
|
1918
|
+
constructor(_secret, _cryptoService) {
|
|
1919
|
+
this._secret = _secret;
|
|
1920
|
+
this._cryptoService = _cryptoService;
|
|
1921
|
+
}
|
|
1922
|
+
_secret;
|
|
1923
|
+
_cryptoService;
|
|
1924
|
+
async generate(subject) {
|
|
1925
|
+
const randomBuffer = this._cryptoService.randomBytes(32);
|
|
1926
|
+
const nonce = btoa(String.fromCharCode(...randomBuffer)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
1927
|
+
const signature = await this._cryptoService.hmacSha256(
|
|
1928
|
+
this._secret,
|
|
1929
|
+
`${subject}.${nonce}`
|
|
1930
|
+
);
|
|
1931
|
+
return `${nonce}.${signature}`;
|
|
1932
|
+
}
|
|
1933
|
+
async validate(token, subject) {
|
|
1934
|
+
const separatorIndex = token.indexOf(".");
|
|
1935
|
+
if (separatorIndex <= 0)
|
|
1936
|
+
return false;
|
|
1937
|
+
const nonce = token.slice(0, separatorIndex);
|
|
1938
|
+
const signature = token.slice(separatorIndex + 1);
|
|
1939
|
+
if (Guards24.isNullOrEmpty(nonce) || Guards24.isNullOrEmpty(signature))
|
|
1940
|
+
return false;
|
|
1941
|
+
const expected = await this._cryptoService.hmacSha256(
|
|
1942
|
+
this._secret,
|
|
1943
|
+
`${subject}.${nonce}`
|
|
1944
|
+
);
|
|
1945
|
+
const encoder = new TextEncoder();
|
|
1946
|
+
const actualBuffer = encoder.encode(signature);
|
|
1947
|
+
const expectedBuffer = encoder.encode(expected);
|
|
1948
|
+
if (actualBuffer.length !== expectedBuffer.length)
|
|
1949
|
+
return false;
|
|
1950
|
+
return this._cryptoService.timingSafeEqual(actualBuffer, expectedBuffer);
|
|
1951
|
+
}
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
});
|
|
1955
|
+
|
|
1956
|
+
// src/infrastructure/services/csrf/index.ts
|
|
1957
|
+
var init_csrf = __esm({
|
|
1958
|
+
"src/infrastructure/services/csrf/index.ts"() {
|
|
1959
|
+
"use strict";
|
|
1960
|
+
init_csrf_token_service();
|
|
1961
|
+
}
|
|
1962
|
+
});
|
|
1963
|
+
|
|
1836
1964
|
// src/infrastructure/services/extractors/extract-bearer.extractor.ts
|
|
1837
|
-
import { Guards as
|
|
1965
|
+
import { Guards as Guards25, StringHelper as StringHelper2 } from "@xeno-js/shared";
|
|
1838
1966
|
var BearerTokenExtractor;
|
|
1839
1967
|
var init_extract_bearer_extractor = __esm({
|
|
1840
1968
|
"src/infrastructure/services/extractors/extract-bearer.extractor.ts"() {
|
|
@@ -1842,16 +1970,16 @@ var init_extract_bearer_extractor = __esm({
|
|
|
1842
1970
|
BearerTokenExtractor = class {
|
|
1843
1971
|
extract(headers) {
|
|
1844
1972
|
const authHeader = StringHelper2.getSingleValue(headers["authorization"]);
|
|
1845
|
-
if (!
|
|
1973
|
+
if (!Guards25.isDefined(authHeader)) {
|
|
1846
1974
|
return void 0;
|
|
1847
1975
|
}
|
|
1848
1976
|
if (authHeader.toLowerCase().startsWith("bearer ")) {
|
|
1849
1977
|
return authHeader.substring(7);
|
|
1850
1978
|
}
|
|
1851
1979
|
const cookieHeader = StringHelper2.getSingleValue(headers["cookie"]);
|
|
1852
|
-
if (
|
|
1980
|
+
if (Guards25.isDefined(cookieHeader)) {
|
|
1853
1981
|
const match = /sb-access-token=([^;]+)/.exec(cookieHeader);
|
|
1854
|
-
if (!
|
|
1982
|
+
if (!Guards25.isNullOrEmpty(match) && Guards25.isDefined(match[1])) {
|
|
1855
1983
|
return match[1].trim();
|
|
1856
1984
|
}
|
|
1857
1985
|
}
|
|
@@ -1863,7 +1991,7 @@ var init_extract_bearer_extractor = __esm({
|
|
|
1863
1991
|
|
|
1864
1992
|
// src/infrastructure/services/extractors/extract-ssr-bearer.extractor.ts
|
|
1865
1993
|
import {
|
|
1866
|
-
Guards as
|
|
1994
|
+
Guards as Guards26,
|
|
1867
1995
|
StringHelper as StringHelper3
|
|
1868
1996
|
} from "@xeno-js/shared";
|
|
1869
1997
|
var SupabaseSsrTokenExtractor;
|
|
@@ -1873,36 +2001,36 @@ var init_extract_ssr_bearer_extractor = __esm({
|
|
|
1873
2001
|
SupabaseSsrTokenExtractor = class {
|
|
1874
2002
|
extract(headers) {
|
|
1875
2003
|
const authHeader = StringHelper3.getSingleValue(headers["authorization"]);
|
|
1876
|
-
if (
|
|
2004
|
+
if (Guards26.isDefined(authHeader) && authHeader.toLowerCase().startsWith("bearer ")) {
|
|
1877
2005
|
return authHeader.substring(7);
|
|
1878
2006
|
}
|
|
1879
2007
|
const cookieHeader = StringHelper3.getSingleValue(headers["cookie"]);
|
|
1880
|
-
if (
|
|
2008
|
+
if (Guards26.isNullOrEmpty(cookieHeader)) return void 0;
|
|
1881
2009
|
const cookies = cookieHeader.split(";").map((c) => c.trim());
|
|
1882
2010
|
const tokenChunks = {};
|
|
1883
2011
|
let unchunkedToken;
|
|
1884
2012
|
for (const cookie of cookies) {
|
|
1885
2013
|
const [name, ...rest] = cookie.split("=");
|
|
1886
|
-
if (!
|
|
2014
|
+
if (!Guards26.isDefined(name) || Guards26.isNullOrEmpty(rest)) continue;
|
|
1887
2015
|
const value = decodeURIComponent(rest.join("="));
|
|
1888
|
-
if (
|
|
2016
|
+
if (Guards26.isDefined(/^sb-[a-z0-9]+-auth-token$/.exec(name))) {
|
|
1889
2017
|
unchunkedToken = value;
|
|
1890
2018
|
} else {
|
|
1891
2019
|
const match = /^sb-[a-z0-9]+-auth-token\.(\d+)$/.exec(name);
|
|
1892
|
-
if (
|
|
2020
|
+
if (Guards26.isDefined(match)) tokenChunks[parseInt(match[1], 10)] = value;
|
|
1893
2021
|
}
|
|
1894
2022
|
}
|
|
1895
2023
|
let fullTokenString = unchunkedToken;
|
|
1896
|
-
if (!
|
|
2024
|
+
if (!Guards26.isDefined(fullTokenString) && Object.keys(tokenChunks).length > 0) {
|
|
1897
2025
|
const indices = Object.keys(tokenChunks).map(Number).sort((a, b) => a - b);
|
|
1898
2026
|
fullTokenString = indices.map((i) => tokenChunks[i]).join("");
|
|
1899
2027
|
}
|
|
1900
|
-
if (
|
|
2028
|
+
if (Guards26.isNullOrEmpty(fullTokenString)) return void 0;
|
|
1901
2029
|
try {
|
|
1902
2030
|
const parsed = StringHelper3.safeParse(fullTokenString);
|
|
1903
|
-
if (
|
|
2031
|
+
if (Guards26.isDefined(parsed) && Guards26.isObject(parsed) && "access_token" in parsed) {
|
|
1904
2032
|
const accessToken = parsed["access_token"];
|
|
1905
|
-
if (
|
|
2033
|
+
if (Guards26.isString(accessToken)) return accessToken;
|
|
1906
2034
|
}
|
|
1907
2035
|
} catch {
|
|
1908
2036
|
return void 0;
|
|
@@ -1912,9 +2040,39 @@ var init_extract_ssr_bearer_extractor = __esm({
|
|
|
1912
2040
|
}
|
|
1913
2041
|
});
|
|
1914
2042
|
|
|
2043
|
+
// src/infrastructure/services/extractors/http-cookie.extractor.ts
|
|
2044
|
+
import { Guards as Guards27 } from "@xeno-js/shared";
|
|
2045
|
+
var HttpCookieExtractor;
|
|
2046
|
+
var init_http_cookie_extractor = __esm({
|
|
2047
|
+
"src/infrastructure/services/extractors/http-cookie.extractor.ts"() {
|
|
2048
|
+
"use strict";
|
|
2049
|
+
HttpCookieExtractor = class {
|
|
2050
|
+
extract(cookie) {
|
|
2051
|
+
if (!Guards27.isDefined(cookie.header))
|
|
2052
|
+
return void 0;
|
|
2053
|
+
for (const rawCookie of cookie.header.split(";")) {
|
|
2054
|
+
const separatorIndex = rawCookie.indexOf("=");
|
|
2055
|
+
if (separatorIndex <= 0)
|
|
2056
|
+
continue;
|
|
2057
|
+
const name = rawCookie.slice(0, separatorIndex).trim();
|
|
2058
|
+
if (name !== cookie.name)
|
|
2059
|
+
continue;
|
|
2060
|
+
const value = rawCookie.slice(separatorIndex + 1).trim();
|
|
2061
|
+
try {
|
|
2062
|
+
return decodeURIComponent(value);
|
|
2063
|
+
} catch {
|
|
2064
|
+
return void 0;
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
return void 0;
|
|
2068
|
+
}
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
});
|
|
2072
|
+
|
|
1915
2073
|
// src/infrastructure/services/extractors/http-header.extractor.ts
|
|
1916
2074
|
import {
|
|
1917
|
-
Guards as
|
|
2075
|
+
Guards as Guards28,
|
|
1918
2076
|
GuidHelper as GuidHelper4,
|
|
1919
2077
|
HttpHelper,
|
|
1920
2078
|
MathHelper,
|
|
@@ -1934,12 +2092,16 @@ var init_http_header_extractor = __esm({
|
|
|
1934
2092
|
* @since 2025-09-30
|
|
1935
2093
|
* @link https://github.com/xeno-js/xeno-js
|
|
1936
2094
|
*/
|
|
1937
|
-
constructor(_bearerExtractor, _trustedIp) {
|
|
2095
|
+
constructor(_bearerExtractor, _cookieExtractor, _trustedIp, _cookieName) {
|
|
1938
2096
|
this._bearerExtractor = _bearerExtractor;
|
|
2097
|
+
this._cookieExtractor = _cookieExtractor;
|
|
1939
2098
|
this._trustedIp = _trustedIp;
|
|
2099
|
+
this._cookieName = _cookieName;
|
|
1940
2100
|
}
|
|
1941
2101
|
_bearerExtractor;
|
|
2102
|
+
_cookieExtractor;
|
|
1942
2103
|
_trustedIp;
|
|
2104
|
+
_cookieName;
|
|
1943
2105
|
extract(headers) {
|
|
1944
2106
|
const correlationId = GuidHelper4.parse(StringHelper4.getSingleValue(headers["x-correlation-id"]));
|
|
1945
2107
|
const requestId = GuidHelper4.parse(StringHelper4.getSingleValue(headers["x-request-id"]));
|
|
@@ -1955,7 +2117,14 @@ var init_http_header_extractor = __esm({
|
|
|
1955
2117
|
const position = StringHelper4.getSingleValue(headers["x-sequence-position"]);
|
|
1956
2118
|
const size = StringHelper4.getSingleValue(headers["x-sequence-size"]);
|
|
1957
2119
|
const expiration = StringHelper4.getSingleValue(headers["x-expiration"]);
|
|
1958
|
-
const csrf = StringHelper4.getSingleValue(headers["x-
|
|
2120
|
+
const csrf = StringHelper4.getSingleValue(headers["x-csrf-token"]);
|
|
2121
|
+
const cookieHeader = StringHelper4.getSingleValue(headers["cookie"]);
|
|
2122
|
+
const csrfCookie = this._cookieExtractor.extract(
|
|
2123
|
+
{
|
|
2124
|
+
header: cookieHeader,
|
|
2125
|
+
name: this._cookieName
|
|
2126
|
+
}
|
|
2127
|
+
);
|
|
1959
2128
|
const origin = StringHelper4.getSingleValue(headers["origin"]);
|
|
1960
2129
|
const cleanOrigin = HttpHelper.sanitizeOriginUrl(origin);
|
|
1961
2130
|
const referer = StringHelper4.getSingleValue(headers["referer"]);
|
|
@@ -1973,14 +2142,15 @@ var init_http_header_extractor = __esm({
|
|
|
1973
2142
|
userAgent,
|
|
1974
2143
|
returnAddress,
|
|
1975
2144
|
csrf,
|
|
2145
|
+
csrfCookie,
|
|
1976
2146
|
origin: cleanOrigin,
|
|
1977
2147
|
referer: cleanReferer,
|
|
1978
2148
|
sequence: {
|
|
1979
2149
|
sequenceId,
|
|
1980
|
-
position:
|
|
1981
|
-
size:
|
|
2150
|
+
position: Guards28.isDefined(position) ? MathHelper.toNumber(position) : void 0,
|
|
2151
|
+
size: Guards28.isDefined(size) ? MathHelper.toNumber(size) : void 0
|
|
1982
2152
|
},
|
|
1983
|
-
expiration:
|
|
2153
|
+
expiration: Guards28.isDefined(expiration) ? MathHelper.toNumber(expiration) : void 0
|
|
1984
2154
|
};
|
|
1985
2155
|
return metadata;
|
|
1986
2156
|
}
|
|
@@ -1994,6 +2164,7 @@ var init_extractors = __esm({
|
|
|
1994
2164
|
"use strict";
|
|
1995
2165
|
init_extract_bearer_extractor();
|
|
1996
2166
|
init_extract_ssr_bearer_extractor();
|
|
2167
|
+
init_http_cookie_extractor();
|
|
1997
2168
|
init_http_header_extractor();
|
|
1998
2169
|
}
|
|
1999
2170
|
});
|
|
@@ -2025,12 +2196,82 @@ var init_resiliences = __esm({
|
|
|
2025
2196
|
}
|
|
2026
2197
|
});
|
|
2027
2198
|
|
|
2199
|
+
// src/infrastructure/services/resolver/utils/socket.utils.ts
|
|
2200
|
+
import { Guards as Guards29 } from "@xeno-js/shared";
|
|
2201
|
+
var SocketIpExtractor;
|
|
2202
|
+
var init_socket_utils = __esm({
|
|
2203
|
+
"src/infrastructure/services/resolver/utils/socket.utils.ts"() {
|
|
2204
|
+
"use strict";
|
|
2205
|
+
SocketIpExtractor = Object.freeze({
|
|
2206
|
+
/**
|
|
2207
|
+
* @description Extracts the IP address of the remote socket from an incoming request.
|
|
2208
|
+
* @param req The incoming request object.
|
|
2209
|
+
* @returns The IP address of the remote socket, or undefined if not available.
|
|
2210
|
+
*/
|
|
2211
|
+
extract(req) {
|
|
2212
|
+
if (Guards29.isDefined(req) && Guards29.isObject(req)) {
|
|
2213
|
+
const candidate = req;
|
|
2214
|
+
return candidate.socket?.remoteAddress ?? candidate.connection?.remoteAddress;
|
|
2215
|
+
}
|
|
2216
|
+
return void 0;
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
});
|
|
2221
|
+
|
|
2222
|
+
// src/infrastructure/services/resolver/utils/index.ts
|
|
2223
|
+
var init_utils = __esm({
|
|
2224
|
+
"src/infrastructure/services/resolver/utils/index.ts"() {
|
|
2225
|
+
"use strict";
|
|
2226
|
+
init_socket_utils();
|
|
2227
|
+
}
|
|
2228
|
+
});
|
|
2229
|
+
|
|
2230
|
+
// src/infrastructure/services/resolver/client-ip.resolver.ts
|
|
2231
|
+
import { Guards as Guards30 } from "@xeno-js/shared";
|
|
2232
|
+
var ClientIpResolver;
|
|
2233
|
+
var init_client_ip_resolver = __esm({
|
|
2234
|
+
"src/infrastructure/services/resolver/client-ip.resolver.ts"() {
|
|
2235
|
+
"use strict";
|
|
2236
|
+
init_utils();
|
|
2237
|
+
ClientIpResolver = class {
|
|
2238
|
+
constructor(_trustedProxies = []) {
|
|
2239
|
+
this._trustedProxies = _trustedProxies;
|
|
2240
|
+
}
|
|
2241
|
+
_trustedProxies;
|
|
2242
|
+
resolve(req, clientIp) {
|
|
2243
|
+
const socketIp = SocketIpExtractor.extract(req);
|
|
2244
|
+
if (!Guards30.isDefined(socketIp))
|
|
2245
|
+
return !Guards30.isNullOrEmpty(clientIp) ? clientIp.split(",")[0].trim() : void 0;
|
|
2246
|
+
const isTrustedProxy = this._trustedProxies.includes(socketIp);
|
|
2247
|
+
if (!isTrustedProxy)
|
|
2248
|
+
return socketIp;
|
|
2249
|
+
if (Guards30.isDefined(clientIp))
|
|
2250
|
+
return clientIp.split(",")[0].trim();
|
|
2251
|
+
return socketIp;
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
});
|
|
2256
|
+
|
|
2257
|
+
// src/infrastructure/services/resolver/index.ts
|
|
2258
|
+
var init_resolver = __esm({
|
|
2259
|
+
"src/infrastructure/services/resolver/index.ts"() {
|
|
2260
|
+
"use strict";
|
|
2261
|
+
init_client_ip_resolver();
|
|
2262
|
+
}
|
|
2263
|
+
});
|
|
2264
|
+
|
|
2028
2265
|
// src/infrastructure/services/index.ts
|
|
2029
2266
|
var services_exports = {};
|
|
2030
2267
|
__export(services_exports, {
|
|
2031
2268
|
AllowMethodRegistry: () => AllowMethodRegistry,
|
|
2032
2269
|
AllowOrigin: () => AllowOrigin,
|
|
2033
2270
|
BearerTokenExtractor: () => BearerTokenExtractor,
|
|
2271
|
+
ClientIpResolver: () => ClientIpResolver,
|
|
2272
|
+
CsrfTokenService: () => CsrfTokenService,
|
|
2273
|
+
EdgeCryptoService: () => EdgeCryptoService,
|
|
2274
|
+
HttpCookieExtractor: () => HttpCookieExtractor,
|
|
2034
2275
|
HttpHeaderExtractor: () => HttpHeaderExtractor,
|
|
2035
2276
|
PLimitConcurrencyService: () => PLimitConcurrencyService,
|
|
2036
2277
|
ServiceResilience: () => ServiceResilience,
|
|
@@ -2042,8 +2283,11 @@ var init_services = __esm({
|
|
|
2042
2283
|
init_allow_methods();
|
|
2043
2284
|
init_allow_origins();
|
|
2044
2285
|
init_concurrency();
|
|
2286
|
+
init_crypto();
|
|
2287
|
+
init_csrf();
|
|
2045
2288
|
init_extractors();
|
|
2046
2289
|
init_resiliences();
|
|
2290
|
+
init_resolver();
|
|
2047
2291
|
}
|
|
2048
2292
|
});
|
|
2049
2293
|
|
|
@@ -2106,7 +2350,7 @@ var init_axios_factory = __esm({
|
|
|
2106
2350
|
});
|
|
2107
2351
|
|
|
2108
2352
|
// src/infrastructure/factories/cockatiel-resilience.factory.ts
|
|
2109
|
-
import { AppError as AppError13, Guards as
|
|
2353
|
+
import { AppError as AppError13, Guards as Guards31, RESILIENCE_DEFAULTS } from "@xeno-js/shared";
|
|
2110
2354
|
import {
|
|
2111
2355
|
bulkhead,
|
|
2112
2356
|
circuitBreaker,
|
|
@@ -2183,13 +2427,13 @@ var init_cockatiel_resilience_factory = __esm({
|
|
|
2183
2427
|
return new ServiceResilience(wrap(bulkheadPolicy, circuitBreakerPolicy, retryPolicy));
|
|
2184
2428
|
}
|
|
2185
2429
|
isTransientError(error) {
|
|
2186
|
-
if (!
|
|
2430
|
+
if (!Guards31.isDefined(error) || !Guards31.isObject(error)) return false;
|
|
2187
2431
|
let status;
|
|
2188
2432
|
let isNetworkError = false;
|
|
2189
2433
|
if (error instanceof AppError13) {
|
|
2190
2434
|
status = error.status;
|
|
2191
2435
|
const cause = error.cause;
|
|
2192
|
-
if (
|
|
2436
|
+
if (Guards31.isDefined(cause) && Guards31.isString(cause.code)) {
|
|
2193
2437
|
isNetworkError = [
|
|
2194
2438
|
"ECONNABORTED",
|
|
2195
2439
|
"ECONNRESET",
|
|
@@ -2201,7 +2445,7 @@ var init_cockatiel_resilience_factory = __esm({
|
|
|
2201
2445
|
} else {
|
|
2202
2446
|
const err = error;
|
|
2203
2447
|
status = err.status;
|
|
2204
|
-
if (
|
|
2448
|
+
if (Guards31.isString(err.code)) {
|
|
2205
2449
|
isNetworkError = [
|
|
2206
2450
|
"ECONNABORTED",
|
|
2207
2451
|
"ECONNRESET",
|
|
@@ -2212,7 +2456,7 @@ var init_cockatiel_resilience_factory = __esm({
|
|
|
2212
2456
|
}
|
|
2213
2457
|
}
|
|
2214
2458
|
if (isNetworkError) return true;
|
|
2215
|
-
if (
|
|
2459
|
+
if (Guards31.isDefined(status)) {
|
|
2216
2460
|
return status === 408 || status === 429 || status >= 500 && status < 600;
|
|
2217
2461
|
}
|
|
2218
2462
|
return false;
|
|
@@ -2222,22 +2466,22 @@ var init_cockatiel_resilience_factory = __esm({
|
|
|
2222
2466
|
let method;
|
|
2223
2467
|
if (error instanceof AppError13) {
|
|
2224
2468
|
const cause = error.cause;
|
|
2225
|
-
if (
|
|
2469
|
+
if (Guards31.isDefined(cause) && Guards31.isDefined(cause.config) && Guards31.isString(cause.config.method)) {
|
|
2226
2470
|
method = cause.config.method.toUpperCase();
|
|
2227
2471
|
}
|
|
2228
2472
|
} else {
|
|
2229
2473
|
const err = error;
|
|
2230
|
-
if (
|
|
2474
|
+
if (Guards31.isDefined(err.config) && Guards31.isString(err.config.method)) {
|
|
2231
2475
|
method = err.config.method.toUpperCase();
|
|
2232
2476
|
}
|
|
2233
2477
|
}
|
|
2234
|
-
if (
|
|
2478
|
+
if (Guards31.isNullOrEmpty(method)) return false;
|
|
2235
2479
|
const idempotentMethods = ["GET", "PUT", "DELETE", "HEAD", "OPTIONS"];
|
|
2236
2480
|
return idempotentMethods.includes(method);
|
|
2237
2481
|
}
|
|
2238
2482
|
checkConfigValue(value, defaultValue, message) {
|
|
2239
|
-
if (
|
|
2240
|
-
|
|
2483
|
+
if (Guards31.isDefined(value)) {
|
|
2484
|
+
Guards31.throwIfNegative(value, message);
|
|
2241
2485
|
return value;
|
|
2242
2486
|
}
|
|
2243
2487
|
return defaultValue;
|
|
@@ -2269,7 +2513,7 @@ var init_db_client_factory = __esm({
|
|
|
2269
2513
|
});
|
|
2270
2514
|
|
|
2271
2515
|
// src/infrastructure/context/request-context.ts
|
|
2272
|
-
import { Guards as
|
|
2516
|
+
import { Guards as Guards32 } from "@xeno-js/shared";
|
|
2273
2517
|
var NodeRequestContext;
|
|
2274
2518
|
var init_request_context = __esm({
|
|
2275
2519
|
"src/infrastructure/context/request-context.ts"() {
|
|
@@ -2301,7 +2545,7 @@ var init_request_context = __esm({
|
|
|
2301
2545
|
}
|
|
2302
2546
|
updateIdentity(identity) {
|
|
2303
2547
|
const store = this._storage.getStore();
|
|
2304
|
-
if (
|
|
2548
|
+
if (Guards32.isDefined(store) && Guards32.isDefined(store.context)) {
|
|
2305
2549
|
store.context = Object.freeze({
|
|
2306
2550
|
...store.context,
|
|
2307
2551
|
identity: Object.freeze(identity)
|
|
@@ -2310,23 +2554,23 @@ var init_request_context = __esm({
|
|
|
2310
2554
|
}
|
|
2311
2555
|
getContext() {
|
|
2312
2556
|
const store = this._storage.getStore();
|
|
2313
|
-
if (!
|
|
2557
|
+
if (!Guards32.isDefined(store)) return void 0;
|
|
2314
2558
|
const context = store.context;
|
|
2315
2559
|
return Object.freeze(context);
|
|
2316
2560
|
}
|
|
2317
2561
|
getIdentity() {
|
|
2318
2562
|
const store = this._storage.getStore();
|
|
2319
|
-
if (!
|
|
2563
|
+
if (!Guards32.isDefined(store)) return void 0;
|
|
2320
2564
|
return Object.freeze(store.context?.identity);
|
|
2321
2565
|
}
|
|
2322
2566
|
getScope() {
|
|
2323
2567
|
const store = this._storage.getStore();
|
|
2324
|
-
if (!
|
|
2568
|
+
if (!Guards32.isDefined(store)) return void 0;
|
|
2325
2569
|
return store.scope;
|
|
2326
2570
|
}
|
|
2327
2571
|
getNetworkContext() {
|
|
2328
2572
|
const store = this._storage.getStore();
|
|
2329
|
-
if (!
|
|
2573
|
+
if (!Guards32.isDefined(store)) return void 0;
|
|
2330
2574
|
return Object.freeze(store.context?.network);
|
|
2331
2575
|
}
|
|
2332
2576
|
};
|
|
@@ -2401,7 +2645,7 @@ var init_sql_light_db_client_factory = __esm({
|
|
|
2401
2645
|
// src/infrastructure/factories/supabase.factory.ts
|
|
2402
2646
|
import { createServerClient } from "@supabase/ssr";
|
|
2403
2647
|
import {
|
|
2404
|
-
Guards as
|
|
2648
|
+
Guards as Guards33,
|
|
2405
2649
|
SupabaseAuthService,
|
|
2406
2650
|
SupabaseClaimsMapper,
|
|
2407
2651
|
SupabaseSessionMapper
|
|
@@ -2415,7 +2659,7 @@ var init_supabase_factory = __esm({
|
|
|
2415
2659
|
config,
|
|
2416
2660
|
container
|
|
2417
2661
|
}) {
|
|
2418
|
-
if (!
|
|
2662
|
+
if (!Guards33.isDefined(config.ssrOpts)) {
|
|
2419
2663
|
throw new Error("ISsrCookieHandler is required for @supabase/ssr initialization.");
|
|
2420
2664
|
}
|
|
2421
2665
|
const cookieService = config.ssrOpts(container);
|
|
@@ -2443,7 +2687,7 @@ var user_context_factory_exports = {};
|
|
|
2443
2687
|
__export(user_context_factory_exports, {
|
|
2444
2688
|
UserContextFactory: () => UserContextFactory
|
|
2445
2689
|
});
|
|
2446
|
-
import { Guards as
|
|
2690
|
+
import { Guards as Guards34 } from "@xeno-js/shared";
|
|
2447
2691
|
var UserContextFactory;
|
|
2448
2692
|
var init_user_context_factory = __esm({
|
|
2449
2693
|
"src/infrastructure/factories/user-context.factory.ts"() {
|
|
@@ -2468,7 +2712,7 @@ var init_user_context_factory = __esm({
|
|
|
2468
2712
|
tenantId: void 0
|
|
2469
2713
|
};
|
|
2470
2714
|
const identity = this._identityFactory.getIdentity();
|
|
2471
|
-
if (
|
|
2715
|
+
if (Guards34.isDefined(identity)) {
|
|
2472
2716
|
output.userId = identity.userId;
|
|
2473
2717
|
output.tenantId = identity.tenantId;
|
|
2474
2718
|
}
|
|
@@ -2561,8 +2805,8 @@ var init_auth_utils = __esm({
|
|
|
2561
2805
|
const { TOKENS: TOKENS4 } = await import("@xeno-js/shared");
|
|
2562
2806
|
const pipelines = [];
|
|
2563
2807
|
const strategies = [];
|
|
2564
|
-
const { Guards:
|
|
2565
|
-
if (
|
|
2808
|
+
const { Guards: Guards45 } = await import("@xeno-js/shared");
|
|
2809
|
+
if (Guards45.isDefined(opts.policies)) {
|
|
2566
2810
|
const { PolicyRegistry: PolicyRegistry2 } = await Promise.resolve().then(() => (init_application(), application_exports));
|
|
2567
2811
|
container.addSingleton(TOKENS4.POLICY_REGISTRY, () => new PolicyRegistry2());
|
|
2568
2812
|
const policyRegistry = opts.policies;
|
|
@@ -2571,16 +2815,16 @@ var init_auth_utils = __esm({
|
|
|
2571
2815
|
for (const [intent, policy] of Object.entries(policyRegistry)) {
|
|
2572
2816
|
const intentLower = intent.toLowerCase();
|
|
2573
2817
|
registryInstance.addPolicy(intentLower, policy);
|
|
2574
|
-
if (!
|
|
2818
|
+
if (!Guards45.isNullOrEmpty(policy.roles)) {
|
|
2575
2819
|
Policies.add("roles");
|
|
2576
2820
|
}
|
|
2577
|
-
if (!
|
|
2821
|
+
if (!Guards45.isNullOrEmpty(policy.permissions)) {
|
|
2578
2822
|
Policies.add("permissions");
|
|
2579
2823
|
}
|
|
2580
|
-
if (!
|
|
2824
|
+
if (!Guards45.isNullOrEmpty(policy.userId)) {
|
|
2581
2825
|
Policies.add("userId");
|
|
2582
2826
|
}
|
|
2583
|
-
if (!
|
|
2827
|
+
if (!Guards45.isNullOrEmpty(policy.tenantId)) {
|
|
2584
2828
|
Policies.add("tenantId");
|
|
2585
2829
|
}
|
|
2586
2830
|
}
|
|
@@ -2629,10 +2873,10 @@ var init_auth_utils = __esm({
|
|
|
2629
2873
|
strategies.push(TOKENS4.TENANT_AUTHORIZATION_PIPELINE);
|
|
2630
2874
|
}
|
|
2631
2875
|
}
|
|
2632
|
-
if (!
|
|
2876
|
+
if (!Guards45.isNullOrEmpty(opts.customAuthorizationStrategy)) {
|
|
2633
2877
|
const customStrategies = opts.customAuthorizationStrategy;
|
|
2634
2878
|
customStrategies.forEach((strategyToken, index) => {
|
|
2635
|
-
if (
|
|
2879
|
+
if (Guards45.isDefined(strategyToken)) {
|
|
2636
2880
|
const token = `CUSTOM_AUTHORIZATION_STRATEGY_${index}`;
|
|
2637
2881
|
container.addSingleton(token, (c) => {
|
|
2638
2882
|
return strategyToken(c);
|
|
@@ -2775,7 +3019,7 @@ __export(unit_of_work_exports, {
|
|
|
2775
3019
|
UnitOfWork: () => UnitOfWork
|
|
2776
3020
|
});
|
|
2777
3021
|
import { AppError as AppError14 } from "@xeno-js/shared";
|
|
2778
|
-
import { Guards as
|
|
3022
|
+
import { Guards as Guards35 } from "@xeno-js/shared";
|
|
2779
3023
|
var UnitOfWork;
|
|
2780
3024
|
var init_unit_of_work = __esm({
|
|
2781
3025
|
"src/infrastructure/transaction/unit-of-work.ts"() {
|
|
@@ -2810,9 +3054,9 @@ var init_unit_of_work = __esm({
|
|
|
2810
3054
|
});
|
|
2811
3055
|
}
|
|
2812
3056
|
async dispose() {
|
|
2813
|
-
if (
|
|
3057
|
+
if (Guards35.isDefined(this._ttx.state)) {
|
|
2814
3058
|
try {
|
|
2815
|
-
if (
|
|
3059
|
+
if (Guards35.hasMethod(this._ttx.state, "rollback")) {
|
|
2816
3060
|
await this._ttx.state.rollback();
|
|
2817
3061
|
}
|
|
2818
3062
|
} finally {
|
|
@@ -2835,7 +3079,7 @@ var init_db_module = __esm({
|
|
|
2835
3079
|
"use strict";
|
|
2836
3080
|
DbModule = class {
|
|
2837
3081
|
async configure(container, opts) {
|
|
2838
|
-
const { Guards:
|
|
3082
|
+
const { Guards: Guards45, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
|
|
2839
3083
|
const { DbUtils: DbUtils2 } = await Promise.resolve().then(() => (init_db_utils(), db_utils_exports));
|
|
2840
3084
|
const db = opts.enableSqlLite ? await DbUtils2.addSqlLite(opts) : await DbUtils2.addDbClient(opts);
|
|
2841
3085
|
const { TransactionState: TransactionState2 } = await Promise.resolve().then(() => (init_transaction_state(), transaction_state_exports));
|
|
@@ -2852,7 +3096,7 @@ var init_db_module = __esm({
|
|
|
2852
3096
|
return new Proxy(db, {
|
|
2853
3097
|
get(_target, prop, receiver) {
|
|
2854
3098
|
const activeState = ttx.state;
|
|
2855
|
-
if (
|
|
3099
|
+
if (Guards45.isDefined(activeState)) {
|
|
2856
3100
|
if (prop === "transaction") {
|
|
2857
3101
|
return activeState.transaction.bind(activeState);
|
|
2858
3102
|
}
|
|
@@ -2889,14 +3133,14 @@ var init_http_utils = __esm({
|
|
|
2889
3133
|
*/
|
|
2890
3134
|
async addAxios(container, opts) {
|
|
2891
3135
|
const { NodeAxiosFactory: NodeAxiosFactory2 } = await Promise.resolve().then(() => (init_factories(), factories_exports));
|
|
2892
|
-
const { Guards:
|
|
2893
|
-
if (!
|
|
3136
|
+
const { Guards: Guards45 } = await import("@xeno-js/shared");
|
|
3137
|
+
if (!Guards45.isDefined(opts.token)) {
|
|
2894
3138
|
throw new Error("HttpConfig.token is required and must be defined.");
|
|
2895
3139
|
}
|
|
2896
3140
|
container.addSingleton(opts.token, () => {
|
|
2897
3141
|
const factory = new NodeAxiosFactory2();
|
|
2898
3142
|
const instance = factory.create(opts.client);
|
|
2899
|
-
if (!
|
|
3143
|
+
if (!Guards45.hasMethod(instance, "get") || !Guards45.hasMethod(instance, "post") || !Guards45.hasMethod(instance, "put") || !Guards45.hasMethod(instance, "patch") || !Guards45.hasMethod(instance, "delete")) {
|
|
2900
3144
|
throw new Error(
|
|
2901
3145
|
"The created HTTP client instance does not implement the required methods of IHttpClient."
|
|
2902
3146
|
);
|
|
@@ -2923,8 +3167,8 @@ var init_http_utils = __esm({
|
|
|
2923
3167
|
});
|
|
2924
3168
|
},
|
|
2925
3169
|
async addAllowOrigin(container, opts) {
|
|
2926
|
-
const { Guards:
|
|
2927
|
-
if (
|
|
3170
|
+
const { Guards: Guards45 } = await import("@xeno-js/shared");
|
|
3171
|
+
if (Guards45.isNullOrEmpty(opts)) throw new Error("At least an allow origin must be passed");
|
|
2928
3172
|
const { TOKENS: TOKENS4 } = await import("@xeno-js/shared");
|
|
2929
3173
|
const { AllowOrigin: AllowOrigin2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
2930
3174
|
const allowOrigin = [];
|
|
@@ -2984,13 +3228,13 @@ var init_validation_utils = __esm({
|
|
|
2984
3228
|
* @link https://github.com/xeno-js/xeno-js
|
|
2985
3229
|
*/
|
|
2986
3230
|
async addValidation(container, opts, logger) {
|
|
2987
|
-
const { Guards:
|
|
2988
|
-
if (!
|
|
3231
|
+
const { Guards: Guards45, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
|
|
3232
|
+
if (!Guards45.isDefined(opts.zod) && Guards45.isNullOrEmpty(opts.customValidationStrategy)) {
|
|
2989
3233
|
return [];
|
|
2990
3234
|
}
|
|
2991
3235
|
const pipelines = [];
|
|
2992
3236
|
const validationStrategies = [];
|
|
2993
|
-
if (
|
|
3237
|
+
if (Guards45.isDefined(opts.zod)) {
|
|
2994
3238
|
const config = opts.zod;
|
|
2995
3239
|
const { ZodValidatorFactory: ZodValidatorFactory2 } = await Promise.resolve().then(() => (init_zod_validator_factory(), zod_validator_factory_exports));
|
|
2996
3240
|
container.addSingleton(TOKENS4.ZOD_VALIDATOR, () => {
|
|
@@ -3004,9 +3248,9 @@ var init_validation_utils = __esm({
|
|
|
3004
3248
|
validationStrategies.push(TOKENS4.SCHEMA_VALIDATION_STRATEGY);
|
|
3005
3249
|
}
|
|
3006
3250
|
const customValidationFactory = [];
|
|
3007
|
-
if (!
|
|
3251
|
+
if (!Guards45.isNullOrEmpty(opts.customValidationStrategy)) {
|
|
3008
3252
|
for (const strategyToken of opts.customValidationStrategy) {
|
|
3009
|
-
if (
|
|
3253
|
+
if (Guards45.isDefined(strategyToken)) {
|
|
3010
3254
|
customValidationFactory.push(strategyToken);
|
|
3011
3255
|
}
|
|
3012
3256
|
}
|
|
@@ -3109,8 +3353,8 @@ var init_pipeline_utils = __esm({
|
|
|
3109
3353
|
*/
|
|
3110
3354
|
async addCommand(container, opts) {
|
|
3111
3355
|
const pipelines = [];
|
|
3112
|
-
const { Guards:
|
|
3113
|
-
if (
|
|
3356
|
+
const { Guards: Guards45, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
|
|
3357
|
+
if (Guards45.isDefined(opts.idempotency)) {
|
|
3114
3358
|
const { IdempotencyStore: IdempotencyStore2 } = await Promise.resolve().then(() => (init_idempotency_store(), idempotency_store_exports));
|
|
3115
3359
|
container.addSingleton(
|
|
3116
3360
|
TOKENS4.IDEMPOTENCY_STORE,
|
|
@@ -3130,7 +3374,7 @@ var init_pipeline_utils = __esm({
|
|
|
3130
3374
|
});
|
|
3131
3375
|
pipelines.push(TOKENS4.IDEMPOTENCY_PIPELINE);
|
|
3132
3376
|
}
|
|
3133
|
-
if (
|
|
3377
|
+
if (Guards45.isDefined(opts.concurrency)) {
|
|
3134
3378
|
const { ConcurrencyRetryPipeline: ConcurrencyRetryPipeline2 } = await Promise.resolve().then(() => (init_application(), application_exports));
|
|
3135
3379
|
container.addSingleton(TOKENS4.CONCURRENCY_RETRY_PIPELINE, () => {
|
|
3136
3380
|
const config = opts.concurrency;
|
|
@@ -3210,13 +3454,13 @@ var init_cqrs_module = __esm({
|
|
|
3210
3454
|
return new PerformancePipeline2(logger, thresholdMs);
|
|
3211
3455
|
});
|
|
3212
3456
|
pipelines.push(TOKENS4.PERFORMANCE_PIPELINE);
|
|
3213
|
-
const { Guards:
|
|
3214
|
-
if (
|
|
3457
|
+
const { Guards: Guards45 } = await import("@xeno-js/shared");
|
|
3458
|
+
if (Guards45.isDefined(opts.authorization.policies) || Guards45.isDefined(opts.authorization.customAuthorizationStrategy)) {
|
|
3215
3459
|
const { AuthUtils: AuthUtils2 } = await Promise.resolve().then(() => (init_auth_utils(), auth_utils_exports));
|
|
3216
3460
|
const authPipelines = await AuthUtils2.addAuthZ(container, opts.authorization);
|
|
3217
3461
|
pipelines.push(...authPipelines);
|
|
3218
3462
|
}
|
|
3219
|
-
if (
|
|
3463
|
+
if (Guards45.isDefined(opts.validation.zod) || Guards45.isDefined(opts.validation.customValidationStrategy)) {
|
|
3220
3464
|
const { ValidationUtils: ValidationUtils2 } = await Promise.resolve().then(() => (init_validation_utils(), validation_utils_exports));
|
|
3221
3465
|
const logger = container.resolve(TOKENS4.LOGGER);
|
|
3222
3466
|
const validationPipelines = await ValidationUtils2.addValidation(
|
|
@@ -3228,11 +3472,11 @@ var init_cqrs_module = __esm({
|
|
|
3228
3472
|
}
|
|
3229
3473
|
const commandPipelines = pipelines;
|
|
3230
3474
|
const queryPipelines = pipelines;
|
|
3231
|
-
if ((
|
|
3475
|
+
if ((Guards45.isDefined(opts.commandBus.idempotency) || opts.queryBus.isEnabled) && opts.isCache) {
|
|
3232
3476
|
const { CacheUtils: CacheUtils2 } = await Promise.resolve().then(() => (init_cache_utils(), cache_utils_exports));
|
|
3233
3477
|
await CacheUtils2.addCache(container, { inMemory: true, redis: void 0 });
|
|
3234
3478
|
}
|
|
3235
|
-
if (
|
|
3479
|
+
if (Guards45.isDefined(opts.commandBus.idempotency) || Guards45.isDefined(opts.commandBus.concurrency)) {
|
|
3236
3480
|
const { PipelineUtils: PipelineUtils2 } = await Promise.resolve().then(() => (init_pipeline_utils(), pipeline_utils_exports));
|
|
3237
3481
|
const newCommandPipelines = await PipelineUtils2.addCommand(container, {
|
|
3238
3482
|
...opts.commandBus,
|
|
@@ -3554,7 +3798,7 @@ var init_composite_middleware = __esm({
|
|
|
3554
3798
|
});
|
|
3555
3799
|
|
|
3556
3800
|
// src/presentation/middlewares/cors.middleware.ts
|
|
3557
|
-
import { Guards as
|
|
3801
|
+
import { Guards as Guards36 } from "@xeno-js/shared";
|
|
3558
3802
|
var CORSMiddleware;
|
|
3559
3803
|
var init_cors_middleware = __esm({
|
|
3560
3804
|
"src/presentation/middlewares/cors.middleware.ts"() {
|
|
@@ -3568,7 +3812,7 @@ var init_cors_middleware = __esm({
|
|
|
3568
3812
|
const { network } = this._requestContext.getContext() ?? {};
|
|
3569
3813
|
const origin = network?.origin;
|
|
3570
3814
|
const response = await next();
|
|
3571
|
-
if (
|
|
3815
|
+
if (Guards36.isDefined(origin))
|
|
3572
3816
|
response.headers = {
|
|
3573
3817
|
...response.headers ?? {},
|
|
3574
3818
|
"Access-Control-Allow-Origin": origin,
|
|
@@ -3585,7 +3829,7 @@ var init_cors_middleware = __esm({
|
|
|
3585
3829
|
import {
|
|
3586
3830
|
ERROR_CODE_MESSAGES as ERROR_CODE_MESSAGES5,
|
|
3587
3831
|
ERROR_CODES as ERROR_CODES6,
|
|
3588
|
-
Guards as
|
|
3832
|
+
Guards as Guards37,
|
|
3589
3833
|
GuidHelper as GuidHelper9,
|
|
3590
3834
|
HttpHelper as HttpHelper6,
|
|
3591
3835
|
STATUS_CODES as STATUS_CODES7
|
|
@@ -3595,30 +3839,72 @@ var init_csrf_middleware = __esm({
|
|
|
3595
3839
|
"src/presentation/middlewares/csrf.middleware.ts"() {
|
|
3596
3840
|
"use strict";
|
|
3597
3841
|
CsrfMiddleware = class {
|
|
3598
|
-
constructor(_requestContext,
|
|
3842
|
+
constructor(_requestContext, _csrfTokenService) {
|
|
3599
3843
|
this._requestContext = _requestContext;
|
|
3600
|
-
this.
|
|
3844
|
+
this._csrfTokenService = _csrfTokenService;
|
|
3601
3845
|
}
|
|
3602
3846
|
_requestContext;
|
|
3603
|
-
|
|
3604
|
-
/**
|
|
3605
|
-
* @param requestContext Dati base della richiesta (metodo, path)
|
|
3606
|
-
* @param headers Header HTTP della richiesta
|
|
3607
|
-
* @param next Funzione delegata per passare al middleware successivo
|
|
3608
|
-
*/
|
|
3847
|
+
_csrfTokenService;
|
|
3609
3848
|
async execute(req, _headers, next) {
|
|
3610
3849
|
const method = req.method.toUpperCase();
|
|
3611
3850
|
const isStateChanging = ["POST", "PUT", "DELETE", "PATCH"].includes(method);
|
|
3612
3851
|
if (isStateChanging) {
|
|
3613
|
-
const { network, tracing } = this._requestContext.getContext() ?? {};
|
|
3614
|
-
|
|
3852
|
+
const { network, tracing, identity } = this._requestContext.getContext() ?? {};
|
|
3853
|
+
const headerToken = network?.csrf;
|
|
3854
|
+
const cookieToken = network?.csrfCookie;
|
|
3855
|
+
if (!Guards37.isDefined(headerToken) || !Guards37.isDefined(cookieToken)) {
|
|
3615
3856
|
return HttpHelper6.error(
|
|
3616
3857
|
{
|
|
3617
3858
|
success: false,
|
|
3618
3859
|
error: {
|
|
3619
3860
|
code: ERROR_CODES6.FORBIDDEN,
|
|
3620
3861
|
message: ERROR_CODE_MESSAGES5[ERROR_CODES6.FORBIDDEN],
|
|
3621
|
-
details: "CSRF
|
|
3862
|
+
details: "CSRF token missing",
|
|
3863
|
+
path: req.path
|
|
3864
|
+
},
|
|
3865
|
+
correlationId: tracing?.correlationId ?? GuidHelper9.generate(),
|
|
3866
|
+
requestId: network?.requestId ?? GuidHelper9.generate(),
|
|
3867
|
+
spanId: tracing?.spanId ?? GuidHelper9.generate(),
|
|
3868
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3869
|
+
},
|
|
3870
|
+
STATUS_CODES7.FORBIDDEN,
|
|
3871
|
+
{
|
|
3872
|
+
"Content-Type": [network?.formatIndicator ?? "application/json"]
|
|
3873
|
+
}
|
|
3874
|
+
);
|
|
3875
|
+
}
|
|
3876
|
+
if (headerToken !== cookieToken) {
|
|
3877
|
+
return HttpHelper6.error(
|
|
3878
|
+
{
|
|
3879
|
+
success: false,
|
|
3880
|
+
error: {
|
|
3881
|
+
code: ERROR_CODES6.FORBIDDEN,
|
|
3882
|
+
message: ERROR_CODE_MESSAGES5[ERROR_CODES6.FORBIDDEN],
|
|
3883
|
+
details: "CSRF token mismatch",
|
|
3884
|
+
path: req.path
|
|
3885
|
+
},
|
|
3886
|
+
correlationId: tracing?.correlationId ?? GuidHelper9.generate(),
|
|
3887
|
+
requestId: network?.requestId ?? GuidHelper9.generate(),
|
|
3888
|
+
spanId: tracing?.spanId ?? GuidHelper9.generate(),
|
|
3889
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3890
|
+
},
|
|
3891
|
+
STATUS_CODES7.FORBIDDEN,
|
|
3892
|
+
{
|
|
3893
|
+
"Content-Type": [network?.formatIndicator ?? "application/json"]
|
|
3894
|
+
}
|
|
3895
|
+
);
|
|
3896
|
+
}
|
|
3897
|
+
if (!Guards37.isDefined(identity?.userId) || !await this._csrfTokenService.validate(
|
|
3898
|
+
headerToken,
|
|
3899
|
+
identity?.userId
|
|
3900
|
+
)) {
|
|
3901
|
+
return HttpHelper6.error(
|
|
3902
|
+
{
|
|
3903
|
+
success: false,
|
|
3904
|
+
error: {
|
|
3905
|
+
code: ERROR_CODES6.FORBIDDEN,
|
|
3906
|
+
message: ERROR_CODE_MESSAGES5[ERROR_CODES6.FORBIDDEN],
|
|
3907
|
+
details: "CSRF token invalid",
|
|
3622
3908
|
path: req.path
|
|
3623
3909
|
},
|
|
3624
3910
|
correlationId: tracing?.correlationId ?? GuidHelper9.generate(),
|
|
@@ -3639,8 +3925,51 @@ var init_csrf_middleware = __esm({
|
|
|
3639
3925
|
}
|
|
3640
3926
|
});
|
|
3641
3927
|
|
|
3928
|
+
// src/presentation/middlewares/csrf-cookie.middleware.ts
|
|
3929
|
+
import { Guards as Guards38 } from "@xeno-js/shared";
|
|
3930
|
+
var CsrfCookieMiddleware;
|
|
3931
|
+
var init_csrf_cookie_middleware = __esm({
|
|
3932
|
+
"src/presentation/middlewares/csrf-cookie.middleware.ts"() {
|
|
3933
|
+
"use strict";
|
|
3934
|
+
CsrfCookieMiddleware = class {
|
|
3935
|
+
constructor(_requestContext, _csrfTokenService, _csrf) {
|
|
3936
|
+
this._requestContext = _requestContext;
|
|
3937
|
+
this._csrfTokenService = _csrfTokenService;
|
|
3938
|
+
this._csrf = _csrf;
|
|
3939
|
+
}
|
|
3940
|
+
_requestContext;
|
|
3941
|
+
_csrfTokenService;
|
|
3942
|
+
_csrf;
|
|
3943
|
+
async execute(_req, _headers, next) {
|
|
3944
|
+
const response = await next();
|
|
3945
|
+
const context = this._requestContext.getContext();
|
|
3946
|
+
const identity = context?.identity;
|
|
3947
|
+
const network = context?.network;
|
|
3948
|
+
if (!Guards38.isDefined(identity?.userId))
|
|
3949
|
+
return response;
|
|
3950
|
+
if (Guards38.isDefined(network?.csrfCookie))
|
|
3951
|
+
return response;
|
|
3952
|
+
const token = await this._csrfTokenService.generate(identity.userId);
|
|
3953
|
+
const cookieName = this._csrf.cookieName ?? "__Host-xeno-csrf";
|
|
3954
|
+
const maxAge = this._csrf.cookieMaxAgeSeconds ?? 3600;
|
|
3955
|
+
const sameSite = this._csrf.sameSite ?? "lax";
|
|
3956
|
+
const cookie = `${cookieName}=${encodeURIComponent(token)}; Path=/; Secure; SameSite=${sameSite}; Max-Age=${maxAge}`;
|
|
3957
|
+
const existingCookies = response.headers["Set-Cookie"];
|
|
3958
|
+
response.headers = {
|
|
3959
|
+
...response.headers ?? {},
|
|
3960
|
+
"Set-Cookie": [
|
|
3961
|
+
...existingCookies ?? [],
|
|
3962
|
+
cookie
|
|
3963
|
+
]
|
|
3964
|
+
};
|
|
3965
|
+
return response;
|
|
3966
|
+
}
|
|
3967
|
+
};
|
|
3968
|
+
}
|
|
3969
|
+
});
|
|
3970
|
+
|
|
3642
3971
|
// src/presentation/middlewares/options.middleware.ts
|
|
3643
|
-
import { Guards as
|
|
3972
|
+
import { Guards as Guards39, HttpHelper as HttpHelper7, STATUS_CODES as STATUS_CODES8 } from "@xeno-js/shared";
|
|
3644
3973
|
var OptionsMiddleware;
|
|
3645
3974
|
var init_options_middleware = __esm({
|
|
3646
3975
|
"src/presentation/middlewares/options.middleware.ts"() {
|
|
@@ -3655,13 +3984,13 @@ var init_options_middleware = __esm({
|
|
|
3655
3984
|
const network = this._requestContext.getNetworkContext();
|
|
3656
3985
|
const origin = network?.origin;
|
|
3657
3986
|
const headers = {};
|
|
3658
|
-
if (
|
|
3987
|
+
if (Guards39.isDefined(origin)) {
|
|
3659
3988
|
headers["Access-Control-Allow-Origin"] = origin;
|
|
3660
3989
|
headers["Access-Control-Allow-Credentials"] = "true";
|
|
3661
3990
|
headers["Vary"] = "Origin";
|
|
3662
3991
|
}
|
|
3663
|
-
headers["Access-Control-Allow-Methods"] = "POST,GET,PUT,DELETE,OPTIONS";
|
|
3664
|
-
headers["Access-Control-Allow-Headers"] = "X-CSRF-Token,
|
|
3992
|
+
headers["Access-Control-Allow-Methods"] = "POST,GET,PUT,PATCH,DELETE,OPTIONS";
|
|
3993
|
+
headers["Access-Control-Allow-Headers"] = "X-CSRF-Token, Accept, Accept-Version, Content-Type, Authorization, X-Correlation-Id";
|
|
3665
3994
|
return HttpHelper7.success(null, STATUS_CODES8.NO_CONTENT, {}, headers);
|
|
3666
3995
|
}
|
|
3667
3996
|
return await next();
|
|
@@ -3687,12 +4016,12 @@ var init_rate_limiter_middleware = __esm({
|
|
|
3687
4016
|
_cache;
|
|
3688
4017
|
_logger;
|
|
3689
4018
|
_opts;
|
|
3690
|
-
async execute(req,
|
|
4019
|
+
async execute(req, _headers, next) {
|
|
3691
4020
|
const { network, tracing } = this._ctxAccessor.getContext() ?? {};
|
|
3692
4021
|
const clientIp = network?.clientIp;
|
|
3693
4022
|
const cacheKey = `rate_limit:${clientIp}`;
|
|
3694
|
-
const currentHits = await this._cache.
|
|
3695
|
-
if (currentHits
|
|
4023
|
+
const currentHits = await this._cache.increment(cacheKey, this._opts.windowSeconds);
|
|
4024
|
+
if (currentHits > this._opts.maxRequests) {
|
|
3696
4025
|
this._logger.warn(`[RateLimit] IP ${clientIp} blocked on ${req.path}`);
|
|
3697
4026
|
return HttpHelper8.error(
|
|
3698
4027
|
{
|
|
@@ -3715,7 +4044,6 @@ var init_rate_limiter_middleware = __esm({
|
|
|
3715
4044
|
}
|
|
3716
4045
|
);
|
|
3717
4046
|
}
|
|
3718
|
-
await this._cache.set(cacheKey, currentHits + 1, this._opts.windowSeconds);
|
|
3719
4047
|
return next();
|
|
3720
4048
|
}
|
|
3721
4049
|
};
|
|
@@ -3723,10 +4051,10 @@ var init_rate_limiter_middleware = __esm({
|
|
|
3723
4051
|
});
|
|
3724
4052
|
|
|
3725
4053
|
// src/presentation/mappers/context.mapper.ts
|
|
3726
|
-
import { Guards as
|
|
4054
|
+
import { Guards as Guards40 } from "@xeno-js/shared";
|
|
3727
4055
|
function _buildMessagingContext(meta) {
|
|
3728
|
-
const hasSequenceData =
|
|
3729
|
-
const hasMessagingData = hasSequenceData ||
|
|
4056
|
+
const hasSequenceData = Guards40.isDefined(meta.sequence?.sequenceId) || Guards40.isDefined(meta.sequence?.position) || Guards40.isDefined(meta.sequence?.size);
|
|
4057
|
+
const hasMessagingData = hasSequenceData || Guards40.isDefined(meta.expiration) || Guards40.isDefined(meta.returnAddress);
|
|
3730
4058
|
const messaging = hasMessagingData ? {
|
|
3731
4059
|
returnAddress: meta.returnAddress,
|
|
3732
4060
|
expiration: meta.expiration,
|
|
@@ -3757,6 +4085,7 @@ var init_context_mapper = __esm({
|
|
|
3757
4085
|
path,
|
|
3758
4086
|
transport,
|
|
3759
4087
|
csrf: metadata.csrf,
|
|
4088
|
+
csrfCookie: metadata.csrfCookie,
|
|
3760
4089
|
origin: metadata.origin
|
|
3761
4090
|
};
|
|
3762
4091
|
const tracing = {
|
|
@@ -3805,13 +4134,15 @@ var init_request_middleware = __esm({
|
|
|
3805
4134
|
* @since 2025-09-30
|
|
3806
4135
|
* @link https://github.com/xeno-js/xeno-js
|
|
3807
4136
|
*/
|
|
3808
|
-
constructor(_requestContext, _extractor, _logger) {
|
|
4137
|
+
constructor(_requestContext, _extractor, _resolver, _logger) {
|
|
3809
4138
|
this._requestContext = _requestContext;
|
|
3810
4139
|
this._extractor = _extractor;
|
|
4140
|
+
this._resolver = _resolver;
|
|
3811
4141
|
this._logger = _logger;
|
|
3812
4142
|
}
|
|
3813
4143
|
_requestContext;
|
|
3814
4144
|
_extractor;
|
|
4145
|
+
_resolver;
|
|
3815
4146
|
_logger;
|
|
3816
4147
|
async execute(req, headers, next) {
|
|
3817
4148
|
const correlationId = GuidHelper11.generate();
|
|
@@ -3820,8 +4151,10 @@ var init_request_middleware = __esm({
|
|
|
3820
4151
|
const formatIndicator = "application/json";
|
|
3821
4152
|
try {
|
|
3822
4153
|
const meta = this._extractor.extract(headers);
|
|
4154
|
+
const clientIp = this._resolver.resolve(req.transport.req, meta.clientIp);
|
|
3823
4155
|
const metadata = {
|
|
3824
4156
|
...meta,
|
|
4157
|
+
clientIp,
|
|
3825
4158
|
correlationId: meta.correlationId ?? correlationId,
|
|
3826
4159
|
requestId: meta.requestId ?? requestId,
|
|
3827
4160
|
spanId: meta.spanId ?? spanId,
|
|
@@ -3874,6 +4207,7 @@ var init_middlewares = __esm({
|
|
|
3874
4207
|
init_composite_middleware();
|
|
3875
4208
|
init_cors_middleware();
|
|
3876
4209
|
init_csrf_middleware();
|
|
4210
|
+
init_csrf_cookie_middleware();
|
|
3877
4211
|
init_options_middleware();
|
|
3878
4212
|
init_rate_limiter_middleware();
|
|
3879
4213
|
init_request_middleware();
|
|
@@ -3888,6 +4222,7 @@ __export(presentation_exports, {
|
|
|
3888
4222
|
BaseController: () => BaseController,
|
|
3889
4223
|
CORSMiddleware: () => CORSMiddleware,
|
|
3890
4224
|
CompositeMiddleware: () => CompositeMiddleware,
|
|
4225
|
+
CsrfCookieMiddleware: () => CsrfCookieMiddleware,
|
|
3891
4226
|
CsrfMiddleware: () => CsrfMiddleware,
|
|
3892
4227
|
MethodCheckMiddleware: () => MethodCheckMiddleware,
|
|
3893
4228
|
OptionsMiddleware: () => OptionsMiddleware,
|
|
@@ -3907,7 +4242,7 @@ var middleware_module_exports = {};
|
|
|
3907
4242
|
__export(middleware_module_exports, {
|
|
3908
4243
|
MiddlewareModule: () => MiddlewareModule
|
|
3909
4244
|
});
|
|
3910
|
-
import { Guards as
|
|
4245
|
+
import { Guards as Guards41 } from "@xeno-js/shared";
|
|
3911
4246
|
var MiddlewareModule;
|
|
3912
4247
|
var init_middleware_module = __esm({
|
|
3913
4248
|
"src/infrastructure/modules/middleware.module.ts"() {
|
|
@@ -3926,15 +4261,19 @@ var init_middleware_module = __esm({
|
|
|
3926
4261
|
const { BearerTokenExtractor: BearerTokenExtractor2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
3927
4262
|
container.addSingleton(TOKENS4.BEARER_TOKEN_EXTRACTOR, () => new BearerTokenExtractor2());
|
|
3928
4263
|
}
|
|
4264
|
+
const { HttpCookieExtractor: HttpCookieExtractor2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
4265
|
+
container.addSingleton("COOKIE_EXTRACTOR", () => new HttpCookieExtractor2());
|
|
3929
4266
|
const { HttpHeaderExtractor: HttpHeaderExtractor2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
3930
4267
|
container.addSingleton(
|
|
3931
4268
|
TOKENS4.SERVICE_EXTRACTOR,
|
|
3932
|
-
(c) => new HttpHeaderExtractor2(c.resolve(TOKENS4.BEARER_TOKEN_EXTRACTOR), opts.trustedIpHeader)
|
|
4269
|
+
(c) => new HttpHeaderExtractor2(c.resolve(TOKENS4.BEARER_TOKEN_EXTRACTOR), c.resolve("COOKIE_EXTRACTOR"), opts.trustedIpHeader, opts.csrf?.cookieName ?? "__Host-xeno-csrf")
|
|
3933
4270
|
);
|
|
3934
4271
|
if (!opts.isLogger) {
|
|
3935
4272
|
const { LoggerUtils: LoggerUtils2 } = await Promise.resolve().then(() => (init_logger_utils(), logger_utils_exports));
|
|
3936
4273
|
await LoggerUtils2.addLogger(container, void 0);
|
|
3937
4274
|
}
|
|
4275
|
+
const { ClientIpResolver: ClientIpResolver2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
4276
|
+
container.addSingleton("IP_RESOLVER", () => new ClientIpResolver2(opts.trustedProxies));
|
|
3938
4277
|
const middlewares = [TOKENS4.REQUEST_CONTEXT_MIDDLEWARE];
|
|
3939
4278
|
const { RequestContextMiddleware: RequestContextMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
|
|
3940
4279
|
container.addSingleton(
|
|
@@ -3942,6 +4281,7 @@ var init_middleware_module = __esm({
|
|
|
3942
4281
|
(c) => new RequestContextMiddleware2(
|
|
3943
4282
|
c.resolve(TOKENS4.REQUEST_CONTEXT),
|
|
3944
4283
|
c.resolve(TOKENS4.SERVICE_EXTRACTOR),
|
|
4284
|
+
c.resolve("IP_RESOLVER"),
|
|
3945
4285
|
c.resolve(TOKENS4.LOGGER)
|
|
3946
4286
|
)
|
|
3947
4287
|
);
|
|
@@ -3953,7 +4293,9 @@ var init_middleware_module = __esm({
|
|
|
3953
4293
|
);
|
|
3954
4294
|
middlewares.push(TOKENS4.OPTIONS_MIDDLEWARE);
|
|
3955
4295
|
}
|
|
3956
|
-
if (!
|
|
4296
|
+
if (!Guards41.isNullOrEmpty(opts.allowOrigins)) {
|
|
4297
|
+
if (Guards41.isDefined(opts.httpConfig.withCredentials) && opts.allowOrigins.includes("*"))
|
|
4298
|
+
throw new Error("Wildcard CORS origin is not allowed when withCredentials is set to true");
|
|
3957
4299
|
const { AllowOrigin: AllowOrigin2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
3958
4300
|
container.addSingleton("ALLOW_ORIGIN", () => {
|
|
3959
4301
|
return new AllowOrigin2(opts.allowOrigins);
|
|
@@ -3975,7 +4317,7 @@ var init_middleware_module = __esm({
|
|
|
3975
4317
|
});
|
|
3976
4318
|
middlewares.push(TOKENS4.CORS_MIDDLEWARE);
|
|
3977
4319
|
}
|
|
3978
|
-
if (
|
|
4320
|
+
if (Guards41.isDefined(opts.routeRegistry)) {
|
|
3979
4321
|
const registry = opts.routeRegistry;
|
|
3980
4322
|
const { AllowMethodFactory: AllowMethodFactory2 } = await Promise.resolve().then(() => (init_factories(), factories_exports));
|
|
3981
4323
|
container.addSingleton(TOKENS4.ALLOW_METHOD, () => new AllowMethodFactory2().create(registry));
|
|
@@ -3989,21 +4331,42 @@ var init_middleware_module = __esm({
|
|
|
3989
4331
|
);
|
|
3990
4332
|
middlewares.push(TOKENS4.METHOD_CHECK_MIDDLEWARE);
|
|
3991
4333
|
}
|
|
3992
|
-
|
|
4334
|
+
const { AuthenticationMiddleware: AuthenticationMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
|
|
4335
|
+
container.addSingleton(TOKENS4.AUTH_MIDDLEWARE, (c) => {
|
|
4336
|
+
return new AuthenticationMiddleware2(
|
|
4337
|
+
c.resolve(TOKENS4.REQUEST_CONTEXT),
|
|
4338
|
+
c.resolve(TOKENS4.BEARER_TOKEN_EXTRACTOR),
|
|
4339
|
+
c.resolve(TOKENS4.GATE_KEEPER),
|
|
4340
|
+
c.resolve(TOKENS4.LOGGER)
|
|
4341
|
+
);
|
|
4342
|
+
});
|
|
4343
|
+
middlewares.push(TOKENS4.AUTH_MIDDLEWARE);
|
|
4344
|
+
if (Guards41.isDefined(opts.csrf)) {
|
|
3993
4345
|
const csrf = opts.csrf;
|
|
4346
|
+
const { CsrfTokenService: CsrfTokenService2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
4347
|
+
container.addSingleton("CSRF_TOKEN_SERVICE", (c) => {
|
|
4348
|
+
return new CsrfTokenService2(
|
|
4349
|
+
csrf.secret,
|
|
4350
|
+
c.resolve("CRYPTO_SERVICE")
|
|
4351
|
+
);
|
|
4352
|
+
});
|
|
4353
|
+
const { CsrfCookieMiddleware: CsrfCookieMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
|
|
4354
|
+
container.addSingleton("CSRF_COOKIE_MIDDLEWARE", (c) => {
|
|
4355
|
+
return new CsrfCookieMiddleware2(c.resolve(TOKENS4.REQUEST_CONTEXT), c.resolve("CSRF_TOKEN_SERVICE"), csrf);
|
|
4356
|
+
});
|
|
3994
4357
|
const { CsrfMiddleware: CsrfMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
|
|
3995
4358
|
container.addSingleton(TOKENS4.CSRF_MIDDLEWARE, (c) => {
|
|
3996
|
-
return new CsrfMiddleware2(c.resolve(TOKENS4.REQUEST_CONTEXT),
|
|
4359
|
+
return new CsrfMiddleware2(c.resolve(TOKENS4.REQUEST_CONTEXT), c.resolve("CSRF_TOKEN_SERVICE"));
|
|
3997
4360
|
});
|
|
3998
4361
|
middlewares.push(TOKENS4.CSRF_MIDDLEWARE);
|
|
3999
4362
|
}
|
|
4000
|
-
if (
|
|
4363
|
+
if (Guards41.isDefined(opts.rateLimite.maxRequests) || Guards41.isDefined(opts.rateLimite.windowSeconds)) {
|
|
4001
4364
|
const maxRequests = opts.rateLimite.maxRequests ?? 30;
|
|
4002
|
-
|
|
4003
|
-
|
|
4365
|
+
Guards41.throwIfNegative(maxRequests, "MaxRequests must be positive");
|
|
4366
|
+
Guards41.throwIfNotInteger(maxRequests, "MaxRequests must be an integer");
|
|
4004
4367
|
const windowSeconds = opts.rateLimite.windowSeconds ?? 30;
|
|
4005
|
-
|
|
4006
|
-
|
|
4368
|
+
Guards41.throwIfNegative(windowSeconds, "WindowSeconds must be positive");
|
|
4369
|
+
Guards41.throwIfNotInteger(windowSeconds, "WindowSeconds must be an integer");
|
|
4007
4370
|
if (!opts.isCache) {
|
|
4008
4371
|
const { CacheUtils: CacheUtils2 } = await Promise.resolve().then(() => (init_cache_utils(), cache_utils_exports));
|
|
4009
4372
|
await CacheUtils2.addCache(container, { inMemory: true, redis: void 0 });
|
|
@@ -4022,16 +4385,6 @@ var init_middleware_module = __esm({
|
|
|
4022
4385
|
});
|
|
4023
4386
|
middlewares.push(TOKENS4.RATE_LIMITER_MIDDLEWARE);
|
|
4024
4387
|
}
|
|
4025
|
-
const { AuthenticationMiddleware: AuthenticationMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
|
|
4026
|
-
container.addSingleton(TOKENS4.AUTH_MIDDLEWARE, (c) => {
|
|
4027
|
-
return new AuthenticationMiddleware2(
|
|
4028
|
-
c.resolve(TOKENS4.REQUEST_CONTEXT),
|
|
4029
|
-
c.resolve(TOKENS4.BEARER_TOKEN_EXTRACTOR),
|
|
4030
|
-
c.resolve(TOKENS4.GATE_KEEPER),
|
|
4031
|
-
c.resolve(TOKENS4.LOGGER)
|
|
4032
|
-
);
|
|
4033
|
-
});
|
|
4034
|
-
middlewares.push(TOKENS4.AUTH_MIDDLEWARE);
|
|
4035
4388
|
const { CompositeMiddleware: CompositeMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
|
|
4036
4389
|
container.addSingleton(TOKENS4.MIDDLEWARE, (c) => {
|
|
4037
4390
|
const resolvedMiddleware = middlewares.map(
|
|
@@ -4101,7 +4454,7 @@ __export(index_exports, {
|
|
|
4101
4454
|
init_application();
|
|
4102
4455
|
|
|
4103
4456
|
// src/infrastructure/builder/app.builder.ts
|
|
4104
|
-
import { Guards as
|
|
4457
|
+
import { Guards as Guards42, LOG_LEVEL as LOG_LEVEL6, TOKENS as TOKENS3 } from "@xeno-js/shared";
|
|
4105
4458
|
|
|
4106
4459
|
// src/infrastructure/configuration/configuration.ts
|
|
4107
4460
|
import { Guards as Guards13 } from "@xeno-js/shared";
|
|
@@ -4377,6 +4730,7 @@ var AppBuilder = class {
|
|
|
4377
4730
|
() => new EnvironmentConfigurationService()
|
|
4378
4731
|
);
|
|
4379
4732
|
this._configuration = this._container.resolve(TOKENS3.CONFIGURATION_SERVICE);
|
|
4733
|
+
this._middlewareConfig.allowOrigins?.push(this._configuration.get("APP_URL") ?? `http://localhost:${this._configuration.getNumber("PORT", 3e3)}`);
|
|
4380
4734
|
}
|
|
4381
4735
|
// --- Module Configurations ---
|
|
4382
4736
|
_modules = [];
|
|
@@ -4408,7 +4762,8 @@ var AppBuilder = class {
|
|
|
4408
4762
|
optionsMiddleware: false,
|
|
4409
4763
|
routeRegistry: void 0,
|
|
4410
4764
|
trustedIpHeader: void 0,
|
|
4411
|
-
|
|
4765
|
+
trustedProxies: [],
|
|
4766
|
+
allowOrigins: [],
|
|
4412
4767
|
cors: true
|
|
4413
4768
|
};
|
|
4414
4769
|
_httpConfig = {
|
|
@@ -4491,7 +4846,7 @@ var AppBuilder = class {
|
|
|
4491
4846
|
pino: { config: void 0 },
|
|
4492
4847
|
customLoggers: void 0
|
|
4493
4848
|
};
|
|
4494
|
-
if (
|
|
4849
|
+
if (Guards42.isDefined(setupAction) && Guards42.isDefined(config))
|
|
4495
4850
|
setupAction(config, this._configuration);
|
|
4496
4851
|
this._modules.push({
|
|
4497
4852
|
priority: 3,
|
|
@@ -4517,7 +4872,7 @@ var AppBuilder = class {
|
|
|
4517
4872
|
addCache(setupAction) {
|
|
4518
4873
|
if (this._isCacheModuleQueued) return this;
|
|
4519
4874
|
this._isCacheModuleQueued = true;
|
|
4520
|
-
if (
|
|
4875
|
+
if (Guards42.isDefined(setupAction)) setupAction(this._config, this._configuration);
|
|
4521
4876
|
this._modules.push({
|
|
4522
4877
|
priority: 3,
|
|
4523
4878
|
name: "CacheModule",
|
|
@@ -4626,7 +4981,7 @@ var AppBuilder = class {
|
|
|
4626
4981
|
* @link https://github.com/xeno-js/xeno-js
|
|
4627
4982
|
*/
|
|
4628
4983
|
addPipeline(setupAction) {
|
|
4629
|
-
if (
|
|
4984
|
+
if (Guards42.isDefined(setupAction)) {
|
|
4630
4985
|
setupAction(this._pipelineConfig, this._configuration);
|
|
4631
4986
|
}
|
|
4632
4987
|
this._queuePipelineModule();
|
|
@@ -4760,7 +5115,7 @@ var AppBuilder = class {
|
|
|
4760
5115
|
console.error(`\u{1F449} Module: **${queued.name}**`);
|
|
4761
5116
|
console.error(`\u{1F4DD} Reason: ${errorMessage}
|
|
4762
5117
|
`);
|
|
4763
|
-
if (error instanceof Error &&
|
|
5118
|
+
if (error instanceof Error && Guards42.isDefined(error.stack)) {
|
|
4764
5119
|
console.error(error.stack);
|
|
4765
5120
|
}
|
|
4766
5121
|
throw new Error(`Bootstrap failed at [${queued.name}]: ${errorMessage}`, { cause: error });
|
|
@@ -4822,7 +5177,8 @@ var AppBuilder = class {
|
|
|
4822
5177
|
...this._middlewareConfig,
|
|
4823
5178
|
isAuth: this._isAuthModuleQueued,
|
|
4824
5179
|
isLogger: this._isLoggerModuleQueued,
|
|
4825
|
-
isCache: this._isCacheModuleQueued || this._isPipelineModuleQueued
|
|
5180
|
+
isCache: this._isCacheModuleQueued || this._isPipelineModuleQueued,
|
|
5181
|
+
httpConfig: this._httpConfig.http.client
|
|
4826
5182
|
});
|
|
4827
5183
|
}
|
|
4828
5184
|
});
|
|
@@ -4889,7 +5245,7 @@ init_validation_utils();
|
|
|
4889
5245
|
|
|
4890
5246
|
// src/infrastructure/repositories/read-dao.ts
|
|
4891
5247
|
import { AppError as AppError16, Result as Result17 } from "@xeno-js/shared";
|
|
4892
|
-
import { Guards as
|
|
5248
|
+
import { Guards as Guards43 } from "@xeno-js/shared";
|
|
4893
5249
|
var ReadDao = class {
|
|
4894
5250
|
/**
|
|
4895
5251
|
* Constructs a new ReadDao instance.
|
|
@@ -4911,7 +5267,7 @@ var ReadDao = class {
|
|
|
4911
5267
|
async findById(id, ctx, signal) {
|
|
4912
5268
|
AppError16.throwIfAborted(signal, "ReadDao.findById");
|
|
4913
5269
|
const result = await this._dataSource.findById(id, ctx, signal);
|
|
4914
|
-
if (
|
|
5270
|
+
if (Guards43.isNullOrEmpty(result)) return Result17.ok();
|
|
4915
5271
|
const entity = this._mapper.toEntity(result);
|
|
4916
5272
|
return Result17.ok(entity);
|
|
4917
5273
|
}
|
|
@@ -4925,7 +5281,7 @@ var ReadDao = class {
|
|
|
4925
5281
|
|
|
4926
5282
|
// src/infrastructure/repositories/repository.ts
|
|
4927
5283
|
import { AppError as AppError17, Result as Result18 } from "@xeno-js/shared";
|
|
4928
|
-
import { Guards as
|
|
5284
|
+
import { Guards as Guards44 } from "@xeno-js/shared";
|
|
4929
5285
|
var Repository = class {
|
|
4930
5286
|
/**
|
|
4931
5287
|
* Constructs a new Repository instance.
|
|
@@ -4947,7 +5303,7 @@ var Repository = class {
|
|
|
4947
5303
|
async findById(id, ctx, signal) {
|
|
4948
5304
|
AppError17.throwIfAborted(signal, "Repository.findById");
|
|
4949
5305
|
const result = await this._dataSource.findById(id, ctx, signal);
|
|
4950
|
-
if (
|
|
5306
|
+
if (Guards44.isNullOrEmpty(result)) return Result18.ok();
|
|
4951
5307
|
const entity = this._mapper.toEntity(result);
|
|
4952
5308
|
return Result18.ok(entity);
|
|
4953
5309
|
}
|
|
@@ -5005,4 +5361,13 @@ export {
|
|
|
5005
5361
|
Specification,
|
|
5006
5362
|
SupabaseServerAuthFactory
|
|
5007
5363
|
};
|
|
5364
|
+
/**
|
|
5365
|
+
* @description The CsrfCookieMiddleware class implements the IMiddleware interface, providing a concrete implementation for handling CSRF token validation and cookie management. It checks the incoming request for a valid CSRF token and sets a CSRF cookie if necessary.
|
|
5366
|
+
*
|
|
5367
|
+
* @author Xeno
|
|
5368
|
+
* @version 1.0.0
|
|
5369
|
+
* @since 2025-09-30
|
|
5370
|
+
* @link https://github.com/xeno-js/xeno-js
|
|
5371
|
+
* @license MIT
|
|
5372
|
+
*/
|
|
5008
5373
|
//# sourceMappingURL=index.js.map
|