fix(cli): add viteReact plugin in tanstack start template

This commit is contained in:
Aman Varshney
2025-08-21 14:55:57 +05:30
parent ee971e838c
commit d58fd61575
6 changed files with 92 additions and 26 deletions

View File

@@ -54,6 +54,24 @@ export async function setupTanStackStartAlchemyDeploy(
alchemyImport.setModuleSpecifier("alchemy/cloudflare/tanstack-start"); alchemyImport.setModuleSpecifier("alchemy/cloudflare/tanstack-start");
} }
const reactImport = sourceFile.getImportDeclaration(
"@vitejs/plugin-react",
);
let reactPluginIdentifier = "viteReact";
if (!reactImport) {
sourceFile.addImportDeclaration({
moduleSpecifier: "@vitejs/plugin-react",
defaultImport: "viteReact",
});
} else {
const defaultImport = reactImport.getDefaultImport();
if (defaultImport) {
reactPluginIdentifier = defaultImport.getText();
} else {
reactImport.setDefaultImport("viteReact");
}
}
const exportAssignment = sourceFile.getExportAssignment( const exportAssignment = sourceFile.getExportAssignment(
(d) => !d.isExportEquals(), (d) => !d.isExportEquals(),
); );
@@ -99,6 +117,7 @@ export async function setupTanStackStartAlchemyDeploy(
.getElements() .getElements()
.filter((el) => el.getText().includes("tanstackStart")); .filter((el) => el.getText().includes("tanstackStart"));
let needsReactPlugin = false;
tanstackElements.forEach((element) => { tanstackElements.forEach((element) => {
if (Node.isCallExpression(element)) { if (Node.isCallExpression(element)) {
const args = element.getArguments(); const args = element.getArguments();
@@ -107,6 +126,7 @@ export async function setupTanStackStartAlchemyDeploy(
target: "cloudflare-module", target: "cloudflare-module",
customViteReactPlugin: true, customViteReactPlugin: true,
}`); }`);
needsReactPlugin = true;
} else if ( } else if (
args.length === 1 && args.length === 1 &&
Node.isObjectLiteralExpression(args[0]) Node.isObjectLiteralExpression(args[0])
@@ -118,15 +138,30 @@ export async function setupTanStackStartAlchemyDeploy(
initializer: '"cloudflare-module"', initializer: '"cloudflare-module"',
}); });
} }
if (!configObj.getProperty("customViteReactPlugin")) { const hasCustomViteReactPlugin = !!configObj.getProperty(
"customViteReactPlugin",
);
if (!hasCustomViteReactPlugin) {
configObj.addPropertyAssignment({ configObj.addPropertyAssignment({
name: "customViteReactPlugin", name: "customViteReactPlugin",
initializer: "true", initializer: "true",
}); });
} }
needsReactPlugin = true;
} }
} }
}); });
const hasReactPlugin = initializer
.getElements()
.some(
(el) =>
Node.isCallExpression(el) &&
el.getExpression().getText() === reactPluginIdentifier,
);
if (needsReactPlugin && !hasReactPlugin) {
initializer.addElement(`${reactPluginIdentifier}()`);
}
} }
} else { } else {
configObject.addPropertyAssignment({ configObject.addPropertyAssignment({

View File

@@ -48,7 +48,7 @@ async function setupWorkersServerDeploy(
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 }); await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
await addPackageDependency({ await addPackageDependency({
devDependencies: ["wrangler", "@types/node", "@cloudflare/workers-types"], devDependencies: ["wrangler", "@types/node"],
projectDir: serverDir, projectDir: serverDir,
}); });
} }
@@ -83,13 +83,7 @@ export async function setupAlchemyServerDeploy(
if (!(await fs.pathExists(serverDir))) return; if (!(await fs.pathExists(serverDir))) return;
await addPackageDependency({ await addPackageDependency({
devDependencies: [ devDependencies: ["alchemy", "wrangler", "@types/node", "dotenv"],
"alchemy",
"wrangler",
"@types/node",
"@cloudflare/workers-types",
"dotenv",
],
projectDir: serverDir, projectDir: serverDir,
}); });

View File

@@ -39,6 +39,22 @@ export async function setupTanstackStartWorkersDeploy(
const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath); const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath);
if (!sourceFile) return; if (!sourceFile) return;
const reactImport = sourceFile.getImportDeclaration("@vitejs/plugin-react");
let reactPluginIdentifier = "viteReact";
if (!reactImport) {
sourceFile.addImportDeclaration({
moduleSpecifier: "@vitejs/plugin-react",
defaultImport: "viteReact",
});
} else {
const defaultImport = reactImport.getDefaultImport();
if (defaultImport) {
reactPluginIdentifier = defaultImport.getText();
} else {
reactImport.setDefaultImport("viteReact");
}
}
const defineCall = sourceFile const defineCall = sourceFile
.getDescendantsOfKind(SyntaxKind.CallExpression) .getDescendantsOfKind(SyntaxKind.CallExpression)
.find((expr) => { .find((expr) => {
@@ -61,7 +77,8 @@ export async function setupTanstackStartWorkersDeploy(
.getElements() .getElements()
.findIndex((el) => el.getText().includes("tanstackStart(")); .findIndex((el) => el.getText().includes("tanstackStart("));
const tanstackPluginText = 'tanstackStart({ target: "cloudflare-module" })'; const tanstackPluginText =
'tanstackStart({ target: "cloudflare-module", customViteReactPlugin: true })';
if (tanstackPluginIndex === -1) { if (tanstackPluginIndex === -1) {
pluginsArray.addElement(tanstackPluginText); pluginsArray.addElement(tanstackPluginText);
@@ -71,5 +88,24 @@ export async function setupTanstackStartWorkersDeploy(
[tanstackPluginIndex].replaceWithText(tanstackPluginText); [tanstackPluginIndex].replaceWithText(tanstackPluginText);
} }
const hasReactPlugin = pluginsArray
.getElements()
.some(
(el) =>
Node.isCallExpression(el) &&
el.getExpression().getText() === reactPluginIdentifier,
);
if (!hasReactPlugin) {
const nextIndex =
pluginsArray
.getElements()
.findIndex((el) => el.getText().includes("tanstackStart(")) + 1;
if (nextIndex > 0) {
pluginsArray.insertElement(nextIndex, `${reactPluginIdentifier}()`);
} else {
pluginsArray.addElement(`${reactPluginIdentifier}()`);
}
}
await tsProject.save(); await tsProject.save();
} }

View File

@@ -8,28 +8,23 @@
"skipLibCheck": true, "skipLibCheck": true,
"baseUrl": "./", "baseUrl": "./",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]{{#if (eq orm "prisma")}},
{{#if (eq orm "prisma")}}, "prisma": ["node_modules/prisma"]{{/if}}
"prisma": ["node_modules/prisma"]
{{/if}}
}, },
"outDir": "./dist", "outDir": "./dist",
"types": [ "types": [
{{#if (eq runtime "node")}} {{#if (eq runtime "node")}}
"node" "node"
{{else if (eq runtime "bun")}} {{else if (eq runtime "bun")}}
"bun" "bun"
{{else if (eq runtime "workers")}} {{else if (eq runtime "workers")}}
"@cloudflare/workers-types", "node"
"node"
{{else}} {{else}}
"node", "node",
"bun" "bun"
{{/if}} {{/if}}
], ]{{#unless (or (eq backend "convex") (eq backend "none"))}},
{{#unless (or (eq backend "convex") (eq backend "none"))}} "composite": true{{/unless}},
"composite": true,
{{/unless}}
"jsx": "react-jsx"{{#if (eq backend "hono")}}, "jsx": "react-jsx"{{#if (eq backend "hono")}},
"jsxImportSource": "hono/jsx"{{/if}} "jsxImportSource": "hono/jsx"{{/if}}
} }

View File

@@ -35,7 +35,7 @@
"@testing-library/react": "^16.2.0", "@testing-library/react": "^16.2.0",
"@types/react": "^19.0.12", "@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4", "@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.5.2", "@vitejs/plugin-react": "^5.0.1",
"jsdom": "^26.0.0", "jsdom": "^26.0.0",
"typescript": "^5.7.2", "typescript": "^5.7.2",
"vite": "^7.0.2", "vite": "^7.0.2",

View File

@@ -2,7 +2,13 @@ import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths"; import tsconfigPaths from "vite-tsconfig-paths";
import { tanstackStart } from "@tanstack/react-start/plugin/vite"; import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import tailwindcss from "@tailwindcss/vite"; import tailwindcss from "@tailwindcss/vite";
import viteReact from "@vitejs/plugin-react";
export default defineConfig({ export default defineConfig({
plugins: [tsconfigPaths(), tailwindcss(), tanstackStart({})], plugins: [
tsconfigPaths(),
tailwindcss(),
tanstackStart({ customViteReactPlugin: true }),
viteReact(),
],
}); });