veryfront 0.1.81 → 0.1.83
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/platform/adapters/base.d.ts +4 -1
- package/esm/src/platform/adapters/base.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/github/adapter.d.ts +2 -1
- package/esm/src/platform/adapters/fs/github/adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/github/adapter.js +2 -2
- package/esm/src/platform/adapters/fs/github/stat-operations.d.ts +2 -1
- package/esm/src/platform/adapters/fs/github/stat-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/github/stat-operations.js +2 -2
- package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts +2 -2
- package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/adapter.js +17 -2
- package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts +2 -2
- package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.js +2 -2
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts +1 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/stat-operations.d.ts +6 -2
- package/esm/src/platform/adapters/fs/veryfront/stat-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/stat-operations.js +131 -21
- package/esm/src/platform/adapters/fs/veryfront/types.d.ts +2 -1
- package/esm/src/platform/adapters/fs/veryfront/types.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/wrapper.d.ts +2 -2
- package/esm/src/platform/adapters/fs/wrapper.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/wrapper.js +2 -2
- package/esm/src/rendering/app-route-resolver.js +0 -9
- package/esm/src/rendering/orchestrator/file-resolver/index.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/file-resolver/index.js +17 -0
- package/esm/src/rendering/orchestrator/module-loader/index.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/module-loader/index.js +7 -20
- package/esm/src/rendering/page-resolution/page-resolver.d.ts.map +1 -1
- package/esm/src/rendering/page-resolution/page-resolver.js +19 -6
- package/esm/src/rendering/router-detection.d.ts +1 -0
- package/esm/src/rendering/router-detection.d.ts.map +1 -1
- package/esm/src/rendering/router-detection.js +3 -0
- package/esm/src/transforms/esm/bundle-manifest.d.ts +3 -1
- package/esm/src/transforms/esm/bundle-manifest.d.ts.map +1 -1
- package/esm/src/transforms/esm/bundle-manifest.js +2 -2
- package/esm/src/transforms/esm/cached-bundle-validation.d.ts +9 -0
- package/esm/src/transforms/esm/cached-bundle-validation.d.ts.map +1 -0
- package/esm/src/transforms/esm/cached-bundle-validation.js +25 -0
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.js +9 -21
- package/esm/src/transforms/pipeline/index.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/index.js +8 -24
- package/esm/src/types/entities/getEntityInfo.d.ts.map +1 -1
- package/esm/src/types/entities/getEntityInfo.js +59 -42
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/platform/adapters/base.ts +5 -1
- package/src/src/platform/adapters/fs/github/adapter.ts +3 -2
- package/src/src/platform/adapters/fs/github/stat-operations.ts +3 -2
- package/src/src/platform/adapters/fs/veryfront/adapter.ts +24 -3
- package/src/src/platform/adapters/fs/veryfront/multi-project-adapter.ts +6 -3
- package/src/src/platform/adapters/fs/veryfront/read-operations.ts +1 -0
- package/src/src/platform/adapters/fs/veryfront/stat-operations.ts +161 -25
- package/src/src/platform/adapters/fs/veryfront/types.ts +2 -1
- package/src/src/platform/adapters/fs/wrapper.ts +10 -3
- package/src/src/rendering/app-route-resolver.ts +0 -8
- package/src/src/rendering/orchestrator/file-resolver/index.ts +19 -0
- package/src/src/rendering/orchestrator/module-loader/index.ts +11 -19
- package/src/src/rendering/page-resolution/page-resolver.ts +26 -17
- package/src/src/rendering/router-detection.ts +7 -0
- package/src/src/transforms/esm/bundle-manifest.ts +6 -3
- package/src/src/transforms/esm/cached-bundle-validation.ts +40 -0
- package/src/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.ts +13 -24
- package/src/src/transforms/pipeline/index.ts +8 -26
- package/src/src/types/entities/getEntityInfo.ts +78 -59
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA2BzE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAkJpE,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,eAAe,UAAQ,GACtB,OAAO,CAAC,MAAM,CAAC,CA4RjB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAqClC"}
|
|
@@ -14,14 +14,12 @@ import { createFileSystem } from "../../../platform/compat/fs.js";
|
|
|
14
14
|
import { getProjectTmpDir } from "../../../modules/react-loader/index.js";
|
|
15
15
|
import { generateCacheKey as generateTransformCacheKey, getOrComputeTransform, initializeTransformCache, setCachedTransformAsync, } from "../../../transforms/esm/transform-cache.js";
|
|
16
16
|
import { TRANSFORM_DISTRIBUTED_TTL_SEC } from "../../../utils/constants/cache.js";
|
|
17
|
-
import {
|
|
18
|
-
import { validateBundleGroup } from "../../../transforms/esm/bundle-manifest.js";
|
|
17
|
+
import { validateCachedBundlesByManifestOrCode } from "../../../transforms/esm/cached-bundle-validation.js";
|
|
19
18
|
import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../utils/cache-dir.js";
|
|
20
19
|
import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
|
|
21
20
|
import { hashCodeHex } from "../../../utils/hash-utils.js";
|
|
22
21
|
import { VERSION } from "../../../utils/version.js";
|
|
23
22
|
import { getModulePathCache, lookupMdxEsmCache, saveModulePathCache, } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
|
|
24
|
-
import { extractHttpBundlePaths } from "../../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
|
|
25
23
|
const logger = rendererLogger.component("module-loader");
|
|
26
24
|
// Re-export utilities
|
|
27
25
|
export { createEsmCache, createModuleCache, generateHash } from "./cache.js";
|
|
@@ -243,30 +241,19 @@ export async function transformModuleWithDeps(filePath, tmpDir, localAdapter, co
|
|
|
243
241
|
let transformedCode = transformResult.code;
|
|
244
242
|
const cacheDir = getHttpBundleCacheDir();
|
|
245
243
|
let bundlesValid = true;
|
|
246
|
-
if (transformResult.cacheHit
|
|
247
|
-
const validation = await
|
|
244
|
+
if (transformResult.cacheHit) {
|
|
245
|
+
const validation = await validateCachedBundlesByManifestOrCode(transformedCode, transformResult.bundleManifestId, cacheDir);
|
|
248
246
|
if (!validation.valid) {
|
|
249
|
-
logger.warn("
|
|
247
|
+
logger.warn("Cached HTTP bundle validation failed, re-transforming", {
|
|
250
248
|
filePath,
|
|
251
|
-
manifestId: transformResult.bundleManifestId
|
|
249
|
+
manifestId: transformResult.bundleManifestId?.slice(0, 12),
|
|
252
250
|
failedHashes: validation.failedHashes,
|
|
251
|
+
reason: validation.reason,
|
|
252
|
+
source: validation.source,
|
|
253
253
|
});
|
|
254
254
|
bundlesValid = false;
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
|
-
else {
|
|
258
|
-
const bundlePaths = extractHttpBundlePaths(transformedCode);
|
|
259
|
-
if (bundlePaths.length > 0) {
|
|
260
|
-
const failed = await ensureHttpBundlesExist(bundlePaths, cacheDir);
|
|
261
|
-
if (failed.length > 0) {
|
|
262
|
-
logger.warn("HTTP bundle recovery failed, re-transforming", {
|
|
263
|
-
filePath,
|
|
264
|
-
failed,
|
|
265
|
-
});
|
|
266
|
-
bundlesValid = false;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
257
|
if (!bundlesValid) {
|
|
271
258
|
transformedCode = await transformToESM(fileContent, filePath, projectDir, adapter, {
|
|
272
259
|
projectId: effectiveProjectId,
|
|
@@ -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;
|
|
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;IAsDxC,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"}
|
|
@@ -4,7 +4,7 @@ import { VeryfrontError } from "../../errors/index.js";
|
|
|
4
4
|
import { FILE_NOT_FOUND } from "../../errors/error-registry.js";
|
|
5
5
|
import { withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
6
6
|
import { getEntityBySlug } from "../../types/entities/getEntityInfo.js";
|
|
7
|
-
import { detectAppRouter, getAppRouteEntity } from "../router-detection.js";
|
|
7
|
+
import { detectAppRouter, getAppRouteEntity, primeRouterDetectionCache, } from "../router-detection.js";
|
|
8
8
|
const PAGE_EXTENSIONS = /\.(mdx|md|tsx|jsx|ts|js)$/;
|
|
9
9
|
const APP_ROUTER_PAGE_PATTERN = /^page\.(mdx|md|tsx|jsx|ts|js)$/;
|
|
10
10
|
function isPageFile(name) {
|
|
@@ -40,20 +40,33 @@ export class PageResolver {
|
|
|
40
40
|
}
|
|
41
41
|
resolvePage(slug) {
|
|
42
42
|
return withSpan("routing.resolve_page", async () => {
|
|
43
|
-
const useAppRouter = await detectAppRouter(this.projectDir, this.config, this.adapter, { projectId: this.projectId });
|
|
44
43
|
const appDirName = this.config.directories?.app ?? "app";
|
|
44
|
+
const cacheKey = this.projectId ?? this.projectDir;
|
|
45
45
|
let pageInfo;
|
|
46
|
-
if (
|
|
46
|
+
if (this.config.router === "app") {
|
|
47
|
+
pageInfo = await getAppRouteEntity(this.projectDir, slug, this.adapter, appDirName);
|
|
48
|
+
if (pageInfo) {
|
|
49
|
+
primeRouterDetectionCache(cacheKey, "app");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (this.config.router === "pages") {
|
|
53
|
+
pageInfo = await getEntityBySlug(this.projectDir, slug, this.adapter);
|
|
54
|
+
if (pageInfo) {
|
|
55
|
+
primeRouterDetectionCache(cacheKey, "pages");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Auto mode stays structural: a single resolved route must not pin router mode
|
|
60
|
+
// for projects that are still transitioning between app/ and pages/.
|
|
47
61
|
pageInfo = await getAppRouteEntity(this.projectDir, slug, this.adapter, appDirName);
|
|
48
62
|
if (!pageInfo) {
|
|
49
|
-
|
|
63
|
+
pageInfo = await getEntityBySlug(this.projectDir, slug, this.adapter);
|
|
50
64
|
}
|
|
51
65
|
}
|
|
52
|
-
pageInfo ??= await getEntityBySlug(this.projectDir, slug, this.adapter);
|
|
53
66
|
if (!pageInfo) {
|
|
54
67
|
throw FILE_NOT_FOUND.create({
|
|
55
68
|
detail: `Page not found: ${slug}`,
|
|
56
|
-
context: { slug,
|
|
69
|
+
context: { slug, router: this.config.router ?? "auto" },
|
|
57
70
|
});
|
|
58
71
|
}
|
|
59
72
|
return pageInfo;
|
|
@@ -21,6 +21,7 @@ export declare function clearRouterDetectionCache(): void;
|
|
|
21
21
|
* @param projectId - The project ID used as cache key. Falls back to projectDir for local dev.
|
|
22
22
|
*/
|
|
23
23
|
export declare function clearRouterDetectionCacheForProject(projectId: string): void;
|
|
24
|
+
export declare function primeRouterDetectionCache(projectKey: string, mode: "app" | "pages"): void;
|
|
24
25
|
export interface DetectAppRouterOptions {
|
|
25
26
|
/** Project ID for cache isolation in multi-tenant deployments */
|
|
26
27
|
projectId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-detection.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/router-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;4BAO4B;AAK5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQ1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAY5D;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE3E;AAED,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,OAAO,CAAC,CA6BlB"}
|
|
1
|
+
{"version":3,"file":"router-detection.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/router-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;4BAO4B;AAK5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQ1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAY5D;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE3E;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,KAAK,GAAG,OAAO,GACpB,IAAI,CAEN;AAED,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,OAAO,CAAC,CA6BlB"}
|
|
@@ -38,6 +38,9 @@ export function clearRouterDetectionCache() {
|
|
|
38
38
|
export function clearRouterDetectionCacheForProject(projectId) {
|
|
39
39
|
routerDetectionCache.delete(projectId);
|
|
40
40
|
}
|
|
41
|
+
export function primeRouterDetectionCache(projectKey, mode) {
|
|
42
|
+
routerDetectionCache.set(projectKey, mode === "app");
|
|
43
|
+
}
|
|
41
44
|
/**
|
|
42
45
|
* Detect if app router should be used based on config and directory structure.
|
|
43
46
|
*
|
|
@@ -20,10 +20,12 @@ interface BundleManifest {
|
|
|
20
20
|
createdAt: number;
|
|
21
21
|
ttlSeconds: number;
|
|
22
22
|
}
|
|
23
|
+
export type ManifestValidationReason = "manifest_missing" | "bundle_missing";
|
|
23
24
|
/** Result of manifest validation. */
|
|
24
|
-
interface ManifestValidationResult {
|
|
25
|
+
export interface ManifestValidationResult {
|
|
25
26
|
valid: boolean;
|
|
26
27
|
failedHashes: string[];
|
|
28
|
+
reason?: ManifestValidationReason;
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
29
31
|
* Compute a deterministic manifest ID from bundle hashes.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle-manifest.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/bundle-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;4BAQ4B;AAiB5B,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oEAAoE;AACpE,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qCAAqC;AACrC,
|
|
1
|
+
{"version":3,"file":"bundle-manifest.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/bundle-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;4BAQ4B;AAiB5B,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oEAAoE;AACpE,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,wBAAwB,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;AAE7E,qCAAqC;AACrC,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC;AAgBD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAEzE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAc1F;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjF;AAuBD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,wBAAwB,CAAC,CA6CnC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAErE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB1E"}
|
|
@@ -106,7 +106,7 @@ export async function validateBundleGroup(manifestId, cacheDir) {
|
|
|
106
106
|
logger.debug(`${LOG_PREFIX} Manifest not found in distributed cache`, {
|
|
107
107
|
manifestId: manifestId.slice(0, 12),
|
|
108
108
|
});
|
|
109
|
-
return { valid: false, failedHashes: [] };
|
|
109
|
+
return { valid: false, failedHashes: [], reason: "manifest_missing" };
|
|
110
110
|
}
|
|
111
111
|
const missingBundles = [];
|
|
112
112
|
await Promise.all(manifest.bundles.map(async ({ hash }) => {
|
|
@@ -132,7 +132,7 @@ export async function validateBundleGroup(manifestId, cacheDir) {
|
|
|
132
132
|
manifestId: manifestId.slice(0, 12),
|
|
133
133
|
unrecoverable: unrecoverableHashes,
|
|
134
134
|
});
|
|
135
|
-
return { valid: false, failedHashes: unrecoverableHashes };
|
|
135
|
+
return { valid: false, failedHashes: unrecoverableHashes, reason: "bundle_missing" };
|
|
136
136
|
}
|
|
137
137
|
logger.info(`${LOG_PREFIX} All missing bundles recovered successfully`, {
|
|
138
138
|
manifestId: manifestId.slice(0, 12),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ManifestValidationReason } from "./bundle-manifest.js";
|
|
2
|
+
export interface CachedBundleValidationResult {
|
|
3
|
+
valid: boolean;
|
|
4
|
+
failedHashes: string[];
|
|
5
|
+
reason?: ManifestValidationReason;
|
|
6
|
+
source: "manifest" | "code";
|
|
7
|
+
}
|
|
8
|
+
export declare function validateCachedBundlesByManifestOrCode(code: string, bundleManifestId: string | undefined, cacheDir: string): Promise<CachedBundleValidationResult>;
|
|
9
|
+
//# sourceMappingURL=cached-bundle-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cached-bundle-validation.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/cached-bundle-validation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,wBAAwB,EAAuB,MAAM,sBAAsB,CAAC;AAE1F,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;CAC7B;AAED,wBAAsB,qCAAqC,CACzD,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,4BAA4B,CAAC,CAwBvC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { extractHttpBundlePaths } from "../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
|
|
2
|
+
import { ensureHttpBundlesExist } from "./http-cache.js";
|
|
3
|
+
import { validateBundleGroup } from "./bundle-manifest.js";
|
|
4
|
+
export async function validateCachedBundlesByManifestOrCode(code, bundleManifestId, cacheDir) {
|
|
5
|
+
if (bundleManifestId) {
|
|
6
|
+
const validation = await validateBundleGroup(bundleManifestId, cacheDir);
|
|
7
|
+
if (validation.valid || validation.reason === "bundle_missing") {
|
|
8
|
+
return { ...validation, source: "manifest" };
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const bundlePaths = extractHttpBundlePaths(code);
|
|
12
|
+
if (bundlePaths.length === 0) {
|
|
13
|
+
return { valid: true, failedHashes: [], source: "code" };
|
|
14
|
+
}
|
|
15
|
+
const failedHashes = await ensureHttpBundlesExist(bundlePaths, cacheDir);
|
|
16
|
+
if (failedHashes.length === 0) {
|
|
17
|
+
return { valid: true, failedHashes: [], source: "code" };
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
valid: false,
|
|
21
|
+
failedHashes,
|
|
22
|
+
reason: "bundle_missing",
|
|
23
|
+
source: "code",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distributed-cache.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"distributed-cache.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AASjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AAWjF,qDAAqD;AACrD,KAAK,gBAAgB,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,8BAA8B,CAAC,CAAC,CAAC,CAAC;AAEhG;;;;;GAKG;AACH,UAAU,0BAA0B;IAClC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4DAA4D;IAC5D,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAoG5C;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,GAAG,EAAE,MAAM,GACV,IAAI,CAqCN"}
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* @module transforms/mdx/esm-module-loader/module-fetcher/distributed-cache
|
|
8
8
|
*/
|
|
9
9
|
import { detokenizeAllCachePaths, tokenizeAllVeryFrontPaths } from "../../../../cache/index.js";
|
|
10
|
-
import { cacheHttpImportsToLocal
|
|
10
|
+
import { cacheHttpImportsToLocal } from "../../../esm/http-cache.js";
|
|
11
11
|
import { loadImportMap } from "../../../../modules/import-map/index.js";
|
|
12
12
|
import { extractHttpBundlePaths } from "../../../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
|
|
13
|
-
import { createBundleManifest, storeBundleManifest
|
|
13
|
+
import { createBundleManifest, storeBundleManifest } from "../../../esm/bundle-manifest.js";
|
|
14
|
+
import { validateCachedBundlesByManifestOrCode } from "../../../esm/cached-bundle-validation.js";
|
|
14
15
|
import { getHttpBundleCacheDir } from "../../../../utils/cache-dir.js";
|
|
15
16
|
import { FRAMEWORK_ROOT, LOG_PREFIX_MDX_LOADER } from "../constants.js";
|
|
16
17
|
import { getDistributedTransformBackend } from "../../../esm/transform-cache.js";
|
|
@@ -50,33 +51,20 @@ export async function readDistributedCache(transformCacheKey, normalizedPath, pr
|
|
|
50
51
|
});
|
|
51
52
|
const bundleManifestKey = `${transformCacheKey}:bm`;
|
|
52
53
|
const manifestId = await distributedCache.get(bundleManifestKey).catch(() => null);
|
|
53
|
-
if (
|
|
54
|
+
if (moduleCode) {
|
|
54
55
|
const cacheDir = getHttpBundleCacheDir();
|
|
55
|
-
const validation = await
|
|
56
|
+
const validation = await validateCachedBundlesByManifestOrCode(moduleCode, manifestId ?? undefined, cacheDir);
|
|
56
57
|
if (!validation.valid) {
|
|
57
|
-
log.warn(`${LOG_PREFIX_MDX_LOADER}
|
|
58
|
+
log.warn(`${LOG_PREFIX_MDX_LOADER} Cached HTTP bundle validation failed`, {
|
|
58
59
|
normalizedPath,
|
|
59
|
-
manifestId: manifestId
|
|
60
|
+
manifestId: manifestId?.slice(0, 12),
|
|
60
61
|
failedHashes: validation.failedHashes,
|
|
62
|
+
reason: validation.reason,
|
|
63
|
+
source: validation.source,
|
|
61
64
|
});
|
|
62
65
|
moduleCode = null;
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
|
-
else {
|
|
66
|
-
// Use detokenized code for bundle path extraction
|
|
67
|
-
const bundlePaths = extractHttpBundlePaths(moduleCode);
|
|
68
|
-
if (bundlePaths.length > 0) {
|
|
69
|
-
const cacheDir = getHttpBundleCacheDir();
|
|
70
|
-
const failed = await ensureHttpBundlesExist(bundlePaths, cacheDir);
|
|
71
|
-
if (failed.length > 0) {
|
|
72
|
-
log.warn(`${LOG_PREFIX_MDX_LOADER} Some HTTP bundles could not be recovered`, {
|
|
73
|
-
normalizedPath,
|
|
74
|
-
failed,
|
|
75
|
-
});
|
|
76
|
-
moduleCode = null;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
68
|
// Use detokenized code for framework path checks
|
|
81
69
|
if (moduleCode && await hasIncompatibleFrameworkPaths(moduleCode, log)) {
|
|
82
70
|
log.warn(`${LOG_PREFIX_MDX_LOADER} Cached code has incompatible framework paths`, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAEhB,eAAe,EAChB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAEhB,eAAe,EAChB,MAAM,YAAY,CAAC;AA0HpB,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAoI1B;AAoBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CASjB;AAmCD,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,SAAS,EACT,KAAK,EACL,KAAK,EACL,YAAY,GACb,MAAM,cAAc,CAAC"}
|
|
@@ -11,10 +11,8 @@ import { computeConfigHash } from "../../cache/config-hash.js";
|
|
|
11
11
|
import { computeDepsHash } from "../../cache/dependency-graph.js";
|
|
12
12
|
import { compilePlugin, cssStripPlugin, finalizePlugin, parsePlugin, resolveImportsPlugin, ssrHttpCachePlugin, ssrHttpStubPlugin, ssrVfModulesPlugin, } from "./stages/index.js";
|
|
13
13
|
import { createFileSystem, exists } from "../../platform/compat/fs.js";
|
|
14
|
-
import { ensureHttpBundlesExist } from "../esm/http-cache.js";
|
|
15
|
-
import { extractHttpBundlePaths } from "../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
|
|
16
14
|
import { getHttpBundleCacheDir } from "../../utils/cache-dir.js";
|
|
17
|
-
import {
|
|
15
|
+
import { validateCachedBundlesByManifestOrCode } from "../esm/cached-bundle-validation.js";
|
|
18
16
|
import { extractFrameworkBundlePaths } from "../shared/framework-bundle-paths.js";
|
|
19
17
|
const SSR_PIPELINE = [
|
|
20
18
|
parsePlugin,
|
|
@@ -96,29 +94,15 @@ async function validateFrameworkBundles(code, cacheKey) {
|
|
|
96
94
|
*/
|
|
97
95
|
async function validateCachedBundles(code, bundleManifestId, cacheKey) {
|
|
98
96
|
const cacheDir = getHttpBundleCacheDir();
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
const validation = await validateBundleGroup(bundleManifestId, cacheDir);
|
|
102
|
-
if (validation.valid)
|
|
103
|
-
return true;
|
|
104
|
-
logger.debug("Bundle manifest validation failed", {
|
|
105
|
-
cacheKey: cacheKey.slice(-40),
|
|
106
|
-
manifestId: bundleManifestId.slice(0, 12),
|
|
107
|
-
failedCount: validation.failedHashes.length,
|
|
108
|
-
});
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
// Fall back to extracting bundle paths from code and validating each
|
|
112
|
-
const bundlePaths = extractHttpBundlePaths(code);
|
|
113
|
-
if (bundlePaths.length === 0)
|
|
114
|
-
return true;
|
|
115
|
-
const failed = await ensureHttpBundlesExist(bundlePaths, cacheDir);
|
|
116
|
-
if (failed.length === 0)
|
|
97
|
+
const validation = await validateCachedBundlesByManifestOrCode(code, bundleManifestId, cacheDir);
|
|
98
|
+
if (validation.valid)
|
|
117
99
|
return true;
|
|
118
|
-
logger.debug("HTTP bundle validation failed", {
|
|
100
|
+
logger.debug("Cached HTTP bundle validation failed", {
|
|
119
101
|
cacheKey: cacheKey.slice(-40),
|
|
120
|
-
|
|
121
|
-
|
|
102
|
+
manifestId: bundleManifestId?.slice(0, 12),
|
|
103
|
+
failedCount: validation.failedHashes.length,
|
|
104
|
+
reason: validation.reason,
|
|
105
|
+
source: validation.source,
|
|
122
106
|
});
|
|
123
107
|
return false;
|
|
124
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getEntityInfo.d.ts","sourceRoot":"","sources":["../../../../src/src/types/entities/getEntityInfo.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAU,UAAU,EAAe,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAWtE,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"getEntityInfo.d.ts","sourceRoot":"","sources":["../../../../src/src/types/entities/getEntityInfo.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAU,UAAU,EAAe,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAWtE,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAmJ5B;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAwM5B;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAyE5B"}
|
|
@@ -29,37 +29,42 @@ export async function getEntityInfo(filePath, adapter) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
try {
|
|
32
|
+
const shouldReadDirectly = adapter
|
|
33
|
+
? isExtendedFSAdapter(adapter.fs) && adapter.fs.isVeryfrontAdapter()
|
|
34
|
+
: false;
|
|
35
|
+
let content;
|
|
32
36
|
if (adapter) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
if (!shouldReadDirectly) {
|
|
38
|
+
try {
|
|
39
|
+
const stat = await withFallback(() => adapter.fs.stat(normalizedPath), async () => {
|
|
40
|
+
const exists = await fs.exists(filePath);
|
|
41
|
+
if (!exists) {
|
|
42
|
+
throw toError(createError({
|
|
43
|
+
type: "file",
|
|
44
|
+
message: "File not found",
|
|
45
|
+
context: { path: filePath, operation: "read" },
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
return await fs.stat(filePath);
|
|
49
|
+
}, { operationName: "stat:getEntityInfo", logError: false });
|
|
50
|
+
if (!stat.isFile)
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
entityInfoScope.runSync(() => {
|
|
55
|
+
throw error;
|
|
56
|
+
}, { path: filePath, details: { reason: "stat-failed" } }, undefined);
|
|
46
57
|
return null;
|
|
58
|
+
}
|
|
47
59
|
}
|
|
48
|
-
|
|
49
|
-
entityInfoScope.runSync(() => {
|
|
50
|
-
throw error;
|
|
51
|
-
}, { path: filePath, details: { reason: "stat-failed" } }, undefined);
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
60
|
+
content = await withFallback(() => adapter.fs.readFile(normalizedPath), () => fs.readTextFile(filePath), { operationName: "readFile:getEntityInfo", logError: false });
|
|
54
61
|
}
|
|
55
62
|
else {
|
|
56
63
|
const exists = await fs.exists(filePath);
|
|
57
64
|
if (!exists)
|
|
58
65
|
return null;
|
|
66
|
+
content = await fs.readTextFile(filePath);
|
|
59
67
|
}
|
|
60
|
-
const content = adapter
|
|
61
|
-
? await withFallback(() => adapter.fs.readFile(normalizedPath), () => fs.readTextFile(filePath), { operationName: "readFile:getEntityInfo", logError: false })
|
|
62
|
-
: await fs.readTextFile(filePath);
|
|
63
68
|
const ext = pathHelper.extname(filePath).toLowerCase();
|
|
64
69
|
let frontmatter = {};
|
|
65
70
|
let body = content;
|
|
@@ -120,23 +125,27 @@ export async function getEntityInfo(filePath, adapter) {
|
|
|
120
125
|
}
|
|
121
126
|
export async function getEntityBySlug(projectDir, slug, adapter) {
|
|
122
127
|
return await withSpan("types.getEntityBySlug", async () => {
|
|
123
|
-
const
|
|
128
|
+
const normalizedSlug = normalizeSlug(slug);
|
|
129
|
+
const isVeryfrontRoute = normalizedSlug.startsWith(".veryfront/") ||
|
|
130
|
+
normalizedSlug === ".veryfront";
|
|
124
131
|
const resolveFile = adapter?.fs.resolveFile;
|
|
125
132
|
logger.debug("START", {
|
|
126
133
|
slug,
|
|
134
|
+
normalizedSlug,
|
|
127
135
|
projectDir,
|
|
128
136
|
isVeryfrontRoute,
|
|
129
137
|
hasResolveFile: !!resolveFile,
|
|
130
138
|
});
|
|
131
139
|
if (resolveFile) {
|
|
132
|
-
const basePaths = [pathHelper.join(projectDir, "pages",
|
|
140
|
+
const basePaths = [pathHelper.join(projectDir, "pages", normalizedSlug)];
|
|
133
141
|
if (isVeryfrontRoute)
|
|
134
|
-
basePaths.unshift(pathHelper.join(projectDir,
|
|
135
|
-
if (
|
|
142
|
+
basePaths.unshift(pathHelper.join(projectDir, normalizedSlug));
|
|
143
|
+
if (normalizedSlug === "index" || normalizedSlug === "") {
|
|
136
144
|
basePaths.unshift(pathHelper.join(projectDir, "pages", "index"));
|
|
137
145
|
}
|
|
138
146
|
logger.debug("Checking paths (resolveFile branch)", {
|
|
139
147
|
slug,
|
|
148
|
+
normalizedSlug,
|
|
140
149
|
basePaths,
|
|
141
150
|
});
|
|
142
151
|
const pathResults = await parallelMap(basePaths, async (basePath) => {
|
|
@@ -153,12 +162,13 @@ export async function getEntityBySlug(projectDir, slug, adapter) {
|
|
|
153
162
|
if (info?.entity.isPage) {
|
|
154
163
|
logger.debug("Found page via resolveFile", {
|
|
155
164
|
slug,
|
|
165
|
+
normalizedSlug,
|
|
156
166
|
path: info.entity.path,
|
|
157
167
|
});
|
|
158
168
|
return info;
|
|
159
169
|
}
|
|
160
170
|
}
|
|
161
|
-
const slugParts =
|
|
171
|
+
const slugParts = normalizedSlug === "" ? [] : normalizedSlug.split("/");
|
|
162
172
|
for (let depth = slugParts.length - 1; depth >= 0; depth--) {
|
|
163
173
|
const parentPath = slugParts.slice(0, depth).join("/");
|
|
164
174
|
const pagesDir = parentPath
|
|
@@ -194,25 +204,25 @@ export async function getEntityBySlug(projectDir, slug, adapter) {
|
|
|
194
204
|
/* expected: directory may not exist or readDir may fail */
|
|
195
205
|
}
|
|
196
206
|
}
|
|
197
|
-
logger.debug("No page found via resolveFile branch", { slug });
|
|
207
|
+
logger.debug("No page found via resolveFile branch", { slug, normalizedSlug });
|
|
198
208
|
return null;
|
|
199
209
|
}
|
|
200
210
|
const possiblePaths = [
|
|
201
|
-
pathHelper.join(projectDir, "pages", `${
|
|
202
|
-
pathHelper.join(projectDir, "pages", `${
|
|
203
|
-
pathHelper.join(projectDir, "pages", `${
|
|
204
|
-
pathHelper.join(projectDir, "pages", `${
|
|
205
|
-
pathHelper.join(projectDir, "pages", `${
|
|
206
|
-
pathHelper.join(projectDir, "pages", `${
|
|
207
|
-
pathHelper.join(projectDir, "pages", `${
|
|
208
|
-
pathHelper.join(projectDir, "pages", `${
|
|
209
|
-
pathHelper.join(projectDir, "pages", `${
|
|
210
|
-
pathHelper.join(projectDir, "pages", `${
|
|
211
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}.mdx`),
|
|
212
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}.md`),
|
|
213
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}.tsx`),
|
|
214
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}.jsx`),
|
|
215
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}.ts`),
|
|
216
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.mdx`),
|
|
217
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.md`),
|
|
218
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.tsx`),
|
|
219
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.jsx`),
|
|
220
|
+
pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.ts`),
|
|
211
221
|
];
|
|
212
222
|
if (isVeryfrontRoute) {
|
|
213
|
-
possiblePaths.unshift(pathHelper.join(projectDir, `${
|
|
223
|
+
possiblePaths.unshift(pathHelper.join(projectDir, `${normalizedSlug}.mdx`), pathHelper.join(projectDir, `${normalizedSlug}.md`), pathHelper.join(projectDir, `${normalizedSlug}.tsx`), pathHelper.join(projectDir, `${normalizedSlug}.ts`));
|
|
214
224
|
}
|
|
215
|
-
if (
|
|
225
|
+
if (normalizedSlug === "index" || normalizedSlug === "") {
|
|
216
226
|
possiblePaths.unshift(pathHelper.join(projectDir, "pages", "index.mdx"), pathHelper.join(projectDir, "pages", "index.md"), pathHelper.join(projectDir, "pages", "index.tsx"), pathHelper.join(projectDir, "pages", "index.ts"));
|
|
217
227
|
}
|
|
218
228
|
const pathResults = await parallelMap(possiblePaths, async (p) => {
|
|
@@ -222,7 +232,7 @@ export async function getEntityBySlug(projectDir, slug, adapter) {
|
|
|
222
232
|
if (info?.entity.isPage)
|
|
223
233
|
return info;
|
|
224
234
|
}
|
|
225
|
-
const slugParts =
|
|
235
|
+
const slugParts = normalizedSlug === "" ? [] : normalizedSlug.split("/");
|
|
226
236
|
for (let depth = slugParts.length - 1; depth >= 0; depth--) {
|
|
227
237
|
const parentPath = slugParts.slice(0, depth).join("/");
|
|
228
238
|
const pagesDir = parentPath
|
|
@@ -267,7 +277,11 @@ export async function getEntityBySlug(projectDir, slug, adapter) {
|
|
|
267
277
|
}
|
|
268
278
|
}
|
|
269
279
|
return null;
|
|
270
|
-
}, {
|
|
280
|
+
}, {
|
|
281
|
+
"entity.slug": slug,
|
|
282
|
+
"entity.normalized_slug": normalizeSlug(slug),
|
|
283
|
+
"entity.projectDir": projectDir,
|
|
284
|
+
});
|
|
271
285
|
}
|
|
272
286
|
export async function getLayoutEntity(projectDir, layoutName, adapter) {
|
|
273
287
|
return await withSpan("types.getLayoutEntity", async () => {
|
|
@@ -345,3 +359,6 @@ function getSlugFromPath(filePath) {
|
|
|
345
359
|
const parentDir = parts[parts.length - 2];
|
|
346
360
|
return parentDir === "pages" ? "" : parentDir ?? "";
|
|
347
361
|
}
|
|
362
|
+
function normalizeSlug(slug) {
|
|
363
|
+
return slug === "/" ? "" : slug.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
364
|
+
}
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -117,7 +117,11 @@ export interface FileSystemAdapter {
|
|
|
117
117
|
makeTempDir(prefix: string): Promise<string>;
|
|
118
118
|
watch(paths: string | string[], options?: WatchOptions): FileWatcher;
|
|
119
119
|
/** Resolve a file path with extension fallback (e.g., pages/test → pages/test.mdx) */
|
|
120
|
-
resolveFile?(basePath: string): Promise<string | null>;
|
|
120
|
+
resolveFile?(basePath: string, options?: ResolveFileOptions): Promise<string | null>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface ResolveFileOptions {
|
|
124
|
+
allowPagesPrefix?: boolean;
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
export interface DirEntry {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { logger } from "../../../../utils/index.js";
|
|
2
2
|
import { CONFIG_INVALID } from "../../../../errors/index.js";
|
|
3
3
|
import { getEnv } from "../../../compat/process.js";
|
|
4
|
+
import type { ResolveFileOptions } from "../../base.js";
|
|
4
5
|
import { FileCache } from "../cache/file-cache.js";
|
|
5
6
|
import type { FSAdapter, FSAdapterConfig } from "../veryfront/types.js";
|
|
6
7
|
import { GitHubApiClient } from "./github-api-client.js";
|
|
@@ -115,9 +116,9 @@ export class GitHubFSAdapter implements FSAdapter {
|
|
|
115
116
|
return this.dirOps.readdir(path);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
async resolveFile(basePath: string): Promise<string | null> {
|
|
119
|
+
async resolveFile(basePath: string, options?: ResolveFileOptions): Promise<string | null> {
|
|
119
120
|
await this.ensureInitialized();
|
|
120
|
-
return this.statOps.resolveFile(basePath);
|
|
121
|
+
return this.statOps.resolveFile(basePath, options);
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
getCacheStats(): {
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
buildGitHubStatCacheKey,
|
|
6
6
|
buildGitHubTreeCacheKey,
|
|
7
7
|
} from "../../../../cache/index.js";
|
|
8
|
+
import type { ResolveFileOptions } from "../../base.js";
|
|
8
9
|
import type { FileCache } from "../cache/file-cache.js";
|
|
9
10
|
import type { GitHubApiClient } from "./github-api-client.js";
|
|
10
11
|
import type { FileIndexEntry, FileInfo, GitHubTreeEntry, ResolvedGitHubConfig } from "./types.js";
|
|
@@ -176,7 +177,7 @@ export class GitHubStatOperations {
|
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
async resolveFile(basePath: string): Promise<string | null> {
|
|
180
|
+
async resolveFile(basePath: string, options?: ResolveFileOptions): Promise<string | null> {
|
|
180
181
|
await this.ensureIndex();
|
|
181
182
|
|
|
182
183
|
const normalizedPath = normalizeGitHubPath(basePath, this.projectDir);
|
|
@@ -185,7 +186,7 @@ export class GitHubStatOperations {
|
|
|
185
186
|
if (cached !== undefined) return cached;
|
|
186
187
|
|
|
187
188
|
const resolved = this.tryResolve(normalizedPath) ??
|
|
188
|
-
this.tryResolveWithPagesPrefix(normalizedPath);
|
|
189
|
+
(options?.allowPagesPrefix === false ? null : this.tryResolveWithPagesPrefix(normalizedPath));
|
|
189
190
|
|
|
190
191
|
this.cache.set(cacheKey, resolved);
|
|
191
192
|
return resolved;
|