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.
Files changed (68) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/platform/adapters/base.d.ts +4 -1
  3. package/esm/src/platform/adapters/base.d.ts.map +1 -1
  4. package/esm/src/platform/adapters/fs/github/adapter.d.ts +2 -1
  5. package/esm/src/platform/adapters/fs/github/adapter.d.ts.map +1 -1
  6. package/esm/src/platform/adapters/fs/github/adapter.js +2 -2
  7. package/esm/src/platform/adapters/fs/github/stat-operations.d.ts +2 -1
  8. package/esm/src/platform/adapters/fs/github/stat-operations.d.ts.map +1 -1
  9. package/esm/src/platform/adapters/fs/github/stat-operations.js +2 -2
  10. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts +2 -2
  11. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
  12. package/esm/src/platform/adapters/fs/veryfront/adapter.js +17 -2
  13. package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts +2 -2
  14. package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.d.ts.map +1 -1
  15. package/esm/src/platform/adapters/fs/veryfront/multi-project-adapter.js +2 -2
  16. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts +1 -0
  17. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
  18. package/esm/src/platform/adapters/fs/veryfront/stat-operations.d.ts +6 -2
  19. package/esm/src/platform/adapters/fs/veryfront/stat-operations.d.ts.map +1 -1
  20. package/esm/src/platform/adapters/fs/veryfront/stat-operations.js +131 -21
  21. package/esm/src/platform/adapters/fs/veryfront/types.d.ts +2 -1
  22. package/esm/src/platform/adapters/fs/veryfront/types.d.ts.map +1 -1
  23. package/esm/src/platform/adapters/fs/wrapper.d.ts +2 -2
  24. package/esm/src/platform/adapters/fs/wrapper.d.ts.map +1 -1
  25. package/esm/src/platform/adapters/fs/wrapper.js +2 -2
  26. package/esm/src/rendering/app-route-resolver.js +0 -9
  27. package/esm/src/rendering/orchestrator/file-resolver/index.d.ts.map +1 -1
  28. package/esm/src/rendering/orchestrator/file-resolver/index.js +17 -0
  29. package/esm/src/rendering/orchestrator/module-loader/index.d.ts.map +1 -1
  30. package/esm/src/rendering/orchestrator/module-loader/index.js +7 -20
  31. package/esm/src/rendering/page-resolution/page-resolver.d.ts.map +1 -1
  32. package/esm/src/rendering/page-resolution/page-resolver.js +19 -6
  33. package/esm/src/rendering/router-detection.d.ts +1 -0
  34. package/esm/src/rendering/router-detection.d.ts.map +1 -1
  35. package/esm/src/rendering/router-detection.js +3 -0
  36. package/esm/src/transforms/esm/bundle-manifest.d.ts +3 -1
  37. package/esm/src/transforms/esm/bundle-manifest.d.ts.map +1 -1
  38. package/esm/src/transforms/esm/bundle-manifest.js +2 -2
  39. package/esm/src/transforms/esm/cached-bundle-validation.d.ts +9 -0
  40. package/esm/src/transforms/esm/cached-bundle-validation.d.ts.map +1 -0
  41. package/esm/src/transforms/esm/cached-bundle-validation.js +25 -0
  42. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.d.ts.map +1 -1
  43. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.js +9 -21
  44. package/esm/src/transforms/pipeline/index.d.ts.map +1 -1
  45. package/esm/src/transforms/pipeline/index.js +8 -24
  46. package/esm/src/types/entities/getEntityInfo.d.ts.map +1 -1
  47. package/esm/src/types/entities/getEntityInfo.js +59 -42
  48. package/package.json +1 -1
  49. package/src/deno.js +1 -1
  50. package/src/src/platform/adapters/base.ts +5 -1
  51. package/src/src/platform/adapters/fs/github/adapter.ts +3 -2
  52. package/src/src/platform/adapters/fs/github/stat-operations.ts +3 -2
  53. package/src/src/platform/adapters/fs/veryfront/adapter.ts +24 -3
  54. package/src/src/platform/adapters/fs/veryfront/multi-project-adapter.ts +6 -3
  55. package/src/src/platform/adapters/fs/veryfront/read-operations.ts +1 -0
  56. package/src/src/platform/adapters/fs/veryfront/stat-operations.ts +161 -25
  57. package/src/src/platform/adapters/fs/veryfront/types.ts +2 -1
  58. package/src/src/platform/adapters/fs/wrapper.ts +10 -3
  59. package/src/src/rendering/app-route-resolver.ts +0 -8
  60. package/src/src/rendering/orchestrator/file-resolver/index.ts +19 -0
  61. package/src/src/rendering/orchestrator/module-loader/index.ts +11 -19
  62. package/src/src/rendering/page-resolution/page-resolver.ts +26 -17
  63. package/src/src/rendering/router-detection.ts +7 -0
  64. package/src/src/transforms/esm/bundle-manifest.ts +6 -3
  65. package/src/src/transforms/esm/cached-bundle-validation.ts +40 -0
  66. package/src/src/transforms/mdx/esm-module-loader/module-fetcher/distributed-cache.ts +13 -24
  67. package/src/src/transforms/pipeline/index.ts +8 -26
  68. package/src/src/types/entities/getEntityInfo.ts +78 -59
@@ -9,14 +9,11 @@
9
9
 
10
10
  import type { Logger } from "../../../../utils/logger/logger.js";
11
11
  import { detokenizeAllCachePaths, tokenizeAllVeryFrontPaths } from "../../../../cache/index.js";
12
- import { cacheHttpImportsToLocal, ensureHttpBundlesExist } from "../../../esm/http-cache.js";
12
+ import { cacheHttpImportsToLocal } from "../../../esm/http-cache.js";
13
13
  import { loadImportMap } from "../../../../modules/import-map/index.js";
14
14
  import { extractHttpBundlePaths } from "../../../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
15
- import {
16
- createBundleManifest,
17
- storeBundleManifest,
18
- validateBundleGroup,
19
- } from "../../../esm/bundle-manifest.js";
15
+ import { createBundleManifest, storeBundleManifest } from "../../../esm/bundle-manifest.js";
16
+ import { validateCachedBundlesByManifestOrCode } from "../../../esm/cached-bundle-validation.js";
20
17
  import { getHttpBundleCacheDir } from "../../../../utils/cache-dir.js";
21
18
  import { FRAMEWORK_ROOT, LOG_PREFIX_MDX_LOADER } from "../constants.js";
22
19
  import { getDistributedTransformBackend } from "../../../esm/transform-cache.js";
@@ -86,31 +83,23 @@ export async function readDistributedCache(
86
83
  const bundleManifestKey = `${transformCacheKey}:bm`;
87
84
  const manifestId = await distributedCache.get(bundleManifestKey).catch(() => null);
88
85
 
89
- if (manifestId) {
86
+ if (moduleCode) {
90
87
  const cacheDir = getHttpBundleCacheDir();
91
- const validation = await validateBundleGroup(manifestId, cacheDir);
88
+ const validation = await validateCachedBundlesByManifestOrCode(
89
+ moduleCode,
90
+ manifestId ?? undefined,
91
+ cacheDir,
92
+ );
92
93
  if (!validation.valid) {
93
- log.warn(`${LOG_PREFIX_MDX_LOADER} Bundle manifest validation failed`, {
94
+ log.warn(`${LOG_PREFIX_MDX_LOADER} Cached HTTP bundle validation failed`, {
94
95
  normalizedPath,
95
- manifestId: manifestId.slice(0, 12),
96
+ manifestId: manifestId?.slice(0, 12),
96
97
  failedHashes: validation.failedHashes,
98
+ reason: validation.reason,
99
+ source: validation.source,
97
100
  });
98
101
  moduleCode = null;
99
102
  }
100
- } else {
101
- // Use detokenized code for bundle path extraction
102
- const bundlePaths = extractHttpBundlePaths(moduleCode);
103
- if (bundlePaths.length > 0) {
104
- const cacheDir = getHttpBundleCacheDir();
105
- const failed = await ensureHttpBundlesExist(bundlePaths, cacheDir);
106
- if (failed.length > 0) {
107
- log.warn(`${LOG_PREFIX_MDX_LOADER} Some HTTP bundles could not be recovered`, {
108
- normalizedPath,
109
- failed,
110
- });
111
- moduleCode = null;
112
- }
113
- }
114
103
  }
115
104
 
116
105
  // Use detokenized code for framework path checks
@@ -31,10 +31,8 @@ import {
31
31
  ssrVfModulesPlugin,
32
32
  } from "./stages/index.js";
33
33
  import { createFileSystem, exists } from "../../platform/compat/fs.js";
34
- import { ensureHttpBundlesExist } from "../esm/http-cache.js";
35
- import { extractHttpBundlePaths } from "../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
36
34
  import { getHttpBundleCacheDir } from "../../utils/cache-dir.js";
37
- import { validateBundleGroup } from "../esm/bundle-manifest.js";
35
+ import { validateCachedBundlesByManifestOrCode } from "../esm/cached-bundle-validation.js";
38
36
  import { extractFrameworkBundlePaths } from "../shared/framework-bundle-paths.js";
39
37
 
40
38
  const SSR_PIPELINE: TransformPlugin[] = [
@@ -130,31 +128,15 @@ async function validateCachedBundles(
130
128
  cacheKey: string,
131
129
  ): Promise<boolean> {
132
130
  const cacheDir = getHttpBundleCacheDir();
131
+ const validation = await validateCachedBundlesByManifestOrCode(code, bundleManifestId, cacheDir);
132
+ if (validation.valid) return true;
133
133
 
134
- // If we have a manifest ID, use the faster manifest-based validation
135
- if (bundleManifestId) {
136
- const validation = await validateBundleGroup(bundleManifestId, cacheDir);
137
- if (validation.valid) return true;
138
-
139
- logger.debug("Bundle manifest validation failed", {
140
- cacheKey: cacheKey.slice(-40),
141
- manifestId: bundleManifestId.slice(0, 12),
142
- failedCount: validation.failedHashes.length,
143
- });
144
- return false;
145
- }
146
-
147
- // Fall back to extracting bundle paths from code and validating each
148
- const bundlePaths = extractHttpBundlePaths(code);
149
- if (bundlePaths.length === 0) return true;
150
-
151
- const failed = await ensureHttpBundlesExist(bundlePaths, cacheDir);
152
- if (failed.length === 0) return true;
153
-
154
- logger.debug("HTTP bundle validation failed", {
134
+ logger.debug("Cached HTTP bundle validation failed", {
155
135
  cacheKey: cacheKey.slice(-40),
156
- failedCount: failed.length,
157
- totalBundles: bundlePaths.length,
136
+ manifestId: bundleManifestId?.slice(0, 12),
137
+ failedCount: validation.failedHashes.length,
138
+ reason: validation.reason,
139
+ source: validation.source,
158
140
  });
159
141
  return false;
160
142
  }
@@ -43,49 +43,55 @@ export async function getEntityInfo(
43
43
  }
44
44
 
45
45
  try {
46
+ const shouldReadDirectly = adapter
47
+ ? isExtendedFSAdapter(adapter.fs) && adapter.fs.isVeryfrontAdapter()
48
+ : false;
49
+
50
+ let content: string;
46
51
  if (adapter) {
47
- try {
48
- const stat = await withFallback(
49
- () => adapter.fs.stat(normalizedPath),
50
- async () => {
51
- const exists = await fs.exists(filePath);
52
- if (!exists) {
53
- throw toError(
54
- createError({
55
- type: "file",
56
- message: "File not found",
57
- context: { path: filePath, operation: "read" },
58
- }),
59
- );
60
- }
61
- return await fs.stat(filePath);
62
- },
63
- { operationName: "stat:getEntityInfo", logError: false },
64
- );
52
+ if (!shouldReadDirectly) {
53
+ try {
54
+ const stat = await withFallback(
55
+ () => adapter.fs.stat(normalizedPath),
56
+ async () => {
57
+ const exists = await fs.exists(filePath);
58
+ if (!exists) {
59
+ throw toError(
60
+ createError({
61
+ type: "file",
62
+ message: "File not found",
63
+ context: { path: filePath, operation: "read" },
64
+ }),
65
+ );
66
+ }
67
+ return await fs.stat(filePath);
68
+ },
69
+ { operationName: "stat:getEntityInfo", logError: false },
70
+ );
65
71
 
66
- if (!stat.isFile) return null;
67
- } catch (error) {
68
- entityInfoScope.runSync(
69
- () => {
70
- throw error;
71
- },
72
- { path: filePath, details: { reason: "stat-failed" } },
73
- undefined,
74
- );
75
- return null;
72
+ if (!stat.isFile) return null;
73
+ } catch (error) {
74
+ entityInfoScope.runSync(
75
+ () => {
76
+ throw error;
77
+ },
78
+ { path: filePath, details: { reason: "stat-failed" } },
79
+ undefined,
80
+ );
81
+ return null;
82
+ }
76
83
  }
77
- } else {
78
- const exists = await fs.exists(filePath);
79
- if (!exists) return null;
80
- }
81
84
 
82
- const content = adapter
83
- ? await withFallback(
85
+ content = await withFallback(
84
86
  () => adapter.fs.readFile(normalizedPath),
85
87
  () => fs.readTextFile(filePath),
86
88
  { operationName: "readFile:getEntityInfo", logError: false },
87
- )
88
- : await fs.readTextFile(filePath);
89
+ );
90
+ } else {
91
+ const exists = await fs.exists(filePath);
92
+ if (!exists) return null;
93
+ content = await fs.readTextFile(filePath);
94
+ }
89
95
 
90
96
  const ext = pathHelper.extname(filePath).toLowerCase();
91
97
 
@@ -171,26 +177,30 @@ export async function getEntityBySlug(
171
177
  return await withSpan(
172
178
  "types.getEntityBySlug",
173
179
  async () => {
174
- const isVeryfrontRoute = slug.startsWith(".veryfront/") || slug === ".veryfront";
180
+ const normalizedSlug = normalizeSlug(slug);
181
+ const isVeryfrontRoute = normalizedSlug.startsWith(".veryfront/") ||
182
+ normalizedSlug === ".veryfront";
175
183
  const resolveFile = adapter?.fs.resolveFile;
176
184
 
177
185
  logger.debug("START", {
178
186
  slug,
187
+ normalizedSlug,
179
188
  projectDir,
180
189
  isVeryfrontRoute,
181
190
  hasResolveFile: !!resolveFile,
182
191
  });
183
192
 
184
193
  if (resolveFile) {
185
- const basePaths = [pathHelper.join(projectDir, "pages", slug)];
194
+ const basePaths = [pathHelper.join(projectDir, "pages", normalizedSlug)];
186
195
 
187
- if (isVeryfrontRoute) basePaths.unshift(pathHelper.join(projectDir, slug));
188
- if (slug === "index" || slug === "") {
196
+ if (isVeryfrontRoute) basePaths.unshift(pathHelper.join(projectDir, normalizedSlug));
197
+ if (normalizedSlug === "index" || normalizedSlug === "") {
189
198
  basePaths.unshift(pathHelper.join(projectDir, "pages", "index"));
190
199
  }
191
200
 
192
201
  logger.debug("Checking paths (resolveFile branch)", {
193
202
  slug,
203
+ normalizedSlug,
194
204
  basePaths,
195
205
  });
196
206
 
@@ -208,13 +218,14 @@ export async function getEntityBySlug(
208
218
  if (info?.entity.isPage) {
209
219
  logger.debug("Found page via resolveFile", {
210
220
  slug,
221
+ normalizedSlug,
211
222
  path: info.entity.path,
212
223
  });
213
224
  return info;
214
225
  }
215
226
  }
216
227
 
217
- const slugParts = slug.split("/");
228
+ const slugParts = normalizedSlug === "" ? [] : normalizedSlug.split("/");
218
229
  for (let depth = slugParts.length - 1; depth >= 0; depth--) {
219
230
  const parentPath = slugParts.slice(0, depth).join("/");
220
231
  const pagesDir = parentPath
@@ -259,33 +270,33 @@ export async function getEntityBySlug(
259
270
  }
260
271
  }
261
272
 
262
- logger.debug("No page found via resolveFile branch", { slug });
273
+ logger.debug("No page found via resolveFile branch", { slug, normalizedSlug });
263
274
  return null;
264
275
  }
265
276
 
266
277
  const possiblePaths = [
267
- pathHelper.join(projectDir, "pages", `${slug}.mdx`),
268
- pathHelper.join(projectDir, "pages", `${slug}.md`),
269
- pathHelper.join(projectDir, "pages", `${slug}.tsx`),
270
- pathHelper.join(projectDir, "pages", `${slug}.jsx`),
271
- pathHelper.join(projectDir, "pages", `${slug}.ts`),
272
- pathHelper.join(projectDir, "pages", `${slug}/index.mdx`),
273
- pathHelper.join(projectDir, "pages", `${slug}/index.md`),
274
- pathHelper.join(projectDir, "pages", `${slug}/index.tsx`),
275
- pathHelper.join(projectDir, "pages", `${slug}/index.jsx`),
276
- pathHelper.join(projectDir, "pages", `${slug}/index.ts`),
278
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}.mdx`),
279
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}.md`),
280
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}.tsx`),
281
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}.jsx`),
282
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}.ts`),
283
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.mdx`),
284
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.md`),
285
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.tsx`),
286
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.jsx`),
287
+ pathHelper.join(projectDir, "pages", `${normalizedSlug}/index.ts`),
277
288
  ];
278
289
 
279
290
  if (isVeryfrontRoute) {
280
291
  possiblePaths.unshift(
281
- pathHelper.join(projectDir, `${slug}.mdx`),
282
- pathHelper.join(projectDir, `${slug}.md`),
283
- pathHelper.join(projectDir, `${slug}.tsx`),
284
- pathHelper.join(projectDir, `${slug}.ts`),
292
+ pathHelper.join(projectDir, `${normalizedSlug}.mdx`),
293
+ pathHelper.join(projectDir, `${normalizedSlug}.md`),
294
+ pathHelper.join(projectDir, `${normalizedSlug}.tsx`),
295
+ pathHelper.join(projectDir, `${normalizedSlug}.ts`),
285
296
  );
286
297
  }
287
298
 
288
- if (slug === "index" || slug === "") {
299
+ if (normalizedSlug === "index" || normalizedSlug === "") {
289
300
  possiblePaths.unshift(
290
301
  pathHelper.join(projectDir, "pages", "index.mdx"),
291
302
  pathHelper.join(projectDir, "pages", "index.md"),
@@ -302,7 +313,7 @@ export async function getEntityBySlug(
302
313
  if (info?.entity.isPage) return info;
303
314
  }
304
315
 
305
- const slugParts = slug.split("/");
316
+ const slugParts = normalizedSlug === "" ? [] : normalizedSlug.split("/");
306
317
  for (let depth = slugParts.length - 1; depth >= 0; depth--) {
307
318
  const parentPath = slugParts.slice(0, depth).join("/");
308
319
  const pagesDir = parentPath
@@ -356,7 +367,11 @@ export async function getEntityBySlug(
356
367
 
357
368
  return null;
358
369
  },
359
- { "entity.slug": slug, "entity.projectDir": projectDir },
370
+ {
371
+ "entity.slug": slug,
372
+ "entity.normalized_slug": normalizeSlug(slug),
373
+ "entity.projectDir": projectDir,
374
+ },
360
375
  );
361
376
  }
362
377
 
@@ -448,3 +463,7 @@ function getSlugFromPath(filePath: string): string {
448
463
  const parentDir = parts[parts.length - 2];
449
464
  return parentDir === "pages" ? "" : parentDir ?? "";
450
465
  }
466
+
467
+ function normalizeSlug(slug: string): string {
468
+ return slug === "/" ? "" : slug.replace(/^\/+/, "").replace(/\/+$/, "");
469
+ }