veryfront 0.1.733 → 0.1.735

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.733",
3
+ "version": "0.1.735",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "minimumDependencyAge": "P2D",
@@ -0,0 +1,25 @@
1
+ import type { RuntimeAdapter } from "../../../platform/adapters/base.js";
2
+ /** Resolved local module dependency discovered in a source module. */
3
+ export type ResolvedModuleDependency = {
4
+ full: string;
5
+ path: string;
6
+ relativePath: string;
7
+ depFilePath: string | null;
8
+ isLocalLib: boolean;
9
+ };
10
+ /** Resolved dependency after its source module has been transformed to a temp file. */
11
+ export type TransformedModuleDependency = ResolvedModuleDependency & {
12
+ depTempPath: string;
13
+ };
14
+ /** Input for resolving local module dependencies from source code. */
15
+ export interface ResolveModuleDependenciesInput {
16
+ fileContent: string;
17
+ filePath: string;
18
+ projectDir: string;
19
+ adapter: RuntimeAdapter;
20
+ }
21
+ /** Resolves @/ alias and relative local imports from a source module. */
22
+ export declare function resolveModuleDependencies(input: ResolveModuleDependenciesInput): Promise<ResolvedModuleDependency[]>;
23
+ /** Rewrites resolved local imports to their transformed temp file URLs. */
24
+ export declare function rewriteResolvedDependencyImports(fileContent: string, transformedDeps: TransformedModuleDependency[]): string;
25
+ //# sourceMappingURL=dependency-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/dependency-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AASzE,sEAAsE;AACtE,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,GAAG;IACnE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;CACzB;AAgFD,yEAAyE;AACzE,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAuBrC;AAED,2EAA2E;AAC3E,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,2BAA2B,EAAE,GAC7C,MAAM,CAMR"}
@@ -0,0 +1,87 @@
1
+ import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
2
+ import { parallelMap, rendererLogger } from "../../../utils/index.js";
3
+ import { findSourceFile } from "../file-resolver/index.js";
4
+ const logger = rendererLogger.component("module-loader");
5
+ function collectAliasImports(fileContent) {
6
+ return [...fileContent.matchAll(/from\s+["'](@\/[^"']+)["']/g)].map((m) => ({
7
+ full: m[0],
8
+ path: m[1] ?? "",
9
+ }));
10
+ }
11
+ function collectRelativeImports(fileContent, fileDir) {
12
+ return [...fileContent.matchAll(/from\s+["'](\.\.?\/[^"']+)["']/g)]
13
+ .map((m) => ({ full: m[0], path: m[1] ?? "", fromDir: fileDir }))
14
+ // Ignore already-transformed file:// imports.
15
+ .filter((imp) => !imp.path.includes("file://"));
16
+ }
17
+ async function resolveAliasImport(imp, projectDir, adapter) {
18
+ const relativePath = imp.path.substring(2); // Remove @/ prefix.
19
+ const depFilePath = (await findSourceFile(relativePath, projectDir, adapter)) ??
20
+ (await findSourceFile(`components/${relativePath}`, projectDir, adapter));
21
+ return { ...imp, relativePath, depFilePath, isLocalLib: false };
22
+ }
23
+ async function resolveRelativeImport(imp, adapter) {
24
+ const basePath = normalize(join(imp.fromDir, imp.path));
25
+ logger.debug("Resolving relative import:", {
26
+ path: imp.path,
27
+ fromDir: imp.fromDir,
28
+ basePath,
29
+ });
30
+ const extensions = [".tsx", ".ts", ".jsx", ".js", ".mdx"];
31
+ let depFilePath = null;
32
+ if (await adapter.fs.exists(basePath)) {
33
+ const stat = await adapter.fs.stat(basePath);
34
+ if (!stat.isDirectory) {
35
+ depFilePath = basePath;
36
+ }
37
+ }
38
+ if (!depFilePath) {
39
+ for (const ext of extensions) {
40
+ const pathWithExt = basePath + ext;
41
+ if (await adapter.fs.exists(pathWithExt)) {
42
+ depFilePath = pathWithExt;
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ if (!depFilePath) {
48
+ for (const ext of extensions) {
49
+ const indexPath = join(basePath, `index${ext}`);
50
+ if (await adapter.fs.exists(indexPath)) {
51
+ depFilePath = indexPath;
52
+ break;
53
+ }
54
+ }
55
+ }
56
+ return {
57
+ full: imp.full,
58
+ path: imp.path,
59
+ relativePath: imp.path,
60
+ depFilePath,
61
+ isLocalLib: false,
62
+ };
63
+ }
64
+ /** Resolves @/ alias and relative local imports from a source module. */
65
+ export async function resolveModuleDependencies(input) {
66
+ const fileDir = dirname(input.filePath);
67
+ const aliasImports = collectAliasImports(input.fileContent);
68
+ const relativeImports = collectRelativeImports(input.fileContent, fileDir);
69
+ logger.debug("Processing file:", {
70
+ filePath: input.filePath,
71
+ aliasImportsCount: aliasImports.length,
72
+ relativeImportsCount: relativeImports.length,
73
+ aliasImports: aliasImports.map((i) => i.path),
74
+ relativeImports: relativeImports.map((i) => i.path),
75
+ });
76
+ const resolvedAliasDeps = await parallelMap(aliasImports, (imp) => resolveAliasImport(imp, input.projectDir, input.adapter));
77
+ const resolvedRelativeDeps = await parallelMap(relativeImports, (imp) => resolveRelativeImport(imp, input.adapter));
78
+ return [...resolvedAliasDeps, ...resolvedRelativeDeps];
79
+ }
80
+ /** Rewrites resolved local imports to their transformed temp file URLs. */
81
+ export function rewriteResolvedDependencyImports(fileContent, transformedDeps) {
82
+ let rewritten = fileContent;
83
+ for (const dep of transformedDeps) {
84
+ rewritten = rewritten.replace(dep.full, `from "file://${dep.depTempPath}"`);
85
+ }
86
+ return rewritten;
87
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA4BzE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAkJpE,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,eAAe,UAAQ,GACtB,OAAO,CAAC,MAAM,CAAC,CAsSjB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI5D;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA6DlC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA+BzE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAmEpE,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,eAAe,UAAQ,GACtB,OAAO,CAAC,MAAM,CAAC,CAsQjB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI5D;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA6DlC"}
@@ -6,9 +6,8 @@
6
6
  *
7
7
  * @module rendering/orchestrator/module-loader
8
8
  */
9
- import { parallelMap, rendererLogger } from "../../../utils/index.js";
9
+ import { rendererLogger } from "../../../utils/index.js";
10
10
  import { getLocalAdapter } from "../../../platform/adapters/registry.js";
11
- import { findSourceFile } from "../file-resolver/index.js";
12
11
  import { transformToESM } from "../../../transforms/esm-transform.js";
13
12
  import { createFileSystem } from "../../../platform/compat/fs.js";
14
13
  import { getProjectTmpDir } from "../../../modules/react-loader/index.js";
@@ -16,10 +15,11 @@ import { generateCacheKey as generateTransformCacheKey, getOrComputeTransform, i
16
15
  import { TRANSFORM_DISTRIBUTED_TTL_SEC } from "../../../utils/constants/cache.js";
17
16
  import { validateCachedBundlesByManifestOrCode } from "../../../transforms/esm/cached-bundle-validation.js";
18
17
  import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../utils/cache-dir.js";
19
- import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
18
+ import { join } from "../../../platform/compat/path/index.js";
20
19
  import { hashCodeHex } from "../../../utils/hash-utils.js";
21
20
  import { getModulePathCache, invalidateMdxEsmModule, lookupMdxEsmCache, saveModulePathCache, } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
22
21
  import { buildMdxEsmPathCacheKey } from "../../../transforms/mdx/esm-module-loader/cache-format.js";
22
+ import { resolveModuleDependencies, rewriteResolvedDependencyImports, } from "./dependency-resolver.js";
23
23
  const logger = rendererLogger.component("module-loader");
24
24
  // Re-export utilities
25
25
  export { createEsmCache, createModuleCache, generateHash } from "./cache.js";
@@ -67,58 +67,6 @@ async function ensureDir(adapter, dir) {
67
67
  pruneCreatedDirs();
68
68
  }
69
69
  }
70
- async function resolveAliasImport(imp, projectDir, adapter) {
71
- const relativePath = imp.path.substring(2); // Remove @/ prefix
72
- const depFilePath = (await findSourceFile(relativePath, projectDir, adapter)) ??
73
- (await findSourceFile(`components/${relativePath}`, projectDir, adapter));
74
- return { ...imp, relativePath, depFilePath, isLocalLib: false };
75
- }
76
- async function resolveRelativeImport(imp, adapter) {
77
- // Resolve the path relative to the file's directory and normalize to resolve ..
78
- const basePath = normalize(join(imp.fromDir, imp.path));
79
- logger.debug("Resolving relative import:", {
80
- path: imp.path,
81
- fromDir: imp.fromDir,
82
- basePath,
83
- });
84
- // Try to find the source file with various extensions
85
- const extensions = [".tsx", ".ts", ".jsx", ".js", ".mdx"];
86
- let depFilePath = null;
87
- // First try the exact path (in case it already has an extension)
88
- if (await adapter.fs.exists(basePath)) {
89
- const stat = await adapter.fs.stat(basePath);
90
- if (!stat.isDirectory) {
91
- depFilePath = basePath;
92
- }
93
- }
94
- // Try with extensions
95
- if (!depFilePath) {
96
- for (const ext of extensions) {
97
- const pathWithExt = basePath + ext;
98
- if (await adapter.fs.exists(pathWithExt)) {
99
- depFilePath = pathWithExt;
100
- break;
101
- }
102
- }
103
- }
104
- // Try index files if path is a directory
105
- if (!depFilePath) {
106
- for (const ext of extensions) {
107
- const indexPath = join(basePath, `index${ext}`);
108
- if (await adapter.fs.exists(indexPath)) {
109
- depFilePath = indexPath;
110
- break;
111
- }
112
- }
113
- }
114
- return {
115
- full: imp.full,
116
- path: imp.path,
117
- relativePath: imp.path,
118
- depFilePath,
119
- isLocalLib: false,
120
- };
121
- }
122
70
  /**
123
71
  * Transform a module and all its local dependencies (@/ alias and relative imports).
124
72
  *
@@ -179,30 +127,13 @@ export async function transformModuleWithDeps(filePath, tmpDir, localAdapter, co
179
127
  }
180
128
  const readAdapter = useLocalAdapter ? localAdapter : adapter;
181
129
  let fileContent = decodeFileContent(await readAdapter.fs.readFile(filePath));
182
- const fileDir = dirname(filePath);
183
- // Match @/ alias imports
184
- const aliasImports = [...fileContent.matchAll(/from\s+["'](@\/[^"']+)["']/g)].map((m) => ({ full: m[0], path: m[1] ?? "" }));
185
- // Match relative imports (./ and ../) - exclude npm:, http://, https://, file://
186
- const relativeImports = [
187
- ...fileContent.matchAll(/from\s+["'](\.\.?\/[^"']+)["']/g),
188
- ]
189
- .map((m) => ({ full: m[0], path: m[1] ?? "", fromDir: fileDir }))
190
- // Filter out already-transformed file:// imports
191
- .filter((imp) => !imp.path.includes("file://"));
192
- logger.debug("Processing file:", {
130
+ const resolvedDeps = await resolveModuleDependencies({
131
+ adapter,
132
+ fileContent,
193
133
  filePath,
194
- aliasImportsCount: aliasImports.length,
195
- relativeImportsCount: relativeImports.length,
196
- aliasImports: aliasImports.map((i) => i.path),
197
- relativeImports: relativeImports.map((i) => i.path),
134
+ projectDir,
198
135
  });
199
- // Resolve alias imports
200
- const resolvedAliasDeps = await parallelMap(aliasImports, (imp) => resolveAliasImport(imp, projectDir, adapter));
201
- // Resolve relative imports
202
- const resolvedRelativeDeps = await parallelMap(relativeImports, (imp) => resolveRelativeImport(imp, adapter));
203
- // Combine all resolved dependencies
204
- const resolvedDeps = [...resolvedAliasDeps, ...resolvedRelativeDeps];
205
- const transformedDeps = await parallelMap(resolvedDeps.filter((d) => d.depFilePath), async (dep) => {
136
+ const transformedDeps = await Promise.all(resolvedDeps.filter((d) => d.depFilePath).map(async (dep) => {
206
137
  logger.debug("Found dependency:", {
207
138
  path: dep.path,
208
139
  depFilePath: dep.depFilePath,
@@ -210,9 +141,9 @@ export async function transformModuleWithDeps(filePath, tmpDir, localAdapter, co
210
141
  });
211
142
  const depTempPath = await transformModuleWithDeps(dep.depFilePath, tmpDir, localAdapter, config, dep.isLocalLib);
212
143
  return { ...dep, depTempPath };
213
- });
144
+ }));
145
+ fileContent = rewriteResolvedDependencyImports(fileContent, transformedDeps);
214
146
  for (const dep of transformedDeps) {
215
- fileContent = fileContent.replace(dep.full, `from "file://${dep.depTempPath}"`);
216
147
  logger.debug("Replaced import:", {
217
148
  path: dep.path,
218
149
  depTempPath: dep.depTempPath,
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Specifier resolution helpers for the SSR VF Modules stage.
3
+ *
4
+ * @module transforms/pipeline/stages/ssr-vf-modules/specifier-resolver
5
+ */
6
+ export interface FrameworkSpecifierResolverInput {
7
+ denoConfigStubUrl: string | null;
8
+ veryfrontReplacements: ReadonlyMap<string, string>;
9
+ relativeReplacements: ReadonlyMap<string, string>;
10
+ reactVersion: string;
11
+ reactImportMap?: Record<string, string>;
12
+ }
13
+ /**
14
+ * Resolve a bare `react` / `react-dom` (or subpath) specifier to its esm.sh
15
+ * URL for the given React version. Returns `null` for anything that is not a
16
+ * React specifier.
17
+ */
18
+ export declare function resolveReactSpecifier(specifier: string, reactVersion: string, reactImportMap?: Record<string, string>): string | null;
19
+ /**
20
+ * If `resolvedPath` is one of veryfront's React re-export modules
21
+ * (`FRAMEWORK_ROOT/react/*.js`), return the esm.sh URL it should be rewritten
22
+ * to for the given React version. Returns `null` for anything else.
23
+ */
24
+ export declare function reactReExportToEsmUrl(resolvedPath: string, reactVersion: string, reactImportMap?: Record<string, string>): string | null;
25
+ /**
26
+ * Build the final specifier resolver for transformed framework code.
27
+ */
28
+ export declare function createFrameworkSpecifierResolver(input: FrameworkSpecifierResolverInput): (specifier: string) => string | null;
29
+ //# sourceMappingURL=specifier-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specifier-resolver.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/specifier-resolver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,WAAW,+BAA+B;IAC9C,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,qBAAqB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,cAAc,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAmC,GACvE,MAAM,GAAG,IAAI,CAef;AAkBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,MAAM,GAAG,IAAI,CAKf;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,+BAA+B,GACrC,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAkBtC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Specifier resolution helpers for the SSR VF Modules stage.
3
+ *
4
+ * @module transforms/pipeline/stages/ssr-vf-modules/specifier-resolver
5
+ */
6
+ import { join } from "../../../../platform/compat/path/index.js";
7
+ import { buildReactUrl, getReactImportMap } from "../../../import-rewriter/url-builder.js";
8
+ import { FRAMEWORK_ROOT } from "./constants.js";
9
+ /**
10
+ * Resolve a bare `react` / `react-dom` (or subpath) specifier to its esm.sh
11
+ * URL for the given React version. Returns `null` for anything that is not a
12
+ * React specifier.
13
+ */
14
+ export function resolveReactSpecifier(specifier, reactVersion, reactImportMap = getReactImportMap(reactVersion)) {
15
+ const mapped = reactImportMap[specifier];
16
+ if (mapped)
17
+ return mapped;
18
+ if (specifier.startsWith("react/")) {
19
+ return buildReactUrl("react", reactVersion, "/" + specifier.slice("react/".length), true);
20
+ }
21
+ if (specifier.startsWith("react-dom/")) {
22
+ return buildReactUrl("react-dom", reactVersion, "/" + specifier.slice("react-dom/".length), true);
23
+ }
24
+ return null;
25
+ }
26
+ /**
27
+ * veryfront's own React re-export modules under `FRAMEWORK_ROOT/react/`
28
+ * mapped to the bare specifier they stand in for.
29
+ */
30
+ const REACT_REEXPORT_SPECIFIERS = {
31
+ "react.js": "react",
32
+ "react-dom.js": "react-dom",
33
+ "react-dom-client.js": "react-dom/client",
34
+ "react-dom-server.js": "react-dom/server",
35
+ "jsx-runtime.js": "react/jsx-runtime",
36
+ "jsx-dev-runtime.js": "react/jsx-dev-runtime",
37
+ };
38
+ /** `FRAMEWORK_ROOT/react/` prefix, precomputed (invariant per process). */
39
+ const REACT_REEXPORT_DIR = join(FRAMEWORK_ROOT, "react") + "/";
40
+ /**
41
+ * If `resolvedPath` is one of veryfront's React re-export modules
42
+ * (`FRAMEWORK_ROOT/react/*.js`), return the esm.sh URL it should be rewritten
43
+ * to for the given React version. Returns `null` for anything else.
44
+ */
45
+ export function reactReExportToEsmUrl(resolvedPath, reactVersion, reactImportMap) {
46
+ if (!resolvedPath.startsWith(REACT_REEXPORT_DIR))
47
+ return null;
48
+ const specifier = REACT_REEXPORT_SPECIFIERS[resolvedPath.slice(REACT_REEXPORT_DIR.length)];
49
+ if (!specifier)
50
+ return null;
51
+ return resolveReactSpecifier(specifier, reactVersion, reactImportMap);
52
+ }
53
+ /**
54
+ * Build the final specifier resolver for transformed framework code.
55
+ */
56
+ export function createFrameworkSpecifierResolver(input) {
57
+ const reactImportMap = input.reactImportMap ?? getReactImportMap(input.reactVersion);
58
+ return (specifier) => {
59
+ if (specifier === "#deno-config") {
60
+ return input.denoConfigStubUrl;
61
+ }
62
+ if (specifier.startsWith("#veryfront/")) {
63
+ return input.veryfrontReplacements.get(specifier) ?? null;
64
+ }
65
+ if (specifier.startsWith("./") || specifier.startsWith("../")) {
66
+ return input.relativeReplacements.get(specifier) ?? null;
67
+ }
68
+ return resolveReactSpecifier(specifier, input.reactVersion, reactImportMap);
69
+ };
70
+ }
@@ -25,12 +25,7 @@ export declare function isCyclePlaceholder(code: string): boolean;
25
25
  * - contentHash: Content-based invalidation
26
26
  */
27
27
  export declare function cacheTransformedCode(transformed: string, vfModulePath: string, fs: ReturnType<typeof createFileSystem>): Promise<string>;
28
- /**
29
- * If `resolvedPath` is one of veryfront's React re-export modules
30
- * (`FRAMEWORK_ROOT/react/*.js`), return the esm.sh URL it should be rewritten
31
- * to for the given React version. Returns `null` for anything else.
32
- */
33
- export declare function reactReExportToEsmUrl(resolvedPath: string, reactVersion: string, reactImportMap?: Record<string, string>): string | null;
28
+ export { reactReExportToEsmUrl } from "./specifier-resolver.js";
34
29
  /**
35
30
  * Core transformation logic for framework TypeScript/TSX files.
36
31
  * Compiles to JavaScript and recursively resolves all imports:
@@ -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;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;AA8ED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,MAAM,GAAG,IAAI,CAKf;AAwMD;;;;;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,CAsPjB;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;AAmBrE,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;AAgBD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAwMhE;;;;;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,CA8OjB;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"}
@@ -14,9 +14,10 @@ import { LRUCache } from "../../../../utils/lru-wrapper.js";
14
14
  import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../../utils/cache-dir.js";
15
15
  import { cacheHttpImportsToLocal } from "../../../esm/http-cache.js";
16
16
  import { loadImportMap } from "../../../../modules/import-map/index.js";
17
- import { buildReactUrl, getReactImportMap } from "../../../import-rewriter/url-builder.js";
17
+ import { getReactImportMap } from "../../../import-rewriter/url-builder.js";
18
18
  import { findRelativeImports } from "./import-finder.js";
19
19
  import { resolveRelativeFrameworkImport, resolveVeryfrontSourcePath } from "./path-resolver.js";
20
+ import { createFrameworkSpecifierResolver, reactReExportToEsmUrl, resolveReactSpecifier, } from "./specifier-resolver.js";
20
21
  import { EMBEDDED_SRC_DIR, FRAMEWORK_ROOT, frameworkFileCache, frameworkWriteFlight, LOG_PREFIX, MAX_RELATIVE_IMPORT_DEPTH, transformingFiles, veryfrontTransformCache, } from "./constants.js";
21
22
  import { buildFrameworkVfModuleCacheFileName } from "../../../mdx/esm-module-loader/cache-format.js";
22
23
  const DENO_CONFIG_STUB_CODE = `export default ${JSON.stringify(denoConfig)};`;
@@ -77,70 +78,7 @@ const FALLBACK_TRANSFORM_CACHE_MAX_ENTRIES = 2000;
77
78
  const fallbackTransformCache = new LRUCache({
78
79
  maxEntries: FALLBACK_TRANSFORM_CACHE_MAX_ENTRIES,
79
80
  });
80
- /**
81
- * Resolve a bare `react` / `react-dom` (or subpath) specifier to its esm.sh
82
- * URL for the given React version. Returns `null` for anything that is not a
83
- * React specifier.
84
- *
85
- * Both the main transform path and the depth-limit fallback use this so a
86
- * framework module always links against the single esm.sh React bundle used
87
- * during SSR. Leaving `react` bare would resolve it to the project's own
88
- * React copy — a second React instance whose dispatcher is null, which makes
89
- * the first hook throw "Cannot read properties of null (reading 'useEffect')".
90
- */
91
- function resolveReactSpecifier(specifier, reactVersion, reactImportMap = getReactImportMap(reactVersion)) {
92
- const mapped = reactImportMap[specifier];
93
- if (mapped)
94
- return mapped;
95
- if (specifier.startsWith("react/")) {
96
- return buildReactUrl("react", reactVersion, "/" + specifier.slice("react/".length), true);
97
- }
98
- if (specifier.startsWith("react-dom/")) {
99
- return buildReactUrl("react-dom", reactVersion, "/" + specifier.slice("react-dom/".length), true);
100
- }
101
- return null;
102
- }
103
- /**
104
- * veryfront's own React re-export modules under `FRAMEWORK_ROOT/react/`
105
- * mapped to the bare specifier they stand in for. Each re-export bridges to
106
- * project React via `export * from "react"` (etc.), which during SSR resolves
107
- * to the project's `node_modules` copy — a *different* React instance than
108
- * the esm.sh react-dom bundle uses. The dnt build rewrites framework
109
- * `import ... from "react"` to a relative import of these files, so a
110
- * framework module that does `useEffect` ends up reading a null dispatcher.
111
- * Rewriting these imports straight to the esm.sh bundle keeps every SSR
112
- * module on a single React instance.
113
- *
114
- * Keys must match the compiled re-export filenames under
115
- * `FRAMEWORK_ROOT/react/`, which the build emits from the `react/*.ts` source
116
- * modules (`react.ts`, `react-dom.ts`, `react-dom-client.ts`,
117
- * `react-dom-server.ts`, `jsx-runtime.ts`, `jsx-dev-runtime.ts`). If one is
118
- * renamed or added, update this map too: a stale key silently reintroduces
119
- * the dual-React-instance bug.
120
- */
121
- const REACT_REEXPORT_SPECIFIERS = {
122
- "react.js": "react",
123
- "react-dom.js": "react-dom",
124
- "react-dom-client.js": "react-dom/client",
125
- "react-dom-server.js": "react-dom/server",
126
- "jsx-runtime.js": "react/jsx-runtime",
127
- "jsx-dev-runtime.js": "react/jsx-dev-runtime",
128
- };
129
- /** `FRAMEWORK_ROOT/react/` prefix, precomputed (invariant per process). */
130
- const REACT_REEXPORT_DIR = join(FRAMEWORK_ROOT, "react") + "/";
131
- /**
132
- * If `resolvedPath` is one of veryfront's React re-export modules
133
- * (`FRAMEWORK_ROOT/react/*.js`), return the esm.sh URL it should be rewritten
134
- * to for the given React version. Returns `null` for anything else.
135
- */
136
- export function reactReExportToEsmUrl(resolvedPath, reactVersion, reactImportMap) {
137
- if (!resolvedPath.startsWith(REACT_REEXPORT_DIR))
138
- return null;
139
- const specifier = REACT_REEXPORT_SPECIFIERS[resolvedPath.slice(REACT_REEXPORT_DIR.length)];
140
- if (!specifier)
141
- return null;
142
- return resolveReactSpecifier(specifier, reactVersion, reactImportMap);
143
- }
81
+ export { reactReExportToEsmUrl } from "./specifier-resolver.js";
144
82
  /**
145
83
  * Pick an esbuild loader for a file path, honoring the embedded `.src`
146
84
  * suffix used in compiled binaries (`foo.ts.src` → `ts`). Recognizes
@@ -490,21 +428,13 @@ export async function transformFrameworkCode(content, sourcePath, ctx, throwOnMi
490
428
  const stubPath = await cacheTransformedCode(DENO_CONFIG_STUB_CODE, "#deno-config-stub", ctx.fs);
491
429
  denoConfigStubUrl = `file://${stubPath}`;
492
430
  }
493
- transformed = await replaceSpecifiers(transformed, (specifier) => {
494
- // Handle Deno import-map aliases
495
- if (specifier === "#deno-config") {
496
- return denoConfigStubUrl;
497
- }
498
- // Handle #veryfront/ imports
499
- if (specifier.startsWith("#veryfront/")) {
500
- return veryfrontReplacements.get(specifier) ?? null;
501
- }
502
- // Handle relative imports
503
- if (specifier.startsWith("./") || specifier.startsWith("../")) {
504
- return relativeReplacements.get(specifier) ?? null;
505
- }
506
- return resolveReactSpecifier(specifier, ctx.reactVersion, reactImportMap);
507
- });
431
+ transformed = await replaceSpecifiers(transformed, createFrameworkSpecifierResolver({
432
+ denoConfigStubUrl,
433
+ veryfrontReplacements,
434
+ relativeReplacements,
435
+ reactVersion: ctx.reactVersion,
436
+ reactImportMap,
437
+ }));
508
438
  // Cache HTTP imports to local filesystem
509
439
  const importMap = await loadImportMap(ctx.projectDir);
510
440
  const cacheResult = await cacheHttpImportsToLocal(transformed, {
@@ -1,3 +1,3 @@
1
1
  /** Shared version value. */
2
- export declare const VERSION = "0.1.733";
2
+ export declare const VERSION = "0.1.735";
3
3
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
3
  /** Shared version value. */
4
- export const VERSION = "0.1.733";
4
+ export const VERSION = "0.1.735";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.733",
3
+ "version": "0.1.735",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",