@holo-js/cache 0.2.6 → 0.3.0

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.
@@ -0,0 +1,152 @@
1
+ // src/config.ts
2
+ import { registerConfigNormalizer } from "@holo-js/config/registry";
3
+ var DEFAULT_CACHE_DRIVER = "file";
4
+ var DEFAULT_CACHE_PREFIX = "";
5
+ var DEFAULT_CACHE_FILE_PATH = "./storage/framework/cache/data";
6
+ var DEFAULT_CACHE_REDIS_CONNECTION = "default";
7
+ var DEFAULT_CACHE_DATABASE_CONNECTION = "default";
8
+ var DEFAULT_CACHE_DATABASE_TABLE = "cache";
9
+ var DEFAULT_CACHE_DATABASE_LOCK_TABLE = "cache_locks";
10
+ var holoCacheDefaults = Object.freeze({
11
+ default: DEFAULT_CACHE_DRIVER,
12
+ prefix: DEFAULT_CACHE_PREFIX,
13
+ drivers: Object.freeze({
14
+ file: Object.freeze({
15
+ name: "file",
16
+ driver: "file",
17
+ path: DEFAULT_CACHE_FILE_PATH,
18
+ prefix: DEFAULT_CACHE_PREFIX
19
+ }),
20
+ memory: Object.freeze({
21
+ name: "memory",
22
+ driver: "memory",
23
+ maxEntries: void 0,
24
+ prefix: DEFAULT_CACHE_PREFIX
25
+ })
26
+ })
27
+ });
28
+ function normalizeOptionalString(value) {
29
+ const normalized = value?.trim();
30
+ return normalized || void 0;
31
+ }
32
+ function normalizeName(value, label) {
33
+ const normalized = value?.trim();
34
+ if (!normalized) {
35
+ throw new Error(`[Holo Cache] ${label} must be a non-empty string.`);
36
+ }
37
+ return normalized;
38
+ }
39
+ function parseOptionalInteger(value, label) {
40
+ if (typeof value === "undefined") return void 0;
41
+ const normalized = typeof value === "number" ? value : value.trim() ? Number(value.trim()) : Number.NaN;
42
+ if (!Number.isFinite(normalized) || !Number.isInteger(normalized)) {
43
+ throw new Error(`[Holo Cache] ${label} must be an integer.`);
44
+ }
45
+ if (normalized < 1) {
46
+ throw new Error(`[Holo Cache] ${label} must be greater than or equal to 1.`);
47
+ }
48
+ return normalized;
49
+ }
50
+ function resolvePrefix(globalPrefix, localPrefix) {
51
+ return normalizeOptionalString(localPrefix) ?? globalPrefix;
52
+ }
53
+ function normalizeDriverConfig(name, config, globalPrefix, defaultRedisConnection, defaultDatabaseConnection) {
54
+ switch (config.driver) {
55
+ case "memory": {
56
+ const memoryConfig = config;
57
+ return Object.freeze({
58
+ name,
59
+ driver: "memory",
60
+ prefix: resolvePrefix(globalPrefix, memoryConfig.prefix),
61
+ maxEntries: parseOptionalInteger(memoryConfig.maxEntries, `cache driver "${name}" maxEntries`)
62
+ });
63
+ }
64
+ case "file": {
65
+ const fileConfig = config;
66
+ return Object.freeze({
67
+ name,
68
+ driver: "file",
69
+ path: normalizeOptionalString(fileConfig.path) || DEFAULT_CACHE_FILE_PATH,
70
+ prefix: resolvePrefix(globalPrefix, fileConfig.prefix)
71
+ });
72
+ }
73
+ case "redis": {
74
+ const redisConfig = config;
75
+ return Object.freeze({
76
+ name,
77
+ driver: "redis",
78
+ connection: normalizeOptionalString(redisConfig.connection) ?? defaultRedisConnection,
79
+ prefix: resolvePrefix(globalPrefix, redisConfig.prefix)
80
+ });
81
+ }
82
+ case "database": {
83
+ const databaseConfig = config;
84
+ return Object.freeze({
85
+ name,
86
+ driver: "database",
87
+ connection: normalizeOptionalString(databaseConfig.connection) ?? defaultDatabaseConnection,
88
+ table: normalizeOptionalString(databaseConfig.table) || DEFAULT_CACHE_DATABASE_TABLE,
89
+ lockTable: normalizeOptionalString(databaseConfig.lockTable) || DEFAULT_CACHE_DATABASE_LOCK_TABLE,
90
+ prefix: resolvePrefix(globalPrefix, databaseConfig.prefix)
91
+ });
92
+ }
93
+ default: {
94
+ const { driver, prefix, ...options } = config;
95
+ return Object.freeze({
96
+ ...options,
97
+ name,
98
+ driver: normalizeName(driver, `Cache driver "${name}" driver`),
99
+ prefix: resolvePrefix(globalPrefix, prefix)
100
+ });
101
+ }
102
+ }
103
+ }
104
+ function normalizeCacheConfig(config = {}, options = {}) {
105
+ const prefix = normalizeOptionalString(config.prefix) ?? DEFAULT_CACHE_PREFIX;
106
+ const defaultRedisConnection = options.redis?.default ?? DEFAULT_CACHE_REDIS_CONNECTION;
107
+ const defaultDatabaseConnection = options.database?.defaultConnection ?? DEFAULT_CACHE_DATABASE_CONNECTION;
108
+ const driverEntries = !config.drivers || Object.keys(config.drivers).length === 0 ? Object.entries(holoCacheDefaults.drivers) : Object.entries(config.drivers);
109
+ const normalizedDriverEntries = driverEntries.map(([name, driver]) => {
110
+ const normalizedName = normalizeName(name, "Cache driver name");
111
+ return [normalizedName, normalizeDriverConfig(
112
+ normalizedName,
113
+ driver,
114
+ prefix,
115
+ defaultRedisConnection,
116
+ defaultDatabaseConnection
117
+ )];
118
+ });
119
+ const drivers = Object.freeze(Object.fromEntries(normalizedDriverEntries));
120
+ const configuredDefault = normalizeOptionalString(config.default);
121
+ if (configuredDefault && !Object.hasOwn(drivers, configuredDefault)) {
122
+ throw new Error(`[Holo Cache] default cache driver "${configuredDefault}" is not configured.`);
123
+ }
124
+ const defaultDriver = configuredDefault ?? normalizedDriverEntries.find(([name]) => name === DEFAULT_CACHE_DRIVER)?.[0] ?? normalizedDriverEntries[0][0];
125
+ return Object.freeze({ default: defaultDriver, prefix, drivers });
126
+ }
127
+ function defineCacheConfig(config) {
128
+ return Object.freeze({ ...config });
129
+ }
130
+ registerConfigNormalizer({
131
+ name: "cache",
132
+ dependencies: ["database", "redis"],
133
+ normalize(config, context) {
134
+ return normalizeCacheConfig(config, {
135
+ database: context.get("database"),
136
+ redis: context.has("redis") ? context.get("redis") : void 0
137
+ });
138
+ }
139
+ });
140
+
141
+ export {
142
+ DEFAULT_CACHE_DRIVER,
143
+ DEFAULT_CACHE_PREFIX,
144
+ DEFAULT_CACHE_FILE_PATH,
145
+ DEFAULT_CACHE_REDIS_CONNECTION,
146
+ DEFAULT_CACHE_DATABASE_CONNECTION,
147
+ DEFAULT_CACHE_DATABASE_TABLE,
148
+ DEFAULT_CACHE_DATABASE_LOCK_TABLE,
149
+ holoCacheDefaults,
150
+ normalizeCacheConfig,
151
+ defineCacheConfig
152
+ };
@@ -0,0 +1,31 @@
1
+ import {
2
+ CacheOptionalPackageError
3
+ } from "./chunk-KIYULZES.mjs";
4
+
5
+ // src/driver-registry.ts
6
+ var cacheDriverRuntime = globalThis;
7
+ cacheDriverRuntime.__holoCacheDriverFactories__ ??= /* @__PURE__ */ new Map();
8
+ var factories = cacheDriverRuntime.__holoCacheDriverFactories__;
9
+ function registerCacheDriverFactory(factory) {
10
+ const driver = factory.driver.trim();
11
+ if (!driver) throw new TypeError("Cache driver factories require a non-empty driver name.");
12
+ const existing = factories.get(driver);
13
+ if (existing && existing !== factory && (!factory.registrationKey || existing.registrationKey !== factory.registrationKey)) {
14
+ throw new Error(`Cache driver factory "${driver}" is already registered.`);
15
+ }
16
+ factories.set(driver, factory);
17
+ }
18
+ function unregisterCacheDriverFactory(factory) {
19
+ if (factories.get(factory.driver.trim()) === factory) factories.delete(factory.driver.trim());
20
+ }
21
+ function requireCacheDriverFactory(driver, message) {
22
+ const factory = factories.get(driver);
23
+ if (!factory) throw new CacheOptionalPackageError(message);
24
+ return factory;
25
+ }
26
+
27
+ export {
28
+ registerCacheDriverFactory,
29
+ unregisterCacheDriverFactory,
30
+ requireCacheDriverFactory
31
+ };
@@ -0,0 +1,119 @@
1
+ // src/plugins.ts
2
+ import { resolve } from "path";
3
+ import {
4
+ loadHoloPluginContributionModules,
5
+ loadHoloPluginDefinitions
6
+ } from "@holo-js/kernel";
7
+ var loadedContractsByProjectRoot = /* @__PURE__ */ new Map();
8
+ var failedLoadsByProjectRoot = /* @__PURE__ */ new Map();
9
+ function isRecord(value) {
10
+ return !!value && typeof value === "object" && !Array.isArray(value);
11
+ }
12
+ function resolvePluginCandidate(moduleValue) {
13
+ return isRecord(moduleValue) && typeof moduleValue.default !== "undefined" ? moduleValue.default : isRecord(moduleValue) && typeof moduleValue.driver !== "undefined" ? moduleValue.driver : moduleValue;
14
+ }
15
+ function isCachePluginDriverFactory(candidate, driverName) {
16
+ return isRecord(candidate) && candidate.driver === driverName && typeof candidate.create === "function";
17
+ }
18
+ function assertCacheDriverContract(candidate, packageName, driverName, expectedName) {
19
+ if (!isRecord(candidate) || candidate.driver !== driverName || candidate.name !== expectedName || typeof candidate.get !== "function" || typeof candidate.put !== "function" || typeof candidate.add !== "function" || typeof candidate.forget !== "function" || typeof candidate.flush !== "function" || typeof candidate.increment !== "function" || typeof candidate.decrement !== "function" || typeof candidate.lock !== "function") {
20
+ throw new Error(`[@holo-js/cache] Plugin ${packageName} cache driver "${driverName}" must export a matching CacheDriverContract.`);
21
+ }
22
+ }
23
+ function resolveCacheDriver(moduleValue, packageName, driverName) {
24
+ const candidate = resolvePluginCandidate(moduleValue);
25
+ assertCacheDriverContract(candidate, packageName, driverName, driverName);
26
+ return candidate;
27
+ }
28
+ function resolveConfiguredCacheDriver(moduleValue, packageName, driverName, config) {
29
+ const candidate = resolvePluginCandidate(moduleValue);
30
+ if (isCachePluginDriverFactory(candidate, driverName)) {
31
+ const driver = candidate.create(config);
32
+ assertCacheDriverContract(driver, packageName, driverName, config.name);
33
+ return driver;
34
+ }
35
+ assertCacheDriverContract(candidate, packageName, driverName, driverName);
36
+ Object.defineProperties(candidate, {
37
+ name: {
38
+ value: config.name,
39
+ enumerable: true,
40
+ configurable: true
41
+ },
42
+ driver: {
43
+ value: driverName,
44
+ enumerable: true,
45
+ configurable: true
46
+ }
47
+ });
48
+ return Object.freeze(candidate);
49
+ }
50
+ function assertConfiguredCacheDriverContributions(configs, contributions) {
51
+ const availableDrivers = new Set(contributions.map((contribution) => contribution.name));
52
+ const missingDrivers = Array.from(new Set(
53
+ configs.map((config) => config.driver).filter((driver) => !availableDrivers.has(driver))
54
+ ));
55
+ if (missingDrivers.length === 0) {
56
+ return;
57
+ }
58
+ const available = contributions.length > 0 ? contributions.map((contribution) => `"${contribution.name}"`).join(", ") : "none";
59
+ throw new Error(
60
+ `[@holo-js/cache] Configured cache plugin driver ${missingDrivers.map((driver) => `"${driver}"`).join(", ")} has no matching plugin contribution. Available cache plugin driver contributions: ${available}.`
61
+ );
62
+ }
63
+ async function loadCachePluginDriverContracts(projectRoot = process.cwd(), pluginNames = []) {
64
+ const root = resolve(projectRoot);
65
+ const cacheKey = `${root}\0${[...pluginNames].sort().join("\0")}`;
66
+ const loadedContracts = loadedContractsByProjectRoot.get(cacheKey);
67
+ if (loadedContracts) {
68
+ return loadedContracts;
69
+ }
70
+ if (failedLoadsByProjectRoot.has(cacheKey)) {
71
+ throw failedLoadsByProjectRoot.get(cacheKey);
72
+ }
73
+ const plugins = await loadHoloPluginDefinitions(root, pluginNames);
74
+ const contributions = await loadHoloPluginContributionModules(root, plugins, "cache", "drivers");
75
+ let drivers;
76
+ try {
77
+ drivers = Object.freeze(contributions.map((contribution) => resolveCacheDriver(
78
+ contribution.module,
79
+ contribution.plugin.packageName,
80
+ contribution.name
81
+ )));
82
+ } catch (error) {
83
+ failedLoadsByProjectRoot.set(cacheKey, error);
84
+ throw error;
85
+ }
86
+ loadedContractsByProjectRoot.set(cacheKey, drivers);
87
+ return drivers;
88
+ }
89
+ async function loadConfiguredCachePluginDriverContracts(projectRoot, pluginNames, configs) {
90
+ if (configs.length === 0) {
91
+ return Object.freeze([]);
92
+ }
93
+ const plugins = await loadHoloPluginDefinitions(projectRoot, pluginNames);
94
+ const contributions = await loadHoloPluginContributionModules(projectRoot, plugins, "cache", "drivers");
95
+ assertConfiguredCacheDriverContributions(configs, contributions);
96
+ const drivers = [];
97
+ for (const contribution of contributions) {
98
+ const matchingConfigs = configs.filter((config) => config.driver === contribution.name);
99
+ for (const config of matchingConfigs) {
100
+ drivers.push(resolveConfiguredCacheDriver(
101
+ contribution.module,
102
+ contribution.plugin.packageName,
103
+ contribution.name,
104
+ config
105
+ ));
106
+ }
107
+ }
108
+ return Object.freeze(drivers);
109
+ }
110
+ function resetCachePluginDriverContracts() {
111
+ loadedContractsByProjectRoot.clear();
112
+ failedLoadsByProjectRoot.clear();
113
+ }
114
+
115
+ export {
116
+ loadCachePluginDriverContracts,
117
+ loadConfiguredCachePluginDriverContracts,
118
+ resetCachePluginDriverContracts
119
+ };
@@ -0,0 +1,96 @@
1
+ import { NormalizedHoloDatabaseConfig } from '@holo-js/db';
2
+ import { NormalizedHoloRedisConfig } from '@holo-js/kernel';
3
+
4
+ type CacheDriver = 'memory' | 'file' | 'redis' | 'database' | (string & {});
5
+ declare module '@holo-js/config' {
6
+ interface HoloConfigRegistry {
7
+ cache: NormalizedHoloCacheConfig;
8
+ }
9
+ }
10
+ interface CacheMemoryDriverConfig {
11
+ readonly driver: 'memory';
12
+ readonly maxEntries?: number | string;
13
+ readonly prefix?: string;
14
+ }
15
+ interface CacheFileDriverConfig {
16
+ readonly driver: 'file';
17
+ readonly path?: string;
18
+ readonly prefix?: string;
19
+ }
20
+ interface CacheRedisDriverConfig {
21
+ readonly driver: 'redis';
22
+ readonly connection?: string;
23
+ readonly prefix?: string;
24
+ }
25
+ interface CacheDatabaseDriverConfig {
26
+ readonly driver: 'database';
27
+ readonly connection?: string;
28
+ readonly table?: string;
29
+ readonly lockTable?: string;
30
+ readonly prefix?: string;
31
+ }
32
+ interface CachePluginDriverConfig {
33
+ readonly driver: string;
34
+ readonly prefix?: string;
35
+ readonly [key: string]: unknown;
36
+ }
37
+ type CacheDriverConfig = CacheMemoryDriverConfig | CacheFileDriverConfig | CacheRedisDriverConfig | CacheDatabaseDriverConfig | CachePluginDriverConfig;
38
+ interface HoloCacheConfig {
39
+ readonly default?: string;
40
+ readonly prefix?: string;
41
+ readonly drivers?: Readonly<Record<string, CacheDriverConfig>>;
42
+ }
43
+ interface NormalizedCacheMemoryDriverConfig {
44
+ readonly name: string;
45
+ readonly driver: 'memory';
46
+ readonly prefix: string;
47
+ readonly maxEntries?: number;
48
+ }
49
+ interface NormalizedCacheFileDriverConfig {
50
+ readonly name: string;
51
+ readonly driver: 'file';
52
+ readonly path: string;
53
+ readonly prefix: string;
54
+ }
55
+ interface NormalizedCacheRedisDriverConfig {
56
+ readonly name: string;
57
+ readonly driver: 'redis';
58
+ readonly connection: string;
59
+ readonly prefix: string;
60
+ }
61
+ interface NormalizedCacheDatabaseDriverConfig {
62
+ readonly name: string;
63
+ readonly driver: 'database';
64
+ readonly connection: string;
65
+ readonly table: string;
66
+ readonly lockTable: string;
67
+ readonly prefix: string;
68
+ }
69
+ interface NormalizedCachePluginDriverConfig {
70
+ readonly name: string;
71
+ readonly driver: string;
72
+ readonly prefix: string;
73
+ readonly [key: string]: unknown;
74
+ }
75
+ type NormalizedCacheDriverConfig = NormalizedCacheMemoryDriverConfig | NormalizedCacheFileDriverConfig | NormalizedCacheRedisDriverConfig | NormalizedCacheDatabaseDriverConfig | NormalizedCachePluginDriverConfig;
76
+ interface NormalizedHoloCacheConfig {
77
+ readonly default: string;
78
+ readonly prefix: string;
79
+ readonly drivers: Readonly<Record<string, NormalizedCacheDriverConfig>>;
80
+ }
81
+ type CacheNormalizationOptions = {
82
+ readonly database?: NormalizedHoloDatabaseConfig;
83
+ readonly redis?: NormalizedHoloRedisConfig;
84
+ };
85
+ declare const DEFAULT_CACHE_DRIVER = "file";
86
+ declare const DEFAULT_CACHE_PREFIX = "";
87
+ declare const DEFAULT_CACHE_FILE_PATH = "./storage/framework/cache/data";
88
+ declare const DEFAULT_CACHE_REDIS_CONNECTION = "default";
89
+ declare const DEFAULT_CACHE_DATABASE_CONNECTION = "default";
90
+ declare const DEFAULT_CACHE_DATABASE_TABLE = "cache";
91
+ declare const DEFAULT_CACHE_DATABASE_LOCK_TABLE = "cache_locks";
92
+ declare const holoCacheDefaults: Readonly<NormalizedHoloCacheConfig>;
93
+ declare function normalizeCacheConfig(config?: HoloCacheConfig, options?: CacheNormalizationOptions): NormalizedHoloCacheConfig;
94
+ declare function defineCacheConfig<TConfig extends HoloCacheConfig>(config: TConfig): Readonly<TConfig>;
95
+
96
+ export { type CacheDatabaseDriverConfig, type CacheDriver, type CacheDriverConfig, type CacheFileDriverConfig, type CacheMemoryDriverConfig, type CacheNormalizationOptions, type CachePluginDriverConfig, type CacheRedisDriverConfig, DEFAULT_CACHE_DATABASE_CONNECTION, DEFAULT_CACHE_DATABASE_LOCK_TABLE, DEFAULT_CACHE_DATABASE_TABLE, DEFAULT_CACHE_DRIVER, DEFAULT_CACHE_FILE_PATH, DEFAULT_CACHE_PREFIX, DEFAULT_CACHE_REDIS_CONNECTION, type HoloCacheConfig, type NormalizedCacheDatabaseDriverConfig, type NormalizedCacheDriverConfig, type NormalizedCacheFileDriverConfig, type NormalizedCacheMemoryDriverConfig, type NormalizedCachePluginDriverConfig, type NormalizedCacheRedisDriverConfig, type NormalizedHoloCacheConfig, defineCacheConfig, holoCacheDefaults, normalizeCacheConfig };
@@ -0,0 +1,24 @@
1
+ import {
2
+ DEFAULT_CACHE_DATABASE_CONNECTION,
3
+ DEFAULT_CACHE_DATABASE_LOCK_TABLE,
4
+ DEFAULT_CACHE_DATABASE_TABLE,
5
+ DEFAULT_CACHE_DRIVER,
6
+ DEFAULT_CACHE_FILE_PATH,
7
+ DEFAULT_CACHE_PREFIX,
8
+ DEFAULT_CACHE_REDIS_CONNECTION,
9
+ defineCacheConfig,
10
+ holoCacheDefaults,
11
+ normalizeCacheConfig
12
+ } from "./chunk-7FH4KYTX.mjs";
13
+ export {
14
+ DEFAULT_CACHE_DATABASE_CONNECTION,
15
+ DEFAULT_CACHE_DATABASE_LOCK_TABLE,
16
+ DEFAULT_CACHE_DATABASE_TABLE,
17
+ DEFAULT_CACHE_DRIVER,
18
+ DEFAULT_CACHE_FILE_PATH,
19
+ DEFAULT_CACHE_PREFIX,
20
+ DEFAULT_CACHE_REDIS_CONNECTION,
21
+ defineCacheConfig,
22
+ holoCacheDefaults,
23
+ normalizeCacheConfig
24
+ };
@@ -1,4 +1,6 @@
1
- import { HoloCacheConfig, NormalizedHoloCacheConfig, HoloDatabaseConfig, NormalizedHoloDatabaseConfig, HoloRedisConfig, NormalizedHoloRedisConfig } from '@holo-js/config';
1
+ import { HoloCacheConfig, NormalizedHoloCacheConfig } from './config.js';
2
+ import { HoloDatabaseConfig, NormalizedHoloDatabaseConfig } from '@holo-js/db';
3
+ import { HoloRedisConfig, NormalizedHoloRedisConfig } from '@holo-js/kernel';
2
4
 
3
5
  declare const cacheKeyBrand: unique symbol;
4
6
  type CacheKey<TValue> = Readonly<{
@@ -0,0 +1,11 @@
1
+ import {
2
+ registerCacheDriverFactory,
3
+ requireCacheDriverFactory,
4
+ unregisterCacheDriverFactory
5
+ } from "./chunk-FRE6NONR.mjs";
6
+ import "./chunk-KIYULZES.mjs";
7
+ export {
8
+ registerCacheDriverFactory,
9
+ requireCacheDriverFactory,
10
+ unregisterCacheDriverFactory
11
+ };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import { CacheFlexibleTtlInput, CacheFacade, CacheRepository, CacheFallback, CacheValueResolver, CacheOptionalPackageError, CacheDriverContract, CacheDependencyIndex, CacheQueryBridge, CacheKeyInput, CacheDependencyDescriptor, CacheRuntimeBindings, CacheKey, CacheTtlInput, CacheLockContract, defineCacheKey, normalizeCacheTtl, serializeCacheValue, deserializeCacheValue } from './contracts.js';
2
2
  export { CacheConfigError, CacheDriverGetResult, CacheDriverPutInput, CacheDriverResolutionError, CacheError, CacheErrorCode, CacheFallbackResolver, CacheInvalidNumericMutationError, CacheInvalidTtlError, CacheLockAcquisitionError, CacheQueryIntegrationError, CacheRuntimeNotConfiguredError, CacheSerializationError, NormalizedCacheTtl, cacheContractsInternals, isCacheKey, resolveCacheKey } from './contracts.js';
3
- import { HoloDatabaseConfig, NormalizedHoloDatabaseConfig, HoloDatabaseConnectionConfig, HoloRedisConfig, NormalizedHoloRedisConfig, NormalizedHoloRedisConnectionConfig, NormalizedHoloCacheConfig, HoloCacheConfig } from '@holo-js/config';
4
- export { CacheDatabaseDriverConfig, CacheDriver, CacheDriverConfig, CacheFileDriverConfig, CacheMemoryDriverConfig, CacheRedisDriverConfig, HoloCacheConfig, NormalizedCacheDatabaseDriverConfig, NormalizedCacheDriverConfig, NormalizedCacheFileDriverConfig, NormalizedCacheMemoryDriverConfig, NormalizedCacheRedisDriverConfig, NormalizedHoloCacheConfig, defineCacheConfig } from '@holo-js/config';
3
+ import { NormalizedHoloCacheConfig, HoloCacheConfig, NormalizedCachePluginDriverConfig } from './config.js';
4
+ export { CacheDatabaseDriverConfig, CacheDriver, CacheDriverConfig, CacheFileDriverConfig, CacheMemoryDriverConfig, CachePluginDriverConfig, CacheRedisDriverConfig, NormalizedCacheDatabaseDriverConfig, NormalizedCacheDriverConfig, NormalizedCacheFileDriverConfig, NormalizedCacheMemoryDriverConfig, NormalizedCacheRedisDriverConfig, defineCacheConfig, holoCacheDefaults, normalizeCacheConfig } from './config.js';
5
+ import { HoloDatabaseConnectionConfig, HoloDatabaseConfig, NormalizedHoloDatabaseConfig } from '@holo-js/db';
6
+ import { mkdir, readdir, rmdir, writeFile } from 'node:fs/promises';
7
+ import { NormalizedHoloRedisConnectionConfig, HoloRedisConfig, NormalizedHoloRedisConfig } from '@holo-js/kernel';
5
8
 
6
9
  type FlexibleEnvelope<TValue> = {
7
10
  readonly __holo_cache_flexible: true;
@@ -56,7 +59,7 @@ declare function resetDatabaseDriverModuleLoader(): void;
56
59
  declare const cacheDbInternals: {
57
60
  isModuleNotFoundError: typeof isModuleNotFoundError$1;
58
61
  isNormalizedDatabaseConfig: typeof isNormalizedDatabaseConfig;
59
- loadDatabaseDriverModule: OptionalDriverModuleLoader<DatabaseCacheDriverModule>;
62
+ loadDatabaseDriverModule: () => Promise<DatabaseCacheDriverModule>;
60
63
  normalizeDatabaseModuleLoadError: typeof normalizeDatabaseModuleLoadError;
61
64
  normalizeRuntimeDatabaseConfig: typeof normalizeRuntimeDatabaseConfig;
62
65
  resolveSharedDatabaseConnection: typeof resolveSharedDatabaseConnection;
@@ -74,6 +77,12 @@ type FileCacheLockEnvelope = {
74
77
  owner: string;
75
78
  expiresAt: number;
76
79
  };
80
+ type FileSystemOperations = {
81
+ readonly mkdir: typeof mkdir;
82
+ readonly readdir: typeof readdir;
83
+ readonly rmdir: typeof rmdir;
84
+ readonly writeFile: typeof writeFile;
85
+ };
77
86
  declare function hashCacheKey(key: string): string;
78
87
  declare function resolveDriverRoot(path: string): string;
79
88
  declare function resolveEntryFilePath(rootPath: string, key: string): string;
@@ -87,6 +96,8 @@ declare const fileDriverInternals: {
87
96
  resolveDriverRoot: typeof resolveDriverRoot;
88
97
  resolveEntryFilePath: typeof resolveEntryFilePath;
89
98
  resolveLockFilePath: typeof resolveLockFilePath;
99
+ resetFileSystemOperations(): void;
100
+ setFileSystemOperations(operations: Partial<FileSystemOperations>): void;
90
101
  };
91
102
 
92
103
  type DependencyIndexState = {
@@ -133,7 +144,7 @@ declare function resetRedisDriverModuleLoader(): void;
133
144
  declare const cacheRedisInternals: {
134
145
  isModuleNotFoundError: typeof isModuleNotFoundError;
135
146
  isNormalizedRedisConfig: typeof isNormalizedRedisConfig;
136
- loadRedisDriverModule: OptionalDriverModuleLoader<RedisCacheDriverModule>;
147
+ loadRedisDriverModule: () => Promise<RedisCacheDriverModule>;
137
148
  normalizeRedisModuleLoadError: typeof normalizeRedisModuleLoadError;
138
149
  normalizeRuntimeRedisConfig: typeof normalizeRuntimeRedisConfig;
139
150
  resolveSharedRedisConnection: typeof resolveSharedRedisConnection;
@@ -141,6 +152,15 @@ declare const cacheRedisInternals: {
141
152
  setRedisDriverModuleLoader: typeof setRedisDriverModuleLoader;
142
153
  };
143
154
 
155
+ interface CacheDriverFactory<TOptions> {
156
+ readonly driver: string;
157
+ readonly registrationKey?: string;
158
+ create(options: TOptions): CacheDriverContract;
159
+ }
160
+ declare function registerCacheDriverFactory<TOptions extends object>(factory: CacheDriverFactory<TOptions>): void;
161
+ declare function unregisterCacheDriverFactory<TOptions extends object>(factory: CacheDriverFactory<TOptions>): void;
162
+ declare function requireCacheDriverFactory<TOptions extends object>(driver: string, message: string): CacheDriverFactory<TOptions>;
163
+
144
164
  type CacheRuntimeFacade = {
145
165
  readonly config: NormalizedHoloCacheConfig;
146
166
  readonly databaseConfig?: NormalizedHoloDatabaseConfig;
@@ -160,6 +180,7 @@ declare function getCacheRuntime(): CacheRuntimeFacade;
160
180
  declare function resolveConfiguredDriver(facade: CacheRuntimeFacade, requestedName?: string): CacheDriverContract;
161
181
 
162
182
  declare function configureCacheRuntime$1(bindings?: CacheRuntimeBindings): void;
183
+ declare function loadCachePluginDrivers(projectRoot?: string, pluginNames?: readonly string[]): Promise<void>;
163
184
  declare const cacheRuntimeInternals: {
164
185
  getCacheRuntimeState: typeof getCacheRuntimeState;
165
186
  isNormalizedCacheConfig: typeof isNormalizedCacheConfig;
@@ -167,6 +188,10 @@ declare const cacheRuntimeInternals: {
167
188
  resolveConfiguredDriver: typeof resolveConfiguredDriver;
168
189
  };
169
190
 
191
+ declare function loadCachePluginDriverContracts(projectRoot?: string, pluginNames?: readonly string[]): Promise<readonly CacheDriverContract[]>;
192
+ declare function loadConfiguredCachePluginDriverContracts(projectRoot: string, pluginNames: readonly string[], configs: readonly NormalizedCachePluginDriverConfig[]): Promise<readonly CacheDriverContract[]>;
193
+ declare function resetCachePluginDriverContracts(): void;
194
+
170
195
  declare function configureCacheRuntime(...parameters: Parameters<typeof configureCacheRuntime$1>): void;
171
196
  declare function resetCacheRuntime(): void;
172
197
  declare const cache: Readonly<{
@@ -195,7 +220,8 @@ declare const cache: Readonly<{
195
220
  configureCacheRuntime: typeof configureCacheRuntime;
196
221
  getCacheRuntime: typeof getCacheRuntime;
197
222
  getCacheRuntimeBindings: typeof getCacheRuntimeBindings;
223
+ loadCachePluginDrivers: typeof loadCachePluginDrivers;
198
224
  resetCacheRuntime: typeof resetCacheRuntime;
199
225
  }>;
200
226
 
201
- export { CacheDependencyDescriptor, CacheDependencyIndex, CacheDriverContract, CacheFacade, CacheFallback, CacheFlexibleTtlInput, CacheKey, CacheKeyInput, CacheLockContract, CacheOptionalPackageError, CacheQueryBridge, CacheRepository, CacheRuntimeBindings, CacheTtlInput, CacheValueResolver, cacheDbInternals, cacheFacade, cacheFacadeInternals, cacheQueryBridgeInternals, cacheRedisInternals, cacheRuntimeInternals, configureCacheRuntime, cache as default, defineCacheKey, deserializeCacheValue, fileDriverInternals, getCacheRuntime, getCacheRuntimeBindings, normalizeCacheTtl, resetCacheRuntime, serializeCacheValue };
227
+ export { CacheDependencyDescriptor, CacheDependencyIndex, CacheDriverContract, type CacheDriverFactory, CacheFacade, CacheFallback, CacheFlexibleTtlInput, CacheKey, CacheKeyInput, CacheLockContract, CacheOptionalPackageError, CacheQueryBridge, CacheRepository, CacheRuntimeBindings, CacheTtlInput, CacheValueResolver, type DatabaseCacheDriverOptions, HoloCacheConfig, NormalizedCachePluginDriverConfig, NormalizedHoloCacheConfig, type RedisCacheDriverOptions, cacheDbInternals, cacheFacade, cacheFacadeInternals, cacheQueryBridgeInternals, cacheRedisInternals, cacheRuntimeInternals, configureCacheRuntime, cache as default, defineCacheKey, deserializeCacheValue, fileDriverInternals, getCacheRuntime, getCacheRuntimeBindings, loadCachePluginDriverContracts, loadCachePluginDrivers, loadConfiguredCachePluginDriverContracts, normalizeCacheTtl, registerCacheDriverFactory, requireCacheDriverFactory, resetCachePluginDriverContracts, resetCacheRuntime, serializeCacheValue, unregisterCacheDriverFactory };
package/dist/index.mjs CHANGED
@@ -1,3 +1,13 @@
1
+ import {
2
+ defineCacheConfig,
3
+ holoCacheDefaults,
4
+ normalizeCacheConfig
5
+ } from "./chunk-7FH4KYTX.mjs";
6
+ import {
7
+ registerCacheDriverFactory,
8
+ requireCacheDriverFactory,
9
+ unregisterCacheDriverFactory
10
+ } from "./chunk-FRE6NONR.mjs";
1
11
  import {
2
12
  CacheConfigError,
3
13
  CacheDriverResolutionError,
@@ -17,9 +27,11 @@ import {
17
27
  resolveCacheKey,
18
28
  serializeCacheValue
19
29
  } from "./chunk-KIYULZES.mjs";
20
-
21
- // src/index.ts
22
- import { defineCacheConfig } from "@holo-js/config";
30
+ import {
31
+ loadCachePluginDriverContracts,
32
+ loadConfiguredCachePluginDriverContracts,
33
+ resetCachePluginDriverContracts
34
+ } from "./chunk-NZGSTXGZ.mjs";
23
35
 
24
36
  // src/flexible.ts
25
37
  function normalizeFlexibleTtl(ttl) {
@@ -93,21 +105,12 @@ async function resolveFlexibleCachedValue(options) {
93
105
  return options.refresh(normalizedTtl);
94
106
  }
95
107
 
96
- // src/runtime-shared.ts
97
- import {
98
- holoCacheDefaults,
99
- normalizeCacheConfig
100
- } from "@holo-js/config";
101
-
102
108
  // src/db.ts
103
109
  import {
104
110
  normalizeDatabaseConfig
105
- } from "@holo-js/config";
111
+ } from "@holo-js/db";
106
112
 
107
113
  // src/optional-driver.ts
108
- import { createRequire } from "module";
109
- import { join } from "path";
110
- import { pathToFileURL } from "url";
111
114
  var CACHE_DRIVER_DISPOSE_SYMBOL = /* @__PURE__ */ Symbol.for("holo.cache.driver.dispose");
112
115
  function escapeRegExp(value) {
113
116
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -138,29 +141,6 @@ function normalizeOptionalDriverModuleLoadError(error, expectedSpecifier, messag
138
141
  }
139
142
  return error;
140
143
  }
141
- async function importOptionalDriverModuleFromProject(specifier) {
142
- const projectRequire = createRequire(join(process.cwd(), "package.json"));
143
- return await import(pathToFileURL(projectRequire.resolve(specifier)).href);
144
- }
145
- function createOptionalDriverModuleLoader(specifier, missingPackageMessage) {
146
- return async () => {
147
- try {
148
- return await import(
149
- /* webpackIgnore: true */
150
- specifier
151
- );
152
- } catch (error) {
153
- if (!isOptionalDriverModuleNotFoundError(error, specifier)) {
154
- throw normalizeOptionalDriverModuleLoadError(error, specifier, missingPackageMessage);
155
- }
156
- try {
157
- return await importOptionalDriverModuleFromProject(specifier);
158
- } catch (fallbackError) {
159
- throw normalizeOptionalDriverModuleLoadError(fallbackError, specifier, missingPackageMessage);
160
- }
161
- }
162
- };
163
- }
164
144
  var LazyOptionalCacheDriver = class {
165
145
  constructor(lazyOptions) {
166
146
  this.lazyOptions = lazyOptions;
@@ -260,7 +240,6 @@ function createLazyOptionalCacheDriver(options) {
260
240
  }
261
241
 
262
242
  // src/db.ts
263
- var DATABASE_CACHE_PACKAGE = "@holo-js/cache-db";
264
243
  var DATABASE_CACHE_MISSING_MESSAGE = "[@holo-js/cache] Database cache support requires @holo-js/cache-db to be installed.";
265
244
  function isNormalizedDatabaseConfig(config) {
266
245
  return typeof config === "object" && config !== null && typeof config.connections === "object" && config.connections !== null;
@@ -288,10 +267,11 @@ function isModuleNotFoundError(error, expectedSpecifier = "@holo-js/cache-db") {
288
267
  function normalizeDatabaseModuleLoadError(error, expectedSpecifier = "@holo-js/cache-db") {
289
268
  return normalizeOptionalDriverModuleLoadError(error, expectedSpecifier, DATABASE_CACHE_MISSING_MESSAGE);
290
269
  }
291
- var loadDatabaseDriverModule = createOptionalDriverModuleLoader(
292
- DATABASE_CACHE_PACKAGE,
293
- DATABASE_CACHE_MISSING_MESSAGE
294
- );
270
+ var loadDatabaseDriverModule = async () => {
271
+ const { requireCacheDriverFactory: requireCacheDriverFactory2 } = await import("./driver-registry-YQMWF4CC.mjs");
272
+ const factory = requireCacheDriverFactory2("database", DATABASE_CACHE_MISSING_MESSAGE);
273
+ return { createDatabaseCacheDriver: (options) => factory.create(options) };
274
+ };
295
275
  var databaseDriverModuleLoader = loadDatabaseDriverModule;
296
276
  function setDatabaseDriverModuleLoader(loader) {
297
277
  databaseDriverModuleLoader = loader;
@@ -321,8 +301,24 @@ var cacheDbInternals = {
321
301
 
322
302
  // src/file.ts
323
303
  import { createHash, randomUUID } from "crypto";
324
- import { mkdir, open, readFile, readdir, rename, rm, rmdir, writeFile } from "fs/promises";
325
- import { dirname, join as join2, resolve } from "path";
304
+ import {
305
+ mkdir as defaultMkdir,
306
+ open,
307
+ readFile,
308
+ readdir as defaultReaddir,
309
+ rename,
310
+ rm,
311
+ rmdir as defaultRmdir,
312
+ writeFile as defaultWriteFile
313
+ } from "fs/promises";
314
+ import { dirname, join, resolve } from "path";
315
+ var defaultFileSystemOperations = {
316
+ mkdir: defaultMkdir,
317
+ readdir: defaultReaddir,
318
+ rmdir: defaultRmdir,
319
+ writeFile: defaultWriteFile
320
+ };
321
+ var fileSystemOperations = defaultFileSystemOperations;
326
322
  var MALFORMED_FILE = /* @__PURE__ */ Symbol("MALFORMED_FILE");
327
323
  function defaultSleep(milliseconds) {
328
324
  return new Promise((resolveDelay) => {
@@ -347,14 +343,14 @@ function resolveDriverRoot(path) {
347
343
  }
348
344
  function resolveEntryFilePath(rootPath, key) {
349
345
  const hash = hashCacheKey(key);
350
- return join2(rootPath, "entries", hash.slice(0, 2), `${hash}.json`);
346
+ return join(rootPath, "entries", hash.slice(0, 2), `${hash}.json`);
351
347
  }
352
348
  function resolveLockFilePath(rootPath, name) {
353
349
  const hash = hashCacheKey(name);
354
- return join2(rootPath, "locks", hash.slice(0, 2), `${hash}.lock`);
350
+ return join(rootPath, "locks", hash.slice(0, 2), `${hash}.lock`);
355
351
  }
356
352
  function resolveLockMarkerFilePath(lockPath, owner) {
357
- return join2(lockPath, `${hashCacheKey(owner)}.json`);
353
+ return join(lockPath, `${hashCacheKey(owner)}.json`);
358
354
  }
359
355
  function isPositiveTimestamp(value) {
360
356
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
@@ -374,14 +370,14 @@ function isFileCacheLockEnvelope(value) {
374
370
  return typeof lock.name === "string" && typeof lock.owner === "string" && isPositiveTimestamp(lock.expiresAt);
375
371
  }
376
372
  async function ensureParentDirectory(filePath) {
377
- await mkdir(dirname(filePath), { recursive: true });
373
+ await fileSystemOperations.mkdir(dirname(filePath), { recursive: true });
378
374
  }
379
375
  async function removeFileIfPresent(filePath) {
380
376
  await rm(filePath, { force: true });
381
377
  }
382
378
  async function removeEmptyDirectoryIfPresent(path) {
383
379
  try {
384
- await rmdir(path);
380
+ await fileSystemOperations.rmdir(path);
385
381
  } catch (error) {
386
382
  if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTEMPTY" || error.code === "ENOTDIR")) {
387
383
  return;
@@ -402,7 +398,7 @@ async function readFileIfPresent(filePath) {
402
398
  async function writeFileAtomically(filePath, contents) {
403
399
  await ensureParentDirectory(filePath);
404
400
  const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
405
- await writeFile(temporaryPath, contents, "utf8");
401
+ await fileSystemOperations.writeFile(temporaryPath, contents, "utf8");
406
402
  try {
407
403
  await rename(temporaryPath, filePath);
408
404
  } catch (error) {
@@ -438,9 +434,9 @@ async function readJsonFile(filePath) {
438
434
  }
439
435
  async function listFiles(rootPath) {
440
436
  try {
441
- const entries = await readdir(rootPath, { withFileTypes: true });
437
+ const entries = await fileSystemOperations.readdir(rootPath, { withFileTypes: true });
442
438
  const nested = await Promise.all(entries.map(async (entry) => {
443
- const entryPath = join2(rootPath, entry.name);
439
+ const entryPath = join(rootPath, entry.name);
444
440
  if (entry.isDirectory()) return listFiles(entryPath);
445
441
  return [entryPath];
446
442
  }));
@@ -468,7 +464,7 @@ async function removeScopedCacheFiles(rootPath, prefix, isEnvelope, resolveName)
468
464
  }
469
465
  if (!prefix) {
470
466
  await rm(rootPath, { recursive: true, force: true });
471
- await mkdir(rootPath, { recursive: true });
467
+ await fileSystemOperations.mkdir(rootPath, { recursive: true });
472
468
  return;
473
469
  }
474
470
  for (const filePath of await listFiles(rootPath)) {
@@ -501,8 +497,8 @@ async function readLock(rootPath, name, now) {
501
497
  const filePath = resolveLockFilePath(rootPath, name);
502
498
  let markerFilePaths;
503
499
  try {
504
- const entries = await readdir(filePath, { withFileTypes: true });
505
- markerFilePaths = entries.filter((entry) => entry.isFile()).map((entry) => join2(filePath, entry.name));
500
+ const entries = await fileSystemOperations.readdir(filePath, { withFileTypes: true });
501
+ markerFilePaths = entries.filter((entry) => entry.isFile()).map((entry) => join(filePath, entry.name));
506
502
  } catch (error) {
507
503
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
508
504
  return {
@@ -585,7 +581,7 @@ function createFileLock(rootPath, name, seconds, now, sleep, ownerFactory) {
585
581
  async function writeLockDirectory(filePath, envelope) {
586
582
  await ensureParentDirectory(filePath);
587
583
  try {
588
- await mkdir(filePath);
584
+ await fileSystemOperations.mkdir(filePath);
589
585
  } catch (error) {
590
586
  if (error instanceof Error && "code" in error && error.code === "EEXIST") {
591
587
  return false;
@@ -593,7 +589,7 @@ function createFileLock(rootPath, name, seconds, now, sleep, ownerFactory) {
593
589
  throw error;
594
590
  }
595
591
  try {
596
- await writeFile(resolveLockMarkerFilePath(filePath, owner), envelope, "utf8");
592
+ await fileSystemOperations.writeFile(resolveLockMarkerFilePath(filePath, owner), envelope, "utf8");
597
593
  } catch (error) {
598
594
  await removeFileIfPresent(resolveLockMarkerFilePath(filePath, owner));
599
595
  await removeEmptyDirectoryIfPresent(filePath);
@@ -747,13 +743,13 @@ function createFileCacheDriver(options) {
747
743
  },
748
744
  async flush() {
749
745
  await removeScopedCacheFiles(
750
- join2(rootPath, "entries"),
746
+ join(rootPath, "entries"),
751
747
  prefix,
752
748
  isFileCacheEntryEnvelope,
753
749
  (entry) => entry.key
754
750
  );
755
751
  await removeScopedCacheFiles(
756
- join2(rootPath, "locks"),
752
+ join(rootPath, "locks"),
757
753
  prefix,
758
754
  isFileCacheLockEnvelope,
759
755
  (lock) => lock.name
@@ -776,7 +772,13 @@ var fileDriverInternals = {
776
772
  isFileCacheLockEnvelope,
777
773
  resolveDriverRoot,
778
774
  resolveEntryFilePath,
779
- resolveLockFilePath
775
+ resolveLockFilePath,
776
+ resetFileSystemOperations() {
777
+ fileSystemOperations = defaultFileSystemOperations;
778
+ },
779
+ setFileSystemOperations(operations) {
780
+ fileSystemOperations = { ...defaultFileSystemOperations, ...operations };
781
+ }
780
782
  };
781
783
 
782
784
  // src/memory.ts
@@ -969,8 +971,7 @@ function createMemoryCacheDriver(options) {
969
971
  // src/redis.ts
970
972
  import {
971
973
  normalizeRedisConfig
972
- } from "@holo-js/config";
973
- var REDIS_CACHE_PACKAGE = "@holo-js/cache-redis";
974
+ } from "@holo-js/kernel";
974
975
  var REDIS_CACHE_MISSING_MESSAGE = "[@holo-js/cache] Redis cache support requires @holo-js/cache-redis to be installed.";
975
976
  function isNormalizedRedisConfig(config) {
976
977
  return typeof config.default === "string" && typeof config.connections === "object" && config.connections !== null && Object.values(config.connections).every((connection) => {
@@ -1000,10 +1001,11 @@ function isModuleNotFoundError2(error, expectedSpecifier = "@holo-js/cache-redis
1000
1001
  function normalizeRedisModuleLoadError(error, expectedSpecifier = "@holo-js/cache-redis") {
1001
1002
  return normalizeOptionalDriverModuleLoadError(error, expectedSpecifier, REDIS_CACHE_MISSING_MESSAGE);
1002
1003
  }
1003
- var loadRedisDriverModule = createOptionalDriverModuleLoader(
1004
- REDIS_CACHE_PACKAGE,
1005
- REDIS_CACHE_MISSING_MESSAGE
1006
- );
1004
+ var loadRedisDriverModule = async () => {
1005
+ const { requireCacheDriverFactory: requireCacheDriverFactory2 } = await import("./driver-registry-YQMWF4CC.mjs");
1006
+ const factory = requireCacheDriverFactory2("redis", REDIS_CACHE_MISSING_MESSAGE);
1007
+ return { createRedisCacheDriver: (options) => factory.create(options) };
1008
+ };
1007
1009
  var redisDriverModuleLoader = loadRedisDriverModule;
1008
1010
  function setRedisDriverModuleLoader(loader) {
1009
1011
  redisDriverModuleLoader = loader;
@@ -1093,45 +1095,55 @@ function resolveConfiguredDriver(facade, requestedName) {
1093
1095
  }
1094
1096
  switch (driverConfig.driver) {
1095
1097
  case "file": {
1098
+ const fileConfig = driverConfig;
1096
1099
  return cacheResolvedDriver(facade, driverName, createFileCacheDriver({
1097
- name: driverConfig.name,
1098
- path: driverConfig.path,
1099
- prefix: driverConfig.prefix
1100
+ name: fileConfig.name,
1101
+ path: fileConfig.path,
1102
+ prefix: fileConfig.prefix
1100
1103
  }));
1101
1104
  }
1102
1105
  case "memory": {
1106
+ const memoryConfig = driverConfig;
1103
1107
  return cacheResolvedDriver(facade, driverName, createMemoryCacheDriver({
1104
- name: driverConfig.name,
1105
- maxEntries: driverConfig.maxEntries
1108
+ name: memoryConfig.name,
1109
+ maxEntries: memoryConfig.maxEntries
1106
1110
  }));
1107
1111
  }
1108
1112
  case "redis": {
1113
+ const redisConfig = driverConfig;
1109
1114
  const connection = cacheRedisInternals.resolveSharedRedisConnection(
1110
1115
  facade.redisConfig,
1111
- driverConfig.connection
1116
+ redisConfig.connection
1112
1117
  );
1113
1118
  return cacheResolvedDriver(facade, driverName, createRedisCacheDriver({
1114
- name: driverConfig.name,
1119
+ name: redisConfig.name,
1115
1120
  connectionName: connection.name,
1116
- prefix: driverConfig.prefix,
1121
+ prefix: redisConfig.prefix,
1117
1122
  redis: connection
1118
1123
  }));
1119
1124
  }
1120
1125
  case "database": {
1126
+ const databaseConfig = driverConfig;
1121
1127
  const connection = cacheDbInternals.resolveSharedDatabaseConnection(
1122
1128
  facade.databaseConfig,
1123
- driverConfig.connection
1129
+ databaseConfig.connection
1124
1130
  );
1125
1131
  return cacheResolvedDriver(facade, driverName, createDatabaseCacheDriver({
1126
- name: driverConfig.name,
1127
- connectionName: driverConfig.connection,
1128
- table: driverConfig.table,
1129
- lockTable: driverConfig.lockTable,
1130
- prefix: driverConfig.prefix,
1132
+ name: databaseConfig.name,
1133
+ connectionName: databaseConfig.connection,
1134
+ table: databaseConfig.table,
1135
+ lockTable: databaseConfig.lockTable,
1136
+ prefix: databaseConfig.prefix,
1131
1137
  connection
1132
1138
  }));
1133
1139
  }
1134
1140
  default:
1141
+ if (typeof driverConfig.driver === "string") {
1142
+ const pluginDriver = facade.drivers.get(driverConfig.driver);
1143
+ if (pluginDriver) {
1144
+ return cacheResolvedDriver(facade, driverName, pluginDriver);
1145
+ }
1146
+ }
1135
1147
  throw new CacheDriverResolutionError(
1136
1148
  `[@holo-js/cache] Cache driver "${driverName}" uses unsupported driver "${String(driverConfig.driver)}" in this phase.`
1137
1149
  );
@@ -1205,14 +1217,11 @@ function resetDefaultDependencyIndex() {
1205
1217
  function resolveDriverContext(driverName) {
1206
1218
  const runtime = getCacheRuntime();
1207
1219
  const configuredDriverName = driverName?.trim() || runtime.config.default;
1208
- const driverConfig = runtime.config.drivers[configuredDriverName];
1209
- let normalizedKeyPrefix = runtime.config.prefix;
1210
- if (typeof driverConfig?.prefix === "string") {
1211
- normalizedKeyPrefix = driverConfig.prefix;
1212
- }
1220
+ const driver = resolveConfiguredDriver(runtime, configuredDriverName);
1221
+ const normalizedKeyPrefix = runtime.config.drivers[configuredDriverName].prefix;
1213
1222
  return Object.freeze({
1214
1223
  driverName: configuredDriverName,
1215
- driver: resolveConfiguredDriver(runtime, configuredDriverName),
1224
+ driver,
1216
1225
  normalizedKeyPrefix
1217
1226
  });
1218
1227
  }
@@ -1370,6 +1379,26 @@ function resetCacheRuntime() {
1370
1379
  getCacheRuntimeState().bindings = void 0;
1371
1380
  resetDefaultDependencyIndex();
1372
1381
  setGlobalDatabaseQueryCacheBridge(void 0);
1382
+ resetCachePluginDriverContracts();
1383
+ }
1384
+ async function loadCachePluginDrivers(projectRoot = process.cwd(), pluginNames = []) {
1385
+ const bindings = getCacheRuntimeState().bindings;
1386
+ if (!bindings) {
1387
+ return;
1388
+ }
1389
+ const pluginDriverConfigs = Object.values(bindings.config.drivers).filter((driver) => {
1390
+ return driver.driver !== "memory" && driver.driver !== "file" && driver.driver !== "redis" && driver.driver !== "database";
1391
+ });
1392
+ for (const driver of await loadConfiguredCachePluginDriverContracts(projectRoot, pluginNames, pluginDriverConfigs)) {
1393
+ bindings.drivers.set(driver.name, driver);
1394
+ }
1395
+ if (pluginDriverConfigs.length > 0) {
1396
+ return;
1397
+ }
1398
+ const { loadCachePluginDriverContracts: loadCachePluginDriverContracts2 } = await import("./plugins-JHYNVE7O.mjs");
1399
+ for (const driver of await loadCachePluginDriverContracts2(projectRoot, pluginNames)) {
1400
+ bindings.drivers.set(driver.name, driver);
1401
+ }
1373
1402
  }
1374
1403
  var cacheRuntimeInternals = {
1375
1404
  getCacheRuntimeState,
@@ -1605,6 +1634,7 @@ var cache = Object.freeze({
1605
1634
  configureCacheRuntime: configureCacheRuntime2,
1606
1635
  getCacheRuntime,
1607
1636
  getCacheRuntimeBindings,
1637
+ loadCachePluginDrivers,
1608
1638
  resetCacheRuntime: resetCacheRuntime2,
1609
1639
  ...cacheFacade
1610
1640
  });
@@ -1635,9 +1665,18 @@ export {
1635
1665
  fileDriverInternals,
1636
1666
  getCacheRuntime,
1637
1667
  getCacheRuntimeBindings,
1668
+ holoCacheDefaults,
1638
1669
  isCacheKey,
1670
+ loadCachePluginDriverContracts,
1671
+ loadCachePluginDrivers,
1672
+ loadConfiguredCachePluginDriverContracts,
1673
+ normalizeCacheConfig,
1639
1674
  normalizeCacheTtl,
1675
+ registerCacheDriverFactory,
1676
+ requireCacheDriverFactory,
1677
+ resetCachePluginDriverContracts,
1640
1678
  resetCacheRuntime2 as resetCacheRuntime,
1641
1679
  resolveCacheKey,
1642
- serializeCacheValue
1680
+ serializeCacheValue,
1681
+ unregisterCacheDriverFactory
1643
1682
  };
@@ -0,0 +1,10 @@
1
+ import {
2
+ loadCachePluginDriverContracts,
3
+ loadConfiguredCachePluginDriverContracts,
4
+ resetCachePluginDriverContracts
5
+ } from "./chunk-NZGSTXGZ.mjs";
6
+ export {
7
+ loadCachePluginDriverContracts,
8
+ loadConfiguredCachePluginDriverContracts,
9
+ resetCachePluginDriverContracts
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holo-js/cache",
3
- "version": "0.2.6",
3
+ "version": "0.3.0",
4
4
  "description": "Holo-JS Framework - cache contracts, config helpers, serialization, and runtime seams",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -10,6 +10,11 @@
10
10
  "import": "./dist/index.mjs",
11
11
  "default": "./dist/index.mjs"
12
12
  },
13
+ "./config": {
14
+ "types": "./dist/config.d.ts",
15
+ "import": "./dist/config.mjs",
16
+ "default": "./dist/config.mjs"
17
+ },
13
18
  "./contracts": {
14
19
  "types": "./dist/contracts.d.ts",
15
20
  "import": "./dist/contracts.mjs",
@@ -28,7 +33,9 @@
28
33
  "test": "vitest --run"
29
34
  },
30
35
  "dependencies": {
31
- "@holo-js/config": "^0.2.6"
36
+ "@holo-js/config": "^0.3.0",
37
+ "@holo-js/db": "^0.3.0",
38
+ "@holo-js/kernel": "^0.3.0"
32
39
  },
33
40
  "devDependencies": {
34
41
  "@types/node": "^22.10.2",