veryfront 0.1.86 → 0.1.88
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/esm/deno.js +1 -1
- package/esm/src/cache/distributed-cache-init.d.ts +9 -0
- package/esm/src/cache/distributed-cache-init.d.ts.map +1 -1
- package/esm/src/cache/distributed-cache-init.js +70 -52
- package/esm/src/cache/module-cache.d.ts +6 -2
- package/esm/src/cache/module-cache.d.ts.map +1 -1
- package/esm/src/cache/module-cache.js +73 -56
- package/esm/src/platform/adapters/fs/veryfront/content-metrics.d.ts +1 -1
- package/esm/src/platform/adapters/fs/veryfront/content-metrics.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/content-metrics.js +7 -1
- package/esm/src/platform/adapters/fs/veryfront/file-list-index.d.ts +10 -0
- package/esm/src/platform/adapters/fs/veryfront/file-list-index.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/file-list-index.js +83 -19
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts +5 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.js +6 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations.js +53 -34
- package/esm/src/rendering/page-resolution/page-resolver.d.ts.map +1 -1
- package/esm/src/rendering/page-resolution/page-resolver.js +10 -4
- package/esm/src/transforms/esm/http-cache-wrapper.d.ts +3 -0
- package/esm/src/transforms/esm/http-cache-wrapper.d.ts.map +1 -1
- package/esm/src/transforms/esm/http-cache-wrapper.js +21 -7
- package/esm/src/utils/version.d.ts +1 -1
- package/esm/src/utils/version.js +1 -1
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/cache/distributed-cache-init.ts +95 -59
- package/src/src/cache/module-cache.ts +95 -57
- package/src/src/platform/adapters/fs/veryfront/content-metrics.ts +13 -2
- package/src/src/platform/adapters/fs/veryfront/file-list-index.ts +101 -18
- package/src/src/platform/adapters/fs/veryfront/read-operations-helpers.ts +10 -0
- package/src/src/platform/adapters/fs/veryfront/read-operations.ts +87 -30
- package/src/src/rendering/page-resolution/page-resolver.ts +17 -6
- package/src/src/transforms/esm/http-cache-wrapper.ts +28 -7
- package/src/src/utils/version.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"read-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAWtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAI9B,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,YAAY,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAClC,iBAAiB,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;IACvD,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,OAAO,CACzB,KAAK,CAAC;QACJ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,GAAG,SAAS,CACf,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,0EAA0E;IAC1E,4BAA4B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3D,+CAA+C;IAC/C,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5D;AAUD,qBAAa,cAAc;IAWvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAfpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAI9B;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,mGAAmG;IACnG,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA6B;gBAGnD,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,cAAc,EAC1B,eAAe,CAAC,EAAE,sBAAsB,YAAA,EACxC,kBAAkB,CAAC,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,aAAA,EAC7C,gBAAgB,CAAC,GAAE,MAAM,OAAO,CAC/C,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CACtD,aAAA;IAKH,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIrD,kBAAkB,IAAI,IAAI;IAK1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAY3C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY3C,OAAO,CAAC,mBAAmB;YAsBb,+BAA+B;YA0C/B,mBAAmB;IA0CjC,OAAO,CAAC,kBAAkB;YAoFZ,2BAA2B;YA8D3B,uCAAuC;IAmCrD,OAAO,CAAC,oBAAoB;YAgBd,YAAY;YA6JZ,qBAAqB;YA8DrB,qBAAqB;YAgDrB,+BAA+B;YA8D/B,iBAAiB;CAyBhC"}
|
|
@@ -4,7 +4,7 @@ import { logContentMetric } from "./content-metrics.js";
|
|
|
4
4
|
import { FileListIndex } from "./file-list-index.js";
|
|
5
5
|
import { InFlightRequestDeduper } from "./in-flight-dedupe.js";
|
|
6
6
|
import { getRequestScopedFile, setRequestScopedFile } from "./multi-project-adapter.js";
|
|
7
|
-
import { assertProjectSourcePath, buildReadFetchState, getResolvedCacheKey, isNotFoundLikeError, READ_OPERATION_EXTENSION_PRIORITY as EXTENSION_PRIORITY, splitKnownFileExtension, } from "./read-operations-helpers.js";
|
|
7
|
+
import { assertProjectSourcePath, buildExtensionCandidatePaths, buildReadFetchState, createNotFoundLikeError, getResolvedCacheKey, isNotFoundLikeError, READ_OPERATION_EXTENSION_PRIORITY as EXTENSION_PRIORITY, splitKnownFileExtension, } from "./read-operations-helpers.js";
|
|
8
8
|
export { endRequestMetrics, getContentMetricsSnapshot, resetContentMetrics, startRequestMetrics, } from "./content-metrics.js";
|
|
9
9
|
const logger = baseLogger.component("read-operations");
|
|
10
10
|
const IN_FLIGHT_REQUEST_TIMEOUT_MS = 15_000;
|
|
@@ -113,10 +113,15 @@ export class ReadOperations {
|
|
|
113
113
|
// - File list is refreshed on every WebSocket poke (websocket-manager.ts:483-500)
|
|
114
114
|
// - Request-scoped cache ensures consistency within a single render
|
|
115
115
|
// - Persistent cache is only written for production mode (to avoid staleness risk in preview)
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
if (skipPersistentCaches) {
|
|
117
|
+
logger.debug("Skipping file list cache due to invalidation", {
|
|
118
|
+
path: normalizedPath,
|
|
119
|
+
cacheKeyPrefix,
|
|
120
|
+
});
|
|
121
|
+
return { status: "unavailable", fresh: false };
|
|
122
|
+
}
|
|
123
|
+
const match = await this.fileListIndex.match(normalizedPath);
|
|
124
|
+
if (match.status === "hit" && match.content) {
|
|
120
125
|
logContentMetric("FILE_LIST_HIT", {
|
|
121
126
|
path: normalizedPath,
|
|
122
127
|
mode: ctx?.sourceType ?? "unknown",
|
|
@@ -126,25 +131,13 @@ export class ReadOperations {
|
|
|
126
131
|
// Only cache to persistent storage for production mode
|
|
127
132
|
// Preview mode uses file list cache directly without persisting (fresher, WebSocket-driven)
|
|
128
133
|
if (isProduction) {
|
|
129
|
-
this.cache.set(cacheKey,
|
|
134
|
+
this.cache.set(cacheKey, match.content);
|
|
130
135
|
}
|
|
131
|
-
setRequestScopedFile(cacheKey,
|
|
132
|
-
return fileListContent;
|
|
136
|
+
setRequestScopedFile(cacheKey, match.content);
|
|
133
137
|
}
|
|
134
|
-
|
|
135
|
-
logContentMetric("CACHE_MISS", {
|
|
136
|
-
path: normalizedPath,
|
|
137
|
-
mode: ctx?.sourceType ?? "unknown",
|
|
138
|
-
missReason: "invalidation",
|
|
139
|
-
isPreviewMode,
|
|
140
|
-
});
|
|
141
|
-
logger.debug("Skipping file list cache due to invalidation", {
|
|
142
|
-
path: normalizedPath,
|
|
143
|
-
cacheKeyPrefix,
|
|
144
|
-
});
|
|
145
|
-
return null;
|
|
138
|
+
return match;
|
|
146
139
|
}
|
|
147
|
-
setupInFlightFetch(normalizedPath, apiPath, cacheKey, isPublished, isProduction, isPreviewMode, ctx) {
|
|
140
|
+
setupInFlightFetch(normalizedPath, apiPath, cacheKey, isPublished, isProduction, isPreviewMode, ctx, missReason) {
|
|
148
141
|
const cleanupResult = this.inFlightRequests.cleanup();
|
|
149
142
|
if (cleanupResult) {
|
|
150
143
|
logger.warn("Cleaned up in-flight requests", cleanupResult);
|
|
@@ -159,11 +152,10 @@ export class ReadOperations {
|
|
|
159
152
|
return existingEntry.promise;
|
|
160
153
|
}
|
|
161
154
|
// Track why we're making a network fetch (for optimization analysis)
|
|
162
|
-
const hasFileListCache = !!this.getFileListCache;
|
|
163
155
|
logContentMetric("CACHE_MISS", {
|
|
164
156
|
path: normalizedPath,
|
|
165
157
|
mode: ctx?.sourceType ?? "unknown",
|
|
166
|
-
missReason
|
|
158
|
+
missReason,
|
|
167
159
|
isPreviewMode,
|
|
168
160
|
});
|
|
169
161
|
// THIS IS A NETWORK FETCH - every call here = API round trip
|
|
@@ -248,10 +240,10 @@ export class ReadOperations {
|
|
|
248
240
|
}
|
|
249
241
|
}
|
|
250
242
|
async tryResolveExtensionlessPathFromFileList(normalizedPath, cacheKeyPrefix, cacheKey, isProduction, ctx, isPreviewMode) {
|
|
251
|
-
const candidatePaths =
|
|
252
|
-
const resolved = await this.fileListIndex.
|
|
253
|
-
if (!resolved)
|
|
254
|
-
return
|
|
243
|
+
const candidatePaths = buildExtensionCandidatePaths(normalizedPath);
|
|
244
|
+
const resolved = await this.fileListIndex.findFirstMatch(candidatePaths);
|
|
245
|
+
if (resolved.status !== "hit" || !resolved.path || !resolved.content)
|
|
246
|
+
return resolved;
|
|
255
247
|
const resolvedCacheKey = getResolvedCacheKey(cacheKeyPrefix, resolved.path);
|
|
256
248
|
this.extensionResolutionCache.set(normalizedPath, resolved.path);
|
|
257
249
|
logContentMetric("FILE_LIST_HIT", {
|
|
@@ -268,7 +260,7 @@ export class ReadOperations {
|
|
|
268
260
|
resolvedCacheKey: resolvedCacheKey === cacheKey ? undefined : resolvedCacheKey,
|
|
269
261
|
});
|
|
270
262
|
this.cacheResolvedContent(cacheKey, resolvedCacheKey, resolved.content, isProduction);
|
|
271
|
-
return resolved
|
|
263
|
+
return resolved;
|
|
272
264
|
}
|
|
273
265
|
cacheResolvedContent(cacheKey, resolvedCacheKey, content, persistToCache) {
|
|
274
266
|
if (persistToCache) {
|
|
@@ -309,20 +301,47 @@ export class ReadOperations {
|
|
|
309
301
|
const persistentCached = await this.getProductionPersistentCacheHit(normalizedPath, cacheKeyPrefix, cacheKey, isProduction, skipPersistentCaches, currentReleaseId, isPrefixInvalidated, ctx);
|
|
310
302
|
if (persistentCached)
|
|
311
303
|
return persistentCached;
|
|
312
|
-
const
|
|
313
|
-
if (
|
|
314
|
-
return
|
|
304
|
+
const fileListMatch = await this.getFileListCacheHit(normalizedPath, cacheKeyPrefix, cacheKey, isProduction, skipPersistentCaches, isPreviewMode, ctx);
|
|
305
|
+
if (fileListMatch.status === "hit" && fileListMatch.content)
|
|
306
|
+
return fileListMatch.content;
|
|
307
|
+
if (fileListMatch.status === "present_without_content") {
|
|
308
|
+
return this.setupInFlightFetch(normalizedPath, apiPath, cacheKey, isPublished, isProduction, isPreviewMode, ctx, "indexed_without_content");
|
|
309
|
+
}
|
|
315
310
|
if (!hasKnownExt) {
|
|
316
311
|
if (!skipPersistentCaches) {
|
|
317
312
|
const resolvedFromFileList = await this.tryResolveExtensionlessPathFromFileList(normalizedPath, cacheKeyPrefix, cacheKey, isProduction, ctx, isPreviewMode);
|
|
318
|
-
if (resolvedFromFileList)
|
|
319
|
-
return resolvedFromFileList;
|
|
313
|
+
if (resolvedFromFileList.status === "hit" && resolvedFromFileList.content) {
|
|
314
|
+
return resolvedFromFileList.content;
|
|
315
|
+
}
|
|
316
|
+
if (resolvedFromFileList.status === "present_without_content" &&
|
|
317
|
+
resolvedFromFileList.path) {
|
|
318
|
+
const resolvedCacheKey = getResolvedCacheKey(cacheKeyPrefix, resolvedFromFileList.path);
|
|
319
|
+
const resolvedApiPath = this.getOriginalApiPath?.(resolvedFromFileList.path) ??
|
|
320
|
+
resolvedFromFileList.path;
|
|
321
|
+
const fetchedResolved = await this.setupInFlightFetch(resolvedFromFileList.path, resolvedApiPath, resolvedCacheKey, isPublished, isProduction, isPreviewMode, ctx, "indexed_without_content");
|
|
322
|
+
this.extensionResolutionCache.set(normalizedPath, resolvedFromFileList.path);
|
|
323
|
+
this.cacheResolvedContent(cacheKey, resolvedCacheKey, fetchedResolved, isProduction && !skipPersistentCaches);
|
|
324
|
+
return fetchedResolved;
|
|
325
|
+
}
|
|
326
|
+
if (fileListMatch.status === "missing" &&
|
|
327
|
+
fileListMatch.fresh &&
|
|
328
|
+
resolvedFromFileList.status === "missing" &&
|
|
329
|
+
resolvedFromFileList.fresh) {
|
|
330
|
+
throw createNotFoundLikeError(normalizedPath);
|
|
331
|
+
}
|
|
320
332
|
}
|
|
321
333
|
const resolved = await this.tryResolveExtensionlessPath(apiPath, cacheKeyPrefix, cacheKey, isProduction, skipPersistentCaches);
|
|
322
334
|
if (resolved)
|
|
323
335
|
return resolved;
|
|
324
336
|
}
|
|
325
|
-
|
|
337
|
+
if (fileListMatch.status === "missing" && fileListMatch.fresh) {
|
|
338
|
+
throw createNotFoundLikeError(normalizedPath);
|
|
339
|
+
}
|
|
340
|
+
return this.setupInFlightFetch(normalizedPath, apiPath, cacheKey, isPublished, isProduction, isPreviewMode, ctx, skipPersistentCaches
|
|
341
|
+
? "invalidation"
|
|
342
|
+
: fileListMatch.status === "missing" && fileListMatch.fresh
|
|
343
|
+
? "not_in_filelist"
|
|
344
|
+
: "no_filelist_cache");
|
|
326
345
|
}
|
|
327
346
|
async fetchPublishedContent(normalizedPath, apiPath, cacheKey, releaseId, environmentName, shouldCache) {
|
|
328
347
|
logger.debug("Fetching published content", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-resolver.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/page-resolution/page-resolver.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAoCvD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAiB;gBAEpB,OAAO,EAAE,mBAAmB;IAOxC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"page-resolver.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/page-resolution/page-resolver.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAoCvD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAiB;gBAEpB,OAAO,EAAE,mBAAmB;IAOxC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAiExC,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAoCxB,sBAAsB;IAoD9B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAY1C,aAAa,IAAI,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC;CAShD"}
|
|
@@ -56,10 +56,16 @@ export class PageResolver {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
else {
|
|
59
|
-
// Auto mode stays structural:
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
if (
|
|
59
|
+
// Auto mode stays structural: detect the dominant router once, then keep
|
|
60
|
+
// pages fallback available for mixed or in-transition projects.
|
|
61
|
+
const useAppRouter = await detectAppRouter(this.projectDir, this.config, this.adapter, { projectId: this.projectId });
|
|
62
|
+
if (useAppRouter) {
|
|
63
|
+
pageInfo = await getAppRouteEntity(this.projectDir, slug, this.adapter, appDirName);
|
|
64
|
+
if (!pageInfo) {
|
|
65
|
+
pageInfo = await getEntityBySlug(this.projectDir, slug, this.adapter);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
63
69
|
pageInfo = await getEntityBySlug(this.projectDir, slug, this.adapter);
|
|
64
70
|
}
|
|
65
71
|
}
|
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module transforms/esm/http-cache-wrapper
|
|
12
12
|
*/
|
|
13
|
+
import type { CacheBackend } from "../../cache/types.js";
|
|
13
14
|
import type { BundleHash, LocalModuleCode, NormalizedUrl, PortableModuleCode } from "./http-cache-types.js";
|
|
14
15
|
import { asBundleHash } from "./http-cache-invariants.js";
|
|
16
|
+
export declare function __setDistributedCacheAccessorForTests(accessor: (() => Promise<CacheBackend | null>) | null): void;
|
|
17
|
+
export declare function initializeHttpModuleDistributedCache(): Promise<boolean>;
|
|
15
18
|
/**
|
|
16
19
|
* Tokenize local code paths to portable format.
|
|
17
20
|
* Replaces absolute cache directory paths with __VF_CACHE_DIR__ tokens.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-cache-wrapper.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/http-cache-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"http-cache-wrapper.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/http-cache-wrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EACV,UAAU,EAEV,eAAe,EACf,aAAa,EACb,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,YAAY,EAKb,MAAM,4BAA4B,CAAC;AAoBpC,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,GACpD,IAAI,CAEN;AAED,wBAAsB,oCAAoC,IAAI,OAAO,CAAC,OAAO,CAAC,CAM7E;AAWD;;;;;;GAMG;AACH,iBAAS,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,CAoB3D;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,eAAe,CAMtE;AAmCD;;GAEG;AACH,UAAU,aAAa;IACrB,wEAAwE;IACxE,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7B,uDAAuD;IACvD,UAAU,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,WAAW,GAAG,oBAAoB,GAAG,cAAc,GAAG,OAAO,CAAC;CAC5E;AAED;;;;;;;;;GASG;AACH,cAAM,eAAe;IACnB;;;;;;OAMG;IACG,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAiDtE;;;;;;OAMG;IACG,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAqCrE;;;;;;;;OAQG;IACG,OAAO,CACX,IAAI,EAAE,UAAU,GAAG,MAAM,EACzB,IAAI,EAAE,eAAe,EACrB,GAAG,EAAE,aAAa,GAAG,MAAM,EAC3B,GAAG,GAAE,MAAwC,GAC5C,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;OAMG;IACG,aAAa,CACjB,MAAM,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,GACjC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IA8CxC;;;;;OAKG;IACG,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcvE;;;;;;OAMG;IACG,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsB7D;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAItC;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,iBAAwB,CAAC;AAErD;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -23,6 +23,20 @@ const logger = rendererLogger.component("http-cache-wrapper");
|
|
|
23
23
|
const BATCH_FETCH_CHUNK_SIZE = 100;
|
|
24
24
|
/** Lazy-loaded distributed cache backend for cross-pod sharing */
|
|
25
25
|
const getDistributedCache = createDistributedCacheAccessor(() => CacheBackends.httpModule(), "HTTP-CACHE-WRAPPER");
|
|
26
|
+
let testDistributedCacheAccessor = null;
|
|
27
|
+
function resolveDistributedCache() {
|
|
28
|
+
return testDistributedCacheAccessor ? testDistributedCacheAccessor() : getDistributedCache();
|
|
29
|
+
}
|
|
30
|
+
export function __setDistributedCacheAccessorForTests(accessor) {
|
|
31
|
+
testDistributedCacheAccessor = accessor;
|
|
32
|
+
}
|
|
33
|
+
export async function initializeHttpModuleDistributedCache() {
|
|
34
|
+
const distributed = await resolveDistributedCache();
|
|
35
|
+
if (!distributed)
|
|
36
|
+
return false;
|
|
37
|
+
logger.info("Initialized distributed cache backend", { backend: distributed.type });
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
26
40
|
/**
|
|
27
41
|
* Generate versioned cache key for HTTP bundles.
|
|
28
42
|
* Format: {VERSION}:{prefix}:{hash}
|
|
@@ -110,7 +124,7 @@ class HttpBundleCache {
|
|
|
110
124
|
* @returns Result containing local code or failure reason
|
|
111
125
|
*/
|
|
112
126
|
async getCodeByHash(hash) {
|
|
113
|
-
const distributed = await
|
|
127
|
+
const distributed = await resolveDistributedCache();
|
|
114
128
|
if (!distributed) {
|
|
115
129
|
return { code: null, wasGzipped: false, failReason: "not_found" };
|
|
116
130
|
}
|
|
@@ -160,7 +174,7 @@ class HttpBundleCache {
|
|
|
160
174
|
* @returns Result containing local code or failure reason
|
|
161
175
|
*/
|
|
162
176
|
async getCodeByUrl(hash) {
|
|
163
|
-
const distributed = await
|
|
177
|
+
const distributed = await resolveDistributedCache();
|
|
164
178
|
if (!distributed) {
|
|
165
179
|
return { code: null, wasGzipped: false, failReason: "not_found" };
|
|
166
180
|
}
|
|
@@ -200,7 +214,7 @@ class HttpBundleCache {
|
|
|
200
214
|
* @param ttl - TTL in seconds (defaults to HTTP_MODULE_DISTRIBUTED_TTL_SEC)
|
|
201
215
|
*/
|
|
202
216
|
async setCode(hash, code, url, ttl = HTTP_MODULE_DISTRIBUTED_TTL_SEC) {
|
|
203
|
-
const distributed = await
|
|
217
|
+
const distributed = await resolveDistributedCache();
|
|
204
218
|
if (!distributed)
|
|
205
219
|
return;
|
|
206
220
|
const hashStr = typeof hash === "string" ? hash : hash;
|
|
@@ -233,7 +247,7 @@ class HttpBundleCache {
|
|
|
233
247
|
* @returns Map of hash -> local code (missing/failed hashes not included)
|
|
234
248
|
*/
|
|
235
249
|
async getBatchCodes(hashes) {
|
|
236
|
-
const distributed = await
|
|
250
|
+
const distributed = await resolveDistributedCache();
|
|
237
251
|
if (!distributed)
|
|
238
252
|
return new Map();
|
|
239
253
|
const results = new Map();
|
|
@@ -278,7 +292,7 @@ class HttpBundleCache {
|
|
|
278
292
|
* @returns Original URL or null
|
|
279
293
|
*/
|
|
280
294
|
async getOriginalUrl(hash) {
|
|
281
|
-
const distributed = await
|
|
295
|
+
const distributed = await resolveDistributedCache();
|
|
282
296
|
if (!distributed)
|
|
283
297
|
return null;
|
|
284
298
|
const hashStr = typeof hash === "string" ? hash : hash;
|
|
@@ -298,7 +312,7 @@ class HttpBundleCache {
|
|
|
298
312
|
* @returns true if deletion was attempted, false if cache unavailable
|
|
299
313
|
*/
|
|
300
314
|
async deleteCode(hash) {
|
|
301
|
-
const distributed = await
|
|
315
|
+
const distributed = await resolveDistributedCache();
|
|
302
316
|
if (!distributed)
|
|
303
317
|
return false;
|
|
304
318
|
const hashStr = typeof hash === "string" ? hash : hash;
|
|
@@ -321,7 +335,7 @@ class HttpBundleCache {
|
|
|
321
335
|
* Check if distributed cache is available.
|
|
322
336
|
*/
|
|
323
337
|
async isAvailable() {
|
|
324
|
-
const distributed = await
|
|
338
|
+
const distributed = await resolveDistributedCache();
|
|
325
339
|
return distributed !== null;
|
|
326
340
|
}
|
|
327
341
|
}
|
package/esm/src/utils/version.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Keep in sync with deno.json version.
|
|
2
2
|
// scripts/release.ts updates this constant during releases.
|
|
3
|
-
export const VERSION = "0.1.
|
|
3
|
+
export const VERSION = "0.1.88";
|
|
4
4
|
export const SERVER_START_TIME = Date.now();
|
|
5
5
|
export function createBuildVersion(projectUpdatedAt) {
|
|
6
6
|
return {
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { initializeFileCacheBackend } from "../platform/adapters/fs/cache/file-cache.js";
|
|
2
2
|
import { initializeSSRDistributedCache } from "../modules/react-loader/ssr-module-loader/index.js";
|
|
3
3
|
import { initializeTransformCache } from "../transforms/esm/transform-cache.js";
|
|
4
|
+
import { initializeHttpModuleDistributedCache } from "../transforms/esm/http-cache-wrapper.js";
|
|
4
5
|
import { SpanNames } from "../observability/tracing/span-names.js";
|
|
5
6
|
import { withSpan } from "../observability/tracing/otlp-setup.js";
|
|
6
7
|
import { initializeProjectCSSCache } from "../html/styles-builder/tailwind-compiler.js";
|
|
@@ -16,8 +17,25 @@ interface DistributedCacheStatus {
|
|
|
16
17
|
ssrModuleCache: boolean;
|
|
17
18
|
fileCache: boolean;
|
|
18
19
|
projectCSSCache: boolean;
|
|
20
|
+
httpModuleCache: boolean;
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
type DistributedCacheInitializers = {
|
|
24
|
+
transformCache: () => Promise<boolean>;
|
|
25
|
+
ssrModuleCache: () => Promise<boolean>;
|
|
26
|
+
fileCache: () => Promise<boolean>;
|
|
27
|
+
projectCSSCache: () => Promise<boolean>;
|
|
28
|
+
httpModuleCache: () => Promise<boolean>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const defaultInitializers: DistributedCacheInitializers = {
|
|
32
|
+
transformCache: initializeTransformCache,
|
|
33
|
+
ssrModuleCache: initializeSSRDistributedCache,
|
|
34
|
+
fileCache: initializeFileCacheBackend,
|
|
35
|
+
projectCSSCache: initializeProjectCSSCache,
|
|
36
|
+
httpModuleCache: initializeHttpModuleDistributedCache,
|
|
37
|
+
};
|
|
38
|
+
|
|
21
39
|
function determineBackend(): DistributedCacheStatus["backend"] {
|
|
22
40
|
if (isApiCacheAvailable()) return "api";
|
|
23
41
|
if (isRedisConfigured()) return "redis";
|
|
@@ -29,6 +47,81 @@ function wasSuccessful(result: PromiseSettledResult<boolean>): boolean {
|
|
|
29
47
|
return result.status === "fulfilled" && result.value;
|
|
30
48
|
}
|
|
31
49
|
|
|
50
|
+
async function initializeDistributedCachesWithInitializers(
|
|
51
|
+
backend: DistributedCacheStatus["backend"],
|
|
52
|
+
initializers: DistributedCacheInitializers,
|
|
53
|
+
): Promise<DistributedCacheStatus> {
|
|
54
|
+
logger.info("Initializing caches...", { backend });
|
|
55
|
+
|
|
56
|
+
const cacheNames = [
|
|
57
|
+
"transformCache",
|
|
58
|
+
"ssrModuleCache",
|
|
59
|
+
"fileCache",
|
|
60
|
+
"projectCSSCache",
|
|
61
|
+
"httpModuleCache",
|
|
62
|
+
] as const;
|
|
63
|
+
const results = await Promise.allSettled([
|
|
64
|
+
initializers.transformCache(),
|
|
65
|
+
initializers.ssrModuleCache(),
|
|
66
|
+
initializers.fileCache(),
|
|
67
|
+
initializers.projectCSSCache(),
|
|
68
|
+
initializers.httpModuleCache(),
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < results.length; i++) {
|
|
72
|
+
const result = results[i];
|
|
73
|
+
if (result && result.status === "rejected") {
|
|
74
|
+
logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
|
|
75
|
+
backend,
|
|
76
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const status: DistributedCacheStatus = {
|
|
82
|
+
backend,
|
|
83
|
+
transformCache: wasSuccessful(results[0]),
|
|
84
|
+
ssrModuleCache: wasSuccessful(results[1]),
|
|
85
|
+
fileCache: wasSuccessful(results[2]),
|
|
86
|
+
projectCSSCache: wasSuccessful(results[3]),
|
|
87
|
+
httpModuleCache: wasSuccessful(results[4]),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const enabled = [
|
|
91
|
+
status.transformCache,
|
|
92
|
+
status.ssrModuleCache,
|
|
93
|
+
status.fileCache,
|
|
94
|
+
status.projectCSSCache,
|
|
95
|
+
status.httpModuleCache,
|
|
96
|
+
].filter(Boolean).length;
|
|
97
|
+
|
|
98
|
+
if (enabled === 0) {
|
|
99
|
+
logger.warn("No caches enabled despite backend being available", {
|
|
100
|
+
backend,
|
|
101
|
+
});
|
|
102
|
+
return status;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
logger.info("Initialization complete", {
|
|
106
|
+
backend,
|
|
107
|
+
enabled,
|
|
108
|
+
transform: status.transformCache,
|
|
109
|
+
ssrModule: status.ssrModuleCache,
|
|
110
|
+
file: status.fileCache,
|
|
111
|
+
projectCSS: status.projectCSSCache,
|
|
112
|
+
httpModule: status.httpModuleCache,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return status;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function __runDistributedCacheInitializationForTests(
|
|
119
|
+
backend: DistributedCacheStatus["backend"],
|
|
120
|
+
initializers: DistributedCacheInitializers,
|
|
121
|
+
): Promise<DistributedCacheStatus> {
|
|
122
|
+
return initializeDistributedCachesWithInitializers(backend, initializers);
|
|
123
|
+
}
|
|
124
|
+
|
|
32
125
|
export function initializeDistributedCaches(): Promise<DistributedCacheStatus> {
|
|
33
126
|
const backend = determineBackend();
|
|
34
127
|
|
|
@@ -39,70 +132,13 @@ export function initializeDistributedCaches(): Promise<DistributedCacheStatus> {
|
|
|
39
132
|
ssrModuleCache: false,
|
|
40
133
|
fileCache: false,
|
|
41
134
|
projectCSSCache: false,
|
|
135
|
+
httpModuleCache: false,
|
|
42
136
|
});
|
|
43
137
|
}
|
|
44
138
|
|
|
45
139
|
return withSpan(
|
|
46
140
|
SpanNames.CACHE_DISTRIBUTED_INIT,
|
|
47
|
-
|
|
48
|
-
logger.info("Initializing caches...", { backend });
|
|
49
|
-
|
|
50
|
-
const cacheNames = [
|
|
51
|
-
"transformCache",
|
|
52
|
-
"ssrModuleCache",
|
|
53
|
-
"fileCache",
|
|
54
|
-
"projectCSSCache",
|
|
55
|
-
] as const;
|
|
56
|
-
const results = await Promise.allSettled([
|
|
57
|
-
initializeTransformCache(),
|
|
58
|
-
initializeSSRDistributedCache(),
|
|
59
|
-
initializeFileCacheBackend(),
|
|
60
|
-
initializeProjectCSSCache(),
|
|
61
|
-
]);
|
|
62
|
-
|
|
63
|
-
for (let i = 0; i < results.length; i++) {
|
|
64
|
-
const result = results[i];
|
|
65
|
-
if (result && result.status === "rejected") {
|
|
66
|
-
logger.error(`Cache initialization failed: ${cacheNames[i]}`, {
|
|
67
|
-
backend,
|
|
68
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const status: DistributedCacheStatus = {
|
|
74
|
-
backend,
|
|
75
|
-
transformCache: wasSuccessful(results[0]),
|
|
76
|
-
ssrModuleCache: wasSuccessful(results[1]),
|
|
77
|
-
fileCache: wasSuccessful(results[2]),
|
|
78
|
-
projectCSSCache: wasSuccessful(results[3]),
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const enabled = [
|
|
82
|
-
status.transformCache,
|
|
83
|
-
status.ssrModuleCache,
|
|
84
|
-
status.fileCache,
|
|
85
|
-
status.projectCSSCache,
|
|
86
|
-
].filter(Boolean).length;
|
|
87
|
-
|
|
88
|
-
if (enabled === 0) {
|
|
89
|
-
logger.warn("No caches enabled despite backend being available", {
|
|
90
|
-
backend,
|
|
91
|
-
});
|
|
92
|
-
return status;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
logger.info("Initialization complete", {
|
|
96
|
-
backend,
|
|
97
|
-
enabled,
|
|
98
|
-
transform: status.transformCache,
|
|
99
|
-
ssrModule: status.ssrModuleCache,
|
|
100
|
-
file: status.fileCache,
|
|
101
|
-
projectCSS: status.projectCSSCache,
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
return status;
|
|
105
|
-
},
|
|
141
|
+
() => initializeDistributedCachesWithInitializers(backend, defaultInitializers),
|
|
106
142
|
{ "cache.backend": backend },
|
|
107
143
|
);
|
|
108
144
|
}
|