opticore-cache 1.0.0 → 1.0.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/dist/index.js CHANGED
@@ -404,6 +404,7 @@ var MemoryCache = class {
404
404
  import fs from "fs";
405
405
  import path from "path";
406
406
  import { promisify } from "util";
407
+ import { LoggerCore } from "opticore-logger";
407
408
  var fsExists = promisify(fs.exists);
408
409
  var fsMkdir = promisify(fs.mkdir);
409
410
  var fsReadFile = promisify(fs.readFile);
@@ -449,7 +450,7 @@ var DiskCache = class {
449
450
  * @private
450
451
  */
451
452
  getCacheDirectory() {
452
- return process.env.CACHE_DISK_DIR || path.join(process.cwd(), "storage", "cache", this.config.namespace);
453
+ return process.env.CACHE_DISK_DIR || path.join(process.cwd(), "src", "core", "cache", this.config.namespace);
453
454
  }
454
455
  /**
455
456
  * Initialise le répertoire de cache
@@ -826,8 +827,8 @@ NE PAS SUPPRIMER MANUELLEMENT ces fichiers pendant l'ex\xE9cution du serveur.
826
827
  if (this.cleanupInterval) {
827
828
  clearInterval(this.cleanupInterval);
828
829
  }
829
- this.cleanupInterval = setInterval(() => {
830
- this.cleanupExpiredEntries();
830
+ this.cleanupInterval = setInterval(async () => {
831
+ await this.cleanupExpiredEntries();
831
832
  }, this.config.cleanupInterval);
832
833
  if (this.config.debug) {
833
834
  console.log(`[DiskCache] Cycle de nettoyage: ${this.config.cleanupInterval}ms`);
@@ -852,6 +853,9 @@ NE PAS SUPPRIMER MANUELLEMENT ces fichiers pendant l'ex\xE9cution du serveur.
852
853
  console.log(`[DiskCache] Nettoyage: ${expiredKeys.length} entr\xE9es expir\xE9es`);
853
854
  }
854
855
  }
856
+ logger() {
857
+ return new LoggerCore();
858
+ }
855
859
  /**
856
860
  * Récupère le chemin du dossier de cache
857
861
  * @returns string
@@ -1213,7 +1217,7 @@ var CacheManagementUseCase = class {
1213
1217
 
1214
1218
  // src/application/services/cacheService.service.ts
1215
1219
  import { translate, translationLoaderConfig } from "opticore-loader-translation";
1216
- import { LoggerCore } from "opticore-logger";
1220
+ import { LoggerCore as LoggerCore2 } from "opticore-logger";
1217
1221
  var CacheService = class _CacheService {
1218
1222
  cacheUseCase;
1219
1223
  cacheRepository;
@@ -1387,7 +1391,7 @@ var CacheService = class _CacheService {
1387
1391
  });
1388
1392
  }
1389
1393
  logger() {
1390
- return new LoggerCore(this.configLogger);
1394
+ return new LoggerCore2(this.configLogger);
1391
1395
  }
1392
1396
  };
1393
1397
 
@@ -1453,11 +1457,11 @@ var RouteValidator = class {
1453
1457
  * @param enableWildcards - Activer le support des wildcards
1454
1458
  * @returns RegExp
1455
1459
  */
1456
- compileToRegex(path2, enableWildcards) {
1457
- if (!enableWildcards || !path2.includes("*")) {
1458
- return new RegExp(`^${this.escapeRegex(path2)}$`, "i");
1460
+ compileToRegex(path3, enableWildcards) {
1461
+ if (!enableWildcards || !path3.includes("*")) {
1462
+ return new RegExp(`^${this.escapeRegex(path3)}$`, "i");
1459
1463
  }
1460
- let regexString = this.escapeRegex(path2).replace(/\\\*/g, ".*");
1464
+ let regexString = this.escapeRegex(path3).replace(/\\\*/g, ".*");
1461
1465
  if (regexString.endsWith("/.*")) {
1462
1466
  regexString = regexString.replace(/\/\.\*$/, "(\\/.*)?");
1463
1467
  }
@@ -1501,11 +1505,11 @@ var RouteValidator = class {
1501
1505
  * @param path - Chemin à normaliser
1502
1506
  * @returns string - Chemin normalisé
1503
1507
  */
1504
- normalizePath(path2) {
1505
- if (path2.length > 1 && path2.endsWith("/")) {
1506
- return path2.slice(0, -1);
1508
+ normalizePath(path3) {
1509
+ if (path3.length > 1 && path3.endsWith("/")) {
1510
+ return path3.slice(0, -1);
1507
1511
  }
1508
- return path2;
1512
+ return path3;
1509
1513
  }
1510
1514
  /**
1511
1515
  * Récupère la liste des patterns compilés (pour debug)
@@ -1649,11 +1653,11 @@ var CacheMiddleware = class {
1649
1653
  * @returns string
1650
1654
  * @private
1651
1655
  */
1652
- normalizePath(path2) {
1653
- if (path2.length > 1 && path2.endsWith("/")) {
1654
- return path2.slice(0, -1);
1656
+ normalizePath(path3) {
1657
+ if (path3.length > 1 && path3.endsWith("/")) {
1658
+ return path3.slice(0, -1);
1655
1659
  }
1656
- return path2;
1660
+ return path3;
1657
1661
  }
1658
1662
  /**
1659
1663
  * Adds HTTP headers related to the cache
@@ -1808,17 +1812,34 @@ var SCacheMiddleware = class {
1808
1812
  };
1809
1813
 
1810
1814
  // src/application/services/adaptedHttpCache.service.ts
1815
+ import { LoggerCore as LoggerCore3 } from "opticore-logger";
1816
+ import { loggerConfig } from "opticore-webapp-core";
1817
+ import { envPath } from "opticore-webapp";
1818
+ import { HttpStatusCode } from "opticore-http-response";
1811
1819
  var AdaptedHttpCacheService = class {
1820
+ /**
1821
+ * Creates an instance of AdaptedHttpCacheService.
1822
+ *
1823
+ * @param cacheService - The underlying cache service instance (must implement getOrSet, delete, etc.)
1824
+ * @param namespace - Namespace prefix for cache keys (default: "http-cache")
1825
+ */
1812
1826
  constructor(cacheService, namespace = "http-cache") {
1813
1827
  this.cacheService = cacheService;
1814
1828
  this.namespace = namespace;
1815
1829
  }
1816
- stats = { totalRequests: 0, cacheHits: 0, cacheMisses: 0 };
1830
+ stats = {
1831
+ totalRequests: 0,
1832
+ cacheHits: 0,
1833
+ cacheMisses: 0
1834
+ };
1817
1835
  /**
1836
+ * Performs a GET request and caches the response.
1818
1837
  *
1819
- * @param url
1820
- * @param options
1821
- * @param cacheOptions
1838
+ * @param url - The URL to fetch
1839
+ * @param options - Optional fetch options (headers, etc.)
1840
+ * @param cacheOptions - Cache configuration (TTL, bypass, custom key)
1841
+ *
1842
+ * @returns A promise resolving to the response data, merged with metadata
1822
1843
  */
1823
1844
  async getWithCache(url, options, cacheOptions) {
1824
1845
  this.stats.totalRequests++;
@@ -1846,12 +1867,15 @@ var AdaptedHttpCacheService = class {
1846
1867
  }
1847
1868
  }
1848
1869
  /**
1870
+ * Performs a POST request and optionally caches the response.
1871
+ *
1872
+ * @param url - The URL to post to
1873
+ * @param data - The payload to send
1874
+ * @param options - Additional fetch options
1875
+ * @param cacheResponse - Whether to cache the response (default: false)
1876
+ * @param cacheOptions - Cache configuration (TTL, bypass, namespace)
1849
1877
  *
1850
- * @param url
1851
- * @param data
1852
- * @param options
1853
- * @param cacheResponse
1854
- * @param cacheOptions
1878
+ * @returns A promise resolving to the response data, merged with metadata
1855
1879
  */
1856
1880
  async postWithCache(url, data, options, cacheResponse = false, cacheOptions) {
1857
1881
  this.stats.totalRequests++;
@@ -1881,18 +1905,26 @@ var AdaptedHttpCacheService = class {
1881
1905
  );
1882
1906
  return this.mergeResponse(cachedResponse);
1883
1907
  } catch (error) {
1884
- console.error(`Cache error for POST ${url}:`, error.message);
1908
+ this.SLogger().error({
1909
+ errorType: error.type,
1910
+ httpCodeValue: HttpStatusCode.INTERNAL_SERVER_ERROR,
1911
+ message: `Cache error for POST ${url}:\`, ${error.message}`,
1912
+ stackTrace: error.stack,
1913
+ title: "ERROR_POST_CACHING"
1914
+ });
1885
1915
  this.stats.cacheMisses++;
1886
1916
  const response = await this.executeRequest("POST", url, requestOptions);
1887
1917
  return this.mergeResponse(response);
1888
1918
  }
1889
1919
  }
1890
1920
  /**
1921
+ * Executes an HTTP request and returns a normalized response.
1891
1922
  *
1892
- * @param method
1893
- * @param url
1894
- * @param options
1895
- * @private
1923
+ * @param method - HTTP method (GET, POST, etc.)
1924
+ * @param url - Request URL
1925
+ * @param options - Fetch options
1926
+ *
1927
+ * @returns A promise resolving to an IHttpClientResponse containing data and metadata
1896
1928
  */
1897
1929
  async executeRequest(method, url, options) {
1898
1930
  const response = await fetch(url, { method, ...options });
@@ -1909,21 +1941,25 @@ var AdaptedHttpCacheService = class {
1909
1941
  };
1910
1942
  }
1911
1943
  /**
1944
+ * Merges response data with metadata, adding a _metadata property.
1912
1945
  *
1913
- * @param response
1914
- * @private
1946
+ * @param response - The HTTP client response containing data and metadata
1947
+ *
1948
+ * @returns The data enriched with a _metadata field
1915
1949
  */
1916
1950
  mergeResponse(response) {
1917
1951
  const result = { ...response.data, _metadata: response.metadata };
1918
1952
  return result;
1919
1953
  }
1920
1954
  /**
1955
+ * Generates a cache key based on request parameters.
1921
1956
  *
1922
- * @param method
1923
- * @param url
1924
- * @param options
1925
- * @param customKey
1926
- * @private
1957
+ * @param method - HTTP method
1958
+ * @param url - Request URL
1959
+ * @param options - Request options (headers, body)
1960
+ * @param customKey - Optional override for the key
1961
+ *
1962
+ * @returns A base64 encoded cache key string
1927
1963
  */
1928
1964
  generateKey(method, url, options, customKey) {
1929
1965
  if (customKey) return customKey;
@@ -1936,35 +1972,48 @@ var AdaptedHttpCacheService = class {
1936
1972
  return Buffer.from(keyParts.join("|")).toString("base64");
1937
1973
  }
1938
1974
  /**
1975
+ * Invalidates cache entries matching a URL or pattern.
1939
1976
  *
1940
- * @param urlOrPattern
1977
+ * @param urlOrPattern - The URL or pattern to invalidate
1978
+ *
1979
+ * @returns A promise resolving to the number of invalidated entries
1941
1980
  */
1942
1981
  async invalidateCache(urlOrPattern) {
1943
1982
  try {
1944
- console.log(`Invalidating cache for pattern: ${urlOrPattern}`);
1945
1983
  const encodedPattern = Buffer.from(urlOrPattern).toString("base64").slice(0, 20);
1946
1984
  const searchPattern = `*${encodedPattern}*`;
1947
- const invalidatedCount = await this.cacheService.invalidate(searchPattern);
1948
- console.log(`Invalidated ${invalidatedCount} entries for pattern: ${urlOrPattern}`);
1949
- return invalidatedCount;
1985
+ return await this.cacheService.invalidate(searchPattern);
1950
1986
  } catch (error) {
1951
- console.error(`Error invalidating cache for ${urlOrPattern}:`, error.message);
1987
+ this.SLogger().error({
1988
+ errorType: error.type,
1989
+ httpCodeValue: HttpStatusCode.INTERNAL_SERVER_ERROR,
1990
+ message: `Error invalidating cache for ${urlOrPattern}: error.message`,
1991
+ stackTrace: error.stackTrace,
1992
+ title: "INVALIDATE CACHE"
1993
+ });
1952
1994
  try {
1953
1995
  if (urlOrPattern.startsWith(this.namespace + ":")) {
1954
1996
  await this.cacheService.delete(urlOrPattern);
1955
1997
  return 1;
1956
1998
  }
1957
1999
  } catch (fallbackError) {
2000
+ this.SLogger().error({
2001
+ errorType: fallbackError.name,
2002
+ httpCodeValue: HttpStatusCode.INTERNAL_SERVER_ERROR,
2003
+ message: fallbackError.message,
2004
+ stackTrace: fallbackError.stackTrace,
2005
+ title: "INVALIDATE_PATTERN"
2006
+ });
1958
2007
  }
1959
2008
  return 0;
1960
2009
  }
1961
2010
  }
1962
2011
  /**
1963
- *
2012
+ * Clears all HTTP cache entries and resets statistics.
2013
+ * @returns A promise that resolves when the cache is cleared
1964
2014
  */
1965
2015
  async clearHttpCache() {
1966
2016
  try {
1967
- console.log("Clearing HTTP cache...");
1968
2017
  if (typeof this.cacheService.clear === "function") {
1969
2018
  await this.cacheService.clear();
1970
2019
  } else if (typeof this.cacheService.keys === "function") {
@@ -1973,15 +2022,31 @@ var AdaptedHttpCacheService = class {
1973
2022
  for (const key of httpKeys) {
1974
2023
  await this.cacheService.delete(key);
1975
2024
  }
1976
- console.log(`Cleared ${httpKeys.length} HTTP cache entries`);
2025
+ this.SLogger().success({
2026
+ title: "CLEAR_HTTP_CACHE_ENTRIES",
2027
+ message: `Cleared ${httpKeys.length} HTTP cache entries`
2028
+ });
1977
2029
  }
1978
2030
  this.stats = { totalRequests: 0, cacheHits: 0, cacheMisses: 0 };
1979
- console.log("HTTP cache cleared successfully");
2031
+ this.SLogger().success({
2032
+ title: "CLEAR_CACHE",
2033
+ message: "HTTP cache cleared successfully"
2034
+ });
1980
2035
  } catch (error) {
1981
- console.error("Error clearing HTTP cache:", error.message);
2036
+ this.SLogger().error({
2037
+ errorType: error.name,
2038
+ httpCodeValue: HttpStatusCode.INTERNAL_SERVER_ERROR,
2039
+ message: error.message,
2040
+ stackTrace: error.stackTrace,
2041
+ title: "ERROR_CLEARING_HTTP_CACHE"
2042
+ });
1982
2043
  throw new Error(`Failed to clear HTTP cache: ${error.message}`);
1983
2044
  }
1984
2045
  }
2046
+ /**
2047
+ * Retrieves current cache statistics.
2048
+ * @returns A promise resolving to an HttpCacheStats object
2049
+ */
1985
2050
  async getStats() {
1986
2051
  try {
1987
2052
  const cacheStats = await this.cacheService.getStatistics();
@@ -2000,10 +2065,20 @@ var AdaptedHttpCacheService = class {
2000
2065
  enabled: this.isEnabled()
2001
2066
  };
2002
2067
  } catch (error) {
2003
- console.error("Error getting cache stats:", error.message);
2068
+ this.SLogger().error({
2069
+ errorType: error.name,
2070
+ httpCodeValue: HttpStatusCode.INTERNAL_SERVER_ERROR,
2071
+ message: error.message,
2072
+ stackTrace: error.stackTrace,
2073
+ title: "ERROR_GETTING_CACHE_STATS"
2074
+ });
2004
2075
  return this.getDefaultStats();
2005
2076
  }
2006
2077
  }
2078
+ /**
2079
+ * Returns default statistics when an error occurs.
2080
+ * @returns A default HttpCacheStats object
2081
+ */
2007
2082
  getDefaultStats() {
2008
2083
  return {
2009
2084
  totalRequests: this.stats.totalRequests,
@@ -2016,6 +2091,10 @@ var AdaptedHttpCacheService = class {
2016
2091
  enabled: false
2017
2092
  };
2018
2093
  }
2094
+ /**
2095
+ * Checks whether the cache service is enabled.
2096
+ * @returns True if the cache is enabled, false otherwise
2097
+ */
2019
2098
  isEnabled() {
2020
2099
  try {
2021
2100
  if (this.cacheService.isEnabled && typeof this.cacheService.isEnabled === "function") {
@@ -2026,6 +2105,13 @@ var AdaptedHttpCacheService = class {
2026
2105
  return false;
2027
2106
  }
2028
2107
  }
2108
+ /**
2109
+ * Creates a logger instance for internal error reporting.
2110
+ * @returns A configured LoggerCore instance
2111
+ */
2112
+ SLogger() {
2113
+ return new LoggerCore3(loggerConfig(envPath));
2114
+ }
2029
2115
  };
2030
2116
 
2031
2117
  // src/application/services/fetch.client.service.ts
@@ -2478,8 +2564,33 @@ var CurlHttpClient = class {
2478
2564
  };
2479
2565
 
2480
2566
  // src/application/services/httpCacheFactory.service.ts
2567
+ import fs2 from "fs";
2568
+ import path2 from "path";
2569
+ import { LoggerCore as LoggerCore4 } from "opticore-logger";
2481
2570
  var HttpCacheFactory = class {
2571
+ /**
2572
+ * Map of created instances, keyed by `${appName}:${clientType}`.
2573
+ * @private
2574
+ */
2482
2575
  static instances = /* @__PURE__ */ new Map();
2576
+ /**
2577
+ * Creates or retrieves an HTTP cache service instance.
2578
+ * If an instance for the given appName and clientType already exists, it is returned.
2579
+ * Otherwise, a new instance is created with the provided configuration.
2580
+ *
2581
+ * @param appName - Name of the application/context (default: "default"). Used for instance caching and default namespace.
2582
+ * @param config - Configuration options for the cache and HTTP client.
2583
+ * @param config.namespace - Namespace prefix for cache keys (default: `http-cache-${appName}`).
2584
+ * @param config.localLang - Localization language (optional).
2585
+ * @param config.storageType - Storage backend type: "memory", "disk", or "hybrid" (default: "disk").
2586
+ * @param config.diskDir - Directory path for disk storage (default: "src/core/cache").
2587
+ * @param config.maxSize - Maximum number of items to store (default: 10000).
2588
+ * @param config.defaultTTL - Default time-to-live in milliseconds (default: 300000).
2589
+ * @param config.clientType - HTTP client to use: "fetch", "node-http", "axios", or "curl" (default: "fetch").
2590
+ * @param config.clientOptions - Additional options for the HTTP client (e.g., timeout, headers, baseURL).
2591
+ *
2592
+ * @returns An HTTP cache service instance implementing IHttpCacheService.
2593
+ */
2483
2594
  static create(appName = "default", config) {
2484
2595
  const instanceKey = `${appName}:${config?.clientType || "fetch"}`;
2485
2596
  if (!this.instances.has(instanceKey)) {
@@ -2504,8 +2615,18 @@ var HttpCacheFactory = class {
2504
2615
  maxSize: config?.maxSize || 1e4,
2505
2616
  defaultTTL: config?.defaultTTL || 3e5,
2506
2617
  storageType: config?.storageType || "disk",
2507
- diskDir: config?.diskDir || `./storage/cache/${appName}`
2618
+ diskDir: config?.diskDir || "src/core/cache"
2508
2619
  };
2620
+ if (cacheConfig.storageType === "disk" || cacheConfig.storageType === "hybrid") {
2621
+ const resolvedDiskDir = path2.resolve(process.cwd(), cacheConfig.diskDir);
2622
+ if (!fs2.existsSync(resolvedDiskDir)) {
2623
+ this.SLogger().warn({
2624
+ title: "UNRESOLVED_CACHE_DIR",
2625
+ message: `[HttpCacheFactory] Cache directory does not exist: ${resolvedDiskDir}
2626
+ Please create it manually or ensure the path is correct.`
2627
+ });
2628
+ }
2629
+ }
2509
2630
  const instance = new HttpCacheClient(httpClient, void 0, {
2510
2631
  cacheConfig,
2511
2632
  timeout: config?.clientOptions?.timeout,
@@ -2516,26 +2637,50 @@ var HttpCacheFactory = class {
2516
2637
  }
2517
2638
  return this.instances.get(instanceKey);
2518
2639
  }
2640
+ /**
2641
+ * Creates an HTTP cache service instance by adapting an existing generic cache service.
2642
+ * This is useful when you already have a cache service from another source and want to
2643
+ * use it with the HTTP caching interface.
2644
+ *
2645
+ * @param cacheService - The underlying cache service instance (must support getOrSet, delete, etc.).
2646
+ * @param namespace - Namespace for cache keys (default: "http-cache").
2647
+ *
2648
+ * @returns An adapted HTTP cache service implementing IHttpCacheService.
2649
+ */
2519
2650
  static createFromExistingCache(cacheService, namespace = "http-cache") {
2520
2651
  return new AdaptedHttpCacheService(cacheService, namespace);
2521
2652
  }
2653
+ /**
2654
+ * Destroys a cached HTTP cache service instance, removing it from the internal map.
2655
+ * After destruction, a new call to `create` will generate a fresh instance.
2656
+ *
2657
+ * @param appName - Name of the application/context (default: "default").
2658
+ * @param clientType - HTTP client type used for the instance (default: "fetch").
2659
+ *
2660
+ * @return void
2661
+ */
2522
2662
  static destroy(appName = "default", clientType) {
2523
2663
  const key = `${appName}:${clientType || "fetch"}`;
2524
2664
  this.instances.delete(key);
2525
2665
  }
2666
+ /**
2667
+ * Internal logger for warnings and errors.
2668
+ * @returns A LoggerCore instance configured for the factory.
2669
+ * @private
2670
+ */
2671
+ static SLogger() {
2672
+ return new LoggerCore4();
2673
+ }
2526
2674
  };
2527
2675
 
2528
2676
  // src/index.ts
2529
2677
  dotenv.config();
2530
- var index_default = {
2531
- SCacheMiddleware,
2532
- CacheService,
2533
- CacheMiddleware,
2678
+ export {
2534
2679
  CacheFactoryRepository,
2535
- RouteValidator,
2680
+ CacheMiddleware,
2681
+ CacheService,
2536
2682
  EnvironmentLoader,
2537
- HttpCacheFactory
2538
- };
2539
- export {
2540
- index_default as default
2683
+ HttpCacheFactory,
2684
+ RouteValidator,
2685
+ SCacheMiddleware
2541
2686
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opticore-cache",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Highly configurable caching system compatible with OptiCore.js",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -31,14 +31,12 @@
31
31
  "ansi-colors": "^4.1.3",
32
32
  "chalk": "^5.4.1",
33
33
  "gradient-string": "^3.0.0",
34
- "opticore-dependency-inject": "^1.0.7",
35
- "opticore-env-access": "^1.0.13",
36
- "opticore-http-response": "^1.0.9",
37
- "opticore-loader-translation": "^1.0.3",
38
- "opticore-logger": "^1.0.29",
39
- "opticore-router": "^1.0.20",
40
- "opticore-webapp": "^1.0.70",
41
- "opticore-webapp-core": "^1.0.20",
34
+ "opticore-express": "^1.0.9",
35
+ "opticore-http-response": "^1.0.11",
36
+ "opticore-loader-translation": "^1.0.9",
37
+ "opticore-logger": "^1.0.32",
38
+ "opticore-webapp": "^1.0.86",
39
+ "opticore-webapp-core": "^1.0.21",
42
40
  "uuidv7": "^1.1.0"
43
41
  },
44
42
  "devDependencies": {