diff --git a/apps/cli/src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts b/apps/cli/src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts index 39ad9d0..e894fca 100644 --- a/apps/cli/src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts +++ b/apps/cli/src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts @@ -54,6 +54,24 @@ export async function setupTanStackStartAlchemyDeploy( 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( (d) => !d.isExportEquals(), ); @@ -99,6 +117,7 @@ export async function setupTanStackStartAlchemyDeploy( .getElements() .filter((el) => el.getText().includes("tanstackStart")); + let needsReactPlugin = false; tanstackElements.forEach((element) => { if (Node.isCallExpression(element)) { const args = element.getArguments(); @@ -107,6 +126,7 @@ export async function setupTanStackStartAlchemyDeploy( target: "cloudflare-module", customViteReactPlugin: true, }`); + needsReactPlugin = true; } else if ( args.length === 1 && Node.isObjectLiteralExpression(args[0]) @@ -118,15 +138,30 @@ export async function setupTanStackStartAlchemyDeploy( initializer: '"cloudflare-module"', }); } - if (!configObj.getProperty("customViteReactPlugin")) { + const hasCustomViteReactPlugin = !!configObj.getProperty( + "customViteReactPlugin", + ); + if (!hasCustomViteReactPlugin) { configObj.addPropertyAssignment({ name: "customViteReactPlugin", initializer: "true", }); } + needsReactPlugin = true; } } }); + + const hasReactPlugin = initializer + .getElements() + .some( + (el) => + Node.isCallExpression(el) && + el.getExpression().getText() === reactPluginIdentifier, + ); + if (needsReactPlugin && !hasReactPlugin) { + initializer.addElement(`${reactPluginIdentifier}()`); + } } } else { configObject.addPropertyAssignment({ diff --git a/apps/cli/src/helpers/deployment/server-deploy-setup.ts b/apps/cli/src/helpers/deployment/server-deploy-setup.ts index 7eeda04..6137c45 100644 --- a/apps/cli/src/helpers/deployment/server-deploy-setup.ts +++ b/apps/cli/src/helpers/deployment/server-deploy-setup.ts @@ -48,7 +48,7 @@ async function setupWorkersServerDeploy( await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 }); await addPackageDependency({ - devDependencies: ["wrangler", "@types/node", "@cloudflare/workers-types"], + devDependencies: ["wrangler", "@types/node"], projectDir: serverDir, }); } @@ -83,13 +83,7 @@ export async function setupAlchemyServerDeploy( if (!(await fs.pathExists(serverDir))) return; await addPackageDependency({ - devDependencies: [ - "alchemy", - "wrangler", - "@types/node", - "@cloudflare/workers-types", - "dotenv", - ], + devDependencies: ["alchemy", "wrangler", "@types/node", "dotenv"], projectDir: serverDir, }); diff --git a/apps/cli/src/helpers/deployment/workers/workers-tanstack-start-setup.ts b/apps/cli/src/helpers/deployment/workers/workers-tanstack-start-setup.ts index 32b09a3..6353a2e 100644 --- a/apps/cli/src/helpers/deployment/workers/workers-tanstack-start-setup.ts +++ b/apps/cli/src/helpers/deployment/workers/workers-tanstack-start-setup.ts @@ -39,6 +39,22 @@ export async function setupTanstackStartWorkersDeploy( const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath); 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 .getDescendantsOfKind(SyntaxKind.CallExpression) .find((expr) => { @@ -61,7 +77,8 @@ export async function setupTanstackStartWorkersDeploy( .getElements() .findIndex((el) => el.getText().includes("tanstackStart(")); - const tanstackPluginText = 'tanstackStart({ target: "cloudflare-module" })'; + const tanstackPluginText = + 'tanstackStart({ target: "cloudflare-module", customViteReactPlugin: true })'; if (tanstackPluginIndex === -1) { pluginsArray.addElement(tanstackPluginText); @@ -71,5 +88,24 @@ export async function setupTanstackStartWorkersDeploy( [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(); } diff --git a/apps/cli/templates/backend/server/server-base/tsconfig.json.hbs b/apps/cli/templates/backend/server/server-base/tsconfig.json.hbs index 41a38fc..045d7fc 100644 --- a/apps/cli/templates/backend/server/server-base/tsconfig.json.hbs +++ b/apps/cli/templates/backend/server/server-base/tsconfig.json.hbs @@ -8,28 +8,23 @@ "skipLibCheck": true, "baseUrl": "./", "paths": { - "@/*": ["./src/*"] - {{#if (eq orm "prisma")}}, - "prisma": ["node_modules/prisma"] - {{/if}} + "@/*": ["./src/*"]{{#if (eq orm "prisma")}}, + "prisma": ["node_modules/prisma"]{{/if}} }, "outDir": "./dist", "types": [ {{#if (eq runtime "node")}} - "node" + "node" {{else if (eq runtime "bun")}} - "bun" + "bun" {{else if (eq runtime "workers")}} - "@cloudflare/workers-types", - "node" + "node" {{else}} - "node", - "bun" + "node", + "bun" {{/if}} - ], - {{#unless (or (eq backend "convex") (eq backend "none"))}} - "composite": true, - {{/unless}} + ]{{#unless (or (eq backend "convex") (eq backend "none"))}}, + "composite": true{{/unless}}, "jsx": "react-jsx"{{#if (eq backend "hono")}}, "jsxImportSource": "hono/jsx"{{/if}} } diff --git a/apps/cli/templates/frontend/react/tanstack-start/package.json.hbs b/apps/cli/templates/frontend/react/tanstack-start/package.json.hbs index 31589e2..53f80ef 100644 --- a/apps/cli/templates/frontend/react/tanstack-start/package.json.hbs +++ b/apps/cli/templates/frontend/react/tanstack-start/package.json.hbs @@ -35,7 +35,7 @@ "@testing-library/react": "^16.2.0", "@types/react": "^19.0.12", "@types/react-dom": "^19.0.4", - "@vitejs/plugin-react": "^4.5.2", + "@vitejs/plugin-react": "^5.0.1", "jsdom": "^26.0.0", "typescript": "^5.7.2", "vite": "^7.0.2", diff --git a/apps/cli/templates/frontend/react/tanstack-start/vite.config.ts b/apps/cli/templates/frontend/react/tanstack-start/vite.config.ts.hbs similarity index 57% rename from apps/cli/templates/frontend/react/tanstack-start/vite.config.ts rename to apps/cli/templates/frontend/react/tanstack-start/vite.config.ts.hbs index 4996232..ac09426 100644 --- a/apps/cli/templates/frontend/react/tanstack-start/vite.config.ts +++ b/apps/cli/templates/frontend/react/tanstack-start/vite.config.ts.hbs @@ -2,7 +2,13 @@ import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; import { tanstackStart } from "@tanstack/react-start/plugin/vite"; import tailwindcss from "@tailwindcss/vite"; +import viteReact from "@vitejs/plugin-react"; export default defineConfig({ - plugins: [tsconfigPaths(), tailwindcss(), tanstackStart({})], + plugins: [ + tsconfigPaths(), + tailwindcss(), + tanstackStart({ customViteReactPlugin: true }), + viteReact(), + ], });