@holo-js/cache 0.1.8 → 0.2.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.
- package/dist/index.d.ts +13 -11
- package/dist/index.mjs +223 -326
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CacheFacade, CacheRepository,
|
|
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
3
|
import { HoloDatabaseConfig, NormalizedHoloDatabaseConfig, HoloDatabaseConnectionConfig, HoloRedisConfig, NormalizedHoloRedisConfig, NormalizedHoloRedisConnectionConfig, NormalizedHoloCacheConfig, HoloCacheConfig } from '@holo-js/config';
|
|
4
4
|
export { CacheDatabaseDriverConfig, CacheDriver, CacheDriverConfig, CacheFileDriverConfig, CacheMemoryDriverConfig, CacheRedisDriverConfig, HoloCacheConfig, NormalizedCacheDatabaseDriverConfig, NormalizedCacheDriverConfig, NormalizedCacheFileDriverConfig, NormalizedCacheMemoryDriverConfig, NormalizedCacheRedisDriverConfig, NormalizedHoloCacheConfig, defineCacheConfig } from '@holo-js/config';
|
|
@@ -13,11 +13,12 @@ type NormalizedFlexibleTtl = {
|
|
|
13
13
|
readonly freshSeconds: number;
|
|
14
14
|
readonly staleSeconds: number;
|
|
15
15
|
};
|
|
16
|
+
declare function normalizeFlexibleTtl(ttl: CacheFlexibleTtlInput): NormalizedFlexibleTtl;
|
|
17
|
+
declare function isFlexibleEnvelope<TValue>(value: unknown): value is FlexibleEnvelope<TValue>;
|
|
18
|
+
|
|
16
19
|
declare function resolveFallback<TValue>(fallback: CacheFallback<TValue>): Promise<TValue> | TValue;
|
|
17
20
|
declare function resolveValue<TValue>(callback: CacheValueResolver<TValue>): Promise<Awaited<TValue>>;
|
|
18
21
|
declare function resolveDriverKey(driverName?: string): string;
|
|
19
|
-
declare function normalizeFlexibleTtl(ttl: CacheFlexibleTtlInput): NormalizedFlexibleTtl;
|
|
20
|
-
declare function isFlexibleEnvelope<TValue>(value: unknown): value is FlexibleEnvelope<TValue>;
|
|
21
22
|
declare function getOrCreateRepository(driverName?: string): CacheRepository;
|
|
22
23
|
declare const cacheFacade: CacheFacade;
|
|
23
24
|
declare const cacheFacadeInternals: {
|
|
@@ -30,6 +31,9 @@ declare const cacheFacadeInternals: {
|
|
|
30
31
|
resolveValue: typeof resolveValue;
|
|
31
32
|
};
|
|
32
33
|
|
|
34
|
+
type OptionalDriverModuleLoader<TModule> = () => Promise<TModule>;
|
|
35
|
+
declare function normalizeOptionalDriverModuleLoadError(error: unknown, expectedSpecifier: string, message: string): CacheOptionalPackageError | unknown;
|
|
36
|
+
|
|
33
37
|
type DatabaseCacheDriverOptions = {
|
|
34
38
|
readonly name: string;
|
|
35
39
|
readonly connectionName: string;
|
|
@@ -41,19 +45,18 @@ type DatabaseCacheDriverOptions = {
|
|
|
41
45
|
type DatabaseCacheDriverModule = {
|
|
42
46
|
createDatabaseCacheDriver(options: DatabaseCacheDriverOptions): CacheDriverContract;
|
|
43
47
|
};
|
|
44
|
-
type DatabaseDriverModuleLoader =
|
|
48
|
+
type DatabaseDriverModuleLoader = OptionalDriverModuleLoader<DatabaseCacheDriverModule>;
|
|
45
49
|
declare function isNormalizedDatabaseConfig(config: HoloDatabaseConfig | NormalizedHoloDatabaseConfig): config is NormalizedHoloDatabaseConfig;
|
|
46
50
|
declare function normalizeRuntimeDatabaseConfig(config: HoloDatabaseConfig | NormalizedHoloDatabaseConfig | undefined): NormalizedHoloDatabaseConfig | undefined;
|
|
47
51
|
declare function resolveSharedDatabaseConnection(databaseConfig: NormalizedHoloDatabaseConfig | undefined, connectionName: string): HoloDatabaseConnectionConfig | string;
|
|
48
52
|
declare function isModuleNotFoundError$1(error: unknown, expectedSpecifier?: string): boolean;
|
|
49
|
-
declare function normalizeDatabaseModuleLoadError(error: unknown, expectedSpecifier?: string):
|
|
50
|
-
declare function loadDatabaseDriverModule(): Promise<DatabaseCacheDriverModule>;
|
|
53
|
+
declare function normalizeDatabaseModuleLoadError(error: unknown, expectedSpecifier?: string): ReturnType<typeof normalizeOptionalDriverModuleLoadError>;
|
|
51
54
|
declare function setDatabaseDriverModuleLoader(loader: DatabaseDriverModuleLoader): void;
|
|
52
55
|
declare function resetDatabaseDriverModuleLoader(): void;
|
|
53
56
|
declare const cacheDbInternals: {
|
|
54
57
|
isModuleNotFoundError: typeof isModuleNotFoundError$1;
|
|
55
58
|
isNormalizedDatabaseConfig: typeof isNormalizedDatabaseConfig;
|
|
56
|
-
loadDatabaseDriverModule:
|
|
59
|
+
loadDatabaseDriverModule: OptionalDriverModuleLoader<DatabaseCacheDriverModule>;
|
|
57
60
|
normalizeDatabaseModuleLoadError: typeof normalizeDatabaseModuleLoadError;
|
|
58
61
|
normalizeRuntimeDatabaseConfig: typeof normalizeRuntimeDatabaseConfig;
|
|
59
62
|
resolveSharedDatabaseConnection: typeof resolveSharedDatabaseConnection;
|
|
@@ -119,19 +122,18 @@ type RedisCacheDriverOptions = {
|
|
|
119
122
|
type RedisCacheDriverModule = {
|
|
120
123
|
createRedisCacheDriver(options: RedisCacheDriverOptions): CacheDriverContract;
|
|
121
124
|
};
|
|
122
|
-
type RedisDriverModuleLoader =
|
|
125
|
+
type RedisDriverModuleLoader = OptionalDriverModuleLoader<RedisCacheDriverModule>;
|
|
123
126
|
declare function isNormalizedRedisConfig(config: HoloRedisConfig | NormalizedHoloRedisConfig): config is NormalizedHoloRedisConfig;
|
|
124
127
|
declare function normalizeRuntimeRedisConfig(config: HoloRedisConfig | NormalizedHoloRedisConfig | undefined): NormalizedHoloRedisConfig | undefined;
|
|
125
128
|
declare function resolveSharedRedisConnection(redisConfig: NormalizedHoloRedisConfig | undefined, connectionName: string): NormalizedHoloRedisConnectionConfig;
|
|
126
129
|
declare function isModuleNotFoundError(error: unknown, expectedSpecifier?: string): boolean;
|
|
127
|
-
declare function normalizeRedisModuleLoadError(error: unknown, expectedSpecifier?: string):
|
|
128
|
-
declare function loadRedisDriverModule(): Promise<RedisCacheDriverModule>;
|
|
130
|
+
declare function normalizeRedisModuleLoadError(error: unknown, expectedSpecifier?: string): ReturnType<typeof normalizeOptionalDriverModuleLoadError>;
|
|
129
131
|
declare function setRedisDriverModuleLoader(loader: RedisDriverModuleLoader): void;
|
|
130
132
|
declare function resetRedisDriverModuleLoader(): void;
|
|
131
133
|
declare const cacheRedisInternals: {
|
|
132
134
|
isModuleNotFoundError: typeof isModuleNotFoundError;
|
|
133
135
|
isNormalizedRedisConfig: typeof isNormalizedRedisConfig;
|
|
134
|
-
loadRedisDriverModule:
|
|
136
|
+
loadRedisDriverModule: OptionalDriverModuleLoader<RedisCacheDriverModule>;
|
|
135
137
|
normalizeRedisModuleLoadError: typeof normalizeRedisModuleLoadError;
|
|
136
138
|
normalizeRuntimeRedisConfig: typeof normalizeRuntimeRedisConfig;
|
|
137
139
|
resolveSharedRedisConnection: typeof resolveSharedRedisConnection;
|
package/dist/index.mjs
CHANGED
|
@@ -21,6 +21,78 @@ import {
|
|
|
21
21
|
// src/index.ts
|
|
22
22
|
import { defineCacheConfig } from "@holo-js/config";
|
|
23
23
|
|
|
24
|
+
// src/flexible.ts
|
|
25
|
+
function normalizeFlexibleTtl(ttl) {
|
|
26
|
+
const freshSeconds = "fresh" in ttl ? ttl.fresh : ttl[0];
|
|
27
|
+
const staleSeconds = "stale" in ttl ? ttl.stale : ttl[1];
|
|
28
|
+
if (!Number.isInteger(freshSeconds) || freshSeconds < 0) {
|
|
29
|
+
throw new CacheInvalidTtlError("[@holo-js/cache] Flexible fresh TTL must be an integer greater than or equal to 0.");
|
|
30
|
+
}
|
|
31
|
+
if (!Number.isInteger(staleSeconds) || staleSeconds < freshSeconds) {
|
|
32
|
+
throw new CacheInvalidTtlError("[@holo-js/cache] Flexible stale TTL must be an integer greater than or equal to the fresh TTL.");
|
|
33
|
+
}
|
|
34
|
+
return Object.freeze({
|
|
35
|
+
freshSeconds,
|
|
36
|
+
staleSeconds
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function createFlexibleEnvelope(ttl, value, now = Date.now()) {
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
__holo_cache_flexible: true,
|
|
42
|
+
value,
|
|
43
|
+
freshUntil: now + ttl.freshSeconds * 1e3,
|
|
44
|
+
staleUntil: now + ttl.staleSeconds * 1e3
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function isFlexibleEnvelope(value) {
|
|
48
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const envelope = value;
|
|
52
|
+
return envelope.__holo_cache_flexible === true && typeof envelope.freshUntil === "number" && Number.isFinite(envelope.freshUntil) && typeof envelope.staleUntil === "number" && Number.isFinite(envelope.staleUntil) && "value" in envelope;
|
|
53
|
+
}
|
|
54
|
+
function resolveFlexibleEnvelopeState(envelope, now = Date.now()) {
|
|
55
|
+
if (now <= envelope.freshUntil) {
|
|
56
|
+
return "fresh";
|
|
57
|
+
}
|
|
58
|
+
if (now <= envelope.staleUntil) {
|
|
59
|
+
return "stale";
|
|
60
|
+
}
|
|
61
|
+
return "expired";
|
|
62
|
+
}
|
|
63
|
+
async function resolveFlexibleCachedValue(options) {
|
|
64
|
+
const normalizedTtl = normalizeFlexibleTtl(options.ttl);
|
|
65
|
+
const cached = await options.read();
|
|
66
|
+
const now = options.now?.() ?? Date.now();
|
|
67
|
+
if (isFlexibleEnvelope(cached)) {
|
|
68
|
+
const state = resolveFlexibleEnvelopeState(cached, now);
|
|
69
|
+
if (state === "fresh") {
|
|
70
|
+
return cached.value;
|
|
71
|
+
}
|
|
72
|
+
if (state === "stale") {
|
|
73
|
+
const refreshLock2 = options.createLock(normalizedTtl);
|
|
74
|
+
void refreshLock2.get(async () => {
|
|
75
|
+
await options.refresh(normalizedTtl);
|
|
76
|
+
return true;
|
|
77
|
+
}).catch(() => void 0);
|
|
78
|
+
return cached.value;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const refreshLock = options.createLock(normalizedTtl);
|
|
82
|
+
const refreshed = await refreshLock.block(
|
|
83
|
+
options.blockSeconds?.(normalizedTtl) ?? 1,
|
|
84
|
+
async () => options.refresh(normalizedTtl)
|
|
85
|
+
);
|
|
86
|
+
if (refreshed !== false) {
|
|
87
|
+
return refreshed;
|
|
88
|
+
}
|
|
89
|
+
const retried = await options.read();
|
|
90
|
+
if (isFlexibleEnvelope(retried) && resolveFlexibleEnvelopeState(retried, now) !== "expired") {
|
|
91
|
+
return retried.value;
|
|
92
|
+
}
|
|
93
|
+
return options.refresh(normalizedTtl);
|
|
94
|
+
}
|
|
95
|
+
|
|
24
96
|
// src/runtime-shared.ts
|
|
25
97
|
import {
|
|
26
98
|
holoCacheDefaults,
|
|
@@ -28,36 +100,19 @@ import {
|
|
|
28
100
|
} from "@holo-js/config";
|
|
29
101
|
|
|
30
102
|
// src/db.ts
|
|
31
|
-
import { createRequire } from "module";
|
|
32
|
-
import { join } from "path";
|
|
33
|
-
import { pathToFileURL } from "url";
|
|
34
103
|
import {
|
|
35
104
|
normalizeDatabaseConfig
|
|
36
105
|
} from "@holo-js/config";
|
|
106
|
+
|
|
107
|
+
// src/optional-driver.ts
|
|
108
|
+
import { createRequire } from "module";
|
|
109
|
+
import { join } from "path";
|
|
110
|
+
import { pathToFileURL } from "url";
|
|
111
|
+
var CACHE_DRIVER_DISPOSE_SYMBOL = /* @__PURE__ */ Symbol.for("holo.cache.driver.dispose");
|
|
37
112
|
function escapeRegExp(value) {
|
|
38
113
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
39
114
|
}
|
|
40
|
-
function
|
|
41
|
-
return typeof config === "object" && config !== null && typeof config.connections === "object" && config.connections !== null;
|
|
42
|
-
}
|
|
43
|
-
function normalizeRuntimeDatabaseConfig(config) {
|
|
44
|
-
if (!config) return void 0;
|
|
45
|
-
return normalizeDatabaseConfig(config);
|
|
46
|
-
}
|
|
47
|
-
function resolveSharedDatabaseConnection(databaseConfig, connectionName) {
|
|
48
|
-
if (!databaseConfig) {
|
|
49
|
-
throw new CacheDriverResolutionError(
|
|
50
|
-
`[@holo-js/cache] Database cache driver "${connectionName}" requires a top-level database config from config/database.ts.`
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
const connection = databaseConfig.connections[connectionName];
|
|
54
|
-
if (connection) return connection;
|
|
55
|
-
const availableConnections = Object.keys(databaseConfig.connections);
|
|
56
|
-
throw new CacheDriverResolutionError(
|
|
57
|
-
`[@holo-js/cache] Database cache connection "${connectionName}" was not found in config/database.ts. Available connections: ${availableConnections.join(", ") || "(none)"}.`
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
function isModuleNotFoundError(error, expectedSpecifier = "@holo-js/cache-db") {
|
|
115
|
+
function isOptionalDriverModuleNotFoundError(error, expectedSpecifier) {
|
|
61
116
|
if (!error || typeof error !== "object") {
|
|
62
117
|
return false;
|
|
63
118
|
}
|
|
@@ -73,63 +128,60 @@ function isModuleNotFoundError(error, expectedSpecifier = "@holo-js/cache-db") {
|
|
|
73
128
|
return true;
|
|
74
129
|
}
|
|
75
130
|
if ("cause" in error) {
|
|
76
|
-
return
|
|
131
|
+
return isOptionalDriverModuleNotFoundError(error.cause, expectedSpecifier);
|
|
77
132
|
}
|
|
78
133
|
return false;
|
|
79
134
|
}
|
|
80
|
-
function
|
|
81
|
-
if (
|
|
82
|
-
return new CacheOptionalPackageError(
|
|
83
|
-
"[@holo-js/cache] Database cache support requires @holo-js/cache-db to be installed.",
|
|
84
|
-
{ cause: error }
|
|
85
|
-
);
|
|
135
|
+
function normalizeOptionalDriverModuleLoadError(error, expectedSpecifier, message) {
|
|
136
|
+
if (isOptionalDriverModuleNotFoundError(error, expectedSpecifier)) {
|
|
137
|
+
return new CacheOptionalPackageError(message, { cause: error });
|
|
86
138
|
}
|
|
87
139
|
return error;
|
|
88
140
|
}
|
|
89
|
-
async function
|
|
141
|
+
async function importOptionalDriverModuleFromProject(specifier) {
|
|
90
142
|
const projectRequire = createRequire(join(process.cwd(), "package.json"));
|
|
91
143
|
return await import(pathToFileURL(projectRequire.resolve(specifier)).href);
|
|
92
144
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
return await import(
|
|
97
|
-
/* webpackIgnore: true */
|
|
98
|
-
specifier
|
|
99
|
-
);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
if (!isModuleNotFoundError(error, specifier)) {
|
|
102
|
-
throw normalizeDatabaseModuleLoadError(error, specifier);
|
|
103
|
-
}
|
|
145
|
+
function createOptionalDriverModuleLoader(specifier, missingPackageMessage) {
|
|
146
|
+
return async () => {
|
|
104
147
|
try {
|
|
105
|
-
return await
|
|
106
|
-
|
|
107
|
-
|
|
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
|
+
}
|
|
108
161
|
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
var databaseDriverModuleLoader = loadDatabaseDriverModule;
|
|
112
|
-
function setDatabaseDriverModuleLoader(loader) {
|
|
113
|
-
databaseDriverModuleLoader = loader;
|
|
114
|
-
}
|
|
115
|
-
function resetDatabaseDriverModuleLoader() {
|
|
116
|
-
databaseDriverModuleLoader = loadDatabaseDriverModule;
|
|
162
|
+
};
|
|
117
163
|
}
|
|
118
|
-
var
|
|
119
|
-
constructor(
|
|
120
|
-
this.
|
|
164
|
+
var LazyOptionalCacheDriver = class {
|
|
165
|
+
constructor(lazyOptions) {
|
|
166
|
+
this.lazyOptions = lazyOptions;
|
|
121
167
|
}
|
|
122
|
-
driver = "database";
|
|
123
168
|
driverInstance;
|
|
124
169
|
pending;
|
|
170
|
+
disposalGeneration = 0;
|
|
125
171
|
get name() {
|
|
126
|
-
return this.
|
|
172
|
+
return this.lazyOptions.name;
|
|
173
|
+
}
|
|
174
|
+
get driver() {
|
|
175
|
+
return this.lazyOptions.driver;
|
|
127
176
|
}
|
|
128
177
|
async resolveDriver() {
|
|
129
178
|
if (this.driverInstance) return this.driverInstance;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this.
|
|
179
|
+
const pendingGeneration = this.disposalGeneration;
|
|
180
|
+
this.pending ??= this.lazyOptions.loadModule().then((module) => {
|
|
181
|
+
const driver = this.lazyOptions.createDriver(module, this.lazyOptions.options);
|
|
182
|
+
if (this.disposalGeneration === pendingGeneration) {
|
|
183
|
+
this.driverInstance = driver;
|
|
184
|
+
}
|
|
133
185
|
return driver;
|
|
134
186
|
}).finally(() => {
|
|
135
187
|
this.pending = void 0;
|
|
@@ -139,6 +191,26 @@ var LazyDatabaseCacheDriver = class {
|
|
|
139
191
|
async withDriver(callback) {
|
|
140
192
|
return callback(await this.resolveDriver());
|
|
141
193
|
}
|
|
194
|
+
[CACHE_DRIVER_DISPOSE_SYMBOL]() {
|
|
195
|
+
if (this.lazyOptions.disposeDriver !== true) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const pending = this.pending;
|
|
199
|
+
const driverInstance = this.driverInstance;
|
|
200
|
+
this.disposalGeneration += 1;
|
|
201
|
+
this.driverInstance = void 0;
|
|
202
|
+
this.pending = void 0;
|
|
203
|
+
if (driverInstance) {
|
|
204
|
+
const disposable = driverInstance;
|
|
205
|
+
disposable[CACHE_DRIVER_DISPOSE_SYMBOL]?.();
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
pending?.then((driver) => {
|
|
209
|
+
const disposable = driver;
|
|
210
|
+
disposable[CACHE_DRIVER_DISPOSE_SYMBOL]?.();
|
|
211
|
+
}).catch(() => {
|
|
212
|
+
});
|
|
213
|
+
}
|
|
142
214
|
createLockProxy(name, seconds) {
|
|
143
215
|
let lockPromise;
|
|
144
216
|
const resolveLock = async () => {
|
|
@@ -183,8 +255,58 @@ var LazyDatabaseCacheDriver = class {
|
|
|
183
255
|
return this.createLockProxy(name, seconds);
|
|
184
256
|
}
|
|
185
257
|
};
|
|
258
|
+
function createLazyOptionalCacheDriver(options) {
|
|
259
|
+
return new LazyOptionalCacheDriver(options);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/db.ts
|
|
263
|
+
var DATABASE_CACHE_PACKAGE = "@holo-js/cache-db";
|
|
264
|
+
var DATABASE_CACHE_MISSING_MESSAGE = "[@holo-js/cache] Database cache support requires @holo-js/cache-db to be installed.";
|
|
265
|
+
function isNormalizedDatabaseConfig(config) {
|
|
266
|
+
return typeof config === "object" && config !== null && typeof config.connections === "object" && config.connections !== null;
|
|
267
|
+
}
|
|
268
|
+
function normalizeRuntimeDatabaseConfig(config) {
|
|
269
|
+
if (!config) return void 0;
|
|
270
|
+
return normalizeDatabaseConfig(config);
|
|
271
|
+
}
|
|
272
|
+
function resolveSharedDatabaseConnection(databaseConfig, connectionName) {
|
|
273
|
+
if (!databaseConfig) {
|
|
274
|
+
throw new CacheDriverResolutionError(
|
|
275
|
+
`[@holo-js/cache] Database cache driver "${connectionName}" requires a top-level database config from config/database.ts.`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
const connection = databaseConfig.connections[connectionName];
|
|
279
|
+
if (connection) return connection;
|
|
280
|
+
const availableConnections = Object.keys(databaseConfig.connections);
|
|
281
|
+
throw new CacheDriverResolutionError(
|
|
282
|
+
`[@holo-js/cache] Database cache connection "${connectionName}" was not found in config/database.ts. Available connections: ${availableConnections.join(", ") || "(none)"}.`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
function isModuleNotFoundError(error, expectedSpecifier = "@holo-js/cache-db") {
|
|
286
|
+
return isOptionalDriverModuleNotFoundError(error, expectedSpecifier);
|
|
287
|
+
}
|
|
288
|
+
function normalizeDatabaseModuleLoadError(error, expectedSpecifier = "@holo-js/cache-db") {
|
|
289
|
+
return normalizeOptionalDriverModuleLoadError(error, expectedSpecifier, DATABASE_CACHE_MISSING_MESSAGE);
|
|
290
|
+
}
|
|
291
|
+
var loadDatabaseDriverModule = createOptionalDriverModuleLoader(
|
|
292
|
+
DATABASE_CACHE_PACKAGE,
|
|
293
|
+
DATABASE_CACHE_MISSING_MESSAGE
|
|
294
|
+
);
|
|
295
|
+
var databaseDriverModuleLoader = loadDatabaseDriverModule;
|
|
296
|
+
function setDatabaseDriverModuleLoader(loader) {
|
|
297
|
+
databaseDriverModuleLoader = loader;
|
|
298
|
+
}
|
|
299
|
+
function resetDatabaseDriverModuleLoader() {
|
|
300
|
+
databaseDriverModuleLoader = loadDatabaseDriverModule;
|
|
301
|
+
}
|
|
186
302
|
function createDatabaseCacheDriver(options) {
|
|
187
|
-
return
|
|
303
|
+
return createLazyOptionalCacheDriver({
|
|
304
|
+
name: options.name,
|
|
305
|
+
driver: "database",
|
|
306
|
+
options,
|
|
307
|
+
loadModule: databaseDriverModuleLoader,
|
|
308
|
+
createDriver: (module, driverOptions) => module.createDatabaseCacheDriver(driverOptions)
|
|
309
|
+
});
|
|
188
310
|
}
|
|
189
311
|
var cacheDbInternals = {
|
|
190
312
|
isModuleNotFoundError,
|
|
@@ -845,13 +967,11 @@ function createMemoryCacheDriver(options) {
|
|
|
845
967
|
}
|
|
846
968
|
|
|
847
969
|
// src/redis.ts
|
|
848
|
-
import { createRequire as createRequire2 } from "module";
|
|
849
|
-
import { join as join3 } from "path";
|
|
850
|
-
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
851
970
|
import {
|
|
852
971
|
normalizeRedisConfig
|
|
853
972
|
} from "@holo-js/config";
|
|
854
|
-
var
|
|
973
|
+
var REDIS_CACHE_PACKAGE = "@holo-js/cache-redis";
|
|
974
|
+
var REDIS_CACHE_MISSING_MESSAGE = "[@holo-js/cache] Redis cache support requires @holo-js/cache-redis to be installed.";
|
|
855
975
|
function isNormalizedRedisConfig(config) {
|
|
856
976
|
return typeof config.default === "string" && typeof config.connections === "object" && config.connections !== null && Object.values(config.connections).every((connection) => {
|
|
857
977
|
return typeof connection === "object" && connection !== null && "name" in connection && "host" in connection && "port" in connection && typeof connection.name === "string" && typeof connection.host === "string" && typeof connection.port === "number";
|
|
@@ -861,9 +981,6 @@ function normalizeRuntimeRedisConfig(config) {
|
|
|
861
981
|
if (!config) return void 0;
|
|
862
982
|
return isNormalizedRedisConfig(config) ? config : normalizeRedisConfig(config);
|
|
863
983
|
}
|
|
864
|
-
function escapeRegExp2(value) {
|
|
865
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
866
|
-
}
|
|
867
984
|
function resolveSharedRedisConnection(redisConfig, connectionName) {
|
|
868
985
|
if (!redisConfig) {
|
|
869
986
|
throw new CacheDriverResolutionError(
|
|
@@ -878,56 +995,15 @@ function resolveSharedRedisConnection(redisConfig, connectionName) {
|
|
|
878
995
|
);
|
|
879
996
|
}
|
|
880
997
|
function isModuleNotFoundError2(error, expectedSpecifier = "@holo-js/cache-redis") {
|
|
881
|
-
|
|
882
|
-
return false;
|
|
883
|
-
}
|
|
884
|
-
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
|
885
|
-
const code = "code" in error ? error.code : void 0;
|
|
886
|
-
const escapedSpecifier = escapeRegExp2(expectedSpecifier);
|
|
887
|
-
if ((code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") && [
|
|
888
|
-
new RegExp(`Cannot find package ['"]${escapedSpecifier}['"]`),
|
|
889
|
-
new RegExp(`Cannot find module ['"]${escapedSpecifier}['"]`),
|
|
890
|
-
new RegExp(`Could not resolve ['"]${escapedSpecifier}['"]`),
|
|
891
|
-
new RegExp(`Failed to load url\\s+(?:['"\`]${escapedSpecifier}['"\`]|${escapedSpecifier}(?=[\\s(]|$))`)
|
|
892
|
-
].some((pattern) => pattern.test(message))) {
|
|
893
|
-
return true;
|
|
894
|
-
}
|
|
895
|
-
if ("cause" in error) {
|
|
896
|
-
return isModuleNotFoundError2(error.cause, expectedSpecifier);
|
|
897
|
-
}
|
|
898
|
-
return false;
|
|
998
|
+
return isOptionalDriverModuleNotFoundError(error, expectedSpecifier);
|
|
899
999
|
}
|
|
900
1000
|
function normalizeRedisModuleLoadError(error, expectedSpecifier = "@holo-js/cache-redis") {
|
|
901
|
-
|
|
902
|
-
return new CacheOptionalPackageError(
|
|
903
|
-
"[@holo-js/cache] Redis cache support requires @holo-js/cache-redis to be installed.",
|
|
904
|
-
{ cause: error }
|
|
905
|
-
);
|
|
906
|
-
}
|
|
907
|
-
return error;
|
|
908
|
-
}
|
|
909
|
-
async function importRedisDriverModuleFromProject(specifier) {
|
|
910
|
-
const projectRequire = createRequire2(join3(process.cwd(), "package.json"));
|
|
911
|
-
return await import(pathToFileURL2(projectRequire.resolve(specifier)).href);
|
|
912
|
-
}
|
|
913
|
-
async function loadRedisDriverModule() {
|
|
914
|
-
const specifier = "@holo-js/cache-redis";
|
|
915
|
-
try {
|
|
916
|
-
return await import(
|
|
917
|
-
/* webpackIgnore: true */
|
|
918
|
-
specifier
|
|
919
|
-
);
|
|
920
|
-
} catch (error) {
|
|
921
|
-
if (!isModuleNotFoundError2(error, specifier)) {
|
|
922
|
-
throw normalizeRedisModuleLoadError(error, specifier);
|
|
923
|
-
}
|
|
924
|
-
try {
|
|
925
|
-
return await importRedisDriverModuleFromProject(specifier);
|
|
926
|
-
} catch (fallbackError) {
|
|
927
|
-
throw normalizeRedisModuleLoadError(fallbackError, specifier);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
1001
|
+
return normalizeOptionalDriverModuleLoadError(error, expectedSpecifier, REDIS_CACHE_MISSING_MESSAGE);
|
|
930
1002
|
}
|
|
1003
|
+
var loadRedisDriverModule = createOptionalDriverModuleLoader(
|
|
1004
|
+
REDIS_CACHE_PACKAGE,
|
|
1005
|
+
REDIS_CACHE_MISSING_MESSAGE
|
|
1006
|
+
);
|
|
931
1007
|
var redisDriverModuleLoader = loadRedisDriverModule;
|
|
932
1008
|
function setRedisDriverModuleLoader(loader) {
|
|
933
1009
|
redisDriverModuleLoader = loader;
|
|
@@ -935,97 +1011,15 @@ function setRedisDriverModuleLoader(loader) {
|
|
|
935
1011
|
function resetRedisDriverModuleLoader() {
|
|
936
1012
|
redisDriverModuleLoader = loadRedisDriverModule;
|
|
937
1013
|
}
|
|
938
|
-
var LazyRedisCacheDriver = class {
|
|
939
|
-
constructor(options) {
|
|
940
|
-
this.options = options;
|
|
941
|
-
}
|
|
942
|
-
driver = "redis";
|
|
943
|
-
driverInstance;
|
|
944
|
-
pending;
|
|
945
|
-
disposalGeneration = 0;
|
|
946
|
-
get name() {
|
|
947
|
-
return this.options.name;
|
|
948
|
-
}
|
|
949
|
-
async resolveDriver() {
|
|
950
|
-
if (this.driverInstance) return this.driverInstance;
|
|
951
|
-
const pendingGeneration = this.disposalGeneration;
|
|
952
|
-
this.pending ??= redisDriverModuleLoader().then((module) => {
|
|
953
|
-
const driver = module.createRedisCacheDriver(this.options);
|
|
954
|
-
if (this.disposalGeneration === pendingGeneration) {
|
|
955
|
-
this.driverInstance = driver;
|
|
956
|
-
}
|
|
957
|
-
return driver;
|
|
958
|
-
}).finally(() => {
|
|
959
|
-
this.pending = void 0;
|
|
960
|
-
});
|
|
961
|
-
return this.pending;
|
|
962
|
-
}
|
|
963
|
-
async withDriver(callback) {
|
|
964
|
-
return callback(await this.resolveDriver());
|
|
965
|
-
}
|
|
966
|
-
[CACHE_DRIVER_DISPOSE_SYMBOL]() {
|
|
967
|
-
const pending = this.pending;
|
|
968
|
-
const driverInstance = this.driverInstance;
|
|
969
|
-
this.disposalGeneration += 1;
|
|
970
|
-
this.driverInstance = void 0;
|
|
971
|
-
this.pending = void 0;
|
|
972
|
-
if (driverInstance) {
|
|
973
|
-
const disposable = driverInstance;
|
|
974
|
-
disposable[CACHE_DRIVER_DISPOSE_SYMBOL]?.();
|
|
975
|
-
return;
|
|
976
|
-
}
|
|
977
|
-
pending?.then((driver) => {
|
|
978
|
-
const disposable = driver;
|
|
979
|
-
disposable[CACHE_DRIVER_DISPOSE_SYMBOL]?.();
|
|
980
|
-
}).catch(() => {
|
|
981
|
-
});
|
|
982
|
-
}
|
|
983
|
-
createLockProxy(name, seconds) {
|
|
984
|
-
let lockPromise;
|
|
985
|
-
const resolveLock = async () => {
|
|
986
|
-
lockPromise ??= this.withDriver((driver) => driver.lock(name, seconds));
|
|
987
|
-
return lockPromise;
|
|
988
|
-
};
|
|
989
|
-
return {
|
|
990
|
-
name,
|
|
991
|
-
async get(callback) {
|
|
992
|
-
return (await resolveLock()).get(callback);
|
|
993
|
-
},
|
|
994
|
-
async release() {
|
|
995
|
-
return (await resolveLock()).release();
|
|
996
|
-
},
|
|
997
|
-
async block(waitSeconds, callback) {
|
|
998
|
-
return (await resolveLock()).block(waitSeconds, callback);
|
|
999
|
-
}
|
|
1000
|
-
};
|
|
1001
|
-
}
|
|
1002
|
-
async get(key) {
|
|
1003
|
-
return this.withDriver((driver) => driver.get(key));
|
|
1004
|
-
}
|
|
1005
|
-
async put(input) {
|
|
1006
|
-
return this.withDriver((driver) => driver.put(input));
|
|
1007
|
-
}
|
|
1008
|
-
async add(input) {
|
|
1009
|
-
return this.withDriver((driver) => driver.add(input));
|
|
1010
|
-
}
|
|
1011
|
-
async forget(key) {
|
|
1012
|
-
return this.withDriver((driver) => driver.forget(key));
|
|
1013
|
-
}
|
|
1014
|
-
async flush() {
|
|
1015
|
-
await this.withDriver((driver) => driver.flush());
|
|
1016
|
-
}
|
|
1017
|
-
async increment(key, amount) {
|
|
1018
|
-
return this.withDriver((driver) => driver.increment(key, amount));
|
|
1019
|
-
}
|
|
1020
|
-
async decrement(key, amount) {
|
|
1021
|
-
return this.withDriver((driver) => driver.decrement(key, amount));
|
|
1022
|
-
}
|
|
1023
|
-
lock(name, seconds) {
|
|
1024
|
-
return this.createLockProxy(name, seconds);
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
1014
|
function createRedisCacheDriver(options) {
|
|
1028
|
-
return
|
|
1015
|
+
return createLazyOptionalCacheDriver({
|
|
1016
|
+
name: options.name,
|
|
1017
|
+
driver: "redis",
|
|
1018
|
+
options,
|
|
1019
|
+
loadModule: redisDriverModuleLoader,
|
|
1020
|
+
createDriver: (module, driverOptions) => module.createRedisCacheDriver(driverOptions),
|
|
1021
|
+
disposeDriver: true
|
|
1022
|
+
});
|
|
1029
1023
|
}
|
|
1030
1024
|
var cacheRedisInternals = {
|
|
1031
1025
|
isModuleNotFoundError: isModuleNotFoundError2,
|
|
@@ -1226,27 +1220,6 @@ function resolveNormalizedKey(key, driverName) {
|
|
|
1226
1220
|
const context = resolveDriverContext(driverName);
|
|
1227
1221
|
return `${context.normalizedKeyPrefix}${resolveCacheKey(key)}`;
|
|
1228
1222
|
}
|
|
1229
|
-
function normalizeFlexibleTtl(ttl) {
|
|
1230
|
-
const freshSeconds = "fresh" in ttl ? ttl.fresh : ttl[0];
|
|
1231
|
-
const staleSeconds = "stale" in ttl ? ttl.stale : ttl[1];
|
|
1232
|
-
if (!Number.isInteger(freshSeconds) || freshSeconds < 0) {
|
|
1233
|
-
throw new CacheInvalidTtlError("[@holo-js/cache] Flexible fresh TTL must be an integer greater than or equal to 0.");
|
|
1234
|
-
}
|
|
1235
|
-
if (!Number.isInteger(staleSeconds) || staleSeconds < freshSeconds) {
|
|
1236
|
-
throw new CacheInvalidTtlError("[@holo-js/cache] Flexible stale TTL must be an integer greater than or equal to the fresh TTL.");
|
|
1237
|
-
}
|
|
1238
|
-
return Object.freeze({
|
|
1239
|
-
freshSeconds,
|
|
1240
|
-
staleSeconds
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
function isFlexibleEnvelope(value) {
|
|
1244
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1245
|
-
return false;
|
|
1246
|
-
}
|
|
1247
|
-
const envelope = value;
|
|
1248
|
-
return envelope.__holo_cache_flexible === true && typeof envelope.freshUntil === "number" && Number.isFinite(envelope.freshUntil) && typeof envelope.staleUntil === "number" && Number.isFinite(envelope.staleUntil) && "value" in envelope;
|
|
1249
|
-
}
|
|
1250
1223
|
async function getCachedValue(key, driverName) {
|
|
1251
1224
|
const context = resolveDriverContext(driverName);
|
|
1252
1225
|
const entry = await context.driver.get(resolveNormalizedKey(key, driverName));
|
|
@@ -1313,18 +1286,9 @@ function createCacheQueryBridge(dependencyIndex = getOrCreateDependencyIndex())
|
|
|
1313
1286
|
},
|
|
1314
1287
|
async flexible(key, ttl, callback, options = {}) {
|
|
1315
1288
|
const indexedKey = createIndexedKey(key, options.driver);
|
|
1316
|
-
const
|
|
1317
|
-
const now = Date.now();
|
|
1318
|
-
const cached = await getCachedValue(key, options.driver);
|
|
1319
|
-
const refreshValue = async () => {
|
|
1289
|
+
const refreshValue = async (normalizedTtl) => {
|
|
1320
1290
|
const value = await callback();
|
|
1321
|
-
const
|
|
1322
|
-
const envelope = {
|
|
1323
|
-
__holo_cache_flexible: true,
|
|
1324
|
-
value,
|
|
1325
|
-
freshUntil: refreshedAt + normalizedTtl.freshSeconds * 1e3,
|
|
1326
|
-
staleUntil: refreshedAt + normalizedTtl.staleSeconds * 1e3
|
|
1327
|
-
};
|
|
1291
|
+
const envelope = createFlexibleEnvelope(normalizedTtl, value);
|
|
1328
1292
|
await putCachedValue(
|
|
1329
1293
|
key,
|
|
1330
1294
|
envelope,
|
|
@@ -1334,31 +1298,12 @@ function createCacheQueryBridge(dependencyIndex = getOrCreateDependencyIndex())
|
|
|
1334
1298
|
await syncDependencies(indexedKey, options.dependencies);
|
|
1335
1299
|
return value;
|
|
1336
1300
|
};
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
void refreshLock2.get(async () => {
|
|
1344
|
-
await refreshValue();
|
|
1345
|
-
return true;
|
|
1346
|
-
}).catch(() => void 0);
|
|
1347
|
-
return cached.value;
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
const refreshLock = createFlexibleLock(key, normalizedTtl, options.driver);
|
|
1351
|
-
const refreshed = await refreshLock.block(1, async () => refreshValue());
|
|
1352
|
-
if (refreshed !== false) {
|
|
1353
|
-
return refreshed;
|
|
1354
|
-
}
|
|
1355
|
-
const retried = await getCachedValue(key, options.driver);
|
|
1356
|
-
if (isFlexibleEnvelope(retried)) {
|
|
1357
|
-
if (Date.now() <= retried.staleUntil) {
|
|
1358
|
-
return retried.value;
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
return refreshValue();
|
|
1301
|
+
return resolveFlexibleCachedValue({
|
|
1302
|
+
ttl,
|
|
1303
|
+
read: async () => getCachedValue(key, options.driver),
|
|
1304
|
+
refresh: (normalizedTtl) => refreshValue(normalizedTtl),
|
|
1305
|
+
createLock: (normalizedTtl) => createFlexibleLock(key, normalizedTtl, options.driver)
|
|
1306
|
+
});
|
|
1362
1307
|
},
|
|
1363
1308
|
async forget(key, options) {
|
|
1364
1309
|
const indexedKey = createIndexedKey(key, options?.driver);
|
|
@@ -1445,27 +1390,6 @@ function resolveDriverKey(driverName) {
|
|
|
1445
1390
|
const normalized = driverName?.trim();
|
|
1446
1391
|
return normalized || "__default__";
|
|
1447
1392
|
}
|
|
1448
|
-
function normalizeFlexibleTtl2(ttl) {
|
|
1449
|
-
const freshSeconds = "fresh" in ttl ? ttl.fresh : ttl[0];
|
|
1450
|
-
const staleSeconds = "stale" in ttl ? ttl.stale : ttl[1];
|
|
1451
|
-
if (!Number.isInteger(freshSeconds) || freshSeconds < 0) {
|
|
1452
|
-
throw new CacheInvalidTtlError("[@holo-js/cache] Flexible fresh TTL must be an integer greater than or equal to 0.");
|
|
1453
|
-
}
|
|
1454
|
-
if (!Number.isInteger(staleSeconds) || staleSeconds < freshSeconds) {
|
|
1455
|
-
throw new CacheInvalidTtlError("[@holo-js/cache] Flexible stale TTL must be an integer greater than or equal to the fresh TTL.");
|
|
1456
|
-
}
|
|
1457
|
-
return Object.freeze({
|
|
1458
|
-
freshSeconds,
|
|
1459
|
-
staleSeconds
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
function isFlexibleEnvelope2(value) {
|
|
1463
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1464
|
-
return false;
|
|
1465
|
-
}
|
|
1466
|
-
const envelope = value;
|
|
1467
|
-
return envelope.__holo_cache_flexible === true && typeof envelope.freshUntil === "number" && Number.isFinite(envelope.freshUntil) && typeof envelope.staleUntil === "number" && Number.isFinite(envelope.staleUntil) && "value" in envelope;
|
|
1468
|
-
}
|
|
1469
1393
|
function createCacheRepository(driverName) {
|
|
1470
1394
|
function resolveDriverContext2() {
|
|
1471
1395
|
const runtime = getCacheRuntime();
|
|
@@ -1511,13 +1435,7 @@ function createCacheRepository(driverName) {
|
|
|
1511
1435
|
});
|
|
1512
1436
|
}
|
|
1513
1437
|
async function putFlexibleEnvelope(key, ttl, value) {
|
|
1514
|
-
const
|
|
1515
|
-
const envelope = {
|
|
1516
|
-
__holo_cache_flexible: true,
|
|
1517
|
-
value,
|
|
1518
|
-
freshUntil: now + ttl.freshSeconds * 1e3,
|
|
1519
|
-
staleUntil: now + ttl.staleSeconds * 1e3
|
|
1520
|
-
};
|
|
1438
|
+
const envelope = createFlexibleEnvelope(ttl, value);
|
|
1521
1439
|
await putSerializedValue(key, serializeCacheValue(envelope), ttl.staleSeconds);
|
|
1522
1440
|
return value;
|
|
1523
1441
|
}
|
|
@@ -1617,40 +1535,19 @@ function createCacheRepository(driverName) {
|
|
|
1617
1535
|
return value;
|
|
1618
1536
|
},
|
|
1619
1537
|
async flexible(key, ttl, callback) {
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
void refreshLock2.get(async () => {
|
|
1630
|
-
await refreshFlexibleValue(key, normalizedTtl, callback);
|
|
1631
|
-
return true;
|
|
1632
|
-
}).catch(() => void 0);
|
|
1633
|
-
return cached.value.value;
|
|
1634
|
-
}
|
|
1635
|
-
}
|
|
1636
|
-
const refreshLock = createRefreshLock(key, normalizedTtl.staleSeconds);
|
|
1637
|
-
const refreshed = await refreshLock.block(
|
|
1638
|
-
Math.min(
|
|
1538
|
+
return resolveFlexibleCachedValue({
|
|
1539
|
+
ttl,
|
|
1540
|
+
read: async () => {
|
|
1541
|
+
const cached = await getCachedValue2(key);
|
|
1542
|
+
return cached.hit ? cached.value : void 0;
|
|
1543
|
+
},
|
|
1544
|
+
refresh: (normalizedTtl) => refreshFlexibleValue(key, normalizedTtl, callback),
|
|
1545
|
+
createLock: (normalizedTtl) => createRefreshLock(key, normalizedTtl.staleSeconds),
|
|
1546
|
+
blockSeconds: (normalizedTtl) => Math.min(
|
|
1639
1547
|
MAX_REFRESH_BLOCK_SECONDS,
|
|
1640
1548
|
Math.max(1, Math.ceil(normalizedTtl.staleSeconds / 300))
|
|
1641
|
-
)
|
|
1642
|
-
|
|
1643
|
-
);
|
|
1644
|
-
if (refreshed !== false) {
|
|
1645
|
-
return refreshed;
|
|
1646
|
-
}
|
|
1647
|
-
const retried = await getCachedValue2(key);
|
|
1648
|
-
if (retried.hit && isFlexibleEnvelope2(retried.value)) {
|
|
1649
|
-
if (Date.now() <= retried.value.staleUntil) {
|
|
1650
|
-
return retried.value.value;
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
return refreshFlexibleValue(key, normalizedTtl, callback);
|
|
1549
|
+
)
|
|
1550
|
+
});
|
|
1654
1551
|
},
|
|
1655
1552
|
lock(name, seconds) {
|
|
1656
1553
|
const { driver } = resolveDriverContext2();
|
|
@@ -1685,8 +1582,8 @@ var cacheFacadeInternals = {
|
|
|
1685
1582
|
return `__flexible__:${resolveCacheKey(key)}`;
|
|
1686
1583
|
},
|
|
1687
1584
|
getOrCreateRepository,
|
|
1688
|
-
isFlexibleEnvelope
|
|
1689
|
-
normalizeFlexibleTtl
|
|
1585
|
+
isFlexibleEnvelope,
|
|
1586
|
+
normalizeFlexibleTtl,
|
|
1690
1587
|
resolveDriverKey,
|
|
1691
1588
|
resolveFallback,
|
|
1692
1589
|
resolveValue
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holo-js/cache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Holo-JS Framework - cache contracts, config helpers, serialization, and runtime seams",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"test": "vitest --run"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@holo-js/config": "^0.
|
|
31
|
+
"@holo-js/config": "^0.2.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^22.10.2",
|