veryfront 0.1.88 → 0.1.89

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 (34) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/rendering/orchestrator/module-loader/index.js +2 -2
  3. package/esm/src/transforms/mdx/esm-module-loader/cache/index.d.ts.map +1 -1
  4. package/esm/src/transforms/mdx/esm-module-loader/cache/index.js +6 -7
  5. package/esm/src/transforms/mdx/esm-module-loader/cache-format.d.ts +10 -0
  6. package/esm/src/transforms/mdx/esm-module-loader/cache-format.d.ts.map +1 -0
  7. package/esm/src/transforms/mdx/esm-module-loader/cache-format.js +61 -0
  8. package/esm/src/transforms/mdx/esm-module-loader/import-transformer.d.ts.map +1 -1
  9. package/esm/src/transforms/mdx/esm-module-loader/import-transformer.js +2 -3
  10. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/cache-keys.js +3 -3
  11. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/framework-validator.d.ts.map +1 -1
  12. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/framework-validator.js +2 -1
  13. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/module-cache.d.ts.map +1 -1
  14. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/module-cache.js +5 -5
  15. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts +2 -2
  16. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts.map +1 -1
  17. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.js +4 -4
  18. package/esm/src/utils/cache-namespace.d.ts +11 -0
  19. package/esm/src/utils/cache-namespace.d.ts.map +1 -0
  20. package/esm/src/utils/cache-namespace.js +24 -0
  21. package/esm/src/utils/version.d.ts +1 -1
  22. package/esm/src/utils/version.js +1 -1
  23. package/package.json +1 -1
  24. package/src/deno.js +1 -1
  25. package/src/src/rendering/orchestrator/module-loader/index.ts +2 -2
  26. package/src/src/transforms/mdx/esm-module-loader/cache/index.ts +6 -8
  27. package/src/src/transforms/mdx/esm-module-loader/cache-format.ts +121 -0
  28. package/src/src/transforms/mdx/esm-module-loader/import-transformer.ts +2 -3
  29. package/src/src/transforms/mdx/esm-module-loader/module-fetcher/cache-keys.ts +3 -3
  30. package/src/src/transforms/mdx/esm-module-loader/module-fetcher/framework-validator.ts +2 -1
  31. package/src/src/transforms/mdx/esm-module-loader/module-fetcher/module-cache.ts +5 -5
  32. package/src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts +4 -4
  33. package/src/src/utils/cache-namespace.ts +42 -0
  34. package/src/src/utils/version.ts +1 -1
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.88",
3
+ "version": "0.1.89",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -18,8 +18,8 @@ import { validateCachedBundlesByManifestOrCode } from "../../../transforms/esm/c
18
18
  import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../utils/cache-dir.js";
19
19
  import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
20
20
  import { hashCodeHex } from "../../../utils/hash-utils.js";
21
- import { VERSION } from "../../../utils/version.js";
22
21
  import { getModulePathCache, lookupMdxEsmCache, saveModulePathCache, } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
22
+ import { buildMdxEsmPathCacheKey } from "../../../transforms/mdx/esm-module-loader/cache-format.js";
23
23
  const logger = rendererLogger.component("module-loader");
24
24
  // Re-export utilities
25
25
  export { createEsmCache, createModuleCache, generateHash } from "./cache.js";
@@ -327,7 +327,7 @@ export async function transformModuleWithDeps(filePath, tmpDir, localAdapter, co
327
327
  }
328
328
  if (contentSourceId) {
329
329
  const normalizedPath = `_vf_modules/${relativePath.replace(/\.(tsx?|jsx|mdx)$/, ".js")}`;
330
- const mdxCacheKey = `v${VERSION}:${normalizedPath}`;
330
+ const mdxCacheKey = buildMdxEsmPathCacheKey(normalizedPath);
331
331
  const cache = await getModulePathCache(tmpDir);
332
332
  cache.set(mdxCacheKey, tempFilePath);
333
333
  saveModulePathCache(tmpDir).catch((err) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAI9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;AA4GH,wBAAgB,UAAU,IAAI,UAAU,CAGvC;AAKD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBvF;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAezE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAQD,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CA0ElE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAevD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAeD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAyG5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAG5D,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAI9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;AA0GH,wBAAgB,UAAU,IAAI,UAAU,CAGvC;AAKD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBvF;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAezE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAQD,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CA0ElE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAevD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAeD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAyG5B"}
@@ -9,14 +9,13 @@ import { join } from "../../../../platform/compat/path/index.js";
9
9
  import { rendererLogger as logger } from "../../../../utils/index.js";
10
10
  import { getCacheBaseDir, getHttpBundleCacheDir, getMdxEsmCacheDir, } from "../../../../utils/cache-dir.js";
11
11
  import { createFileSystem, isNotFoundError, } from "../../../../platform/compat/fs.js";
12
- import { VERSION } from "../../../../utils/version.js";
13
12
  import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
14
13
  import { LRUCache } from "../../../../utils/lru-wrapper.js";
14
+ import { buildMdxEsmPathCacheKey, MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE } from "../cache-format.js";
15
15
  const MAX_VERIFIED_MODULE_DEPS = 2_000;
16
16
  export const verifiedModuleDeps = new LRUCache({
17
17
  maxEntries: MAX_VERIFIED_MODULE_DEPS,
18
18
  });
19
- const FILE_PATH_PATTERN = /file:\/\/([^"'\s]+)/gi;
20
19
  /**
21
20
  * Check if cached code has file:// paths from a different environment.
22
21
  * Checks both HTTP bundle paths and MDX ESM cache paths.
@@ -25,7 +24,7 @@ function hasIncompatibleCachePaths(code) {
25
24
  const localCacheBaseDir = getCacheBaseDir();
26
25
  const localHttpCacheDir = getHttpBundleCacheDir();
27
26
  const localMdxCacheDir = getMdxEsmCacheDir();
28
- const pattern = new RegExp(FILE_PATH_PATTERN.source, "gi");
27
+ const pattern = new RegExp(MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE, "gi");
29
28
  let match;
30
29
  while ((match = pattern.exec(code)) !== null) {
31
30
  const path = match[1];
@@ -64,7 +63,7 @@ function hasIncompatibleCachePaths(code) {
64
63
  */
65
64
  async function findMissingFileDependencies(code) {
66
65
  const localFs = getLocalFs();
67
- const pattern = new RegExp(FILE_PATH_PATTERN.source, "gi");
66
+ const pattern = new RegExp(MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE, "gi");
68
67
  const missing = [];
69
68
  let match;
70
69
  while ((match = pattern.exec(code)) !== null) {
@@ -284,7 +283,7 @@ function toMdxEsmCacheKey(filePath, projectDir) {
284
283
  }
285
284
  relativePath = relativePath.replace(/^\/+/, "");
286
285
  const jsPath = relativePath.replace(/\.(tsx?|jsx|mdx)$/, ".js");
287
- return `v${VERSION}:_vf_modules/${jsPath}`;
286
+ return buildMdxEsmPathCacheKey(`_vf_modules/${jsPath}`);
288
287
  }
289
288
  export async function lookupMdxEsmCache(filePath, cacheDir, projectDir, _contentHash) {
290
289
  const cache = await getModulePathCache(cacheDir);
@@ -356,9 +355,9 @@ export async function lookupMdxEsmCache(filePath, cacheDir, projectDir, _content
356
355
  };
357
356
  }
358
357
  // Note: We intentionally skip contentHash validation for MDX-ESM cached files.
359
- // The MDX-ESM cache uses transformed-code hashes in filenames (vfmod-v{VERSION}-{hash}.mjs),
358
+ // The MDX-ESM cache uses transformed-code hashes in namespaced filenames,
360
359
  // while the SSR loader provides source-code hashes. These will never match.
361
- // The cache version in the key (v{VERSION}:) provides sufficient staleness protection,
360
+ // The cache namespace in the key provides sufficient staleness protection,
362
361
  // and the file's existence confirms it's a valid transform for this codebase.
363
362
  // This allows both loaders to share the same module instance, preventing
364
363
  // duplicate React contexts which break hooks like useContext.
@@ -0,0 +1,10 @@
1
+ export declare const MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE: string;
2
+ export declare const MDX_ESM_MJS_FILE_URL_PATTERN_SOURCE: string;
3
+ export declare const MDX_ESM_CACHE_NAMESPACE: string;
4
+ export declare const FRAMEWORK_VF_MODULE_CACHE_NAMESPACE: string;
5
+ export declare function buildMdxEsmTransformCacheKey(projectId: string, normalizedPath: string, contentHash: string): string;
6
+ export declare function buildMdxEsmPathCacheKey(normalizedPath: string): string;
7
+ export declare function buildMdxEsmModuleFileName(contentHash: string): string;
8
+ export declare function buildMdxJsxCacheFileName(filePath: string): string;
9
+ export declare function buildFrameworkVfModuleCacheFileName(pathHash: string, envKey: string, contentHash: string): string;
10
+ //# sourceMappingURL=cache-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-format.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/cache-format.ts"],"names":[],"mappings":"AAuEA,eAAO,MAAM,mCAAmC,QAA8B,CAAC;AAC/E,eAAO,MAAM,mCAAmC,QAA8B,CAAC;AAE/E,eAAO,MAAM,uBAAuB,QAGnC,CAAC;AAEF,eAAO,MAAM,mCAAmC,QAG/C,CAAC;AAEF,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,MAAM,CAOR;AAED,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,MAAM,CAOR"}
@@ -0,0 +1,61 @@
1
+ import { hashCodeHex } from "../../../utils/hash-utils.js";
2
+ import { createCacheNamespace } from "../../../utils/cache-namespace.js";
3
+ import { UNRESOLVED_VF_MODULES_PATTERN } from "./constants.js";
4
+ import { hashString } from "./utils/hash.js";
5
+ const ALL_FILE_URL_PATTERN_SOURCE = /file:\/\/([^"'\s]+)/.source;
6
+ const MJS_FILE_URL_PATTERN_SOURCE = /file:\/\/([^"'\s]+\.mjs)/.source;
7
+ const CACHE_NAMESPACE_SENTINEL = "__vf_cache_namespace__";
8
+ function formatMdxEsmTransformCacheKey(namespace, projectId, normalizedPath, contentHash) {
9
+ return `${namespace}:${projectId}:${normalizedPath}:${contentHash}:ssr`;
10
+ }
11
+ function formatMdxEsmPathCacheKey(namespace, normalizedPath) {
12
+ return `${namespace}:${normalizedPath}`;
13
+ }
14
+ function formatMdxEsmModuleFileName(namespace, contentHash) {
15
+ return `vfmod-${namespace}-${contentHash}.mjs`;
16
+ }
17
+ function formatMdxJsxCacheFileName(namespace, filePath) {
18
+ return `jsx-${namespace}-${hashString(filePath)}.mjs`;
19
+ }
20
+ function formatFrameworkVfModuleCacheFileName(namespace, pathHash, envKey, contentHash) {
21
+ return `vfmod-${namespace}-${pathHash}-${envKey}-${contentHash}.mjs`;
22
+ }
23
+ function buildMdxEsmCacheSchemaSample() {
24
+ return {
25
+ transformKey: formatMdxEsmTransformCacheKey(CACHE_NAMESPACE_SENTINEL, "__vf_project__", "_vf_modules/pages/index.js", "deadbeef"),
26
+ pathKey: formatMdxEsmPathCacheKey(CACHE_NAMESPACE_SENTINEL, "_vf_modules/pages/index.js"),
27
+ moduleFile: formatMdxEsmModuleFileName(CACHE_NAMESPACE_SENTINEL, "deadbeef"),
28
+ jsxFile: formatMdxJsxCacheFileName(CACHE_NAMESPACE_SENTINEL, "/tmp/project/Button.tsx"),
29
+ unresolvedVfModulesPattern: UNRESOLVED_VF_MODULES_PATTERN.source,
30
+ allFileUrlPattern: ALL_FILE_URL_PATTERN_SOURCE,
31
+ mjsFileUrlPattern: MJS_FILE_URL_PATTERN_SOURCE,
32
+ sourceHashing: [
33
+ hashString("_vf_modules/pages/index.jsexport default 1;"),
34
+ hashString("/tmp/project/Button.tsx"),
35
+ ],
36
+ };
37
+ }
38
+ function buildFrameworkVfModuleCacheSchemaSample() {
39
+ return {
40
+ moduleFile: formatFrameworkVfModuleCacheFileName(CACHE_NAMESPACE_SENTINEL, hashCodeHex("_vf_modules/_veryfront/react/components/Head.js"), hashCodeHex("/app/.cache/veryfront-mdx-esm").slice(0, 8), hashCodeHex("export default function Head() {}")),
41
+ };
42
+ }
43
+ export const MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE = ALL_FILE_URL_PATTERN_SOURCE;
44
+ export const MDX_ESM_MJS_FILE_URL_PATTERN_SOURCE = MJS_FILE_URL_PATTERN_SOURCE;
45
+ export const MDX_ESM_CACHE_NAMESPACE = createCacheNamespace("mdx-esm", buildMdxEsmCacheSchemaSample());
46
+ export const FRAMEWORK_VF_MODULE_CACHE_NAMESPACE = createCacheNamespace("vf-framework", buildFrameworkVfModuleCacheSchemaSample());
47
+ export function buildMdxEsmTransformCacheKey(projectId, normalizedPath, contentHash) {
48
+ return formatMdxEsmTransformCacheKey(MDX_ESM_CACHE_NAMESPACE, projectId, normalizedPath, contentHash);
49
+ }
50
+ export function buildMdxEsmPathCacheKey(normalizedPath) {
51
+ return formatMdxEsmPathCacheKey(MDX_ESM_CACHE_NAMESPACE, normalizedPath);
52
+ }
53
+ export function buildMdxEsmModuleFileName(contentHash) {
54
+ return formatMdxEsmModuleFileName(MDX_ESM_CACHE_NAMESPACE, contentHash);
55
+ }
56
+ export function buildMdxJsxCacheFileName(filePath) {
57
+ return formatMdxJsxCacheFileName(MDX_ESM_CACHE_NAMESPACE, filePath);
58
+ }
59
+ export function buildFrameworkVfModuleCacheFileName(pathHash, envKey, contentHash) {
60
+ return formatFrameworkVfModuleCacheFileName(FRAMEWORK_VF_MODULE_CACHE_NAMESPACE, pathHash, envKey, contentHash);
61
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"import-transformer.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/import-transformer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAgB5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9E;AAyBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAIjF;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,EACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CA0HjB"}
1
+ {"version":3,"file":"import-transformer.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/import-transformer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAe5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/D;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9E;AAyBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAIjF;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,EACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CA0HjB"}
@@ -9,12 +9,11 @@
9
9
  import { join } from "../../../platform/compat/path/index.js";
10
10
  import { rendererLogger as logger } from "../../../utils/index.js";
11
11
  import { transformImportsWithMap } from "../../../modules/import-map/index.js";
12
- import { VERSION } from "../../../utils/version.js";
13
12
  import { replaceSpecifiers } from "../../esm/lexer.js";
14
13
  import { getLocalReactPaths, isReactSpecifier } from "../../../platform/compat/react-paths.js";
15
14
  import { ESBUILD_JSX_FACTORY, ESBUILD_JSX_FRAGMENT, FRAMEWORK_ROOT, JSX_IMPORT_PATTERN, LOG_PREFIX_MDX_LOADER, REACT_IMPORT_PATTERN, } from "./constants.js";
16
15
  import { getLocalFs } from "./cache/index.js";
17
- import { hashString } from "./utils/hash.js";
16
+ import { buildMdxJsxCacheFileName } from "./cache-format.js";
18
17
  import { rewriteDntImports } from "./module-fetcher/index.js";
19
18
  import { ensureCachedJsxModulePatched } from "./jsx-cache.js";
20
19
  /**
@@ -93,7 +92,7 @@ export async function transformJsxImports(code, adapter, esmCacheDir) {
93
92
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Transforming ${importsToProcess.length} JSX imports in parallel`);
94
93
  const transformResults = await Promise.all(importsToProcess.map(async ({ fullMatch, importClause, filePath, ext }) => {
95
94
  try {
96
- const transformedFileName = `jsx-v${VERSION}-${hashString(filePath)}.mjs`;
95
+ const transformedFileName = buildMdxJsxCacheFileName(filePath);
97
96
  const transformedPath = join(esmCacheDir, transformedFileName);
98
97
  try {
99
98
  const stat = await getLocalFs().stat(transformedPath);
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @module transforms/mdx/esm-module-loader/module-fetcher/cache-keys
5
5
  */
6
- import { VERSION } from "../../../../utils/version.js";
6
+ import { buildMdxEsmPathCacheKey, buildMdxEsmTransformCacheKey } from "../cache-format.js";
7
7
  /**
8
8
  * Build cache key for transformed module.
9
9
  * Includes content hash so cache invalidates when source changes.
@@ -12,8 +12,8 @@ import { VERSION } from "../../../../utils/version.js";
12
12
  * that use relative paths (../lib/utils.js) instead of absolute paths (/_vf_modules/lib/utils.js).
13
13
  */
14
14
  export function getTransformCacheKey(projectId, normalizedPath, contentHash) {
15
- return `v${VERSION}:${projectId}:${normalizedPath}:${contentHash}:ssr`;
15
+ return buildMdxEsmTransformCacheKey(projectId, normalizedPath, contentHash);
16
16
  }
17
17
  export function getVersionedPathCacheKey(normalizedPath) {
18
- return `v${VERSION}:${normalizedPath}`;
18
+ return buildMdxEsmPathCacheKey(normalizedPath);
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"framework-validator.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/framework-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAOjE;;;;;;;;;;;;GAYG;AACH,wBAAsB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqE/F;AAED;;;;;;GAMG;AACH,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BnB;AAYD,wBAAsB,oBAAoB,CACxC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAkDlB"}
1
+ {"version":3,"file":"framework-validator.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/framework-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAQjE;;;;;;;;;;;;GAYG;AACH,wBAAsB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqE/F;AAED;;;;;;GAMG;AACH,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BnB;AAYD,wBAAsB,oBAAoB,CACxC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAkDlB"}
@@ -11,6 +11,7 @@ import { FRAMEWORK_ROOT, LOG_PREFIX_MDX_LOADER } from "../constants.js";
11
11
  import { getLocalFs } from "../cache/index.js";
12
12
  import { extractHttpBundlePaths } from "../../../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
13
13
  import { ensureHttpBundlesExist } from "../../../esm/http-cache.js";
14
+ import { MDX_ESM_MJS_FILE_URL_PATTERN_SOURCE } from "../cache-format.js";
14
15
  /**
15
16
  * Check if cached code has file:// paths that are incompatible with this environment.
16
17
  * Returns true if the cached code should be invalidated (has paths from a different environment).
@@ -97,7 +98,7 @@ export async function hasIncompatibleFrameworkPaths(code, log) {
97
98
  */
98
99
  export async function findMissingFileDependenciesInCode(code, log) {
99
100
  const localFs = getLocalFs();
100
- const pattern = /file:\/\/([^"'\s]+\.mjs)/gi;
101
+ const pattern = new RegExp(MDX_ESM_MJS_FILE_URL_PATTERN_SOURCE, "gi");
101
102
  const missing = [];
102
103
  const checked = new Set();
103
104
  let match;
@@ -1 +1 @@
1
- {"version":3,"file":"module-cache.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/module-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AASjE;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAanF;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkCxB"}
1
+ {"version":3,"file":"module-cache.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/module-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAQjE;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAanF;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmCxB"}
@@ -8,11 +8,10 @@
8
8
  */
9
9
  import { join } from "../../../../platform/compat/path/index.js";
10
10
  import * as posix from "../../../../../deps/jsr.io/@std/path/1.1.4/posix/mod.js";
11
- import { VERSION } from "../../../../utils/version.js";
12
11
  import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
13
12
  import { getLocalFs, saveModulePathCache } from "../cache/index.js";
14
13
  import { hashString } from "../utils/hash.js";
15
- import { getVersionedPathCacheKey } from "./cache-keys.js";
14
+ import { buildMdxEsmModuleFileName, buildMdxEsmPathCacheKey } from "../cache-format.js";
16
15
  import { hasUnresolvedImports } from "./nested-imports.js";
17
16
  import { recordModuleToSession } from "./render-sessions.js";
18
17
  /**
@@ -46,12 +45,13 @@ export async function cacheModule(normalizedPath, moduleCode, esmCacheDir, pathC
46
45
  return null;
47
46
  }
48
47
  const contentHash = hashString(normalizedPath + moduleCode);
49
- const cachePath = join(esmCacheDir, `vfmod-v${VERSION}-${contentHash}.mjs`);
48
+ const cachePath = join(esmCacheDir, buildMdxEsmModuleFileName(contentHash));
49
+ const pathCacheKey = buildMdxEsmPathCacheKey(normalizedPath);
50
50
  const localFs = getLocalFs();
51
51
  try {
52
52
  const stat = await localFs.stat(cachePath);
53
53
  if (stat?.isFile) {
54
- pathCache.set(getVersionedPathCacheKey(normalizedPath), cachePath);
54
+ pathCache.set(pathCacheKey, cachePath);
55
55
  log.debug(`${LOG_PREFIX_MDX_LOADER} Content cache hit: ${normalizedPath}`);
56
56
  recordModuleToSession(normalizedPath);
57
57
  return cachePath;
@@ -62,7 +62,7 @@ export async function cacheModule(normalizedPath, moduleCode, esmCacheDir, pathC
62
62
  }
63
63
  await localFs.mkdir(esmCacheDir, { recursive: true });
64
64
  await localFs.writeTextFile(cachePath, moduleCode);
65
- pathCache.set(getVersionedPathCacheKey(normalizedPath), cachePath);
65
+ pathCache.set(pathCacheKey, cachePath);
66
66
  await saveModulePathCache(esmCacheDir);
67
67
  log.debug(`${LOG_PREFIX_MDX_LOADER} Cached vf_module: ${normalizedPath} -> ${cachePath}`);
68
68
  recordModuleToSession(normalizedPath);
@@ -16,10 +16,10 @@ export declare function isCyclePlaceholder(code: string): boolean;
16
16
  /**
17
17
  * Cache transformed framework code and return the file:// path.
18
18
  *
19
- * Cache key format: vfmod-{VERSION}-{pathHash}-{envKey}-{contentHash}.mjs
19
+ * Cache key format: vfmod-{namespace}-{pathHash}-{envKey}-{contentHash}.mjs
20
20
  *
21
21
  * Cache invalidation is handled by:
22
- * - VERSION prefix: Auto-invalidates on framework releases
22
+ * - namespace prefix: Auto-rolls when the framework vfmod cache shape changes
23
23
  * - envKey (FRAMEWORK_ROOT hash): Prevents cross-environment contamination
24
24
  * (compiled binary vs source have different FRAMEWORK_ROOT values)
25
25
  * - contentHash: Content-based invalidation
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAcrE,OAAO,EAOL,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AAIxB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,gBAAgB,EACrB,oBAAoB,UAAQ,EAC5B,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC,CAyQjB;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,CACtD,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4CxB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CAEjB"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAarE,OAAO,EAOL,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AAKxB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,gBAAgB,EACrB,oBAAoB,UAAQ,EAC5B,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC,CAyQjB;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,CACtD,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4CxB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CAEjB"}
@@ -13,11 +13,11 @@ import { hashCodeHex } from "../../../../utils/hash-utils.js";
13
13
  import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../../utils/cache-dir.js";
14
14
  import { cacheHttpImportsToLocal } from "../../../esm/http-cache.js";
15
15
  import { loadImportMap } from "../../../../modules/import-map/index.js";
16
- import { VERSION } from "../../../../utils/version.js";
17
16
  import { buildReactUrl, getReactImportMap } from "../../../import-rewriter/url-builder.js";
18
17
  import { findRelativeImports } from "./import-finder.js";
19
18
  import { resolveRelativeFrameworkImport, resolveVeryfrontSourcePath } from "./path-resolver.js";
20
19
  import { EMBEDDED_SRC_DIR, FRAMEWORK_ROOT, frameworkFileCache, frameworkWriteFlight, LOG_PREFIX, MAX_RELATIVE_IMPORT_DEPTH, transformingFiles, veryfrontTransformCache, } from "./constants.js";
20
+ import { buildFrameworkVfModuleCacheFileName } from "../../../mdx/esm-module-loader/cache-format.js";
21
21
  const DENO_CONFIG_STUB_CODE = `export default ${JSON.stringify(denoConfig)};`;
22
22
  /**
23
23
  * Check if a transformed code string is a cycle placeholder.
@@ -31,10 +31,10 @@ export function isCyclePlaceholder(code) {
31
31
  /**
32
32
  * Cache transformed framework code and return the file:// path.
33
33
  *
34
- * Cache key format: vfmod-{VERSION}-{pathHash}-{envKey}-{contentHash}.mjs
34
+ * Cache key format: vfmod-{namespace}-{pathHash}-{envKey}-{contentHash}.mjs
35
35
  *
36
36
  * Cache invalidation is handled by:
37
- * - VERSION prefix: Auto-invalidates on framework releases
37
+ * - namespace prefix: Auto-rolls when the framework vfmod cache shape changes
38
38
  * - envKey (FRAMEWORK_ROOT hash): Prevents cross-environment contamination
39
39
  * (compiled binary vs source have different FRAMEWORK_ROOT values)
40
40
  * - contentHash: Content-based invalidation
@@ -47,7 +47,7 @@ export async function cacheTransformedCode(transformed, vfModulePath, fs) {
47
47
  const envKey = hashCodeHex(FRAMEWORK_ROOT).slice(0, 8);
48
48
  const contentHash = hashCodeHex(transformed);
49
49
  const pathHash = hashCodeHex(vfModulePath);
50
- const fileName = `vfmod-${VERSION}-${pathHash}-${envKey}-${contentHash}.mjs`;
50
+ const fileName = buildFrameworkVfModuleCacheFileName(pathHash, envKey, contentHash);
51
51
  const frameworkCacheDir = join(cacheDir, "framework");
52
52
  const cachePath = join(frameworkCacheDir, fileName);
53
53
  // Use Singleflight to prevent concurrent writes to the same file
@@ -0,0 +1,11 @@
1
+ type CacheNamespaceValue = string | number | boolean | null | readonly CacheNamespaceValue[] | {
2
+ readonly [key: string]: CacheNamespaceValue;
3
+ };
4
+ /**
5
+ * Build a deterministic cache namespace from a declarative schema description.
6
+ * Keep the schema close to the cache builders so format changes roll the
7
+ * namespace automatically instead of relying on a manually bumped constant.
8
+ */
9
+ export declare function createCacheNamespace(scope: string, schema: CacheNamespaceValue, length?: number): string;
10
+ export {};
11
+ //# sourceMappingURL=cache-namespace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-namespace.d.ts","sourceRoot":"","sources":["../../../src/src/utils/cache-namespace.ts"],"names":[],"mappings":"AAEA,KAAK,mBAAmB,GACpB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,mBAAmB,EAAE,GAC9B;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAAA;CAAE,CAAC;AAqBpD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mBAAmB,EAC3B,MAAM,SAAK,GACV,MAAM,CAGR"}
@@ -0,0 +1,24 @@
1
+ import { fnv1aHash } from "./hash-utils.js";
2
+ function serializeCacheNamespaceValue(value) {
3
+ if (value === null)
4
+ return "null";
5
+ if (Array.isArray(value)) {
6
+ return `[${value.map((entry) => serializeCacheNamespaceValue(entry)).join(",")}]`;
7
+ }
8
+ if (typeof value === "object") {
9
+ const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
10
+ return `{${entries
11
+ .map(([key, entry]) => `${JSON.stringify(key)}:${serializeCacheNamespaceValue(entry)}`)
12
+ .join(",")}}`;
13
+ }
14
+ return JSON.stringify(value);
15
+ }
16
+ /**
17
+ * Build a deterministic cache namespace from a declarative schema description.
18
+ * Keep the schema close to the cache builders so format changes roll the
19
+ * namespace automatically instead of relying on a manually bumped constant.
20
+ */
21
+ export function createCacheNamespace(scope, schema, length = 10) {
22
+ const serialized = serializeCacheNamespaceValue(schema);
23
+ return `${scope}-${fnv1aHash(serialized).slice(0, length)}`;
24
+ }
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "0.1.88";
1
+ export declare const VERSION = "0.1.89";
2
2
  export declare const SERVER_START_TIME: number;
3
3
  export interface BuildVersion {
4
4
  framework: string;
@@ -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.88";
3
+ export const VERSION = "0.1.89";
4
4
  export const SERVER_START_TIME = Date.now();
5
5
  export function createBuildVersion(projectUpdatedAt) {
6
6
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.88",
3
+ "version": "0.1.89",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.88",
3
+ "version": "0.1.89",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -25,12 +25,12 @@ import { validateCachedBundlesByManifestOrCode } from "../../../transforms/esm/c
25
25
  import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../utils/cache-dir.js";
26
26
  import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
27
27
  import { hashCodeHex } from "../../../utils/hash-utils.js";
28
- import { VERSION } from "../../../utils/version.js";
29
28
  import {
30
29
  getModulePathCache,
31
30
  lookupMdxEsmCache,
32
31
  saveModulePathCache,
33
32
  } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
33
+ import { buildMdxEsmPathCacheKey } from "../../../transforms/mdx/esm-module-loader/cache-format.js";
34
34
 
35
35
  const logger = rendererLogger.component("module-loader");
36
36
 
@@ -455,7 +455,7 @@ export async function transformModuleWithDeps(
455
455
 
456
456
  if (contentSourceId) {
457
457
  const normalizedPath = `_vf_modules/${relativePath.replace(/\.(tsx?|jsx|mdx)$/, ".js")}`;
458
- const mdxCacheKey = `v${VERSION}:${normalizedPath}`;
458
+ const mdxCacheKey = buildMdxEsmPathCacheKey(normalizedPath);
459
459
  const cache = await getModulePathCache(tmpDir);
460
460
  cache.set(mdxCacheKey, tempFilePath);
461
461
 
@@ -18,9 +18,9 @@ import {
18
18
  type FileSystem,
19
19
  isNotFoundError,
20
20
  } from "../../../../platform/compat/fs.js";
21
- import { VERSION } from "../../../../utils/version.js";
22
21
  import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
23
22
  import { LRUCache } from "../../../../utils/lru-wrapper.js";
23
+ import { buildMdxEsmPathCacheKey, MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE } from "../cache-format.js";
24
24
 
25
25
  export type CacheLookupResult =
26
26
  | { status: "hit"; path: string }
@@ -33,8 +33,6 @@ export const verifiedModuleDeps = new LRUCache<string, true>({
33
33
  maxEntries: MAX_VERIFIED_MODULE_DEPS,
34
34
  });
35
35
 
36
- const FILE_PATH_PATTERN = /file:\/\/([^"'\s]+)/gi;
37
-
38
36
  /**
39
37
  * Check if cached code has file:// paths from a different environment.
40
38
  * Checks both HTTP bundle paths and MDX ESM cache paths.
@@ -43,7 +41,7 @@ function hasIncompatibleCachePaths(code: string): boolean {
43
41
  const localCacheBaseDir = getCacheBaseDir();
44
42
  const localHttpCacheDir = getHttpBundleCacheDir();
45
43
  const localMdxCacheDir = getMdxEsmCacheDir();
46
- const pattern = new RegExp(FILE_PATH_PATTERN.source, "gi");
44
+ const pattern = new RegExp(MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE, "gi");
47
45
 
48
46
  let match: RegExpExecArray | null;
49
47
  while ((match = pattern.exec(code)) !== null) {
@@ -87,7 +85,7 @@ function hasIncompatibleCachePaths(code: string): boolean {
87
85
  */
88
86
  async function findMissingFileDependencies(code: string): Promise<string[]> {
89
87
  const localFs = getLocalFs();
90
- const pattern = new RegExp(FILE_PATH_PATTERN.source, "gi");
88
+ const pattern = new RegExp(MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE, "gi");
91
89
  const missing: string[] = [];
92
90
  let match;
93
91
  while ((match = pattern.exec(code)) !== null) {
@@ -335,7 +333,7 @@ function toMdxEsmCacheKey(filePath: string, projectDir?: string): string {
335
333
  relativePath = relativePath.replace(/^\/+/, "");
336
334
  const jsPath = relativePath.replace(/\.(tsx?|jsx|mdx)$/, ".js");
337
335
 
338
- return `v${VERSION}:_vf_modules/${jsPath}`;
336
+ return buildMdxEsmPathCacheKey(`_vf_modules/${jsPath}`);
339
337
  }
340
338
 
341
339
  export async function lookupMdxEsmCache(
@@ -429,9 +427,9 @@ export async function lookupMdxEsmCache(
429
427
  }
430
428
 
431
429
  // Note: We intentionally skip contentHash validation for MDX-ESM cached files.
432
- // The MDX-ESM cache uses transformed-code hashes in filenames (vfmod-v{VERSION}-{hash}.mjs),
430
+ // The MDX-ESM cache uses transformed-code hashes in namespaced filenames,
433
431
  // while the SSR loader provides source-code hashes. These will never match.
434
- // The cache version in the key (v{VERSION}:) provides sufficient staleness protection,
432
+ // The cache namespace in the key provides sufficient staleness protection,
435
433
  // and the file's existence confirms it's a valid transform for this codebase.
436
434
  // This allows both loaders to share the same module instance, preventing
437
435
  // duplicate React contexts which break hooks like useContext.
@@ -0,0 +1,121 @@
1
+ import { hashCodeHex } from "../../../utils/hash-utils.js";
2
+ import { createCacheNamespace } from "../../../utils/cache-namespace.js";
3
+ import { UNRESOLVED_VF_MODULES_PATTERN } from "./constants.js";
4
+ import { hashString } from "./utils/hash.js";
5
+
6
+ const ALL_FILE_URL_PATTERN_SOURCE = /file:\/\/([^"'\s]+)/.source;
7
+ const MJS_FILE_URL_PATTERN_SOURCE = /file:\/\/([^"'\s]+\.mjs)/.source;
8
+ const CACHE_NAMESPACE_SENTINEL = "__vf_cache_namespace__";
9
+
10
+ function formatMdxEsmTransformCacheKey(
11
+ namespace: string,
12
+ projectId: string,
13
+ normalizedPath: string,
14
+ contentHash: string,
15
+ ): string {
16
+ return `${namespace}:${projectId}:${normalizedPath}:${contentHash}:ssr`;
17
+ }
18
+
19
+ function formatMdxEsmPathCacheKey(namespace: string, normalizedPath: string): string {
20
+ return `${namespace}:${normalizedPath}`;
21
+ }
22
+
23
+ function formatMdxEsmModuleFileName(namespace: string, contentHash: string): string {
24
+ return `vfmod-${namespace}-${contentHash}.mjs`;
25
+ }
26
+
27
+ function formatMdxJsxCacheFileName(namespace: string, filePath: string): string {
28
+ return `jsx-${namespace}-${hashString(filePath)}.mjs`;
29
+ }
30
+
31
+ function formatFrameworkVfModuleCacheFileName(
32
+ namespace: string,
33
+ pathHash: string,
34
+ envKey: string,
35
+ contentHash: string,
36
+ ): string {
37
+ return `vfmod-${namespace}-${pathHash}-${envKey}-${contentHash}.mjs`;
38
+ }
39
+
40
+ function buildMdxEsmCacheSchemaSample() {
41
+ return {
42
+ transformKey: formatMdxEsmTransformCacheKey(
43
+ CACHE_NAMESPACE_SENTINEL,
44
+ "__vf_project__",
45
+ "_vf_modules/pages/index.js",
46
+ "deadbeef",
47
+ ),
48
+ pathKey: formatMdxEsmPathCacheKey(CACHE_NAMESPACE_SENTINEL, "_vf_modules/pages/index.js"),
49
+ moduleFile: formatMdxEsmModuleFileName(CACHE_NAMESPACE_SENTINEL, "deadbeef"),
50
+ jsxFile: formatMdxJsxCacheFileName(CACHE_NAMESPACE_SENTINEL, "/tmp/project/Button.tsx"),
51
+ unresolvedVfModulesPattern: UNRESOLVED_VF_MODULES_PATTERN.source,
52
+ allFileUrlPattern: ALL_FILE_URL_PATTERN_SOURCE,
53
+ mjsFileUrlPattern: MJS_FILE_URL_PATTERN_SOURCE,
54
+ sourceHashing: [
55
+ hashString("_vf_modules/pages/index.jsexport default 1;"),
56
+ hashString("/tmp/project/Button.tsx"),
57
+ ],
58
+ };
59
+ }
60
+
61
+ function buildFrameworkVfModuleCacheSchemaSample() {
62
+ return {
63
+ moduleFile: formatFrameworkVfModuleCacheFileName(
64
+ CACHE_NAMESPACE_SENTINEL,
65
+ hashCodeHex("_vf_modules/_veryfront/react/components/Head.js"),
66
+ hashCodeHex("/app/.cache/veryfront-mdx-esm").slice(0, 8),
67
+ hashCodeHex("export default function Head() {}"),
68
+ ),
69
+ };
70
+ }
71
+
72
+ export const MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE = ALL_FILE_URL_PATTERN_SOURCE;
73
+ export const MDX_ESM_MJS_FILE_URL_PATTERN_SOURCE = MJS_FILE_URL_PATTERN_SOURCE;
74
+
75
+ export const MDX_ESM_CACHE_NAMESPACE = createCacheNamespace(
76
+ "mdx-esm",
77
+ buildMdxEsmCacheSchemaSample(),
78
+ );
79
+
80
+ export const FRAMEWORK_VF_MODULE_CACHE_NAMESPACE = createCacheNamespace(
81
+ "vf-framework",
82
+ buildFrameworkVfModuleCacheSchemaSample(),
83
+ );
84
+
85
+ export function buildMdxEsmTransformCacheKey(
86
+ projectId: string,
87
+ normalizedPath: string,
88
+ contentHash: string,
89
+ ): string {
90
+ return formatMdxEsmTransformCacheKey(
91
+ MDX_ESM_CACHE_NAMESPACE,
92
+ projectId,
93
+ normalizedPath,
94
+ contentHash,
95
+ );
96
+ }
97
+
98
+ export function buildMdxEsmPathCacheKey(normalizedPath: string): string {
99
+ return formatMdxEsmPathCacheKey(MDX_ESM_CACHE_NAMESPACE, normalizedPath);
100
+ }
101
+
102
+ export function buildMdxEsmModuleFileName(contentHash: string): string {
103
+ return formatMdxEsmModuleFileName(MDX_ESM_CACHE_NAMESPACE, contentHash);
104
+ }
105
+
106
+ export function buildMdxJsxCacheFileName(filePath: string): string {
107
+ return formatMdxJsxCacheFileName(MDX_ESM_CACHE_NAMESPACE, filePath);
108
+ }
109
+
110
+ export function buildFrameworkVfModuleCacheFileName(
111
+ pathHash: string,
112
+ envKey: string,
113
+ contentHash: string,
114
+ ): string {
115
+ return formatFrameworkVfModuleCacheFileName(
116
+ FRAMEWORK_VF_MODULE_CACHE_NAMESPACE,
117
+ pathHash,
118
+ envKey,
119
+ contentHash,
120
+ );
121
+ }
@@ -11,7 +11,6 @@ import { join } from "../../../platform/compat/path/index.js";
11
11
  import { rendererLogger as logger } from "../../../utils/index.js";
12
12
  import { transformImportsWithMap } from "../../../modules/import-map/index.js";
13
13
  import type { ImportMapConfig } from "../../../modules/import-map/index.js";
14
- import { VERSION } from "../../../utils/version.js";
15
14
  import { replaceSpecifiers } from "../../esm/lexer.js";
16
15
  import { getLocalReactPaths, isReactSpecifier } from "../../../platform/compat/react-paths.js";
17
16
  import {
@@ -23,7 +22,7 @@ import {
23
22
  REACT_IMPORT_PATTERN,
24
23
  } from "./constants.js";
25
24
  import { getLocalFs } from "./cache/index.js";
26
- import { hashString } from "./utils/hash.js";
25
+ import { buildMdxJsxCacheFileName } from "./cache-format.js";
27
26
  import { rewriteDntImports } from "./module-fetcher/index.js";
28
27
  import { ensureCachedJsxModulePatched } from "./jsx-cache.js";
29
28
  import type { ESMLoaderContext } from "./types.js";
@@ -128,7 +127,7 @@ export async function transformJsxImports(
128
127
  const transformResults = await Promise.all(
129
128
  importsToProcess.map(async ({ fullMatch, importClause, filePath, ext }) => {
130
129
  try {
131
- const transformedFileName = `jsx-v${VERSION}-${hashString(filePath)}.mjs`;
130
+ const transformedFileName = buildMdxJsxCacheFileName(filePath);
132
131
  const transformedPath = join(esmCacheDir, transformedFileName);
133
132
 
134
133
  try {
@@ -4,7 +4,7 @@
4
4
  * @module transforms/mdx/esm-module-loader/module-fetcher/cache-keys
5
5
  */
6
6
 
7
- import { VERSION } from "../../../../utils/version.js";
7
+ import { buildMdxEsmPathCacheKey, buildMdxEsmTransformCacheKey } from "../cache-format.js";
8
8
 
9
9
  /**
10
10
  * Build cache key for transformed module.
@@ -18,9 +18,9 @@ export function getTransformCacheKey(
18
18
  normalizedPath: string,
19
19
  contentHash: string,
20
20
  ): string {
21
- return `v${VERSION}:${projectId}:${normalizedPath}:${contentHash}:ssr`;
21
+ return buildMdxEsmTransformCacheKey(projectId, normalizedPath, contentHash);
22
22
  }
23
23
 
24
24
  export function getVersionedPathCacheKey(normalizedPath: string): string {
25
- return `v${VERSION}:${normalizedPath}`;
25
+ return buildMdxEsmPathCacheKey(normalizedPath);
26
26
  }
@@ -13,6 +13,7 @@ import { FRAMEWORK_ROOT, LOG_PREFIX_MDX_LOADER } from "../constants.js";
13
13
  import { getLocalFs } from "../cache/index.js";
14
14
  import { extractHttpBundlePaths } from "../../../../modules/react-loader/ssr-module-loader/http-bundle-helpers.js";
15
15
  import { ensureHttpBundlesExist } from "../../../esm/http-cache.js";
16
+ import { MDX_ESM_MJS_FILE_URL_PATTERN_SOURCE } from "../cache-format.js";
16
17
 
17
18
  /**
18
19
  * Check if cached code has file:// paths that are incompatible with this environment.
@@ -110,7 +111,7 @@ export async function findMissingFileDependenciesInCode(
110
111
  log: Logger,
111
112
  ): Promise<string[]> {
112
113
  const localFs = getLocalFs();
113
- const pattern = /file:\/\/([^"'\s]+\.mjs)/gi;
114
+ const pattern = new RegExp(MDX_ESM_MJS_FILE_URL_PATTERN_SOURCE, "gi");
114
115
  const missing: string[] = [];
115
116
  const checked = new Set<string>();
116
117
 
@@ -10,11 +10,10 @@
10
10
  import { join } from "../../../../platform/compat/path/index.js";
11
11
  import * as posix from "../../../../../deps/jsr.io/@std/path/1.1.4/posix/mod.js";
12
12
  import type { Logger } from "../../../../utils/logger/logger.js";
13
- import { VERSION } from "../../../../utils/version.js";
14
13
  import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
15
14
  import { getLocalFs, saveModulePathCache } from "../cache/index.js";
16
15
  import { hashString } from "../utils/hash.js";
17
- import { getVersionedPathCacheKey } from "./cache-keys.js";
16
+ import { buildMdxEsmModuleFileName, buildMdxEsmPathCacheKey } from "../cache-format.js";
18
17
  import { hasUnresolvedImports } from "./nested-imports.js";
19
18
  import { recordModuleToSession } from "./render-sessions.js";
20
19
 
@@ -60,13 +59,14 @@ export async function cacheModule(
60
59
  }
61
60
 
62
61
  const contentHash = hashString(normalizedPath + moduleCode);
63
- const cachePath = join(esmCacheDir, `vfmod-v${VERSION}-${contentHash}.mjs`);
62
+ const cachePath = join(esmCacheDir, buildMdxEsmModuleFileName(contentHash));
63
+ const pathCacheKey = buildMdxEsmPathCacheKey(normalizedPath);
64
64
 
65
65
  const localFs = getLocalFs();
66
66
  try {
67
67
  const stat = await localFs.stat(cachePath);
68
68
  if (stat?.isFile) {
69
- pathCache.set(getVersionedPathCacheKey(normalizedPath), cachePath);
69
+ pathCache.set(pathCacheKey, cachePath);
70
70
  log.debug(`${LOG_PREFIX_MDX_LOADER} Content cache hit: ${normalizedPath}`);
71
71
  recordModuleToSession(normalizedPath);
72
72
  return cachePath;
@@ -77,7 +77,7 @@ export async function cacheModule(
77
77
 
78
78
  await localFs.mkdir(esmCacheDir, { recursive: true });
79
79
  await localFs.writeTextFile(cachePath, moduleCode);
80
- pathCache.set(getVersionedPathCacheKey(normalizedPath), cachePath);
80
+ pathCache.set(pathCacheKey, cachePath);
81
81
  await saveModulePathCache(esmCacheDir);
82
82
  log.debug(`${LOG_PREFIX_MDX_LOADER} Cached vf_module: ${normalizedPath} -> ${cachePath}`);
83
83
 
@@ -15,7 +15,6 @@ import { hashCodeHex } from "../../../../utils/hash-utils.js";
15
15
  import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../../utils/cache-dir.js";
16
16
  import { cacheHttpImportsToLocal } from "../../../esm/http-cache.js";
17
17
  import { loadImportMap } from "../../../../modules/import-map/index.js";
18
- import { VERSION } from "../../../../utils/version.js";
19
18
  import { buildReactUrl, getReactImportMap } from "../../../import-rewriter/url-builder.js";
20
19
  import { findRelativeImports } from "./import-finder.js";
21
20
  import { resolveRelativeFrameworkImport, resolveVeryfrontSourcePath } from "./path-resolver.js";
@@ -30,6 +29,7 @@ import {
30
29
  transformingFiles,
31
30
  veryfrontTransformCache,
32
31
  } from "./constants.js";
32
+ import { buildFrameworkVfModuleCacheFileName } from "../../../mdx/esm-module-loader/cache-format.js";
33
33
 
34
34
  const DENO_CONFIG_STUB_CODE = `export default ${JSON.stringify(denoConfig)};`;
35
35
 
@@ -46,10 +46,10 @@ export function isCyclePlaceholder(code: string): boolean {
46
46
  /**
47
47
  * Cache transformed framework code and return the file:// path.
48
48
  *
49
- * Cache key format: vfmod-{VERSION}-{pathHash}-{envKey}-{contentHash}.mjs
49
+ * Cache key format: vfmod-{namespace}-{pathHash}-{envKey}-{contentHash}.mjs
50
50
  *
51
51
  * Cache invalidation is handled by:
52
- * - VERSION prefix: Auto-invalidates on framework releases
52
+ * - namespace prefix: Auto-rolls when the framework vfmod cache shape changes
53
53
  * - envKey (FRAMEWORK_ROOT hash): Prevents cross-environment contamination
54
54
  * (compiled binary vs source have different FRAMEWORK_ROOT values)
55
55
  * - contentHash: Content-based invalidation
@@ -66,7 +66,7 @@ export async function cacheTransformedCode(
66
66
  const envKey = hashCodeHex(FRAMEWORK_ROOT).slice(0, 8);
67
67
  const contentHash = hashCodeHex(transformed);
68
68
  const pathHash = hashCodeHex(vfModulePath);
69
- const fileName = `vfmod-${VERSION}-${pathHash}-${envKey}-${contentHash}.mjs`;
69
+ const fileName = buildFrameworkVfModuleCacheFileName(pathHash, envKey, contentHash);
70
70
  const frameworkCacheDir = join(cacheDir, "framework");
71
71
  const cachePath = join(frameworkCacheDir, fileName);
72
72
 
@@ -0,0 +1,42 @@
1
+ import { fnv1aHash } from "./hash-utils.js";
2
+
3
+ type CacheNamespaceValue =
4
+ | string
5
+ | number
6
+ | boolean
7
+ | null
8
+ | readonly CacheNamespaceValue[]
9
+ | { readonly [key: string]: CacheNamespaceValue };
10
+
11
+ function serializeCacheNamespaceValue(value: CacheNamespaceValue): string {
12
+ if (value === null) return "null";
13
+
14
+ if (Array.isArray(value)) {
15
+ return `[${value.map((entry) => serializeCacheNamespaceValue(entry)).join(",")}]`;
16
+ }
17
+
18
+ if (typeof value === "object") {
19
+ const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
20
+ return `{${
21
+ entries
22
+ .map(([key, entry]) => `${JSON.stringify(key)}:${serializeCacheNamespaceValue(entry)}`)
23
+ .join(",")
24
+ }}`;
25
+ }
26
+
27
+ return JSON.stringify(value);
28
+ }
29
+
30
+ /**
31
+ * Build a deterministic cache namespace from a declarative schema description.
32
+ * Keep the schema close to the cache builders so format changes roll the
33
+ * namespace automatically instead of relying on a manually bumped constant.
34
+ */
35
+ export function createCacheNamespace(
36
+ scope: string,
37
+ schema: CacheNamespaceValue,
38
+ length = 10,
39
+ ): string {
40
+ const serialized = serializeCacheNamespaceValue(schema);
41
+ return `${scope}-${fnv1aHash(serialized).slice(0, length)}`;
42
+ }
@@ -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.88";
3
+ export const VERSION = "0.1.89";
4
4
 
5
5
  export const SERVER_START_TIME: number = Date.now();
6
6