veryfront 0.0.86 → 0.0.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.
- package/esm/_dnt.shims.d.ts +14 -14
- package/esm/_dnt.shims.d.ts.map +1 -1
- package/esm/deno.d.ts +0 -1
- package/esm/deno.js +8 -9
- package/esm/proxy/main.d.ts +2 -0
- package/esm/proxy/main.d.ts.map +1 -0
- package/esm/proxy/main.js +400 -0
- package/esm/src/cli/commands/init/config-generator.js +1 -1
- package/esm/src/cli/index/arg-parser.d.ts.map +1 -1
- package/esm/src/cli/index/arg-parser.js +1 -0
- package/esm/src/cli/index/command-router.d.ts.map +1 -1
- package/esm/src/cli/index/command-router.js +54 -39
- package/esm/src/cli/index/types.d.ts +4 -0
- package/esm/src/cli/index/types.d.ts.map +1 -1
- package/esm/src/cli/mcp/advanced-tools.d.ts +2 -2
- package/esm/src/cli/templates/manifest.d.ts +448 -448
- package/esm/src/cli/templates/manifest.js +480 -480
- package/esm/src/config/loader.d.ts.map +1 -1
- package/esm/src/config/loader.js +5 -4
- package/esm/src/html/utils.js +2 -2
- package/esm/src/modules/import-map/default-import-map.d.ts +1 -11
- package/esm/src/modules/import-map/default-import-map.d.ts.map +1 -1
- package/esm/src/modules/import-map/default-import-map.js +3 -20
- package/esm/src/modules/import-map/loader.d.ts.map +1 -1
- package/esm/src/modules/import-map/loader.js +7 -22
- package/esm/src/modules/import-map/resolver.d.ts.map +1 -1
- package/esm/src/modules/import-map/resolver.js +12 -8
- package/esm/src/modules/react-loader/component-loader.d.ts.map +1 -1
- package/esm/src/modules/react-loader/component-loader.js +2 -0
- package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts +1 -6
- package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/loader.js +40 -32
- package/esm/src/modules/react-loader/ssr-module-loader/types.d.ts +2 -0
- package/esm/src/modules/react-loader/ssr-module-loader/types.d.ts.map +1 -1
- package/esm/src/modules/react-loader/types.d.ts +2 -0
- package/esm/src/modules/react-loader/types.d.ts.map +1 -1
- package/esm/src/modules/react-loader/unified-loader.d.ts.map +1 -1
- package/esm/src/modules/react-loader/unified-loader.js +7 -4
- package/esm/src/modules/server/module-batch-handler.d.ts +2 -0
- package/esm/src/modules/server/module-batch-handler.d.ts.map +1 -1
- package/esm/src/modules/server/module-batch-handler.js +3 -1
- package/esm/src/modules/server/module-server.d.ts +2 -0
- package/esm/src/modules/server/module-server.d.ts.map +1 -1
- package/esm/src/modules/server/module-server.js +4 -2
- package/esm/src/modules/server/ssr-import-rewriter.d.ts.map +1 -1
- package/esm/src/modules/server/ssr-import-rewriter.js +9 -17
- package/esm/src/platform/compat/path-helper.d.ts +7 -7
- package/esm/src/platform/compat/path-helper.d.ts.map +1 -1
- package/esm/src/react/compat/ssr-adapter/string-renderer.js +1 -1
- package/esm/src/react/components/Head.d.ts.map +1 -1
- package/esm/src/react/components/Head.js +6 -2
- package/esm/src/react/components/ai/agent-card.d.ts +1 -1
- package/esm/src/react/components/ai/agent-card.d.ts.map +1 -1
- package/esm/src/react/components/ai/chat/composition/api.d.ts +5 -4
- package/esm/src/react/components/ai/chat/composition/api.d.ts.map +1 -1
- package/esm/src/react/components/ai/chat/index.d.ts +7 -2
- package/esm/src/react/components/ai/chat/index.d.ts.map +1 -1
- package/esm/src/react/components/ai/message.d.ts +2 -2
- package/esm/src/react/components/ai/message.d.ts.map +1 -1
- package/esm/src/react/primitives/agent-primitives.d.ts +3 -3
- package/esm/src/react/primitives/agent-primitives.d.ts.map +1 -1
- package/esm/src/react/primitives/chat-container.d.ts +1 -1
- package/esm/src/react/primitives/chat-container.d.ts.map +1 -1
- package/esm/src/react/primitives/input-box.d.ts +3 -3
- package/esm/src/react/primitives/input-box.d.ts.map +1 -1
- package/esm/src/react/primitives/input-box.js +6 -2
- package/esm/src/react/primitives/message-list.d.ts +4 -4
- package/esm/src/react/primitives/message-list.d.ts.map +1 -1
- package/esm/src/react/primitives/tool-primitives.d.ts +3 -3
- package/esm/src/react/primitives/tool-primitives.d.ts.map +1 -1
- package/esm/src/rendering/component-handling.d.ts +2 -0
- package/esm/src/rendering/component-handling.d.ts.map +1 -1
- package/esm/src/rendering/component-handling.js +4 -2
- package/esm/src/rendering/layouts/layout-applicator.d.ts.map +1 -1
- package/esm/src/rendering/layouts/layout-applicator.js +2 -0
- package/esm/src/rendering/orchestrator/module-loader/index.d.ts +3 -0
- package/esm/src/rendering/orchestrator/module-loader/index.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/module-loader/index.js +74 -19
- package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/pipeline.js +2 -0
- package/esm/src/rendering/rsc/server-renderer/tree-processor.d.ts.map +1 -1
- package/esm/src/rendering/rsc/server-renderer/tree-processor.js +3 -1
- package/esm/src/rendering/ssr-globals/context.d.ts +6 -1
- package/esm/src/rendering/ssr-globals/context.d.ts.map +1 -1
- package/esm/src/transforms/esm/http-bundler.d.ts +15 -4
- package/esm/src/transforms/esm/http-bundler.d.ts.map +1 -1
- package/esm/src/transforms/esm/http-bundler.js +105 -12
- package/esm/src/transforms/esm/http-cache.d.ts.map +1 -1
- package/esm/src/transforms/esm/http-cache.js +26 -27
- package/esm/src/transforms/esm/import-rewriter.d.ts.map +1 -1
- package/esm/src/transforms/esm/import-rewriter.js +3 -3
- package/esm/src/transforms/esm/package-registry.d.ts +15 -13
- package/esm/src/transforms/esm/package-registry.d.ts.map +1 -1
- package/esm/src/transforms/esm/package-registry.js +45 -32
- package/esm/src/transforms/esm/react-imports.d.ts.map +1 -1
- package/esm/src/transforms/esm/react-imports.js +3 -7
- package/esm/src/transforms/esm/types.d.ts +2 -0
- package/esm/src/transforms/esm/types.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/cache/index.d.ts +14 -0
- package/esm/src/transforms/mdx/esm-module-loader/cache/index.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/cache/index.js +67 -0
- package/esm/src/transforms/mdx/esm-module-loader/loader.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/loader.js +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.d.ts +1 -0
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.js +1 -0
- package/esm/src/transforms/mdx/esm-module-loader/types.d.ts +4 -0
- package/esm/src/transforms/mdx/esm-module-loader/types.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/context.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/context.js +7 -15
- package/esm/src/transforms/pipeline/stages/finalize.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/finalize.js +1 -1
- package/esm/src/utils/constants/cdn.d.ts.map +1 -1
- package/esm/src/utils/constants/cdn.js +22 -11
- package/esm/src/utils/hash-utils.d.ts +2 -0
- package/esm/src/utils/hash-utils.d.ts.map +1 -1
- package/esm/src/utils/hash-utils.js +4 -0
- package/package.json +1 -1
- package/src/deno.js +8 -9
- package/src/proxy/main.ts +471 -0
- package/src/src/cli/commands/init/config-generator.ts +1 -1
- package/src/src/cli/index/arg-parser.ts +1 -0
- package/src/src/cli/index/command-router.ts +57 -40
- package/src/src/cli/index/types.ts +5 -0
- package/src/src/cli/templates/manifest.js +480 -480
- package/src/src/config/loader.ts +5 -4
- package/src/src/html/utils.ts +2 -2
- package/src/src/modules/import-map/default-import-map.ts +3 -25
- package/src/src/modules/import-map/loader.ts +7 -23
- package/src/src/modules/import-map/resolver.ts +13 -8
- package/src/src/modules/react-loader/component-loader.ts +2 -0
- package/src/src/modules/react-loader/ssr-module-loader/loader.ts +51 -37
- package/src/src/modules/react-loader/ssr-module-loader/types.ts +2 -0
- package/src/src/modules/react-loader/types.ts +2 -0
- package/src/src/modules/react-loader/unified-loader.ts +7 -4
- package/src/src/modules/server/module-batch-handler.ts +7 -0
- package/src/src/modules/server/module-server.ts +6 -1
- package/src/src/modules/server/ssr-import-rewriter.ts +9 -17
- package/src/src/react/compat/ssr-adapter/stream-renderer.ts +1 -1
- package/src/src/react/compat/ssr-adapter/string-renderer.ts +2 -2
- package/src/src/react/components/Head.tsx +6 -2
- package/src/src/react/primitives/input-box.tsx +4 -2
- package/src/src/rendering/component-handling.ts +6 -0
- package/src/src/rendering/layouts/layout-applicator.ts +4 -5
- package/src/src/rendering/orchestrator/module-loader/index.ts +91 -20
- package/src/src/rendering/orchestrator/pipeline.ts +2 -0
- package/src/src/rendering/orchestrator/ssr-orchestrator.ts +1 -1
- package/src/src/rendering/rsc/server-renderer/tree-processor.ts +13 -3
- package/src/src/transforms/esm/http-bundler.ts +101 -11
- package/src/src/transforms/esm/http-cache.ts +27 -28
- package/src/src/transforms/esm/import-rewriter.ts +5 -3
- package/src/src/transforms/esm/package-registry.ts +46 -32
- package/src/src/transforms/esm/react-imports.ts +3 -7
- package/src/src/transforms/esm/types.ts +2 -0
- package/src/src/transforms/mdx/esm-module-loader/cache/index.ts +84 -0
- package/src/src/transforms/mdx/esm-module-loader/loader.ts +1 -0
- package/src/src/transforms/mdx/esm-module-loader/module-fetcher/index.ts +2 -1
- package/src/src/transforms/mdx/esm-module-loader/types.ts +4 -0
- package/src/src/transforms/pipeline/context.ts +7 -18
- package/src/src/transforms/pipeline/stages/finalize.ts +6 -1
- package/src/src/transforms/plugins/babel-node-positions.ts +2 -2
- package/src/src/utils/constants/cdn.ts +21 -12
- package/src/src/utils/hash-utils.ts +5 -0
|
@@ -9,23 +9,35 @@
|
|
|
9
9
|
export const DEFAULT_REACT_VERSION = "19.1.1";
|
|
10
10
|
export const TAILWIND_VERSION = "4.1.8";
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Validate React version format (semver: X.Y.Z).
|
|
14
|
+
* Returns true if valid, false otherwise.
|
|
15
|
+
*/
|
|
16
|
+
export function isValidReactVersion(version: string): boolean {
|
|
17
|
+
return /^\d+\.\d+\.\d+$/.test(version);
|
|
18
|
+
}
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
21
|
+
* Validate and normalize React version.
|
|
22
|
+
* Returns the version if valid, or DEFAULT_REACT_VERSION if invalid.
|
|
23
|
+
* Logs a warning if the version is invalid.
|
|
18
24
|
*/
|
|
19
|
-
export function
|
|
20
|
-
|
|
25
|
+
export function normalizeReactVersion(version: string | undefined): string {
|
|
26
|
+
if (!version) return DEFAULT_REACT_VERSION;
|
|
27
|
+
if (isValidReactVersion(version)) return version;
|
|
28
|
+
console.warn(
|
|
29
|
+
`[VERYFRONT] Invalid React version format "${version}" (expected X.Y.Z). Using default: ${DEFAULT_REACT_VERSION}`,
|
|
30
|
+
);
|
|
31
|
+
return DEFAULT_REACT_VERSION;
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
35
|
+
* @deprecated Global React version is no longer supported.
|
|
36
|
+
* Use config.react.version passed through TransformOptions instead.
|
|
37
|
+
* This function now always returns DEFAULT_REACT_VERSION.
|
|
26
38
|
*/
|
|
27
39
|
export function getReactVersion(): string {
|
|
28
|
-
return
|
|
40
|
+
return DEFAULT_REACT_VERSION;
|
|
29
41
|
}
|
|
30
42
|
|
|
31
43
|
/** @deprecated Use DEFAULT_REACT_VERSION or getReactVersion() */
|
|
@@ -50,8 +62,15 @@ export const REACT_VERSION = DEFAULT_REACT_VERSION;
|
|
|
50
62
|
*/
|
|
51
63
|
export const TRANSFORM_CACHE_VERSION = 12;
|
|
52
64
|
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
/** csstype version - must match deno.json for type consistency */
|
|
66
|
+
const CSSTYPE_VERSION = "3.2.3";
|
|
67
|
+
|
|
68
|
+
/** Build esm.sh URL with deps=csstype for React packages (ensures type consistency) */
|
|
69
|
+
function esmShReact(pkg: string, version: string, path = "", external = false): string {
|
|
70
|
+
const params = external
|
|
71
|
+
? [`external=react`, `target=es2022`, `deps=csstype@${CSSTYPE_VERSION}`]
|
|
72
|
+
: [`target=es2022`, `deps=csstype@${CSSTYPE_VERSION}`];
|
|
73
|
+
return `https://esm.sh/${pkg}@${version}${path}?${params.join("&")}`;
|
|
55
74
|
}
|
|
56
75
|
|
|
57
76
|
/**
|
|
@@ -78,12 +97,12 @@ export function getEsmShUrl(pkg: string, version: string, external?: readonly st
|
|
|
78
97
|
export function getReactUrls(version?: string): Record<string, string> {
|
|
79
98
|
const v = version ?? getReactVersion();
|
|
80
99
|
return {
|
|
81
|
-
react:
|
|
82
|
-
"react-dom":
|
|
83
|
-
"react-dom/client":
|
|
84
|
-
"react-dom/server":
|
|
85
|
-
"react/jsx-runtime":
|
|
86
|
-
"react/jsx-dev-runtime":
|
|
100
|
+
react: esmShReact("react", v),
|
|
101
|
+
"react-dom": esmShReact("react-dom", v, "", true),
|
|
102
|
+
"react-dom/client": esmShReact("react-dom", v, "/client", true),
|
|
103
|
+
"react-dom/server": esmShReact("react-dom", v, "/server", true),
|
|
104
|
+
"react/jsx-runtime": esmShReact("react", v, "/jsx-runtime", true),
|
|
105
|
+
"react/jsx-dev-runtime": esmShReact("react", v, "/jsx-dev-runtime", true),
|
|
87
106
|
};
|
|
88
107
|
}
|
|
89
108
|
|
|
@@ -102,30 +121,25 @@ export function getReactImportMap(version?: string): Record<string, string> {
|
|
|
102
121
|
return {
|
|
103
122
|
...getReactUrls(v),
|
|
104
123
|
// Prefix match for any react/* subpath imports
|
|
105
|
-
"react/":
|
|
124
|
+
"react/": esmShReact("react", v, "/", true),
|
|
106
125
|
};
|
|
107
126
|
}
|
|
108
127
|
|
|
109
128
|
/**
|
|
110
|
-
* Get React
|
|
111
|
-
* Uses
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* Benefits over esm.sh:
|
|
115
|
-
* - Automatic semantic version deduplication (like Node's node_modules)
|
|
116
|
-
* - No manual external= flags or shared-*.ts wrapper files needed
|
|
117
|
-
* - Native support in Deno 2+
|
|
129
|
+
* Get React esm.sh URLs for Deno SSR.
|
|
130
|
+
* Uses esm.sh for both SSR and browser to ensure identical React instances.
|
|
131
|
+
* All sub-packages use external=react to share the same React instance.
|
|
118
132
|
*
|
|
119
133
|
* @param version - React version to use (defaults to REACT_VERSION)
|
|
120
134
|
*/
|
|
121
135
|
export function getDenoNpmReactMap(version?: string): Record<string, string> {
|
|
122
136
|
const v = version ?? getReactVersion();
|
|
123
137
|
return {
|
|
124
|
-
"react":
|
|
125
|
-
"react-dom":
|
|
126
|
-
"react-dom/client":
|
|
127
|
-
"react-dom/server":
|
|
128
|
-
"react/jsx-runtime":
|
|
129
|
-
"react/jsx-dev-runtime":
|
|
138
|
+
"react": esmShReact("react", v),
|
|
139
|
+
"react-dom": esmShReact("react-dom", v, "", true),
|
|
140
|
+
"react-dom/client": esmShReact("react-dom", v, "/client", true),
|
|
141
|
+
"react-dom/server": esmShReact("react-dom", v, "/server", true),
|
|
142
|
+
"react/jsx-runtime": esmShReact("react", v, "/jsx-runtime", true),
|
|
143
|
+
"react/jsx-dev-runtime": esmShReact("react", v, "/jsx-dev-runtime", true),
|
|
130
144
|
};
|
|
131
145
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { replaceSpecifiers } from "./lexer.js";
|
|
2
|
-
import {
|
|
3
|
-
import { isDeno } from "../../platform/compat/runtime.js";
|
|
4
|
-
import { getLocalReactPaths } from "../../platform/compat/react-paths.js";
|
|
2
|
+
import { getReactImportMap, REACT_VERSION } from "./package-registry.js";
|
|
5
3
|
|
|
6
4
|
const srcDir = new URL(".", import.meta.url).pathname.replace(
|
|
7
5
|
/\/(build|src)\/transforms\/esm\/?$/,
|
|
@@ -28,12 +26,10 @@ export async function resolveReactImports(
|
|
|
28
26
|
return replaceSpecifiers(code, (specifier) => reactImports[specifier] ?? null);
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
// For
|
|
32
|
-
// For Node/Bun SSR: Use local node_modules paths (auto-deduplicated by Node)
|
|
33
|
-
// See: https://deno.com/blog/not-using-npm-specifiers-doing-it-wrong
|
|
29
|
+
// For SSR: Use esm.sh URLs consistently (NO npm: specifiers per plan requirements)
|
|
34
30
|
const ssrImports: Record<string, string> = {
|
|
35
31
|
...getVeryfrontModulePaths(),
|
|
36
|
-
...
|
|
32
|
+
...reactImports,
|
|
37
33
|
};
|
|
38
34
|
|
|
39
35
|
return replaceSpecifiers(code, (specifier) => ssrImports[specifier] ?? null);
|
|
@@ -9,6 +9,8 @@ export interface TransformOptions {
|
|
|
9
9
|
ssr?: boolean;
|
|
10
10
|
apiBaseUrl?: string;
|
|
11
11
|
studioEmbed?: boolean;
|
|
12
|
+
/** React version for transforms (from project config, defaults to DEFAULT_REACT_VERSION) */
|
|
13
|
+
reactVersion?: string;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export interface TransformContext {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type FileSystem,
|
|
15
15
|
isNotFoundError,
|
|
16
16
|
} from "../../../../platform/compat/fs.js";
|
|
17
|
+
import { TRANSFORM_CACHE_VERSION } from "../../../esm/package-registry.js";
|
|
17
18
|
import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
|
|
18
19
|
|
|
19
20
|
// Local filesystem for cache operations (not project's FSAdapter which may be remote/read-only)
|
|
@@ -150,3 +151,86 @@ export async function clearESMDiskCache(): Promise<void> {
|
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Convert a project-relative file path to MDX-ESM cache key format.
|
|
157
|
+
*
|
|
158
|
+
* @param filePath - Project-relative path like "lib/ChatContext.tsx" or absolute path
|
|
159
|
+
* @param projectDir - Project directory to strip from absolute paths
|
|
160
|
+
* @returns Cache key like "v10:_vf_modules/lib/ChatContext.js"
|
|
161
|
+
*/
|
|
162
|
+
function toMdxEsmCacheKey(filePath: string, projectDir?: string): string {
|
|
163
|
+
// Strip project directory prefix if present
|
|
164
|
+
let relativePath = filePath;
|
|
165
|
+
if (projectDir && filePath.startsWith(projectDir)) {
|
|
166
|
+
relativePath = filePath.slice(projectDir.length).replace(/^\/+/, "");
|
|
167
|
+
}
|
|
168
|
+
// Strip leading slashes
|
|
169
|
+
relativePath = relativePath.replace(/^\/+/, "");
|
|
170
|
+
|
|
171
|
+
// Convert extension to .js
|
|
172
|
+
const jsPath = relativePath.replace(/\.(tsx?|jsx|mdx)$/, ".js");
|
|
173
|
+
|
|
174
|
+
// Build the versioned key in MDX-ESM format
|
|
175
|
+
return `v${TRANSFORM_CACHE_VERSION}:_vf_modules/${jsPath}`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Look up a module in the MDX-ESM cache.
|
|
180
|
+
*
|
|
181
|
+
* This allows other loaders (like SSR loader) to reuse modules that
|
|
182
|
+
* MDX-ESM has already transformed and cached, preventing duplicate
|
|
183
|
+
* module instances (which breaks React context, etc.).
|
|
184
|
+
*
|
|
185
|
+
* @param filePath - Project-relative file path like "lib/ChatContext.tsx"
|
|
186
|
+
* @param cacheDir - The MDX-ESM cache directory for this project/contentSource
|
|
187
|
+
* @param projectDir - Project directory to strip from absolute paths
|
|
188
|
+
* @param contentHash - Optional content hash to validate cached file freshness
|
|
189
|
+
* @returns The cached file path if found and valid, null otherwise
|
|
190
|
+
*/
|
|
191
|
+
export async function lookupMdxEsmCache(
|
|
192
|
+
filePath: string,
|
|
193
|
+
cacheDir: string,
|
|
194
|
+
projectDir?: string,
|
|
195
|
+
contentHash?: string,
|
|
196
|
+
): Promise<string | null> {
|
|
197
|
+
const cache = await getModulePathCache(cacheDir);
|
|
198
|
+
const cacheKey = toMdxEsmCacheKey(filePath, projectDir);
|
|
199
|
+
|
|
200
|
+
const cachedPath = cache.get(cacheKey);
|
|
201
|
+
if (!cachedPath) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Verify the cached file still exists
|
|
206
|
+
try {
|
|
207
|
+
const stat = await getLocalFs().stat(cachedPath);
|
|
208
|
+
if (!stat?.isFile) {
|
|
209
|
+
cache.delete(cacheKey);
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// If contentHash provided, validate the cached file contains matching hash
|
|
214
|
+
// The cached filename includes the content hash (e.g., module.abc123.js)
|
|
215
|
+
if (contentHash) {
|
|
216
|
+
const filename = cachedPath.split("/").pop() ?? "";
|
|
217
|
+
if (!filename.includes(contentHash.slice(0, 8))) {
|
|
218
|
+
logger.debug(
|
|
219
|
+
`${LOG_PREFIX_MDX_LOADER} Cache hash mismatch, invalidating: ${filePath}`,
|
|
220
|
+
);
|
|
221
|
+
cache.delete(cacheKey);
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
logger.debug(
|
|
227
|
+
`${LOG_PREFIX_MDX_LOADER} SSR reusing MDX-ESM cache: ${filePath} -> ${cachedPath}`,
|
|
228
|
+
);
|
|
229
|
+
return cachedPath;
|
|
230
|
+
} catch {
|
|
231
|
+
// File no longer exists, remove stale entry
|
|
232
|
+
cache.delete(cacheKey);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
@@ -568,6 +568,7 @@ async function doFetchAndCacheModule(
|
|
|
568
568
|
projectId,
|
|
569
569
|
dev: true,
|
|
570
570
|
ssr: true,
|
|
571
|
+
reactVersion: context.reactVersion,
|
|
571
572
|
});
|
|
572
573
|
} catch (transformError) {
|
|
573
574
|
logger.error(`${LOG_PREFIX_MDX_LOADER} Transform failed for module`, {
|
|
@@ -685,7 +686,7 @@ export function createModuleFetcherContext(
|
|
|
685
686
|
adapter: RuntimeAdapter,
|
|
686
687
|
projectDir: string,
|
|
687
688
|
projectId: string,
|
|
688
|
-
options?: { isLocalDev?: boolean; projectSlug?: string },
|
|
689
|
+
options?: { isLocalDev?: boolean; projectSlug?: string; reactVersion?: string },
|
|
689
690
|
): ModuleFetcherContext {
|
|
690
691
|
return {
|
|
691
692
|
esmCacheDir,
|
|
@@ -10,6 +10,8 @@ export interface ESMLoaderContext {
|
|
|
10
10
|
projectDir?: string;
|
|
11
11
|
projectSlug?: string;
|
|
12
12
|
contentSourceId?: string;
|
|
13
|
+
/** React version for transforms (from project config) */
|
|
14
|
+
reactVersion?: string;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export interface FSAdapter {
|
|
@@ -51,6 +53,8 @@ export interface ModuleFetcherContext {
|
|
|
51
53
|
* This prevents infinite recursion when A imports B which imports A.
|
|
52
54
|
*/
|
|
53
55
|
inFlightModules?: Map<string, Promise<string | null>>;
|
|
56
|
+
/** React version for transforms (from project config) */
|
|
57
|
+
reactVersion?: string;
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
export interface JSXTransform {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as dntShim from "../../../_dnt.shims.js";
|
|
2
1
|
import { computeShortContentHash } from "../esm/transform-utils.js";
|
|
3
2
|
import { REACT_VERSION } from "../esm/package-registry.js";
|
|
4
3
|
import type {
|
|
@@ -8,20 +7,12 @@ import type {
|
|
|
8
7
|
TransformTarget,
|
|
9
8
|
} from "./types.js";
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const reactVersion = { ...pkg.dependencies, ...pkg.devDependencies }?.react;
|
|
20
|
-
if (reactVersion) return reactVersion.replace(/^[\^~]/, "");
|
|
21
|
-
} catch {
|
|
22
|
-
// Project doesn't have package.json or no React dependency
|
|
23
|
-
}
|
|
24
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Get React version for transforms.
|
|
12
|
+
* Uses REACT_VERSION constant - the centralized version from package-registry.
|
|
13
|
+
* Prefer passing reactVersion through TransformOptions for per-project versions.
|
|
14
|
+
*/
|
|
15
|
+
function getDefaultReactVersion(): string {
|
|
25
16
|
return REACT_VERSION;
|
|
26
17
|
}
|
|
27
18
|
|
|
@@ -64,9 +55,7 @@ export async function createTransformContext(
|
|
|
64
55
|
): Promise<TransformContext> {
|
|
65
56
|
const [contentHash, reactVersion] = await Promise.all([
|
|
66
57
|
computeShortContentHash(source),
|
|
67
|
-
options.reactVersion
|
|
68
|
-
? Promise.resolve(options.reactVersion)
|
|
69
|
-
: detectProjectReactVersion(projectDir),
|
|
58
|
+
Promise.resolve(options.reactVersion ?? getDefaultReactVersion()),
|
|
70
59
|
]);
|
|
71
60
|
|
|
72
61
|
return buildContext(source, filePath, projectDir, contentHash, options, reactVersion);
|
|
@@ -10,7 +10,12 @@ export const finalizePlugin: TransformPlugin = {
|
|
|
10
10
|
async transform(ctx: TransformContext): Promise<string> {
|
|
11
11
|
if (!isSSR(ctx)) return ctx.code;
|
|
12
12
|
|
|
13
|
-
const result = bundleHttpImports(
|
|
13
|
+
const result = bundleHttpImports(
|
|
14
|
+
ctx.code,
|
|
15
|
+
getHttpBundleCacheDir(),
|
|
16
|
+
ctx.contentHash,
|
|
17
|
+
ctx.reactVersion,
|
|
18
|
+
);
|
|
14
19
|
return result instanceof Promise ? await result : result;
|
|
15
20
|
},
|
|
16
21
|
};
|
|
@@ -141,7 +141,7 @@ export function injectNodePositions(source: string, _options: TransformOptions):
|
|
|
141
141
|
|
|
142
142
|
let nodeCounter = 0;
|
|
143
143
|
|
|
144
|
-
traverse(ast, {
|
|
144
|
+
traverse(ast as t.Node, {
|
|
145
145
|
JSXElement: {
|
|
146
146
|
enter(path: BabelNodePath<t.JSXElement>) {
|
|
147
147
|
const openingElement = path.node.openingElement;
|
|
@@ -184,7 +184,7 @@ export function injectNodePositions(source: string, _options: TransformOptions):
|
|
|
184
184
|
},
|
|
185
185
|
});
|
|
186
186
|
|
|
187
|
-
const output = generate(ast, {
|
|
187
|
+
const output = generate(ast as t.Node, {
|
|
188
188
|
retainLines: true,
|
|
189
189
|
compact: false,
|
|
190
190
|
});
|
|
@@ -10,36 +10,45 @@ export const REACT_VERSION_19 = "19.1.1";
|
|
|
10
10
|
|
|
11
11
|
export const REACT_DEFAULT_VERSION = REACT_VERSION_19;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
/**
|
|
14
|
+
* esm.sh URL builder with consistent query params.
|
|
15
|
+
*
|
|
16
|
+
* For React packages (react-dom, jsx-runtime), we only need external=react:
|
|
17
|
+
* - react-dom depends on react → external=react makes it import "react" as bare specifier
|
|
18
|
+
* - react-dom doesn't need external=react-dom because it IS react-dom
|
|
19
|
+
* - jsx-runtime depends on react core → external=react
|
|
20
|
+
*
|
|
21
|
+
* Third-party packages (e.g., @tanstack/react-query) need external=react,react-dom
|
|
22
|
+
* because they may depend on BOTH. That's handled by bundleHttpImports() separately.
|
|
23
|
+
*/
|
|
24
|
+
function esmSh(pkg: string, version: string, path = "", external = false): string {
|
|
25
|
+
const params = ["target=es2022"];
|
|
26
|
+
if (external) params.push("external=react");
|
|
27
|
+
return `${ESM_CDN_BASE}/${pkg}@${version}${path}?${params.join("&")}`;
|
|
19
28
|
}
|
|
20
29
|
|
|
21
30
|
export function getReactCDNUrl(version: string = REACT_DEFAULT_VERSION): string {
|
|
22
|
-
return
|
|
31
|
+
return esmSh("react", version);
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
export function getReactDOMCDNUrl(version: string = REACT_DEFAULT_VERSION): string {
|
|
26
|
-
return
|
|
35
|
+
return esmSh("react-dom", version, "", true);
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
export function getReactDOMClientCDNUrl(version: string = REACT_DEFAULT_VERSION): string {
|
|
30
|
-
return
|
|
39
|
+
return esmSh("react-dom", version, "/client", true);
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
export function getReactDOMServerCDNUrl(version: string = REACT_DEFAULT_VERSION): string {
|
|
34
|
-
return
|
|
43
|
+
return esmSh("react-dom", version, "/server", true);
|
|
35
44
|
}
|
|
36
45
|
|
|
37
46
|
export function getReactJSXRuntimeCDNUrl(version: string = REACT_DEFAULT_VERSION): string {
|
|
38
|
-
return
|
|
47
|
+
return esmSh("react", version, "/jsx-runtime", true);
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
export function getReactJSXDevRuntimeCDNUrl(version: string = REACT_DEFAULT_VERSION): string {
|
|
42
|
-
return
|
|
51
|
+
return esmSh("react", version, "/jsx-dev-runtime", true);
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
export function getReactImportMap(version: string = REACT_DEFAULT_VERSION): Record<string, string> {
|
|
@@ -34,6 +34,11 @@ export function simpleHash(str: string): number {
|
|
|
34
34
|
return Math.abs(hash);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/** Hash string to hex (base 16) - used for module filenames */
|
|
38
|
+
export function hashCodeHex(str: string): string {
|
|
39
|
+
return simpleHash(str).toString(16);
|
|
40
|
+
}
|
|
41
|
+
|
|
37
42
|
export async function shortHash(content: string): Promise<string> {
|
|
38
43
|
const fullHash = await computeHash(content);
|
|
39
44
|
return fullHash.slice(0, 8);
|