@hypequery/clickhouse 0.0.0-canary-20260306132943
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/LICENSE +201 -0
- package/README-CLI.md +123 -0
- package/README.md +316 -0
- package/dist/cli/bin.js +285 -0
- package/dist/cli/generate-types.d.ts +5 -0
- package/dist/cli/generate-types.js +218 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +2 -0
- package/dist/core/cache/cache-manager.d.ts +4 -0
- package/dist/core/cache/cache-manager.d.ts.map +1 -0
- package/dist/core/cache/cache-manager.js +176 -0
- package/dist/core/cache/controller.d.ts +15 -0
- package/dist/core/cache/controller.d.ts.map +1 -0
- package/dist/core/cache/controller.js +58 -0
- package/dist/core/cache/key.d.ts +11 -0
- package/dist/core/cache/key.d.ts.map +1 -0
- package/dist/core/cache/key.js +26 -0
- package/dist/core/cache/providers/memory-lru.d.ts +31 -0
- package/dist/core/cache/providers/memory-lru.d.ts.map +1 -0
- package/dist/core/cache/providers/memory-lru.js +156 -0
- package/dist/core/cache/providers/noop.d.ts +7 -0
- package/dist/core/cache/providers/noop.d.ts.map +1 -0
- package/dist/core/cache/providers/noop.js +11 -0
- package/dist/core/cache/runtime-context.d.ts +30 -0
- package/dist/core/cache/runtime-context.d.ts.map +1 -0
- package/dist/core/cache/runtime-context.js +58 -0
- package/dist/core/cache/serialization.d.ts +6 -0
- package/dist/core/cache/serialization.d.ts.map +1 -0
- package/dist/core/cache/serialization.js +166 -0
- package/dist/core/cache/types.d.ts +52 -0
- package/dist/core/cache/types.d.ts.map +1 -0
- package/dist/core/cache/types.js +1 -0
- package/dist/core/cache/utils.d.ts +9 -0
- package/dist/core/cache/utils.d.ts.map +1 -0
- package/dist/core/cache/utils.js +30 -0
- package/dist/core/connection.d.ts +112 -0
- package/dist/core/connection.d.ts.map +1 -0
- package/dist/core/connection.js +150 -0
- package/dist/core/cross-filter.d.ts +73 -0
- package/dist/core/cross-filter.d.ts.map +1 -0
- package/dist/core/cross-filter.js +142 -0
- package/dist/core/env/auto-client.browser.d.ts +3 -0
- package/dist/core/env/auto-client.browser.d.ts.map +1 -0
- package/dist/core/env/auto-client.browser.js +3 -0
- package/dist/core/env/auto-client.d.ts +9 -0
- package/dist/core/env/auto-client.d.ts.map +1 -0
- package/dist/core/env/auto-client.js +21 -0
- package/dist/core/features/aggregations.d.ts +98 -0
- package/dist/core/features/aggregations.d.ts.map +1 -0
- package/dist/core/features/aggregations.js +36 -0
- package/dist/core/features/analytics.d.ts +81 -0
- package/dist/core/features/analytics.d.ts.map +1 -0
- package/dist/core/features/analytics.js +45 -0
- package/dist/core/features/cross-filtering.d.ts +11 -0
- package/dist/core/features/cross-filtering.d.ts.map +1 -0
- package/dist/core/features/cross-filtering.js +90 -0
- package/dist/core/features/executor.d.ts +21 -0
- package/dist/core/features/executor.d.ts.map +1 -0
- package/dist/core/features/executor.js +146 -0
- package/dist/core/features/filtering.d.ts +99 -0
- package/dist/core/features/filtering.d.ts.map +1 -0
- package/dist/core/features/filtering.js +118 -0
- package/dist/core/features/joins.d.ts +26 -0
- package/dist/core/features/joins.d.ts.map +1 -0
- package/dist/core/features/joins.js +17 -0
- package/dist/core/features/query-modifiers.d.ts +116 -0
- package/dist/core/features/query-modifiers.d.ts.map +1 -0
- package/dist/core/features/query-modifiers.js +51 -0
- package/dist/core/formatters/sql-formatter.d.ts +9 -0
- package/dist/core/formatters/sql-formatter.d.ts.map +1 -0
- package/dist/core/formatters/sql-formatter.js +131 -0
- package/dist/core/join-relationships.d.ts +51 -0
- package/dist/core/join-relationships.d.ts.map +1 -0
- package/dist/core/join-relationships.js +54 -0
- package/dist/core/query-builder.d.ts +236 -0
- package/dist/core/query-builder.d.ts.map +1 -0
- package/dist/core/query-builder.js +495 -0
- package/dist/core/tests/index.d.ts +2 -0
- package/dist/core/tests/index.d.ts.map +1 -0
- package/dist/core/tests/index.js +1 -0
- package/dist/core/tests/integration/setup.d.ts +48 -0
- package/dist/core/tests/integration/setup.d.ts.map +1 -0
- package/dist/core/tests/integration/setup.js +349 -0
- package/dist/core/tests/integration/test-config.d.ts +15 -0
- package/dist/core/tests/integration/test-config.d.ts.map +1 -0
- package/dist/core/tests/integration/test-config.js +14 -0
- package/dist/core/tests/integration/test-data.json +190 -0
- package/dist/core/tests/test-utils.d.ts +44 -0
- package/dist/core/tests/test-utils.d.ts.map +1 -0
- package/dist/core/tests/test-utils.js +65 -0
- package/dist/core/types/builder-state.d.ts +27 -0
- package/dist/core/types/builder-state.d.ts.map +1 -0
- package/dist/core/types/builder-state.js +1 -0
- package/dist/core/types/select-types.d.ts +33 -0
- package/dist/core/types/select-types.d.ts.map +1 -0
- package/dist/core/types/select-types.js +1 -0
- package/dist/core/types/type-helpers.d.ts +5 -0
- package/dist/core/types/type-helpers.d.ts.map +1 -0
- package/dist/core/types/type-helpers.js +1 -0
- package/dist/core/utils/logger.d.ts +43 -0
- package/dist/core/utils/logger.d.ts.map +1 -0
- package/dist/core/utils/logger.js +104 -0
- package/dist/core/utils/predicate-builder.d.ts +33 -0
- package/dist/core/utils/predicate-builder.d.ts.map +1 -0
- package/dist/core/utils/predicate-builder.js +95 -0
- package/dist/core/utils/sql-expressions.d.ts +77 -0
- package/dist/core/utils/sql-expressions.d.ts.map +1 -0
- package/dist/core/utils/sql-expressions.js +54 -0
- package/dist/core/utils/streaming-helpers.d.ts +2 -0
- package/dist/core/utils/streaming-helpers.d.ts.map +1 -0
- package/dist/core/utils/streaming-helpers.js +137 -0
- package/dist/core/utils.d.ts +3 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +29 -0
- package/dist/core/validators/filter-validator.d.ts +9 -0
- package/dist/core/validators/filter-validator.d.ts.map +1 -0
- package/dist/core/validators/filter-validator.js +19 -0
- package/dist/core/validators/value-validator.d.ts +7 -0
- package/dist/core/validators/value-validator.d.ts.map +1 -0
- package/dist/core/validators/value-validator.js +47 -0
- package/dist/formatters/index.d.ts +2 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/types/base.d.ts +50 -0
- package/dist/types/base.d.ts.map +1 -0
- package/dist/types/base.js +1 -0
- package/dist/types/clickhouse-types.d.ts +17 -0
- package/dist/types/clickhouse-types.d.ts.map +1 -0
- package/dist/types/clickhouse-types.js +1 -0
- package/dist/types/filters.d.ts +53 -0
- package/dist/types/filters.d.ts.map +1 -0
- package/dist/types/filters.js +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/schema.d.ts +19 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { computeCacheKey } from './key.js';
|
|
2
|
+
import { mergeCacheOptions } from './runtime-context.js';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
import { substituteParameters } from '../utils.js';
|
|
5
|
+
function isCacheable(options) {
|
|
6
|
+
const ttl = options.ttlMs ?? 0;
|
|
7
|
+
const stale = options.staleTtlMs ?? 0;
|
|
8
|
+
return ttl > 0 || stale > 0;
|
|
9
|
+
}
|
|
10
|
+
function deriveTags(builder) {
|
|
11
|
+
const tags = new Set();
|
|
12
|
+
tags.add(builder.getTableName());
|
|
13
|
+
const joins = builder.getConfig().joins || [];
|
|
14
|
+
joins.forEach(join => tags.add(join.table));
|
|
15
|
+
return Array.from(tags);
|
|
16
|
+
}
|
|
17
|
+
async function logCacheHit({ sql, parameters, status, cacheKey, options, rowCount, ageMs, queryId }) {
|
|
18
|
+
const finalSQL = substituteParameters(sql, parameters);
|
|
19
|
+
const timestamp = Date.now();
|
|
20
|
+
logger.logQuery({
|
|
21
|
+
query: finalSQL,
|
|
22
|
+
parameters,
|
|
23
|
+
startTime: timestamp,
|
|
24
|
+
endTime: timestamp,
|
|
25
|
+
duration: 0,
|
|
26
|
+
status: 'completed',
|
|
27
|
+
rowCount,
|
|
28
|
+
queryId,
|
|
29
|
+
cacheStatus: status,
|
|
30
|
+
cacheKey,
|
|
31
|
+
cacheMode: options.mode,
|
|
32
|
+
cacheAgeMs: ageMs,
|
|
33
|
+
cacheRowCount: rowCount
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export async function executeWithCache(builder, options) {
|
|
37
|
+
const runtime = builder.getRuntimeContext();
|
|
38
|
+
const provider = runtime.provider;
|
|
39
|
+
const normalizedExecuteCache = options?.cache === false
|
|
40
|
+
? { mode: 'no-store' }
|
|
41
|
+
: options?.cache;
|
|
42
|
+
const mergedOptions = mergeCacheOptions(runtime.defaults, builder.getCacheOptions(), normalizedExecuteCache);
|
|
43
|
+
const mode = mergedOptions.mode ?? 'no-store';
|
|
44
|
+
if (!provider || mode === 'no-store' || !isCacheable(mergedOptions)) {
|
|
45
|
+
return runWithoutCache('bypass');
|
|
46
|
+
}
|
|
47
|
+
const activeProvider = provider;
|
|
48
|
+
const { sql, parameters } = builder.toSQLWithParams();
|
|
49
|
+
const tableName = builder.getTableName();
|
|
50
|
+
const namespace = mergedOptions.namespace || runtime.namespace;
|
|
51
|
+
const key = mergedOptions.key || computeCacheKey({
|
|
52
|
+
namespace,
|
|
53
|
+
sql,
|
|
54
|
+
parameters,
|
|
55
|
+
settings: builder.getConfig().settings ? { settings: builder.getConfig().settings } : undefined,
|
|
56
|
+
version: runtime.versionTag,
|
|
57
|
+
tableName
|
|
58
|
+
});
|
|
59
|
+
const entry = await activeProvider.get(key);
|
|
60
|
+
if (!entry) {
|
|
61
|
+
runtime.parsedValues.delete(key);
|
|
62
|
+
}
|
|
63
|
+
const fresh = entry ? Date.now() < entry.createdAt + entry.ttlMs : false;
|
|
64
|
+
const staleAcceptable = entry ? Date.now() < entry.createdAt + entry.ttlMs + entry.staleTtlMs : false;
|
|
65
|
+
const deserialize = mergedOptions.deserialize || runtime.deserialize;
|
|
66
|
+
const serialize = mergedOptions.serialize || runtime.serialize;
|
|
67
|
+
const respondFromCache = async (cacheEntry, status) => {
|
|
68
|
+
const memoized = runtime.parsedValues.get(key);
|
|
69
|
+
let rows;
|
|
70
|
+
if (memoized && memoized.createdAt === cacheEntry.createdAt) {
|
|
71
|
+
rows = memoized.rows;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
rows = await deserialize(cacheEntry.value);
|
|
75
|
+
runtime.parsedValues.set(key, { createdAt: cacheEntry.createdAt, rows, tags: cacheEntry.tags });
|
|
76
|
+
}
|
|
77
|
+
const cacheAge = Date.now() - cacheEntry.createdAt;
|
|
78
|
+
if (status === 'hit') {
|
|
79
|
+
runtime.stats.hits += 1;
|
|
80
|
+
}
|
|
81
|
+
else if (status === 'stale-hit') {
|
|
82
|
+
runtime.stats.staleHits += 1;
|
|
83
|
+
}
|
|
84
|
+
await logCacheHit({
|
|
85
|
+
sql,
|
|
86
|
+
parameters,
|
|
87
|
+
status,
|
|
88
|
+
cacheKey: key,
|
|
89
|
+
options: mergedOptions,
|
|
90
|
+
rowCount: cacheEntry.rowCount ?? rows.length,
|
|
91
|
+
ageMs: cacheAge,
|
|
92
|
+
queryId: options?.queryId
|
|
93
|
+
});
|
|
94
|
+
return rows;
|
|
95
|
+
};
|
|
96
|
+
if (mode === 'cache-first') {
|
|
97
|
+
if (entry && fresh) {
|
|
98
|
+
return respondFromCache(entry, 'hit');
|
|
99
|
+
}
|
|
100
|
+
runtime.stats.misses += 1;
|
|
101
|
+
return fetchAndStore('miss');
|
|
102
|
+
}
|
|
103
|
+
if (mode === 'stale-while-revalidate') {
|
|
104
|
+
if (entry && fresh) {
|
|
105
|
+
return respondFromCache(entry, 'hit');
|
|
106
|
+
}
|
|
107
|
+
if (entry && staleAcceptable) {
|
|
108
|
+
scheduleRevalidation();
|
|
109
|
+
return respondFromCache(entry, 'stale-hit');
|
|
110
|
+
}
|
|
111
|
+
runtime.stats.misses += 1;
|
|
112
|
+
return fetchAndStore('miss');
|
|
113
|
+
}
|
|
114
|
+
if (mode === 'network-first') {
|
|
115
|
+
try {
|
|
116
|
+
runtime.stats.misses += 1;
|
|
117
|
+
return await fetchAndStore('miss');
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (mergedOptions.staleIfError && entry && staleAcceptable) {
|
|
121
|
+
return respondFromCache(entry, 'stale-hit');
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return runWithoutCache('bypass');
|
|
127
|
+
async function fetchAndStore(cacheStatus) {
|
|
128
|
+
if (mergedOptions.dedupe !== false && runtime.inFlight.has(key)) {
|
|
129
|
+
return runtime.inFlight.get(key);
|
|
130
|
+
}
|
|
131
|
+
const promise = (async () => {
|
|
132
|
+
const rows = await builder.getExecutor().execute({
|
|
133
|
+
queryId: options?.queryId,
|
|
134
|
+
logContext: { cacheStatus, cacheKey: key, cacheMode: mode }
|
|
135
|
+
});
|
|
136
|
+
const encoded = await serialize(rows);
|
|
137
|
+
const ttlMs = mergedOptions.ttlMs ?? 0;
|
|
138
|
+
const staleTtlMs = mergedOptions.staleTtlMs ?? 0;
|
|
139
|
+
const cacheTimeMs = mergedOptions.cacheTimeMs ?? ttlMs + staleTtlMs;
|
|
140
|
+
const derivedTags = deriveTags(builder);
|
|
141
|
+
const tagSet = new Set([...(mergedOptions.tags || []), ...derivedTags]);
|
|
142
|
+
const newEntry = {
|
|
143
|
+
value: encoded.payload,
|
|
144
|
+
createdAt: Date.now(),
|
|
145
|
+
ttlMs,
|
|
146
|
+
staleTtlMs,
|
|
147
|
+
cacheTimeMs,
|
|
148
|
+
tags: Array.from(tagSet),
|
|
149
|
+
rowCount: rows.length,
|
|
150
|
+
byteSize: encoded.byteSize,
|
|
151
|
+
sqlFingerprint: key
|
|
152
|
+
};
|
|
153
|
+
await activeProvider.set(key, newEntry);
|
|
154
|
+
runtime.parsedValues.set(key, { createdAt: newEntry.createdAt, rows, tags: newEntry.tags });
|
|
155
|
+
return rows;
|
|
156
|
+
})();
|
|
157
|
+
if (mergedOptions.dedupe !== false) {
|
|
158
|
+
runtime.inFlight.set(key, promise);
|
|
159
|
+
promise.finally(() => runtime.inFlight.delete(key));
|
|
160
|
+
}
|
|
161
|
+
return promise;
|
|
162
|
+
}
|
|
163
|
+
function scheduleRevalidation() {
|
|
164
|
+
runtime.stats.revalidations += 1;
|
|
165
|
+
fetchAndStore('revalidate').catch(() => undefined);
|
|
166
|
+
}
|
|
167
|
+
function runWithoutCache(cacheStatus) {
|
|
168
|
+
if (provider) {
|
|
169
|
+
runtime.stats.misses += 1;
|
|
170
|
+
}
|
|
171
|
+
return builder.getExecutor().execute({
|
|
172
|
+
queryId: options?.queryId,
|
|
173
|
+
logContext: { cacheStatus, cacheMode: mode }
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { QueryRuntimeContext } from './runtime-context.js';
|
|
2
|
+
import type { CacheStats } from './types.js';
|
|
3
|
+
export declare class CacheController {
|
|
4
|
+
private context;
|
|
5
|
+
constructor(context: QueryRuntimeContext);
|
|
6
|
+
invalidateKey(key: string): Promise<void>;
|
|
7
|
+
invalidateTags(tags: string[]): Promise<void>;
|
|
8
|
+
clear(): Promise<void>;
|
|
9
|
+
warm(queries: Array<() => Promise<unknown>>): Promise<void>;
|
|
10
|
+
getStats(): CacheStats & {
|
|
11
|
+
hitRate: number;
|
|
12
|
+
};
|
|
13
|
+
private removeParsedValuesByTags;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/core/cache/controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,qBAAa,eAAe;IACd,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,mBAAmB;IAE1C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAe7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjE,QAAQ,IAAI,UAAU,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;IAO5C,OAAO,CAAC,wBAAwB;CAWjC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js';
|
|
2
|
+
export class CacheController {
|
|
3
|
+
context;
|
|
4
|
+
constructor(context) {
|
|
5
|
+
this.context = context;
|
|
6
|
+
}
|
|
7
|
+
async invalidateKey(key) {
|
|
8
|
+
this.context.parsedValues.delete(key);
|
|
9
|
+
if (!this.context.provider)
|
|
10
|
+
return;
|
|
11
|
+
await this.context.provider.delete(key);
|
|
12
|
+
}
|
|
13
|
+
async invalidateTags(tags) {
|
|
14
|
+
if (!tags.length)
|
|
15
|
+
return;
|
|
16
|
+
const deleteByTag = this.context.provider?.deleteByTag;
|
|
17
|
+
if (!deleteByTag) {
|
|
18
|
+
logger.warn('Cache provider does not support tag invalidation. Tags ignored.', {
|
|
19
|
+
namespace: this.context.namespace,
|
|
20
|
+
tags
|
|
21
|
+
});
|
|
22
|
+
this.removeParsedValuesByTags(tags);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
await Promise.all(tags.map(tag => deleteByTag.call(this.context.provider, this.context.namespace, tag)));
|
|
26
|
+
this.removeParsedValuesByTags(tags);
|
|
27
|
+
}
|
|
28
|
+
async clear() {
|
|
29
|
+
if (this.context.provider?.clearNamespace) {
|
|
30
|
+
await this.context.provider.clearNamespace(this.context.namespace);
|
|
31
|
+
}
|
|
32
|
+
this.context.parsedValues.clear();
|
|
33
|
+
}
|
|
34
|
+
async warm(queries) {
|
|
35
|
+
if (!queries.length)
|
|
36
|
+
return;
|
|
37
|
+
await Promise.all(queries.map(query => query()));
|
|
38
|
+
}
|
|
39
|
+
getStats() {
|
|
40
|
+
const stats = { ...this.context.stats };
|
|
41
|
+
const total = stats.hits + stats.misses + stats.staleHits;
|
|
42
|
+
const hitRate = total > 0 ? (stats.hits + stats.staleHits) / total : 0;
|
|
43
|
+
return { ...stats, hitRate };
|
|
44
|
+
}
|
|
45
|
+
removeParsedValuesByTags(tags) {
|
|
46
|
+
if (!tags.length)
|
|
47
|
+
return;
|
|
48
|
+
const target = new Set(tags);
|
|
49
|
+
for (const [key, record] of this.context.parsedValues) {
|
|
50
|
+
if (!record.tags?.length)
|
|
51
|
+
continue;
|
|
52
|
+
const intersects = record.tags.some(tag => target.has(tag));
|
|
53
|
+
if (intersects) {
|
|
54
|
+
this.context.parsedValues.delete(key);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface CacheKeyInput {
|
|
2
|
+
namespace: string;
|
|
3
|
+
sql: string;
|
|
4
|
+
parameters: unknown[];
|
|
5
|
+
settings?: Record<string, unknown> | undefined;
|
|
6
|
+
version?: string;
|
|
7
|
+
tableName?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function computeCacheKey({ namespace, sql, parameters, settings, version, tableName }: CacheKeyInput): string;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../../src/core/cache/key.ts"],"names":[],"mappings":"AAEA,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqBD,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,GAAG,EACH,UAAU,EACV,QAAQ,EACR,OAAc,EACd,SAAS,EACV,EAAE,aAAa,GAAG,MAAM,CAOxB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { stableStringify } from './serialization.js';
|
|
2
|
+
const FNV_OFFSET = BigInt('0xcbf29ce484222325');
|
|
3
|
+
const FNV_PRIME = BigInt('0x100000001b3');
|
|
4
|
+
const FNV_MOD = BigInt('0x10000000000000000');
|
|
5
|
+
function fnv1a64(value) {
|
|
6
|
+
let hash = FNV_OFFSET;
|
|
7
|
+
for (let i = 0; i < value.length; i++) {
|
|
8
|
+
hash ^= BigInt(value.charCodeAt(i));
|
|
9
|
+
hash = (hash * FNV_PRIME) % FNV_MOD;
|
|
10
|
+
}
|
|
11
|
+
return hash.toString(16);
|
|
12
|
+
}
|
|
13
|
+
function formatSegment(segment) {
|
|
14
|
+
if (!segment)
|
|
15
|
+
return 'query';
|
|
16
|
+
const sanitized = segment.replace(/[^a-zA-Z0-9_-]/g, '-');
|
|
17
|
+
return sanitized.slice(0, 48) || 'query';
|
|
18
|
+
}
|
|
19
|
+
export function computeCacheKey({ namespace, sql, parameters, settings, version = 'v1', tableName }) {
|
|
20
|
+
const serializedParams = stableStringify(parameters);
|
|
21
|
+
const serializedSettings = stableStringify(settings || null);
|
|
22
|
+
const material = `${sql}\n${serializedParams}\n${serializedSettings}`;
|
|
23
|
+
const digest = fnv1a64(material);
|
|
24
|
+
const tableSegment = formatSegment(tableName);
|
|
25
|
+
return `hq:${version}:${namespace}:${tableSegment}:${digest}`;
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CacheEntry, CacheProvider } from '../types.js';
|
|
2
|
+
export interface MemoryLRUCacheOptions {
|
|
3
|
+
maxEntries?: number;
|
|
4
|
+
maxBytes?: number;
|
|
5
|
+
cleanupIntervalMs?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class MemoryCacheProvider implements CacheProvider {
|
|
8
|
+
private entries;
|
|
9
|
+
private tagIndex;
|
|
10
|
+
private currentBytes;
|
|
11
|
+
private maxEntries;
|
|
12
|
+
private maxBytes;
|
|
13
|
+
private cleanupIntervalMs;
|
|
14
|
+
private cleanupTimer?;
|
|
15
|
+
constructor(options?: MemoryLRUCacheOptions);
|
|
16
|
+
dispose(): void;
|
|
17
|
+
get(key: string): Promise<CacheEntry | null>;
|
|
18
|
+
set(key: string, entry: CacheEntry): Promise<void>;
|
|
19
|
+
delete(key: string): Promise<void>;
|
|
20
|
+
deleteByTag(namespace: string, tag: string): Promise<void>;
|
|
21
|
+
clearNamespace(namespace: string): Promise<void>;
|
|
22
|
+
private touch;
|
|
23
|
+
private enforceLimits;
|
|
24
|
+
private cleanup;
|
|
25
|
+
private indexTags;
|
|
26
|
+
private unindexTags;
|
|
27
|
+
private getTagIndexKey;
|
|
28
|
+
private cleanupTagIndex;
|
|
29
|
+
}
|
|
30
|
+
export { MemoryCacheProvider as MemoryLRUCacheProvider };
|
|
31
|
+
//# sourceMappingURL=memory-lru.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-lru.d.ts","sourceRoot":"","sources":["../../../../src/core/cache/providers/memory-lru.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAgBD,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,YAAY,CAAC,CAAiC;gBAE1C,OAAO,GAAE,qBAA0B;IAa/C,OAAO,IAAI,IAAI;IAOT,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAY5C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1D,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,eAAe;CAYxB;AAED,OAAO,EAAE,mBAAmB,IAAI,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
function extractNamespace(key) {
|
|
2
|
+
const parts = key.split(':');
|
|
3
|
+
if (parts.length < 4) {
|
|
4
|
+
return 'default';
|
|
5
|
+
}
|
|
6
|
+
if (parts.length === 4) {
|
|
7
|
+
return parts[2];
|
|
8
|
+
}
|
|
9
|
+
// Namespace may contain additional ':' (e.g., protocol prefixes); rejoin everything
|
|
10
|
+
// between the version segment and the trailing table/digest tokens.
|
|
11
|
+
const namespace = parts.slice(2, -2).join(':');
|
|
12
|
+
return namespace || 'default';
|
|
13
|
+
}
|
|
14
|
+
export class MemoryCacheProvider {
|
|
15
|
+
entries = new Map();
|
|
16
|
+
tagIndex = new Map();
|
|
17
|
+
currentBytes = 0;
|
|
18
|
+
maxEntries;
|
|
19
|
+
maxBytes;
|
|
20
|
+
cleanupIntervalMs;
|
|
21
|
+
cleanupTimer;
|
|
22
|
+
constructor(options = {}) {
|
|
23
|
+
this.maxEntries = options.maxEntries ?? 1000;
|
|
24
|
+
this.maxBytes = options.maxBytes ?? 50 * 1024 * 1024;
|
|
25
|
+
this.cleanupIntervalMs = options.cleanupIntervalMs ?? 30_000;
|
|
26
|
+
if (this.cleanupIntervalMs > 0 && typeof setInterval !== 'undefined') {
|
|
27
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), this.cleanupIntervalMs);
|
|
28
|
+
const timer = this.cleanupTimer;
|
|
29
|
+
if (typeof timer.unref === 'function') {
|
|
30
|
+
timer.unref();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
dispose() {
|
|
35
|
+
if (this.cleanupTimer) {
|
|
36
|
+
clearInterval(this.cleanupTimer);
|
|
37
|
+
this.cleanupTimer = undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async get(key) {
|
|
41
|
+
this.cleanup();
|
|
42
|
+
const entry = this.entries.get(key);
|
|
43
|
+
if (!entry)
|
|
44
|
+
return null;
|
|
45
|
+
if (entry.cacheTimeMs > 0 && Date.now() > entry.createdAt + entry.cacheTimeMs) {
|
|
46
|
+
await this.delete(key);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
this.touch(key, entry);
|
|
50
|
+
return entry;
|
|
51
|
+
}
|
|
52
|
+
async set(key, entry) {
|
|
53
|
+
const existing = this.entries.get(key);
|
|
54
|
+
if (existing) {
|
|
55
|
+
this.currentBytes -= existing.byteSize || 0;
|
|
56
|
+
this.unindexTags(key, existing.tags);
|
|
57
|
+
}
|
|
58
|
+
this.entries.set(key, entry);
|
|
59
|
+
this.currentBytes += entry.byteSize || 0;
|
|
60
|
+
this.indexTags(key, entry.tags);
|
|
61
|
+
this.enforceLimits();
|
|
62
|
+
}
|
|
63
|
+
async delete(key) {
|
|
64
|
+
const entry = this.entries.get(key);
|
|
65
|
+
if (!entry)
|
|
66
|
+
return;
|
|
67
|
+
this.entries.delete(key);
|
|
68
|
+
this.currentBytes -= entry.byteSize || 0;
|
|
69
|
+
this.unindexTags(key, entry.tags);
|
|
70
|
+
}
|
|
71
|
+
async deleteByTag(namespace, tag) {
|
|
72
|
+
const indexKey = this.getTagIndexKey(namespace, tag);
|
|
73
|
+
const keys = this.tagIndex.get(indexKey);
|
|
74
|
+
if (!keys)
|
|
75
|
+
return;
|
|
76
|
+
for (const key of keys) {
|
|
77
|
+
await this.delete(key);
|
|
78
|
+
}
|
|
79
|
+
this.tagIndex.delete(indexKey);
|
|
80
|
+
}
|
|
81
|
+
async clearNamespace(namespace) {
|
|
82
|
+
const keys = Array.from(this.entries.keys());
|
|
83
|
+
await Promise.all(keys.map(key => {
|
|
84
|
+
if (extractNamespace(key) === namespace) {
|
|
85
|
+
return this.delete(key);
|
|
86
|
+
}
|
|
87
|
+
return Promise.resolve();
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
touch(key, entry) {
|
|
91
|
+
this.entries.delete(key);
|
|
92
|
+
this.entries.set(key, entry);
|
|
93
|
+
}
|
|
94
|
+
enforceLimits() {
|
|
95
|
+
while (this.entries.size > this.maxEntries || this.currentBytes > this.maxBytes) {
|
|
96
|
+
const oldestKey = this.entries.keys().next().value;
|
|
97
|
+
if (!oldestKey)
|
|
98
|
+
break;
|
|
99
|
+
this.delete(oldestKey);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
cleanup() {
|
|
103
|
+
if (!this.entries.size)
|
|
104
|
+
return;
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
for (const [key, entry] of this.entries) {
|
|
107
|
+
if (entry.cacheTimeMs > 0 && now > entry.createdAt + entry.cacheTimeMs) {
|
|
108
|
+
this.delete(key);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
this.cleanupTagIndex();
|
|
112
|
+
}
|
|
113
|
+
indexTags(key, tags) {
|
|
114
|
+
if (!tags || !tags.length)
|
|
115
|
+
return;
|
|
116
|
+
const namespace = extractNamespace(key);
|
|
117
|
+
tags.forEach(tag => {
|
|
118
|
+
const indexKey = this.getTagIndexKey(namespace, tag);
|
|
119
|
+
if (!this.tagIndex.has(indexKey)) {
|
|
120
|
+
this.tagIndex.set(indexKey, new Set());
|
|
121
|
+
}
|
|
122
|
+
this.tagIndex.get(indexKey).add(key);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
unindexTags(key, tags) {
|
|
126
|
+
if (!tags || !tags.length)
|
|
127
|
+
return;
|
|
128
|
+
const namespace = extractNamespace(key);
|
|
129
|
+
tags.forEach(tag => {
|
|
130
|
+
const indexKey = this.getTagIndexKey(namespace, tag);
|
|
131
|
+
const bucket = this.tagIndex.get(indexKey);
|
|
132
|
+
if (!bucket)
|
|
133
|
+
return;
|
|
134
|
+
bucket.delete(key);
|
|
135
|
+
if (!bucket.size) {
|
|
136
|
+
this.tagIndex.delete(indexKey);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
getTagIndexKey(namespace, tag) {
|
|
141
|
+
return `${namespace}:${tag}`;
|
|
142
|
+
}
|
|
143
|
+
cleanupTagIndex() {
|
|
144
|
+
for (const [indexKey, keys] of this.tagIndex) {
|
|
145
|
+
for (const key of keys) {
|
|
146
|
+
if (!this.entries.has(key)) {
|
|
147
|
+
keys.delete(key);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (!keys.size) {
|
|
151
|
+
this.tagIndex.delete(indexKey);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export { MemoryCacheProvider as MemoryLRUCacheProvider };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CacheEntry, CacheProvider } from '../types.js';
|
|
2
|
+
export declare class NoopCacheProvider implements CacheProvider {
|
|
3
|
+
get(_key: string): Promise<CacheEntry | null>;
|
|
4
|
+
set(_key: string, _entry: CacheEntry): Promise<void>;
|
|
5
|
+
delete(_key: string): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=noop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noop.d.ts","sourceRoot":"","sources":["../../../../src/core/cache/providers/noop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7D,qBAAa,iBAAkB,YAAW,aAAa;IAC/C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI7C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CacheConfig, CacheOptions, CacheProvider, CacheSerializeFn, CacheDeserializeFn, CacheStats } from './types.js';
|
|
2
|
+
export interface QueryRuntimeContext {
|
|
3
|
+
provider?: CacheProvider;
|
|
4
|
+
defaults: CacheOptions;
|
|
5
|
+
namespace: string;
|
|
6
|
+
versionTag: string;
|
|
7
|
+
serialize: CacheSerializeFn;
|
|
8
|
+
deserialize: CacheDeserializeFn;
|
|
9
|
+
inFlight: Map<string, Promise<unknown>>;
|
|
10
|
+
stats: CacheStats;
|
|
11
|
+
parsedValues: Map<string, ParsedValueEntry>;
|
|
12
|
+
}
|
|
13
|
+
export interface ParsedValueEntry {
|
|
14
|
+
createdAt: number;
|
|
15
|
+
rows: unknown;
|
|
16
|
+
tags?: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function createCacheStats(): CacheStats;
|
|
19
|
+
export declare function mergeCacheOptions(...candidates: Array<CacheOptions | undefined>): CacheOptions;
|
|
20
|
+
export interface CacheRuntimeConfig {
|
|
21
|
+
namespace: string;
|
|
22
|
+
versionTag: string;
|
|
23
|
+
provider?: CacheProvider;
|
|
24
|
+
defaults: CacheOptions;
|
|
25
|
+
serialize: CacheSerializeFn;
|
|
26
|
+
deserialize: CacheDeserializeFn;
|
|
27
|
+
}
|
|
28
|
+
export declare function buildRuntimeContext(config: CacheRuntimeConfig): QueryRuntimeContext;
|
|
29
|
+
export declare function resolveCacheConfig(config: CacheConfig | undefined, fallbackNamespace: string): CacheRuntimeConfig;
|
|
30
|
+
//# sourceMappingURL=runtime-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../../../src/core/cache/runtime-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACX,MAAM,YAAY,CAAC;AAWpB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACxC,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CAE7C;AAQD,wBAAgB,iBAAiB,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,YAAY,CAe9F;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,WAAW,EAAE,kBAAkB,CAAC;CACjC;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,mBAAmB,CAYnF;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,EAAE,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAUjH"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { defaultSerialize, defaultDeserialize } from './serialization.js';
|
|
2
|
+
const DEFAULT_CACHE_OPTIONS = {
|
|
3
|
+
mode: 'no-store',
|
|
4
|
+
ttlMs: 0,
|
|
5
|
+
staleTtlMs: 0,
|
|
6
|
+
staleIfError: false,
|
|
7
|
+
dedupe: true
|
|
8
|
+
};
|
|
9
|
+
export function createCacheStats() {
|
|
10
|
+
return { hits: 0, misses: 0, staleHits: 0, revalidations: 0 };
|
|
11
|
+
}
|
|
12
|
+
function uniqueTags(left, right) {
|
|
13
|
+
const combined = [...(left || []), ...(right || [])];
|
|
14
|
+
if (!combined.length)
|
|
15
|
+
return undefined;
|
|
16
|
+
return Array.from(new Set(combined));
|
|
17
|
+
}
|
|
18
|
+
export function mergeCacheOptions(...candidates) {
|
|
19
|
+
return candidates.reduce((acc, candidate) => {
|
|
20
|
+
if (!candidate)
|
|
21
|
+
return acc;
|
|
22
|
+
const next = { ...acc };
|
|
23
|
+
for (const [key, value] of Object.entries(candidate)) {
|
|
24
|
+
if (key === 'tags') {
|
|
25
|
+
next.tags = uniqueTags(next.tags, value);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (value !== undefined) {
|
|
29
|
+
next[key] = value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return next;
|
|
33
|
+
}, { ...DEFAULT_CACHE_OPTIONS });
|
|
34
|
+
}
|
|
35
|
+
export function buildRuntimeContext(config) {
|
|
36
|
+
return {
|
|
37
|
+
provider: config.provider,
|
|
38
|
+
defaults: { ...config.defaults },
|
|
39
|
+
namespace: config.namespace,
|
|
40
|
+
versionTag: config.versionTag,
|
|
41
|
+
serialize: config.serialize,
|
|
42
|
+
deserialize: config.deserialize,
|
|
43
|
+
inFlight: new Map(),
|
|
44
|
+
stats: createCacheStats(),
|
|
45
|
+
parsedValues: new Map()
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function resolveCacheConfig(config, fallbackNamespace) {
|
|
49
|
+
const defaults = mergeCacheOptions(config);
|
|
50
|
+
return {
|
|
51
|
+
namespace: config?.namespace || fallbackNamespace,
|
|
52
|
+
versionTag: config?.versionTag || 'v1',
|
|
53
|
+
provider: config?.provider,
|
|
54
|
+
defaults,
|
|
55
|
+
serialize: config?.serialize || ((value) => defaultSerialize(value)),
|
|
56
|
+
deserialize: config?.deserialize || ((raw) => defaultDeserialize(raw))
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CacheSerializationResult } from './types.js';
|
|
2
|
+
export declare function stableStringify(value: unknown): string;
|
|
3
|
+
export declare function defaultSerialize(value: unknown): CacheSerializationResult;
|
|
4
|
+
export declare function defaultDeserialize<T = unknown>(raw: string | Uint8Array): T;
|
|
5
|
+
export declare function estimateByteSize(value: unknown): number;
|
|
6
|
+
//# sourceMappingURL=serialization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialization.d.ts","sourceRoot":"","sources":["../../../src/core/cache/serialization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAiH3D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD;AAyDD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAOzE;AAED,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,CAAC,CAQ3E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMvD"}
|