Skip to content

Commit 5a0e494

Browse files
committed
wip
1 parent ad90ed4 commit 5a0e494

File tree

10 files changed

+294
-95
lines changed

10 files changed

+294
-95
lines changed

packages/vue/injectors/ast-utils.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,23 @@ import babel from "recast/parsers/babel.js";
55
const {namedTypes: n, builders: b} = recast.types;
66

77
/**
8-
* Selects the appropriate parser based on file extension
9-
* @param {string} fileName - Name of the file being processed
8+
* Selects the appropriate parser based on typescript flag
9+
* @param {boolean} useTypeScript - Whether to use the TypeScript parser
1010
* @returns {object} The parser to use
1111
*/
12-
export function selectParser(fileName) {
13-
return fileName.endsWith(".ts") || fileName.endsWith(".tsx") ? ts : babel;
12+
export function selectParser(useTypeScript) {
13+
return useTypeScript ? ts : babel;
1414
}
1515

1616
/**
1717
* Parse source code into an AST
1818
* @param {string} sourceCode - Source code to parse
19-
* @param {string} fileName - File name (used for parser selection and source mapping)
19+
* @param {string} fileName - File name (used for source mapping)
20+
* @param {boolean} useTypeScript - Whether to use the TypeScript parser
2021
* @returns {object} The resulting AST
2122
*/
22-
export function parseCode(sourceCode, fileName = "") {
23-
const parser = selectParser(fileName);
23+
export function parseCode(sourceCode, fileName = "", useTypeScript = false) {
24+
const parser = selectParser(useTypeScript);
2425
return recast.parse(sourceCode, {
2526
parser,
2627
sourceFileName: fileName
@@ -30,9 +31,10 @@ export function parseCode(sourceCode, fileName = "") {
3031
/**
3132
* Handles useFusion import in AST
3233
* @param {object} ast - The AST to modify
34+
* @param {string} fusionPath - The path to use for the fusion import
3335
* @returns {object} Object containing information about useFusion imports
3436
*/
35-
export function handleFusionImport(ast) {
37+
export function handleFusionImport(ast, fusionPath) {
3638
let fusionLocalName = null;
3739
let hasUseFusionImport = false;
3840

@@ -54,7 +56,7 @@ export function handleFusionImport(ast) {
5456
}
5557
});
5658
// Update the import source.
57-
path.node.source.value = "__aliasedFusionPath__";
59+
path.node.source.value = fusionPath;
5860
hasUseFusionImport = true;
5961
}
6062
this.traverse(path);
@@ -68,13 +70,14 @@ export function handleFusionImport(ast) {
6870
* Adds a useFusion import if one doesn't exist
6971
* @param {object} ast - The AST to modify
7072
* @param {boolean} hasUseFusionImport - Whether a useFusion import already exists
73+
* @param {string} fusionPath - The path to use for the fusion import
7174
* @returns {string} The local name for useFusion (default is "useFusion")
7275
*/
73-
export function ensureFusionImport(ast, hasUseFusionImport) {
76+
export function ensureFusionImport(ast, hasUseFusionImport, fusionPath) {
7477
if (!hasUseFusionImport) {
7578
const fusionImport = b.importDeclaration(
7679
[b.importSpecifier(b.identifier("useFusion"))],
77-
b.literal("__aliasedFusionPath__")
80+
b.literal(fusionPath)
7881
);
7982

8083
// Find the best position to insert the import (after other imports)

packages/vue/injectors/createScriptSetupAst.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import recast from "recast";
33

44
const {builders: b} = recast.types;
55

6-
export default function injector(code, fileName, keys) {
7-
// Build an AST for a new program (the script setup content)
6+
export default function injector(code, fileName, keys, fusionPath = "__aliasedFusionPath__", useTypeScript = false) {
7+
// The useTypeScript parameter is not used directly here as this injector
8+
// creates a new script block rather than parsing existing code
89
const program = b.program([]);
910

10-
// 1. import { useFusion } from "__aliasedFusionPath__";
11+
// 1. import { useFusion } from fusion path
1112
const importUseFusion = b.importDeclaration(
1213
[b.importSpecifier(b.identifier("useFusion"), b.identifier("useFusion"))],
13-
b.literal("__aliasedFusionPath__")
14+
b.literal(fusionPath)
1415
);
1516

1617
// 2. import useHotFusion from "@fusion/vue/hmr";

packages/vue/injectors/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,19 @@ import optionsWithoutSetup from './optionsWithoutSetup.js'
33
import createScriptSetup from './createScriptSetup.js'
44
import modifyScriptSetup from './modifyScriptSetup.js'
55

6+
import optionsWithSetupAst from './optionsWithSetupAst.js'
7+
import optionsWithoutSetupAst from './optionsWithoutSetupAst.js'
8+
import createScriptSetupAst from './createScriptSetupAst.js'
9+
import modifyScriptSetupAst from './modifyScriptSetupAst.js'
10+
611
export default {
712
optionsWithSetup,
813
optionsWithoutSetup,
914
createScriptSetup,
1015
modifyScriptSetup,
16+
17+
optionsWithSetupAst,
18+
optionsWithoutSetupAst,
19+
createScriptSetupAst,
20+
modifyScriptSetupAst,
1121
}

packages/vue/injectors/modifyScriptSetupAst.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ import recast from "recast";
1010

1111
const {builders: b} = recast.types;
1212

13-
export function transformCode(sourceCode, fileName = "", keys = []) {
14-
// Parse the source code into an AST
15-
const ast = parseCode(sourceCode, fileName);
13+
export function transformCode(sourceCode, fileName = "", keys = [], fusionPath = "__aliasedFusionPath__", useTypeScript = false) {
14+
// Parse the source code into an AST using explicit TypeScript flag
15+
const ast = parseCode(sourceCode, fileName, useTypeScript);
1616

1717
// Handle imports and get fusion local name
18-
const {fusionLocalName: localName, hasUseFusionImport} = handleFusionImport(ast);
18+
const {fusionLocalName: localName, hasUseFusionImport} = handleFusionImport(ast, fusionPath);
1919
const fusionLocalName = localName || (hasUseFusionImport ? localName : "useFusion");
2020

2121
// Collect keys from existing useFusion calls and update them to include __props.fusion
@@ -34,7 +34,7 @@ export function transformCode(sourceCode, fileName = "", keys = []) {
3434
if (missingKeys.length > 0) {
3535
// Ensure the import exists.
3636
if (!hasUseFusionImport) {
37-
ensureFusionImport(ast, hasUseFusionImport);
37+
ensureFusionImport(ast, hasUseFusionImport, fusionPath);
3838
}
3939

4040
// Find the index after the last import.
@@ -62,7 +62,7 @@ export function transformCode(sourceCode, fileName = "", keys = []) {
6262
// Case 2: No useFusion call exists.
6363
// Ensure an import for useFusion is injected.
6464
if (!hasUseFusionImport) {
65-
ensureFusionImport(ast, hasUseFusionImport);
65+
ensureFusionImport(ast, hasUseFusionImport, fusionPath);
6666
}
6767

6868
// Find the index after the last import.

packages/vue/injectors/optionsWithSetupAst.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import recast from "recast";
1111

1212
const {namedTypes: n, builders: b} = recast.types;
1313

14-
export function optionsWithSetup(sourceCode, fileName = "", keys = []) {
15-
// Parse the source code.
16-
const ast = parseCode(sourceCode, fileName);
14+
export function optionsWithSetup(sourceCode, fileName = "", keys = [], fusionPath = "__aliasedFusionPath__", useTypeScript = false) {
15+
// Parse the source code using explicit TypeScript flag
16+
const ast = parseCode(sourceCode, fileName, useTypeScript);
1717

1818
// ------------------------------
1919
// Step 1: Remove any existing useFusion imports.
@@ -137,7 +137,7 @@ export function optionsWithSetup(sourceCode, fileName = "", keys = []) {
137137

138138
// ------------------------------
139139
// Step 6: Insert a new import for useFusion.
140-
ensureFusionImport(ast, false);
140+
ensureFusionImport(ast, false, fusionPath);
141141

142142
// ------------------------------
143143
// Step 7: Append a wrapper to override the setup function.

packages/vue/injectors/optionsWithoutSetupAst.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@ import recast from "recast";
1010

1111
const {builders: b} = recast.types;
1212

13-
export default function injector(code, fileName, keys) {
14-
// Parse the source code using Babel's parser.
13+
export default function injector(code, fileName, keys, fusionPath = "__aliasedFusionPath__", useTypeScript = false) {
14+
// Use the explicit TypeScript flag instead of inferring from filename
15+
const parser = useTypeScript ? babelParser : babelParser; // Both use babelParser in this file
16+
17+
// Parse the source code using the appropriate parser.
1518
const ast = recast.parse(code, {
16-
parser: babelParser,
19+
parser,
1720
sourceFileName: fileName
1821
});
1922

2023
// 1. Determine the local name for useFusion.
21-
const {fusionLocalName: localName, hasUseFusionImport} = handleFusionImport(ast);
22-
const fusionLocalName = localName || ensureFusionImport(ast, hasUseFusionImport) || "useFusion";
24+
const {fusionLocalName: localName, hasUseFusionImport} = handleFusionImport(ast, fusionPath);
25+
const fusionLocalName = localName || ensureFusionImport(ast, hasUseFusionImport, fusionPath) || "useFusion";
2326

2427
// 2. Rewrite the default export:
2528
extractDefaultExport(ast);

packages/vue/tests/injectors/createScriptSetupAst.test.js

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ describe("injector", () => {
99
test("appends a script setup block to simple code", () => {
1010
const code = `console.log("Hello");`;
1111
const keys = ["name", "email"];
12-
const result = injector(code, "test.js", keys);
12+
const result = injector(code, "test.js", keys, "__aliasedFusionPath__", false);
1313
const expected = `
1414
console.log("Hello");
1515
<script setup>
@@ -29,7 +29,7 @@ useHotFusion(__fusionData);
2929
<p>Test paragraph</p>
3030
`;
3131
const keys = ["user", "age"];
32-
const result = injector(code, "test.js", keys);
32+
const result = injector(code, "test.js", keys, "__aliasedFusionPath__", false);
3333
const expected = `
3434
<div>Hello World</div>
3535
<p>Test paragraph</p>
@@ -47,7 +47,7 @@ useHotFusion(__fusionData);
4747
test("handles empty code by injecting only the script setup block", () => {
4848
const code = ``;
4949
const keys = ["foo"];
50-
const result = injector(code, "test.js", keys);
50+
const result = injector(code, "test.js", keys, "__aliasedFusionPath__", false);
5151
const expected = `
5252
<script setup>
5353
import { useFusion } from "__aliasedFusionPath__";
@@ -67,7 +67,7 @@ let a = 10;
6767
/* User code end */
6868
`;
6969
const keys = ["first", "last", "email"];
70-
const result = injector(code, "test.js", keys);
70+
const result = injector(code, "test.js", keys, "__aliasedFusionPath__", false);
7171
const expected = `
7272
/* User code start */
7373
let a = 10;
@@ -78,6 +78,42 @@ import useHotFusion from "@fusion/vue/hmr";
7878
const __fusionData = useFusion([first, last, email], __props.fusion);
7979
const { first: first, last: last, email: email } = __fusionData;
8080
useHotFusion(__fusionData);
81+
</script>
82+
`;
83+
expect(result.code).toMatchCode(expected);
84+
});
85+
86+
test("supports custom fusion path", () => {
87+
const code = `console.log("Hello");`;
88+
const keys = ["name", "email"];
89+
const result = injector(code, "test.js", keys, "@custom/fusion-path", false);
90+
const expected = `
91+
console.log("Hello");
92+
<script setup>
93+
import { useFusion } from "@custom/fusion-path";
94+
import useHotFusion from "@fusion/vue/hmr";
95+
const __fusionData = useFusion([name, email], __props.fusion);
96+
const { name: name, email: email } = __fusionData;
97+
useHotFusion(__fusionData);
98+
</script>
99+
`;
100+
expect(result.code).toMatchCode(expected);
101+
});
102+
103+
// TypeScript flag doesn't affect this injector much since it generates new code,
104+
// but including a test for completeness
105+
test("accepts typescript flag without changing behavior", () => {
106+
const code = `console.log("Hello");`;
107+
const keys = ["name", "email"];
108+
const result = injector(code, "test.js", keys, "__aliasedFusionPath__", true);
109+
const expected = `
110+
console.log("Hello");
111+
<script setup>
112+
import { useFusion } from "__aliasedFusionPath__";
113+
import useHotFusion from "@fusion/vue/hmr";
114+
const __fusionData = useFusion([name, email], __props.fusion);
115+
const { name: name, email: email } = __fusionData;
116+
useHotFusion(__fusionData);
81117
</script>
82118
`;
83119
expect(result.code).toMatchCode(expected);

0 commit comments

Comments
 (0)