@xeno-js/core 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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
- sendDefaultPii: false,
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: Guards39, LOG_LEVEL: LOG_LEVEL7, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
1513
- if (!Guards39.isDefined(opts) || opts.console) {
1511
+ const { Guards: Guards46, LOG_LEVEL: LOG_LEVEL7, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
1512
+ if (!Guards46.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 (Guards39.isDefined(opts)) {
1520
- if (Guards39.isDefined(opts.sentry.config)) {
1518
+ if (Guards46.isDefined(opts)) {
1519
+ if (Guards46.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 (Guards39.isDefined(opts.pino.config)) {
1527
+ if (Guards46.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 (!Guards39.isNullOrEmpty(opts.customLoggers)) {
1535
+ if (!Guards46.isNullOrEmpty(opts.customLoggers)) {
1537
1536
  const customLoggers = opts.customLoggers;
1538
1537
  customLoggers.forEach((f) => {
1539
- if (Guards39.isDefined(f)) {
1538
+ if (Guards46.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 Guards19, StringHelper } from "@xeno-js/shared";
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 (!Guards19.isDefined(value)) {
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 = Guards19.isDefined(ttl) ? ttl : 86400;
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 = Guards19.isDefined(ttl) ? ttl : 300;
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 Guards20 } from "@xeno-js/shared";
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 (Guards20.isDefined(password)) {
1670
+ if (Guards21.isDefined(password)) {
1643
1671
  redisOptions.password = password;
1644
1672
  }
1645
- if (Guards20.isDefined(username)) {
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: Guards39, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
1684
- if (!opts.inMemory && !Guards39.isDefined(opts.redis)) {
1711
+ const { Guards: Guards46, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
1712
+ if (!opts.inMemory && !Guards46.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 || !Guards39.isDefined(opts.redis)) {
1695
- const { InMemoryCache } = await import("@xeno-js/shared");
1696
- container.addSingleton(TOKENS4.CACHE, () => new InMemoryCache());
1722
+ if (opts.inMemory || !Guards46.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 (Guards39.isDefined(opts.redis)) {
1727
+ if (Guards46.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 Guards21 } from "@xeno-js/shared";
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 (Guards21.isDefined(staticMethods)) return staticMethods.includes(method);
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 Guards22 } from "@xeno-js/shared";
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 (Guards22.isNullOrEmpty(origin)) return true;
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 (!Guards22.isNullOrEmpty(prefix) && !prefix.includes(".")) return true;
1818
+ if (!Guards23.isNullOrEmpty(prefix) && !prefix.includes(".")) return true;
1791
1819
  }
1792
1820
  }
1793
1821
  }
@@ -1833,8 +1861,99 @@ 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(this._secret, `${subject}.${nonce}`);
1928
+ return `${nonce}.${signature}`;
1929
+ }
1930
+ async validate(token, subject) {
1931
+ const separatorIndex = token.indexOf(".");
1932
+ if (separatorIndex <= 0) return false;
1933
+ const nonce = token.slice(0, separatorIndex);
1934
+ const signature = token.slice(separatorIndex + 1);
1935
+ if (Guards24.isNullOrEmpty(nonce) || Guards24.isNullOrEmpty(signature)) return false;
1936
+ const expected = await this._cryptoService.hmacSha256(this._secret, `${subject}.${nonce}`);
1937
+ const encoder = new TextEncoder();
1938
+ const actualBuffer = encoder.encode(signature);
1939
+ const expectedBuffer = encoder.encode(expected);
1940
+ if (actualBuffer.length !== expectedBuffer.length) return false;
1941
+ return this._cryptoService.timingSafeEqual(actualBuffer, expectedBuffer);
1942
+ }
1943
+ };
1944
+ }
1945
+ });
1946
+
1947
+ // src/infrastructure/services/csrf/index.ts
1948
+ var init_csrf = __esm({
1949
+ "src/infrastructure/services/csrf/index.ts"() {
1950
+ "use strict";
1951
+ init_csrf_token_service();
1952
+ }
1953
+ });
1954
+
1836
1955
  // src/infrastructure/services/extractors/extract-bearer.extractor.ts
1837
- import { Guards as Guards23, StringHelper as StringHelper2 } from "@xeno-js/shared";
1956
+ import { Guards as Guards25, StringHelper as StringHelper2 } from "@xeno-js/shared";
1838
1957
  var BearerTokenExtractor;
1839
1958
  var init_extract_bearer_extractor = __esm({
1840
1959
  "src/infrastructure/services/extractors/extract-bearer.extractor.ts"() {
@@ -1842,16 +1961,16 @@ var init_extract_bearer_extractor = __esm({
1842
1961
  BearerTokenExtractor = class {
1843
1962
  extract(headers) {
1844
1963
  const authHeader = StringHelper2.getSingleValue(headers["authorization"]);
1845
- if (!Guards23.isDefined(authHeader)) {
1964
+ if (!Guards25.isDefined(authHeader)) {
1846
1965
  return void 0;
1847
1966
  }
1848
1967
  if (authHeader.toLowerCase().startsWith("bearer ")) {
1849
1968
  return authHeader.substring(7);
1850
1969
  }
1851
1970
  const cookieHeader = StringHelper2.getSingleValue(headers["cookie"]);
1852
- if (Guards23.isDefined(cookieHeader)) {
1971
+ if (Guards25.isDefined(cookieHeader)) {
1853
1972
  const match = /sb-access-token=([^;]+)/.exec(cookieHeader);
1854
- if (!Guards23.isNullOrEmpty(match) && Guards23.isDefined(match[1])) {
1973
+ if (!Guards25.isNullOrEmpty(match) && Guards25.isDefined(match[1])) {
1855
1974
  return match[1].trim();
1856
1975
  }
1857
1976
  }
@@ -1863,7 +1982,7 @@ var init_extract_bearer_extractor = __esm({
1863
1982
 
1864
1983
  // src/infrastructure/services/extractors/extract-ssr-bearer.extractor.ts
1865
1984
  import {
1866
- Guards as Guards24,
1985
+ Guards as Guards26,
1867
1986
  StringHelper as StringHelper3
1868
1987
  } from "@xeno-js/shared";
1869
1988
  var SupabaseSsrTokenExtractor;
@@ -1873,36 +1992,36 @@ var init_extract_ssr_bearer_extractor = __esm({
1873
1992
  SupabaseSsrTokenExtractor = class {
1874
1993
  extract(headers) {
1875
1994
  const authHeader = StringHelper3.getSingleValue(headers["authorization"]);
1876
- if (Guards24.isDefined(authHeader) && authHeader.toLowerCase().startsWith("bearer ")) {
1995
+ if (Guards26.isDefined(authHeader) && authHeader.toLowerCase().startsWith("bearer ")) {
1877
1996
  return authHeader.substring(7);
1878
1997
  }
1879
1998
  const cookieHeader = StringHelper3.getSingleValue(headers["cookie"]);
1880
- if (Guards24.isNullOrEmpty(cookieHeader)) return void 0;
1999
+ if (Guards26.isNullOrEmpty(cookieHeader)) return void 0;
1881
2000
  const cookies = cookieHeader.split(";").map((c) => c.trim());
1882
2001
  const tokenChunks = {};
1883
2002
  let unchunkedToken;
1884
2003
  for (const cookie of cookies) {
1885
2004
  const [name, ...rest] = cookie.split("=");
1886
- if (!Guards24.isDefined(name) || Guards24.isNullOrEmpty(rest)) continue;
2005
+ if (!Guards26.isDefined(name) || Guards26.isNullOrEmpty(rest)) continue;
1887
2006
  const value = decodeURIComponent(rest.join("="));
1888
- if (Guards24.isDefined(/^sb-[a-z0-9]+-auth-token$/.exec(name))) {
2007
+ if (Guards26.isDefined(/^sb-[a-z0-9]+-auth-token$/.exec(name))) {
1889
2008
  unchunkedToken = value;
1890
2009
  } else {
1891
2010
  const match = /^sb-[a-z0-9]+-auth-token\.(\d+)$/.exec(name);
1892
- if (Guards24.isDefined(match)) tokenChunks[parseInt(match[1], 10)] = value;
2011
+ if (Guards26.isDefined(match)) tokenChunks[parseInt(match[1], 10)] = value;
1893
2012
  }
1894
2013
  }
1895
2014
  let fullTokenString = unchunkedToken;
1896
- if (!Guards24.isDefined(fullTokenString) && Object.keys(tokenChunks).length > 0) {
2015
+ if (!Guards26.isDefined(fullTokenString) && Object.keys(tokenChunks).length > 0) {
1897
2016
  const indices = Object.keys(tokenChunks).map(Number).sort((a, b) => a - b);
1898
2017
  fullTokenString = indices.map((i) => tokenChunks[i]).join("");
1899
2018
  }
1900
- if (Guards24.isNullOrEmpty(fullTokenString)) return void 0;
2019
+ if (Guards26.isNullOrEmpty(fullTokenString)) return void 0;
1901
2020
  try {
1902
2021
  const parsed = StringHelper3.safeParse(fullTokenString);
1903
- if (Guards24.isDefined(parsed) && Guards24.isObject(parsed) && "access_token" in parsed) {
2022
+ if (Guards26.isDefined(parsed) && Guards26.isObject(parsed) && "access_token" in parsed) {
1904
2023
  const accessToken = parsed["access_token"];
1905
- if (Guards24.isString(accessToken)) return accessToken;
2024
+ if (Guards26.isString(accessToken)) return accessToken;
1906
2025
  }
1907
2026
  } catch {
1908
2027
  return void 0;
@@ -1912,9 +2031,36 @@ var init_extract_ssr_bearer_extractor = __esm({
1912
2031
  }
1913
2032
  });
1914
2033
 
2034
+ // src/infrastructure/services/extractors/http-cookie.extractor.ts
2035
+ import { Guards as Guards27 } from "@xeno-js/shared";
2036
+ var HttpCookieExtractor;
2037
+ var init_http_cookie_extractor = __esm({
2038
+ "src/infrastructure/services/extractors/http-cookie.extractor.ts"() {
2039
+ "use strict";
2040
+ HttpCookieExtractor = class {
2041
+ extract(cookie) {
2042
+ if (!Guards27.isDefined(cookie.header)) return void 0;
2043
+ for (const rawCookie of cookie.header.split(";")) {
2044
+ const separatorIndex = rawCookie.indexOf("=");
2045
+ if (separatorIndex <= 0) continue;
2046
+ const name = rawCookie.slice(0, separatorIndex).trim();
2047
+ if (name !== cookie.name) continue;
2048
+ const value = rawCookie.slice(separatorIndex + 1).trim();
2049
+ try {
2050
+ return decodeURIComponent(value);
2051
+ } catch {
2052
+ return void 0;
2053
+ }
2054
+ }
2055
+ return void 0;
2056
+ }
2057
+ };
2058
+ }
2059
+ });
2060
+
1915
2061
  // src/infrastructure/services/extractors/http-header.extractor.ts
1916
2062
  import {
1917
- Guards as Guards25,
2063
+ Guards as Guards28,
1918
2064
  GuidHelper as GuidHelper4,
1919
2065
  HttpHelper,
1920
2066
  MathHelper,
@@ -1934,12 +2080,16 @@ var init_http_header_extractor = __esm({
1934
2080
  * @since 2025-09-30
1935
2081
  * @link https://github.com/xeno-js/xeno-js
1936
2082
  */
1937
- constructor(_bearerExtractor, _trustedIp) {
2083
+ constructor(_bearerExtractor, _cookieExtractor, _trustedIp, _cookieName) {
1938
2084
  this._bearerExtractor = _bearerExtractor;
2085
+ this._cookieExtractor = _cookieExtractor;
1939
2086
  this._trustedIp = _trustedIp;
2087
+ this._cookieName = _cookieName;
1940
2088
  }
1941
2089
  _bearerExtractor;
2090
+ _cookieExtractor;
1942
2091
  _trustedIp;
2092
+ _cookieName;
1943
2093
  extract(headers) {
1944
2094
  const correlationId = GuidHelper4.parse(StringHelper4.getSingleValue(headers["x-correlation-id"]));
1945
2095
  const requestId = GuidHelper4.parse(StringHelper4.getSingleValue(headers["x-request-id"]));
@@ -1955,7 +2105,12 @@ var init_http_header_extractor = __esm({
1955
2105
  const position = StringHelper4.getSingleValue(headers["x-sequence-position"]);
1956
2106
  const size = StringHelper4.getSingleValue(headers["x-sequence-size"]);
1957
2107
  const expiration = StringHelper4.getSingleValue(headers["x-expiration"]);
1958
- const csrf = StringHelper4.getSingleValue(headers["x-requested-with"]);
2108
+ const csrf = StringHelper4.getSingleValue(headers["x-csrf-token"]);
2109
+ const cookieHeader = StringHelper4.getSingleValue(headers["cookie"]);
2110
+ const csrfCookie = this._cookieExtractor.extract({
2111
+ header: cookieHeader,
2112
+ name: this._cookieName
2113
+ });
1959
2114
  const origin = StringHelper4.getSingleValue(headers["origin"]);
1960
2115
  const cleanOrigin = HttpHelper.sanitizeOriginUrl(origin);
1961
2116
  const referer = StringHelper4.getSingleValue(headers["referer"]);
@@ -1973,14 +2128,15 @@ var init_http_header_extractor = __esm({
1973
2128
  userAgent,
1974
2129
  returnAddress,
1975
2130
  csrf,
2131
+ csrfCookie,
1976
2132
  origin: cleanOrigin,
1977
2133
  referer: cleanReferer,
1978
2134
  sequence: {
1979
2135
  sequenceId,
1980
- position: Guards25.isDefined(position) ? MathHelper.toNumber(position) : void 0,
1981
- size: Guards25.isDefined(size) ? MathHelper.toNumber(size) : void 0
2136
+ position: Guards28.isDefined(position) ? MathHelper.toNumber(position) : void 0,
2137
+ size: Guards28.isDefined(size) ? MathHelper.toNumber(size) : void 0
1982
2138
  },
1983
- expiration: Guards25.isDefined(expiration) ? MathHelper.toNumber(expiration) : void 0
2139
+ expiration: Guards28.isDefined(expiration) ? MathHelper.toNumber(expiration) : void 0
1984
2140
  };
1985
2141
  return metadata;
1986
2142
  }
@@ -1994,6 +2150,7 @@ var init_extractors = __esm({
1994
2150
  "use strict";
1995
2151
  init_extract_bearer_extractor();
1996
2152
  init_extract_ssr_bearer_extractor();
2153
+ init_http_cookie_extractor();
1997
2154
  init_http_header_extractor();
1998
2155
  }
1999
2156
  });
@@ -2025,12 +2182,80 @@ var init_resiliences = __esm({
2025
2182
  }
2026
2183
  });
2027
2184
 
2185
+ // src/infrastructure/services/resolver/utils/socket.utils.ts
2186
+ import { Guards as Guards29 } from "@xeno-js/shared";
2187
+ var SocketIpExtractor;
2188
+ var init_socket_utils = __esm({
2189
+ "src/infrastructure/services/resolver/utils/socket.utils.ts"() {
2190
+ "use strict";
2191
+ SocketIpExtractor = Object.freeze({
2192
+ /**
2193
+ * @description Extracts the IP address of the remote socket from an incoming request.
2194
+ * @param req The incoming request object.
2195
+ * @returns The IP address of the remote socket, or undefined if not available.
2196
+ */
2197
+ extract(req) {
2198
+ if (Guards29.isDefined(req) && Guards29.isObject(req)) {
2199
+ const candidate = req;
2200
+ return candidate.socket?.remoteAddress ?? candidate.connection?.remoteAddress;
2201
+ }
2202
+ return void 0;
2203
+ }
2204
+ });
2205
+ }
2206
+ });
2207
+
2208
+ // src/infrastructure/services/resolver/utils/index.ts
2209
+ var init_utils = __esm({
2210
+ "src/infrastructure/services/resolver/utils/index.ts"() {
2211
+ "use strict";
2212
+ init_socket_utils();
2213
+ }
2214
+ });
2215
+
2216
+ // src/infrastructure/services/resolver/client-ip.resolver.ts
2217
+ import { Guards as Guards30 } from "@xeno-js/shared";
2218
+ var ClientIpResolver;
2219
+ var init_client_ip_resolver = __esm({
2220
+ "src/infrastructure/services/resolver/client-ip.resolver.ts"() {
2221
+ "use strict";
2222
+ init_utils();
2223
+ ClientIpResolver = class {
2224
+ constructor(_trustedProxies = []) {
2225
+ this._trustedProxies = _trustedProxies;
2226
+ }
2227
+ _trustedProxies;
2228
+ resolve(req, clientIp) {
2229
+ const socketIp = SocketIpExtractor.extract(req);
2230
+ if (!Guards30.isDefined(socketIp))
2231
+ return !Guards30.isNullOrEmpty(clientIp) ? clientIp.split(",")[0].trim() : void 0;
2232
+ const isTrustedProxy = this._trustedProxies.includes(socketIp);
2233
+ if (!isTrustedProxy) return socketIp;
2234
+ if (Guards30.isDefined(clientIp)) return clientIp.split(",")[0].trim();
2235
+ return socketIp;
2236
+ }
2237
+ };
2238
+ }
2239
+ });
2240
+
2241
+ // src/infrastructure/services/resolver/index.ts
2242
+ var init_resolver = __esm({
2243
+ "src/infrastructure/services/resolver/index.ts"() {
2244
+ "use strict";
2245
+ init_client_ip_resolver();
2246
+ }
2247
+ });
2248
+
2028
2249
  // src/infrastructure/services/index.ts
2029
2250
  var services_exports = {};
2030
2251
  __export(services_exports, {
2031
2252
  AllowMethodRegistry: () => AllowMethodRegistry,
2032
2253
  AllowOrigin: () => AllowOrigin,
2033
2254
  BearerTokenExtractor: () => BearerTokenExtractor,
2255
+ ClientIpResolver: () => ClientIpResolver,
2256
+ CsrfTokenService: () => CsrfTokenService,
2257
+ EdgeCryptoService: () => EdgeCryptoService,
2258
+ HttpCookieExtractor: () => HttpCookieExtractor,
2034
2259
  HttpHeaderExtractor: () => HttpHeaderExtractor,
2035
2260
  PLimitConcurrencyService: () => PLimitConcurrencyService,
2036
2261
  ServiceResilience: () => ServiceResilience,
@@ -2042,8 +2267,11 @@ var init_services = __esm({
2042
2267
  init_allow_methods();
2043
2268
  init_allow_origins();
2044
2269
  init_concurrency();
2270
+ init_crypto();
2271
+ init_csrf();
2045
2272
  init_extractors();
2046
2273
  init_resiliences();
2274
+ init_resolver();
2047
2275
  }
2048
2276
  });
2049
2277
 
@@ -2106,7 +2334,7 @@ var init_axios_factory = __esm({
2106
2334
  });
2107
2335
 
2108
2336
  // src/infrastructure/factories/cockatiel-resilience.factory.ts
2109
- import { AppError as AppError13, Guards as Guards26, RESILIENCE_DEFAULTS } from "@xeno-js/shared";
2337
+ import { AppError as AppError13, Guards as Guards31, RESILIENCE_DEFAULTS } from "@xeno-js/shared";
2110
2338
  import {
2111
2339
  bulkhead,
2112
2340
  circuitBreaker,
@@ -2183,13 +2411,13 @@ var init_cockatiel_resilience_factory = __esm({
2183
2411
  return new ServiceResilience(wrap(bulkheadPolicy, circuitBreakerPolicy, retryPolicy));
2184
2412
  }
2185
2413
  isTransientError(error) {
2186
- if (!Guards26.isDefined(error) || !Guards26.isObject(error)) return false;
2414
+ if (!Guards31.isDefined(error) || !Guards31.isObject(error)) return false;
2187
2415
  let status;
2188
2416
  let isNetworkError = false;
2189
2417
  if (error instanceof AppError13) {
2190
2418
  status = error.status;
2191
2419
  const cause = error.cause;
2192
- if (Guards26.isDefined(cause) && Guards26.isString(cause.code)) {
2420
+ if (Guards31.isDefined(cause) && Guards31.isString(cause.code)) {
2193
2421
  isNetworkError = [
2194
2422
  "ECONNABORTED",
2195
2423
  "ECONNRESET",
@@ -2201,7 +2429,7 @@ var init_cockatiel_resilience_factory = __esm({
2201
2429
  } else {
2202
2430
  const err = error;
2203
2431
  status = err.status;
2204
- if (Guards26.isString(err.code)) {
2432
+ if (Guards31.isString(err.code)) {
2205
2433
  isNetworkError = [
2206
2434
  "ECONNABORTED",
2207
2435
  "ECONNRESET",
@@ -2212,7 +2440,7 @@ var init_cockatiel_resilience_factory = __esm({
2212
2440
  }
2213
2441
  }
2214
2442
  if (isNetworkError) return true;
2215
- if (Guards26.isDefined(status)) {
2443
+ if (Guards31.isDefined(status)) {
2216
2444
  return status === 408 || status === 429 || status >= 500 && status < 600;
2217
2445
  }
2218
2446
  return false;
@@ -2222,22 +2450,22 @@ var init_cockatiel_resilience_factory = __esm({
2222
2450
  let method;
2223
2451
  if (error instanceof AppError13) {
2224
2452
  const cause = error.cause;
2225
- if (Guards26.isDefined(cause) && Guards26.isDefined(cause.config) && Guards26.isString(cause.config.method)) {
2453
+ if (Guards31.isDefined(cause) && Guards31.isDefined(cause.config) && Guards31.isString(cause.config.method)) {
2226
2454
  method = cause.config.method.toUpperCase();
2227
2455
  }
2228
2456
  } else {
2229
2457
  const err = error;
2230
- if (Guards26.isDefined(err.config) && Guards26.isString(err.config.method)) {
2458
+ if (Guards31.isDefined(err.config) && Guards31.isString(err.config.method)) {
2231
2459
  method = err.config.method.toUpperCase();
2232
2460
  }
2233
2461
  }
2234
- if (Guards26.isNullOrEmpty(method)) return false;
2462
+ if (Guards31.isNullOrEmpty(method)) return false;
2235
2463
  const idempotentMethods = ["GET", "PUT", "DELETE", "HEAD", "OPTIONS"];
2236
2464
  return idempotentMethods.includes(method);
2237
2465
  }
2238
2466
  checkConfigValue(value, defaultValue, message) {
2239
- if (Guards26.isDefined(value)) {
2240
- Guards26.throwIfNegative(value, message);
2467
+ if (Guards31.isDefined(value)) {
2468
+ Guards31.throwIfNegative(value, message);
2241
2469
  return value;
2242
2470
  }
2243
2471
  return defaultValue;
@@ -2269,7 +2497,7 @@ var init_db_client_factory = __esm({
2269
2497
  });
2270
2498
 
2271
2499
  // src/infrastructure/context/request-context.ts
2272
- import { Guards as Guards27 } from "@xeno-js/shared";
2500
+ import { Guards as Guards32 } from "@xeno-js/shared";
2273
2501
  var NodeRequestContext;
2274
2502
  var init_request_context = __esm({
2275
2503
  "src/infrastructure/context/request-context.ts"() {
@@ -2301,7 +2529,7 @@ var init_request_context = __esm({
2301
2529
  }
2302
2530
  updateIdentity(identity) {
2303
2531
  const store = this._storage.getStore();
2304
- if (Guards27.isDefined(store) && Guards27.isDefined(store.context)) {
2532
+ if (Guards32.isDefined(store) && Guards32.isDefined(store.context)) {
2305
2533
  store.context = Object.freeze({
2306
2534
  ...store.context,
2307
2535
  identity: Object.freeze(identity)
@@ -2310,23 +2538,23 @@ var init_request_context = __esm({
2310
2538
  }
2311
2539
  getContext() {
2312
2540
  const store = this._storage.getStore();
2313
- if (!Guards27.isDefined(store)) return void 0;
2541
+ if (!Guards32.isDefined(store)) return void 0;
2314
2542
  const context = store.context;
2315
2543
  return Object.freeze(context);
2316
2544
  }
2317
2545
  getIdentity() {
2318
2546
  const store = this._storage.getStore();
2319
- if (!Guards27.isDefined(store)) return void 0;
2547
+ if (!Guards32.isDefined(store)) return void 0;
2320
2548
  return Object.freeze(store.context?.identity);
2321
2549
  }
2322
2550
  getScope() {
2323
2551
  const store = this._storage.getStore();
2324
- if (!Guards27.isDefined(store)) return void 0;
2552
+ if (!Guards32.isDefined(store)) return void 0;
2325
2553
  return store.scope;
2326
2554
  }
2327
2555
  getNetworkContext() {
2328
2556
  const store = this._storage.getStore();
2329
- if (!Guards27.isDefined(store)) return void 0;
2557
+ if (!Guards32.isDefined(store)) return void 0;
2330
2558
  return Object.freeze(store.context?.network);
2331
2559
  }
2332
2560
  };
@@ -2401,7 +2629,7 @@ var init_sql_light_db_client_factory = __esm({
2401
2629
  // src/infrastructure/factories/supabase.factory.ts
2402
2630
  import { createServerClient } from "@supabase/ssr";
2403
2631
  import {
2404
- Guards as Guards28,
2632
+ Guards as Guards33,
2405
2633
  SupabaseAuthService,
2406
2634
  SupabaseClaimsMapper,
2407
2635
  SupabaseSessionMapper
@@ -2415,7 +2643,7 @@ var init_supabase_factory = __esm({
2415
2643
  config,
2416
2644
  container
2417
2645
  }) {
2418
- if (!Guards28.isDefined(config.ssrOpts)) {
2646
+ if (!Guards33.isDefined(config.ssrOpts)) {
2419
2647
  throw new Error("ISsrCookieHandler is required for @supabase/ssr initialization.");
2420
2648
  }
2421
2649
  const cookieService = config.ssrOpts(container);
@@ -2443,7 +2671,7 @@ var user_context_factory_exports = {};
2443
2671
  __export(user_context_factory_exports, {
2444
2672
  UserContextFactory: () => UserContextFactory
2445
2673
  });
2446
- import { Guards as Guards29 } from "@xeno-js/shared";
2674
+ import { Guards as Guards34 } from "@xeno-js/shared";
2447
2675
  var UserContextFactory;
2448
2676
  var init_user_context_factory = __esm({
2449
2677
  "src/infrastructure/factories/user-context.factory.ts"() {
@@ -2468,7 +2696,7 @@ var init_user_context_factory = __esm({
2468
2696
  tenantId: void 0
2469
2697
  };
2470
2698
  const identity = this._identityFactory.getIdentity();
2471
- if (Guards29.isDefined(identity)) {
2699
+ if (Guards34.isDefined(identity)) {
2472
2700
  output.userId = identity.userId;
2473
2701
  output.tenantId = identity.tenantId;
2474
2702
  }
@@ -2561,8 +2789,8 @@ var init_auth_utils = __esm({
2561
2789
  const { TOKENS: TOKENS4 } = await import("@xeno-js/shared");
2562
2790
  const pipelines = [];
2563
2791
  const strategies = [];
2564
- const { Guards: Guards39 } = await import("@xeno-js/shared");
2565
- if (Guards39.isDefined(opts.policies)) {
2792
+ const { Guards: Guards46 } = await import("@xeno-js/shared");
2793
+ if (Guards46.isDefined(opts.policies)) {
2566
2794
  const { PolicyRegistry: PolicyRegistry2 } = await Promise.resolve().then(() => (init_application(), application_exports));
2567
2795
  container.addSingleton(TOKENS4.POLICY_REGISTRY, () => new PolicyRegistry2());
2568
2796
  const policyRegistry = opts.policies;
@@ -2571,16 +2799,16 @@ var init_auth_utils = __esm({
2571
2799
  for (const [intent, policy] of Object.entries(policyRegistry)) {
2572
2800
  const intentLower = intent.toLowerCase();
2573
2801
  registryInstance.addPolicy(intentLower, policy);
2574
- if (!Guards39.isNullOrEmpty(policy.roles)) {
2802
+ if (!Guards46.isNullOrEmpty(policy.roles)) {
2575
2803
  Policies.add("roles");
2576
2804
  }
2577
- if (!Guards39.isNullOrEmpty(policy.permissions)) {
2805
+ if (!Guards46.isNullOrEmpty(policy.permissions)) {
2578
2806
  Policies.add("permissions");
2579
2807
  }
2580
- if (!Guards39.isNullOrEmpty(policy.userId)) {
2808
+ if (!Guards46.isNullOrEmpty(policy.userId)) {
2581
2809
  Policies.add("userId");
2582
2810
  }
2583
- if (!Guards39.isNullOrEmpty(policy.tenantId)) {
2811
+ if (!Guards46.isNullOrEmpty(policy.tenantId)) {
2584
2812
  Policies.add("tenantId");
2585
2813
  }
2586
2814
  }
@@ -2629,10 +2857,10 @@ var init_auth_utils = __esm({
2629
2857
  strategies.push(TOKENS4.TENANT_AUTHORIZATION_PIPELINE);
2630
2858
  }
2631
2859
  }
2632
- if (!Guards39.isNullOrEmpty(opts.customAuthorizationStrategy)) {
2860
+ if (!Guards46.isNullOrEmpty(opts.customAuthorizationStrategy)) {
2633
2861
  const customStrategies = opts.customAuthorizationStrategy;
2634
2862
  customStrategies.forEach((strategyToken, index) => {
2635
- if (Guards39.isDefined(strategyToken)) {
2863
+ if (Guards46.isDefined(strategyToken)) {
2636
2864
  const token = `CUSTOM_AUTHORIZATION_STRATEGY_${index}`;
2637
2865
  container.addSingleton(token, (c) => {
2638
2866
  return strategyToken(c);
@@ -2775,7 +3003,7 @@ __export(unit_of_work_exports, {
2775
3003
  UnitOfWork: () => UnitOfWork
2776
3004
  });
2777
3005
  import { AppError as AppError14 } from "@xeno-js/shared";
2778
- import { Guards as Guards30 } from "@xeno-js/shared";
3006
+ import { Guards as Guards35 } from "@xeno-js/shared";
2779
3007
  var UnitOfWork;
2780
3008
  var init_unit_of_work = __esm({
2781
3009
  "src/infrastructure/transaction/unit-of-work.ts"() {
@@ -2810,9 +3038,9 @@ var init_unit_of_work = __esm({
2810
3038
  });
2811
3039
  }
2812
3040
  async dispose() {
2813
- if (Guards30.isDefined(this._ttx.state)) {
3041
+ if (Guards35.isDefined(this._ttx.state)) {
2814
3042
  try {
2815
- if (Guards30.hasMethod(this._ttx.state, "rollback")) {
3043
+ if (Guards35.hasMethod(this._ttx.state, "rollback")) {
2816
3044
  await this._ttx.state.rollback();
2817
3045
  }
2818
3046
  } finally {
@@ -2835,7 +3063,7 @@ var init_db_module = __esm({
2835
3063
  "use strict";
2836
3064
  DbModule = class {
2837
3065
  async configure(container, opts) {
2838
- const { Guards: Guards39, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
3066
+ const { Guards: Guards46, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
2839
3067
  const { DbUtils: DbUtils2 } = await Promise.resolve().then(() => (init_db_utils(), db_utils_exports));
2840
3068
  const db = opts.enableSqlLite ? await DbUtils2.addSqlLite(opts) : await DbUtils2.addDbClient(opts);
2841
3069
  const { TransactionState: TransactionState2 } = await Promise.resolve().then(() => (init_transaction_state(), transaction_state_exports));
@@ -2852,7 +3080,7 @@ var init_db_module = __esm({
2852
3080
  return new Proxy(db, {
2853
3081
  get(_target, prop, receiver) {
2854
3082
  const activeState = ttx.state;
2855
- if (Guards39.isDefined(activeState)) {
3083
+ if (Guards46.isDefined(activeState)) {
2856
3084
  if (prop === "transaction") {
2857
3085
  return activeState.transaction.bind(activeState);
2858
3086
  }
@@ -2889,14 +3117,14 @@ var init_http_utils = __esm({
2889
3117
  */
2890
3118
  async addAxios(container, opts) {
2891
3119
  const { NodeAxiosFactory: NodeAxiosFactory2 } = await Promise.resolve().then(() => (init_factories(), factories_exports));
2892
- const { Guards: Guards39 } = await import("@xeno-js/shared");
2893
- if (!Guards39.isDefined(opts.token)) {
3120
+ const { Guards: Guards46 } = await import("@xeno-js/shared");
3121
+ if (!Guards46.isDefined(opts.token)) {
2894
3122
  throw new Error("HttpConfig.token is required and must be defined.");
2895
3123
  }
2896
3124
  container.addSingleton(opts.token, () => {
2897
3125
  const factory = new NodeAxiosFactory2();
2898
3126
  const instance = factory.create(opts.client);
2899
- if (!Guards39.hasMethod(instance, "get") || !Guards39.hasMethod(instance, "post") || !Guards39.hasMethod(instance, "put") || !Guards39.hasMethod(instance, "patch") || !Guards39.hasMethod(instance, "delete")) {
3127
+ if (!Guards46.hasMethod(instance, "get") || !Guards46.hasMethod(instance, "post") || !Guards46.hasMethod(instance, "put") || !Guards46.hasMethod(instance, "patch") || !Guards46.hasMethod(instance, "delete")) {
2900
3128
  throw new Error(
2901
3129
  "The created HTTP client instance does not implement the required methods of IHttpClient."
2902
3130
  );
@@ -2923,8 +3151,8 @@ var init_http_utils = __esm({
2923
3151
  });
2924
3152
  },
2925
3153
  async addAllowOrigin(container, opts) {
2926
- const { Guards: Guards39 } = await import("@xeno-js/shared");
2927
- if (Guards39.isNullOrEmpty(opts)) throw new Error("At least an allow origin must be passed");
3154
+ const { Guards: Guards46 } = await import("@xeno-js/shared");
3155
+ if (Guards46.isNullOrEmpty(opts)) throw new Error("At least an allow origin must be passed");
2928
3156
  const { TOKENS: TOKENS4 } = await import("@xeno-js/shared");
2929
3157
  const { AllowOrigin: AllowOrigin2 } = await Promise.resolve().then(() => (init_services(), services_exports));
2930
3158
  const allowOrigin = [];
@@ -2984,13 +3212,13 @@ var init_validation_utils = __esm({
2984
3212
  * @link https://github.com/xeno-js/xeno-js
2985
3213
  */
2986
3214
  async addValidation(container, opts, logger) {
2987
- const { Guards: Guards39, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
2988
- if (!Guards39.isDefined(opts.zod) && Guards39.isNullOrEmpty(opts.customValidationStrategy)) {
3215
+ const { Guards: Guards46, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
3216
+ if (!Guards46.isDefined(opts.zod) && Guards46.isNullOrEmpty(opts.customValidationStrategy)) {
2989
3217
  return [];
2990
3218
  }
2991
3219
  const pipelines = [];
2992
3220
  const validationStrategies = [];
2993
- if (Guards39.isDefined(opts.zod)) {
3221
+ if (Guards46.isDefined(opts.zod)) {
2994
3222
  const config = opts.zod;
2995
3223
  const { ZodValidatorFactory: ZodValidatorFactory2 } = await Promise.resolve().then(() => (init_zod_validator_factory(), zod_validator_factory_exports));
2996
3224
  container.addSingleton(TOKENS4.ZOD_VALIDATOR, () => {
@@ -3004,9 +3232,9 @@ var init_validation_utils = __esm({
3004
3232
  validationStrategies.push(TOKENS4.SCHEMA_VALIDATION_STRATEGY);
3005
3233
  }
3006
3234
  const customValidationFactory = [];
3007
- if (!Guards39.isNullOrEmpty(opts.customValidationStrategy)) {
3235
+ if (!Guards46.isNullOrEmpty(opts.customValidationStrategy)) {
3008
3236
  for (const strategyToken of opts.customValidationStrategy) {
3009
- if (Guards39.isDefined(strategyToken)) {
3237
+ if (Guards46.isDefined(strategyToken)) {
3010
3238
  customValidationFactory.push(strategyToken);
3011
3239
  }
3012
3240
  }
@@ -3109,8 +3337,8 @@ var init_pipeline_utils = __esm({
3109
3337
  */
3110
3338
  async addCommand(container, opts) {
3111
3339
  const pipelines = [];
3112
- const { Guards: Guards39, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
3113
- if (Guards39.isDefined(opts.idempotency)) {
3340
+ const { Guards: Guards46, TOKENS: TOKENS4 } = await import("@xeno-js/shared");
3341
+ if (Guards46.isDefined(opts.idempotency)) {
3114
3342
  const { IdempotencyStore: IdempotencyStore2 } = await Promise.resolve().then(() => (init_idempotency_store(), idempotency_store_exports));
3115
3343
  container.addSingleton(
3116
3344
  TOKENS4.IDEMPOTENCY_STORE,
@@ -3130,7 +3358,7 @@ var init_pipeline_utils = __esm({
3130
3358
  });
3131
3359
  pipelines.push(TOKENS4.IDEMPOTENCY_PIPELINE);
3132
3360
  }
3133
- if (Guards39.isDefined(opts.concurrency)) {
3361
+ if (Guards46.isDefined(opts.concurrency)) {
3134
3362
  const { ConcurrencyRetryPipeline: ConcurrencyRetryPipeline2 } = await Promise.resolve().then(() => (init_application(), application_exports));
3135
3363
  container.addSingleton(TOKENS4.CONCURRENCY_RETRY_PIPELINE, () => {
3136
3364
  const config = opts.concurrency;
@@ -3210,13 +3438,13 @@ var init_cqrs_module = __esm({
3210
3438
  return new PerformancePipeline2(logger, thresholdMs);
3211
3439
  });
3212
3440
  pipelines.push(TOKENS4.PERFORMANCE_PIPELINE);
3213
- const { Guards: Guards39 } = await import("@xeno-js/shared");
3214
- if (Guards39.isDefined(opts.authorization.policies) || Guards39.isDefined(opts.authorization.customAuthorizationStrategy)) {
3441
+ const { Guards: Guards46 } = await import("@xeno-js/shared");
3442
+ if (Guards46.isDefined(opts.authorization.policies) || Guards46.isDefined(opts.authorization.customAuthorizationStrategy)) {
3215
3443
  const { AuthUtils: AuthUtils2 } = await Promise.resolve().then(() => (init_auth_utils(), auth_utils_exports));
3216
3444
  const authPipelines = await AuthUtils2.addAuthZ(container, opts.authorization);
3217
3445
  pipelines.push(...authPipelines);
3218
3446
  }
3219
- if (Guards39.isDefined(opts.validation.zod) || Guards39.isDefined(opts.validation.customValidationStrategy)) {
3447
+ if (Guards46.isDefined(opts.validation.zod) || Guards46.isDefined(opts.validation.customValidationStrategy)) {
3220
3448
  const { ValidationUtils: ValidationUtils2 } = await Promise.resolve().then(() => (init_validation_utils(), validation_utils_exports));
3221
3449
  const logger = container.resolve(TOKENS4.LOGGER);
3222
3450
  const validationPipelines = await ValidationUtils2.addValidation(
@@ -3228,11 +3456,11 @@ var init_cqrs_module = __esm({
3228
3456
  }
3229
3457
  const commandPipelines = pipelines;
3230
3458
  const queryPipelines = pipelines;
3231
- if ((Guards39.isDefined(opts.commandBus.idempotency) || opts.queryBus.isEnabled) && opts.isCache) {
3459
+ if ((Guards46.isDefined(opts.commandBus.idempotency) || opts.queryBus.isEnabled) && opts.isCache) {
3232
3460
  const { CacheUtils: CacheUtils2 } = await Promise.resolve().then(() => (init_cache_utils(), cache_utils_exports));
3233
3461
  await CacheUtils2.addCache(container, { inMemory: true, redis: void 0 });
3234
3462
  }
3235
- if (Guards39.isDefined(opts.commandBus.idempotency) || Guards39.isDefined(opts.commandBus.concurrency)) {
3463
+ if (Guards46.isDefined(opts.commandBus.idempotency) || Guards46.isDefined(opts.commandBus.concurrency)) {
3236
3464
  const { PipelineUtils: PipelineUtils2 } = await Promise.resolve().then(() => (init_pipeline_utils(), pipeline_utils_exports));
3237
3465
  const newCommandPipelines = await PipelineUtils2.addCommand(container, {
3238
3466
  ...opts.commandBus,
@@ -3554,7 +3782,7 @@ var init_composite_middleware = __esm({
3554
3782
  });
3555
3783
 
3556
3784
  // src/presentation/middlewares/cors.middleware.ts
3557
- import { Guards as Guards31 } from "@xeno-js/shared";
3785
+ import { Guards as Guards36 } from "@xeno-js/shared";
3558
3786
  var CORSMiddleware;
3559
3787
  var init_cors_middleware = __esm({
3560
3788
  "src/presentation/middlewares/cors.middleware.ts"() {
@@ -3568,7 +3796,7 @@ var init_cors_middleware = __esm({
3568
3796
  const { network } = this._requestContext.getContext() ?? {};
3569
3797
  const origin = network?.origin;
3570
3798
  const response = await next();
3571
- if (Guards31.isDefined(origin))
3799
+ if (Guards36.isDefined(origin))
3572
3800
  response.headers = {
3573
3801
  ...response.headers ?? {},
3574
3802
  "Access-Control-Allow-Origin": origin,
@@ -3585,7 +3813,7 @@ var init_cors_middleware = __esm({
3585
3813
  import {
3586
3814
  ERROR_CODE_MESSAGES as ERROR_CODE_MESSAGES5,
3587
3815
  ERROR_CODES as ERROR_CODES6,
3588
- Guards as Guards32,
3816
+ Guards as Guards37,
3589
3817
  GuidHelper as GuidHelper9,
3590
3818
  HttpHelper as HttpHelper6,
3591
3819
  STATUS_CODES as STATUS_CODES7
@@ -3595,30 +3823,69 @@ var init_csrf_middleware = __esm({
3595
3823
  "src/presentation/middlewares/csrf.middleware.ts"() {
3596
3824
  "use strict";
3597
3825
  CsrfMiddleware = class {
3598
- constructor(_requestContext, _csrf) {
3826
+ constructor(_requestContext, _csrfTokenService) {
3599
3827
  this._requestContext = _requestContext;
3600
- this._csrf = _csrf;
3828
+ this._csrfTokenService = _csrfTokenService;
3601
3829
  }
3602
3830
  _requestContext;
3603
- _csrf;
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
- */
3831
+ _csrfTokenService;
3609
3832
  async execute(req, _headers, next) {
3610
3833
  const method = req.method.toUpperCase();
3611
3834
  const isStateChanging = ["POST", "PUT", "DELETE", "PATCH"].includes(method);
3612
3835
  if (isStateChanging) {
3613
- const { network, tracing } = this._requestContext.getContext() ?? {};
3614
- if (!Guards32.isDefined(network?.csrf) || network.csrf.toLowerCase() !== this._csrf.toLowerCase()) {
3836
+ const { network, tracing, identity } = this._requestContext.getContext() ?? {};
3837
+ const headerToken = network?.csrf;
3838
+ const cookieToken = network?.csrfCookie;
3839
+ if (!Guards37.isDefined(headerToken) || !Guards37.isDefined(cookieToken)) {
3840
+ return HttpHelper6.error(
3841
+ {
3842
+ success: false,
3843
+ error: {
3844
+ code: ERROR_CODES6.FORBIDDEN,
3845
+ message: ERROR_CODE_MESSAGES5[ERROR_CODES6.FORBIDDEN],
3846
+ details: "CSRF token missing",
3847
+ path: req.path
3848
+ },
3849
+ correlationId: tracing?.correlationId ?? GuidHelper9.generate(),
3850
+ requestId: network?.requestId ?? GuidHelper9.generate(),
3851
+ spanId: tracing?.spanId ?? GuidHelper9.generate(),
3852
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3853
+ },
3854
+ STATUS_CODES7.FORBIDDEN,
3855
+ {
3856
+ "Content-Type": [network?.formatIndicator ?? "application/json"]
3857
+ }
3858
+ );
3859
+ }
3860
+ if (headerToken !== cookieToken) {
3861
+ return HttpHelper6.error(
3862
+ {
3863
+ success: false,
3864
+ error: {
3865
+ code: ERROR_CODES6.FORBIDDEN,
3866
+ message: ERROR_CODE_MESSAGES5[ERROR_CODES6.FORBIDDEN],
3867
+ details: "CSRF token mismatch",
3868
+ path: req.path
3869
+ },
3870
+ correlationId: tracing?.correlationId ?? GuidHelper9.generate(),
3871
+ requestId: network?.requestId ?? GuidHelper9.generate(),
3872
+ spanId: tracing?.spanId ?? GuidHelper9.generate(),
3873
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3874
+ },
3875
+ STATUS_CODES7.FORBIDDEN,
3876
+ {
3877
+ "Content-Type": [network?.formatIndicator ?? "application/json"]
3878
+ }
3879
+ );
3880
+ }
3881
+ if (!Guards37.isDefined(identity?.userId) || !await this._csrfTokenService.validate(headerToken, identity?.userId)) {
3615
3882
  return HttpHelper6.error(
3616
3883
  {
3617
3884
  success: false,
3618
3885
  error: {
3619
3886
  code: ERROR_CODES6.FORBIDDEN,
3620
3887
  message: ERROR_CODE_MESSAGES5[ERROR_CODES6.FORBIDDEN],
3621
- details: "CSRF header is missing or invalid",
3888
+ details: "CSRF token invalid",
3622
3889
  path: req.path
3623
3890
  },
3624
3891
  correlationId: tracing?.correlationId ?? GuidHelper9.generate(),
@@ -3639,8 +3906,46 @@ var init_csrf_middleware = __esm({
3639
3906
  }
3640
3907
  });
3641
3908
 
3909
+ // src/presentation/middlewares/csrf-cookie.middleware.ts
3910
+ import { Guards as Guards38 } from "@xeno-js/shared";
3911
+ var CsrfCookieMiddleware;
3912
+ var init_csrf_cookie_middleware = __esm({
3913
+ "src/presentation/middlewares/csrf-cookie.middleware.ts"() {
3914
+ "use strict";
3915
+ CsrfCookieMiddleware = class {
3916
+ constructor(_requestContext, _csrfTokenService, _csrf) {
3917
+ this._requestContext = _requestContext;
3918
+ this._csrfTokenService = _csrfTokenService;
3919
+ this._csrf = _csrf;
3920
+ }
3921
+ _requestContext;
3922
+ _csrfTokenService;
3923
+ _csrf;
3924
+ async execute(_req, _headers, next) {
3925
+ const response = await next();
3926
+ const context = this._requestContext.getContext();
3927
+ const identity = context?.identity;
3928
+ const network = context?.network;
3929
+ if (!Guards38.isDefined(identity?.userId)) return response;
3930
+ if (Guards38.isDefined(network?.csrfCookie)) return response;
3931
+ const token = await this._csrfTokenService.generate(identity.userId);
3932
+ const cookieName = this._csrf.cookieName ?? "__Host-xeno-csrf";
3933
+ const maxAge = this._csrf.cookieMaxAgeSeconds ?? 3600;
3934
+ const sameSite = this._csrf.sameSite ?? "lax";
3935
+ const cookie = `${cookieName}=${encodeURIComponent(token)}; Path=/; Secure; SameSite=${sameSite}; Max-Age=${maxAge}`;
3936
+ const existingCookies = response.headers["Set-Cookie"];
3937
+ response.headers = {
3938
+ ...response.headers ?? {},
3939
+ "Set-Cookie": [...existingCookies ?? [], cookie]
3940
+ };
3941
+ return response;
3942
+ }
3943
+ };
3944
+ }
3945
+ });
3946
+
3642
3947
  // src/presentation/middlewares/options.middleware.ts
3643
- import { Guards as Guards33, HttpHelper as HttpHelper7, STATUS_CODES as STATUS_CODES8 } from "@xeno-js/shared";
3948
+ import { Guards as Guards39, HttpHelper as HttpHelper7, STATUS_CODES as STATUS_CODES8 } from "@xeno-js/shared";
3644
3949
  var OptionsMiddleware;
3645
3950
  var init_options_middleware = __esm({
3646
3951
  "src/presentation/middlewares/options.middleware.ts"() {
@@ -3655,13 +3960,13 @@ var init_options_middleware = __esm({
3655
3960
  const network = this._requestContext.getNetworkContext();
3656
3961
  const origin = network?.origin;
3657
3962
  const headers = {};
3658
- if (Guards33.isDefined(origin)) {
3963
+ if (Guards39.isDefined(origin)) {
3659
3964
  headers["Access-Control-Allow-Origin"] = origin;
3660
3965
  headers["Access-Control-Allow-Credentials"] = "true";
3661
3966
  headers["Vary"] = "Origin";
3662
3967
  }
3663
- headers["Access-Control-Allow-Methods"] = "POST,GET,PUT,DELETE,OPTIONS";
3664
- headers["Access-Control-Allow-Headers"] = "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Type, Authorization, X-Correlation-Id";
3968
+ headers["Access-Control-Allow-Methods"] = "POST,GET,PUT,PATCH,DELETE,OPTIONS";
3969
+ headers["Access-Control-Allow-Headers"] = "X-CSRF-Token, Accept, Accept-Version, Content-Type, Authorization, X-Correlation-Id";
3665
3970
  return HttpHelper7.success(null, STATUS_CODES8.NO_CONTENT, {}, headers);
3666
3971
  }
3667
3972
  return await next();
@@ -3671,7 +3976,7 @@ var init_options_middleware = __esm({
3671
3976
  });
3672
3977
 
3673
3978
  // src/presentation/middlewares/rate-limiter.middleware.ts
3674
- import { ERROR_CODES as ERROR_CODES7, GuidHelper as GuidHelper10, HttpHelper as HttpHelper8 } from "@xeno-js/shared";
3979
+ import { ERROR_CODES as ERROR_CODES7, Guards as Guards40, GuidHelper as GuidHelper10, HttpHelper as HttpHelper8, STATUS_CODES as STATUS_CODES9 } from "@xeno-js/shared";
3675
3980
  var RateLimitMiddleware;
3676
3981
  var init_rate_limiter_middleware = __esm({
3677
3982
  "src/presentation/middlewares/rate-limiter.middleware.ts"() {
@@ -3687,12 +3992,33 @@ var init_rate_limiter_middleware = __esm({
3687
3992
  _cache;
3688
3993
  _logger;
3689
3994
  _opts;
3690
- async execute(req, headers, next) {
3995
+ async execute(req, _headers, next) {
3691
3996
  const { network, tracing } = this._ctxAccessor.getContext() ?? {};
3997
+ if (!Guards40.isDefined(network?.clientIp))
3998
+ return HttpHelper8.error(
3999
+ {
4000
+ success: false,
4001
+ error: {
4002
+ code: ERROR_CODES7.SYSTEM_ERROR,
4003
+ message: "IP undefined. Please contact the administrator.",
4004
+ details: `IP undefined. Please contact the administrator.`,
4005
+ path: req.path
4006
+ },
4007
+ correlationId: tracing?.correlationId ?? GuidHelper10.generate(),
4008
+ requestId: network?.requestId ?? GuidHelper10.generate(),
4009
+ spanId: tracing?.spanId ?? GuidHelper10.generate(),
4010
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4011
+ },
4012
+ STATUS_CODES9.SERVICE_UNAVAILABLE,
4013
+ {
4014
+ "Content-Type": [network?.formatIndicator ?? "application/json"],
4015
+ "Retry-After": [String(this._opts.windowSeconds)]
4016
+ }
4017
+ );
3692
4018
  const clientIp = network?.clientIp;
3693
4019
  const cacheKey = `rate_limit:${clientIp}`;
3694
- const currentHits = await this._cache.get(cacheKey) ?? 0;
3695
- if (currentHits >= this._opts.maxRequests) {
4020
+ const currentHits = await this._cache.increment(cacheKey, this._opts.windowSeconds);
4021
+ if (currentHits > this._opts.maxRequests) {
3696
4022
  this._logger.warn(`[RateLimit] IP ${clientIp} blocked on ${req.path}`);
3697
4023
  return HttpHelper8.error(
3698
4024
  {
@@ -3708,14 +4034,13 @@ var init_rate_limiter_middleware = __esm({
3708
4034
  spanId: tracing?.spanId ?? GuidHelper10.generate(),
3709
4035
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
3710
4036
  },
3711
- 429,
4037
+ STATUS_CODES9.TOO_MANY_REQUESTS,
3712
4038
  {
3713
4039
  "Content-Type": [network?.formatIndicator ?? "application/json"],
3714
4040
  "Retry-After": [String(this._opts.windowSeconds)]
3715
4041
  }
3716
4042
  );
3717
4043
  }
3718
- await this._cache.set(cacheKey, currentHits + 1, this._opts.windowSeconds);
3719
4044
  return next();
3720
4045
  }
3721
4046
  };
@@ -3723,10 +4048,10 @@ var init_rate_limiter_middleware = __esm({
3723
4048
  });
3724
4049
 
3725
4050
  // src/presentation/mappers/context.mapper.ts
3726
- import { Guards as Guards34 } from "@xeno-js/shared";
4051
+ import { Guards as Guards41 } from "@xeno-js/shared";
3727
4052
  function _buildMessagingContext(meta) {
3728
- const hasSequenceData = Guards34.isDefined(meta.sequence?.sequenceId) || Guards34.isDefined(meta.sequence?.position) || Guards34.isDefined(meta.sequence?.size);
3729
- const hasMessagingData = hasSequenceData || Guards34.isDefined(meta.expiration) || Guards34.isDefined(meta.returnAddress);
4053
+ const hasSequenceData = Guards41.isDefined(meta.sequence?.sequenceId) || Guards41.isDefined(meta.sequence?.position) || Guards41.isDefined(meta.sequence?.size);
4054
+ const hasMessagingData = hasSequenceData || Guards41.isDefined(meta.expiration) || Guards41.isDefined(meta.returnAddress);
3730
4055
  const messaging = hasMessagingData ? {
3731
4056
  returnAddress: meta.returnAddress,
3732
4057
  expiration: meta.expiration,
@@ -3757,6 +4082,7 @@ var init_context_mapper = __esm({
3757
4082
  path,
3758
4083
  transport,
3759
4084
  csrf: metadata.csrf,
4085
+ csrfCookie: metadata.csrfCookie,
3760
4086
  origin: metadata.origin
3761
4087
  };
3762
4088
  const tracing = {
@@ -3786,7 +4112,7 @@ import {
3786
4112
  GUEST as GUEST3,
3787
4113
  GuidHelper as GuidHelper11,
3788
4114
  HttpHelper as HttpHelper9,
3789
- STATUS_CODES as STATUS_CODES9
4115
+ STATUS_CODES as STATUS_CODES10
3790
4116
  } from "@xeno-js/shared";
3791
4117
  var RequestContextMiddleware;
3792
4118
  var init_request_middleware = __esm({
@@ -3805,13 +4131,15 @@ var init_request_middleware = __esm({
3805
4131
  * @since 2025-09-30
3806
4132
  * @link https://github.com/xeno-js/xeno-js
3807
4133
  */
3808
- constructor(_requestContext, _extractor, _logger) {
4134
+ constructor(_requestContext, _extractor, _resolver, _logger) {
3809
4135
  this._requestContext = _requestContext;
3810
4136
  this._extractor = _extractor;
4137
+ this._resolver = _resolver;
3811
4138
  this._logger = _logger;
3812
4139
  }
3813
4140
  _requestContext;
3814
4141
  _extractor;
4142
+ _resolver;
3815
4143
  _logger;
3816
4144
  async execute(req, headers, next) {
3817
4145
  const correlationId = GuidHelper11.generate();
@@ -3820,8 +4148,10 @@ var init_request_middleware = __esm({
3820
4148
  const formatIndicator = "application/json";
3821
4149
  try {
3822
4150
  const meta = this._extractor.extract(headers);
4151
+ const clientIp = this._resolver.resolve(req.transport.req, meta.clientIp);
3823
4152
  const metadata = {
3824
4153
  ...meta,
4154
+ clientIp,
3825
4155
  correlationId: meta.correlationId ?? correlationId,
3826
4156
  requestId: meta.requestId ?? requestId,
3827
4157
  spanId: meta.spanId ?? spanId,
@@ -3855,7 +4185,7 @@ var init_request_middleware = __esm({
3855
4185
  spanId,
3856
4186
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
3857
4187
  },
3858
- STATUS_CODES9.INTERNAL_SERVER_ERROR,
4188
+ STATUS_CODES10.INTERNAL_SERVER_ERROR,
3859
4189
  { "Content-Type": [formatIndicator] }
3860
4190
  );
3861
4191
  }
@@ -3874,6 +4204,7 @@ var init_middlewares = __esm({
3874
4204
  init_composite_middleware();
3875
4205
  init_cors_middleware();
3876
4206
  init_csrf_middleware();
4207
+ init_csrf_cookie_middleware();
3877
4208
  init_options_middleware();
3878
4209
  init_rate_limiter_middleware();
3879
4210
  init_request_middleware();
@@ -3888,6 +4219,7 @@ __export(presentation_exports, {
3888
4219
  BaseController: () => BaseController,
3889
4220
  CORSMiddleware: () => CORSMiddleware,
3890
4221
  CompositeMiddleware: () => CompositeMiddleware,
4222
+ CsrfCookieMiddleware: () => CsrfCookieMiddleware,
3891
4223
  CsrfMiddleware: () => CsrfMiddleware,
3892
4224
  MethodCheckMiddleware: () => MethodCheckMiddleware,
3893
4225
  OptionsMiddleware: () => OptionsMiddleware,
@@ -3907,7 +4239,9 @@ var middleware_module_exports = {};
3907
4239
  __export(middleware_module_exports, {
3908
4240
  MiddlewareModule: () => MiddlewareModule
3909
4241
  });
3910
- import { Guards as Guards35 } from "@xeno-js/shared";
4242
+ import {
4243
+ Guards as Guards42
4244
+ } from "@xeno-js/shared";
3911
4245
  var MiddlewareModule;
3912
4246
  var init_middleware_module = __esm({
3913
4247
  "src/infrastructure/modules/middleware.module.ts"() {
@@ -3926,15 +4260,24 @@ var init_middleware_module = __esm({
3926
4260
  const { BearerTokenExtractor: BearerTokenExtractor2 } = await Promise.resolve().then(() => (init_services(), services_exports));
3927
4261
  container.addSingleton(TOKENS4.BEARER_TOKEN_EXTRACTOR, () => new BearerTokenExtractor2());
3928
4262
  }
4263
+ const { HttpCookieExtractor: HttpCookieExtractor2 } = await Promise.resolve().then(() => (init_services(), services_exports));
4264
+ container.addSingleton("COOKIE_EXTRACTOR", () => new HttpCookieExtractor2());
3929
4265
  const { HttpHeaderExtractor: HttpHeaderExtractor2 } = await Promise.resolve().then(() => (init_services(), services_exports));
3930
4266
  container.addSingleton(
3931
4267
  TOKENS4.SERVICE_EXTRACTOR,
3932
- (c) => new HttpHeaderExtractor2(c.resolve(TOKENS4.BEARER_TOKEN_EXTRACTOR), opts.trustedIpHeader)
4268
+ (c) => new HttpHeaderExtractor2(
4269
+ c.resolve(TOKENS4.BEARER_TOKEN_EXTRACTOR),
4270
+ c.resolve("COOKIE_EXTRACTOR"),
4271
+ opts.trustedIpHeader,
4272
+ opts.csrf?.cookieName ?? "__Host-xeno-csrf"
4273
+ )
3933
4274
  );
3934
4275
  if (!opts.isLogger) {
3935
4276
  const { LoggerUtils: LoggerUtils2 } = await Promise.resolve().then(() => (init_logger_utils(), logger_utils_exports));
3936
4277
  await LoggerUtils2.addLogger(container, void 0);
3937
4278
  }
4279
+ const { ClientIpResolver: ClientIpResolver2 } = await Promise.resolve().then(() => (init_services(), services_exports));
4280
+ container.addSingleton("IP_RESOLVER", () => new ClientIpResolver2(opts.trustedProxies));
3938
4281
  const middlewares = [TOKENS4.REQUEST_CONTEXT_MIDDLEWARE];
3939
4282
  const { RequestContextMiddleware: RequestContextMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
3940
4283
  container.addSingleton(
@@ -3942,18 +4285,14 @@ var init_middleware_module = __esm({
3942
4285
  (c) => new RequestContextMiddleware2(
3943
4286
  c.resolve(TOKENS4.REQUEST_CONTEXT),
3944
4287
  c.resolve(TOKENS4.SERVICE_EXTRACTOR),
4288
+ c.resolve("IP_RESOLVER"),
3945
4289
  c.resolve(TOKENS4.LOGGER)
3946
4290
  )
3947
4291
  );
3948
- if (opts.optionsMiddleware) {
3949
- const { OptionsMiddleware: OptionsMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
3950
- container.addSingleton(
3951
- TOKENS4.OPTIONS_MIDDLEWARE,
3952
- (c) => new OptionsMiddleware2(c.resolve(TOKENS4.NETWORK_CONTEXT_ACCESSOR))
3953
- );
3954
- middlewares.push(TOKENS4.OPTIONS_MIDDLEWARE);
3955
- }
3956
- if (!Guards35.isNullOrEmpty(opts.allowOrigins)) {
4292
+ if (!Guards42.isNullOrEmpty(opts.allowOrigins)) {
4293
+ const withCredentials = Guards42.isDefined(opts.httpConfig.withCredentials) ? opts.httpConfig.withCredentials : false;
4294
+ if (withCredentials && opts.allowOrigins.includes("*"))
4295
+ throw new Error("Wildcard CORS origin is not allowed when withCredentials is set to true");
3957
4296
  const { AllowOrigin: AllowOrigin2 } = await Promise.resolve().then(() => (init_services(), services_exports));
3958
4297
  container.addSingleton("ALLOW_ORIGIN", () => {
3959
4298
  return new AllowOrigin2(opts.allowOrigins);
@@ -3968,6 +4307,14 @@ var init_middleware_module = __esm({
3968
4307
  });
3969
4308
  middlewares.push(TOKENS4.ALLOW_ORIGIN_MIDDLEWARE);
3970
4309
  }
4310
+ if (opts.optionsMiddleware) {
4311
+ const { OptionsMiddleware: OptionsMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
4312
+ container.addSingleton(
4313
+ TOKENS4.OPTIONS_MIDDLEWARE,
4314
+ (c) => new OptionsMiddleware2(c.resolve(TOKENS4.NETWORK_CONTEXT_ACCESSOR))
4315
+ );
4316
+ middlewares.push(TOKENS4.OPTIONS_MIDDLEWARE);
4317
+ }
3971
4318
  if (opts.cors) {
3972
4319
  const { CORSMiddleware: CORSMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
3973
4320
  container.addSingleton(TOKENS4.CORS_MIDDLEWARE, (c) => {
@@ -3975,7 +4322,7 @@ var init_middleware_module = __esm({
3975
4322
  });
3976
4323
  middlewares.push(TOKENS4.CORS_MIDDLEWARE);
3977
4324
  }
3978
- if (Guards35.isDefined(opts.routeRegistry)) {
4325
+ if (Guards42.isDefined(opts.routeRegistry)) {
3979
4326
  const registry = opts.routeRegistry;
3980
4327
  const { AllowMethodFactory: AllowMethodFactory2 } = await Promise.resolve().then(() => (init_factories(), factories_exports));
3981
4328
  container.addSingleton(TOKENS4.ALLOW_METHOD, () => new AllowMethodFactory2().create(registry));
@@ -3989,21 +4336,47 @@ var init_middleware_module = __esm({
3989
4336
  );
3990
4337
  middlewares.push(TOKENS4.METHOD_CHECK_MIDDLEWARE);
3991
4338
  }
3992
- if (Guards35.isDefined(opts.csrf)) {
4339
+ const { AuthenticationMiddleware: AuthenticationMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
4340
+ container.addSingleton(TOKENS4.AUTH_MIDDLEWARE, (c) => {
4341
+ return new AuthenticationMiddleware2(
4342
+ c.resolve(TOKENS4.REQUEST_CONTEXT),
4343
+ c.resolve(TOKENS4.BEARER_TOKEN_EXTRACTOR),
4344
+ c.resolve(TOKENS4.GATE_KEEPER),
4345
+ c.resolve(TOKENS4.LOGGER)
4346
+ );
4347
+ });
4348
+ middlewares.push(TOKENS4.AUTH_MIDDLEWARE);
4349
+ if (Guards42.isDefined(opts.csrf)) {
3993
4350
  const csrf = opts.csrf;
4351
+ const { CsrfTokenService: CsrfTokenService2 } = await Promise.resolve().then(() => (init_services(), services_exports));
4352
+ container.addSingleton("CSRF_TOKEN_SERVICE", (c) => {
4353
+ return new CsrfTokenService2(csrf.secret, c.resolve("CRYPTO_SERVICE"));
4354
+ });
4355
+ const { CsrfCookieMiddleware: CsrfCookieMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
4356
+ container.addSingleton("CSRF_COOKIE_MIDDLEWARE", (c) => {
4357
+ return new CsrfCookieMiddleware2(
4358
+ c.resolve(TOKENS4.REQUEST_CONTEXT),
4359
+ c.resolve("CSRF_TOKEN_SERVICE"),
4360
+ csrf
4361
+ );
4362
+ });
4363
+ middlewares.push("CSRF_COOKIE_MIDDLEWARE");
3994
4364
  const { CsrfMiddleware: CsrfMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
3995
4365
  container.addSingleton(TOKENS4.CSRF_MIDDLEWARE, (c) => {
3996
- return new CsrfMiddleware2(c.resolve(TOKENS4.REQUEST_CONTEXT), csrf);
4366
+ return new CsrfMiddleware2(
4367
+ c.resolve(TOKENS4.REQUEST_CONTEXT),
4368
+ c.resolve("CSRF_TOKEN_SERVICE")
4369
+ );
3997
4370
  });
3998
4371
  middlewares.push(TOKENS4.CSRF_MIDDLEWARE);
3999
4372
  }
4000
- if (Guards35.isDefined(opts.rateLimite.maxRequests) || Guards35.isDefined(opts.rateLimite.windowSeconds)) {
4373
+ if (Guards42.isDefined(opts.rateLimite.maxRequests) || Guards42.isDefined(opts.rateLimite.windowSeconds)) {
4001
4374
  const maxRequests = opts.rateLimite.maxRequests ?? 30;
4002
- Guards35.throwIfNegative(maxRequests, "MaxRequests must be positive");
4003
- Guards35.throwIfNotInteger(maxRequests, "MaxRequests must be an integer");
4375
+ Guards42.throwIfNegative(maxRequests, "MaxRequests must be positive");
4376
+ Guards42.throwIfNotInteger(maxRequests, "MaxRequests must be an integer");
4004
4377
  const windowSeconds = opts.rateLimite.windowSeconds ?? 30;
4005
- Guards35.throwIfNegative(windowSeconds, "WindowSeconds must be positive");
4006
- Guards35.throwIfNotInteger(windowSeconds, "WindowSeconds must be an integer");
4378
+ Guards42.throwIfNegative(windowSeconds, "WindowSeconds must be positive");
4379
+ Guards42.throwIfNotInteger(windowSeconds, "WindowSeconds must be an integer");
4007
4380
  if (!opts.isCache) {
4008
4381
  const { CacheUtils: CacheUtils2 } = await Promise.resolve().then(() => (init_cache_utils(), cache_utils_exports));
4009
4382
  await CacheUtils2.addCache(container, { inMemory: true, redis: void 0 });
@@ -4022,16 +4395,6 @@ var init_middleware_module = __esm({
4022
4395
  });
4023
4396
  middlewares.push(TOKENS4.RATE_LIMITER_MIDDLEWARE);
4024
4397
  }
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
4398
  const { CompositeMiddleware: CompositeMiddleware2 } = await Promise.resolve().then(() => (init_presentation(), presentation_exports));
4036
4399
  container.addSingleton(TOKENS4.MIDDLEWARE, (c) => {
4037
4400
  const resolvedMiddleware = middlewares.map(
@@ -4101,7 +4464,7 @@ __export(index_exports, {
4101
4464
  init_application();
4102
4465
 
4103
4466
  // src/infrastructure/builder/app.builder.ts
4104
- import { Guards as Guards36, LOG_LEVEL as LOG_LEVEL6, TOKENS as TOKENS3 } from "@xeno-js/shared";
4467
+ import { Guards as Guards43, LOG_LEVEL as LOG_LEVEL6, TOKENS as TOKENS3 } from "@xeno-js/shared";
4105
4468
 
4106
4469
  // src/infrastructure/configuration/configuration.ts
4107
4470
  import { Guards as Guards13 } from "@xeno-js/shared";
@@ -4377,6 +4740,9 @@ var AppBuilder = class {
4377
4740
  () => new EnvironmentConfigurationService()
4378
4741
  );
4379
4742
  this._configuration = this._container.resolve(TOKENS3.CONFIGURATION_SERVICE);
4743
+ this._middlewareConfig.allowOrigins?.push(
4744
+ this._configuration.get("APP_URL") ?? `http://localhost:${this._configuration.getNumber("PORT", 3e3)}`
4745
+ );
4380
4746
  }
4381
4747
  // --- Module Configurations ---
4382
4748
  _modules = [];
@@ -4408,7 +4774,8 @@ var AppBuilder = class {
4408
4774
  optionsMiddleware: false,
4409
4775
  routeRegistry: void 0,
4410
4776
  trustedIpHeader: void 0,
4411
- allowOrigins: ["*"],
4777
+ trustedProxies: [],
4778
+ allowOrigins: [],
4412
4779
  cors: true
4413
4780
  };
4414
4781
  _httpConfig = {
@@ -4491,7 +4858,7 @@ var AppBuilder = class {
4491
4858
  pino: { config: void 0 },
4492
4859
  customLoggers: void 0
4493
4860
  };
4494
- if (Guards36.isDefined(setupAction) && Guards36.isDefined(config))
4861
+ if (Guards43.isDefined(setupAction) && Guards43.isDefined(config))
4495
4862
  setupAction(config, this._configuration);
4496
4863
  this._modules.push({
4497
4864
  priority: 3,
@@ -4517,7 +4884,7 @@ var AppBuilder = class {
4517
4884
  addCache(setupAction) {
4518
4885
  if (this._isCacheModuleQueued) return this;
4519
4886
  this._isCacheModuleQueued = true;
4520
- if (Guards36.isDefined(setupAction)) setupAction(this._config, this._configuration);
4887
+ if (Guards43.isDefined(setupAction)) setupAction(this._config, this._configuration);
4521
4888
  this._modules.push({
4522
4889
  priority: 3,
4523
4890
  name: "CacheModule",
@@ -4626,7 +4993,7 @@ var AppBuilder = class {
4626
4993
  * @link https://github.com/xeno-js/xeno-js
4627
4994
  */
4628
4995
  addPipeline(setupAction) {
4629
- if (Guards36.isDefined(setupAction)) {
4996
+ if (Guards43.isDefined(setupAction)) {
4630
4997
  setupAction(this._pipelineConfig, this._configuration);
4631
4998
  }
4632
4999
  this._queuePipelineModule();
@@ -4760,7 +5127,7 @@ var AppBuilder = class {
4760
5127
  console.error(`\u{1F449} Module: **${queued.name}**`);
4761
5128
  console.error(`\u{1F4DD} Reason: ${errorMessage}
4762
5129
  `);
4763
- if (error instanceof Error && Guards36.isDefined(error.stack)) {
5130
+ if (error instanceof Error && Guards43.isDefined(error.stack)) {
4764
5131
  console.error(error.stack);
4765
5132
  }
4766
5133
  throw new Error(`Bootstrap failed at [${queued.name}]: ${errorMessage}`, { cause: error });
@@ -4822,7 +5189,8 @@ var AppBuilder = class {
4822
5189
  ...this._middlewareConfig,
4823
5190
  isAuth: this._isAuthModuleQueued,
4824
5191
  isLogger: this._isLoggerModuleQueued,
4825
- isCache: this._isCacheModuleQueued || this._isPipelineModuleQueued
5192
+ isCache: this._isCacheModuleQueued || this._isPipelineModuleQueued,
5193
+ httpConfig: this._httpConfig.http.client
4826
5194
  });
4827
5195
  }
4828
5196
  });
@@ -4889,7 +5257,7 @@ init_validation_utils();
4889
5257
 
4890
5258
  // src/infrastructure/repositories/read-dao.ts
4891
5259
  import { AppError as AppError16, Result as Result17 } from "@xeno-js/shared";
4892
- import { Guards as Guards37 } from "@xeno-js/shared";
5260
+ import { Guards as Guards44 } from "@xeno-js/shared";
4893
5261
  var ReadDao = class {
4894
5262
  /**
4895
5263
  * Constructs a new ReadDao instance.
@@ -4911,7 +5279,7 @@ var ReadDao = class {
4911
5279
  async findById(id, ctx, signal) {
4912
5280
  AppError16.throwIfAborted(signal, "ReadDao.findById");
4913
5281
  const result = await this._dataSource.findById(id, ctx, signal);
4914
- if (Guards37.isNullOrEmpty(result)) return Result17.ok();
5282
+ if (Guards44.isNullOrEmpty(result)) return Result17.ok();
4915
5283
  const entity = this._mapper.toEntity(result);
4916
5284
  return Result17.ok(entity);
4917
5285
  }
@@ -4925,7 +5293,7 @@ var ReadDao = class {
4925
5293
 
4926
5294
  // src/infrastructure/repositories/repository.ts
4927
5295
  import { AppError as AppError17, Result as Result18 } from "@xeno-js/shared";
4928
- import { Guards as Guards38 } from "@xeno-js/shared";
5296
+ import { Guards as Guards45 } from "@xeno-js/shared";
4929
5297
  var Repository = class {
4930
5298
  /**
4931
5299
  * Constructs a new Repository instance.
@@ -4947,7 +5315,7 @@ var Repository = class {
4947
5315
  async findById(id, ctx, signal) {
4948
5316
  AppError17.throwIfAborted(signal, "Repository.findById");
4949
5317
  const result = await this._dataSource.findById(id, ctx, signal);
4950
- if (Guards38.isNullOrEmpty(result)) return Result18.ok();
5318
+ if (Guards45.isNullOrEmpty(result)) return Result18.ok();
4951
5319
  const entity = this._mapper.toEntity(result);
4952
5320
  return Result18.ok(entity);
4953
5321
  }
@@ -5005,4 +5373,13 @@ export {
5005
5373
  Specification,
5006
5374
  SupabaseServerAuthFactory
5007
5375
  };
5376
+ /**
5377
+ * @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.
5378
+ *
5379
+ * @author Xeno
5380
+ * @version 1.0.0
5381
+ * @since 2025-09-30
5382
+ * @link https://github.com/xeno-js/xeno-js
5383
+ * @license MIT
5384
+ */
5008
5385
  //# sourceMappingURL=index.js.map