mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
feat(cli): add react router support with alchemy (#542)
This commit is contained in:
@@ -138,7 +138,7 @@ export const dependencyVersionMap = {
|
|||||||
"@sveltejs/adapter-cloudflare": "^7.2.1",
|
"@sveltejs/adapter-cloudflare": "^7.2.1",
|
||||||
"@cloudflare/workers-types": "^4.20250822.0",
|
"@cloudflare/workers-types": "^4.20250822.0",
|
||||||
|
|
||||||
alchemy: "^0.62.1",
|
alchemy: "^0.63.0",
|
||||||
// temporary workaround for alchemy + tanstack start
|
// temporary workaround for alchemy + tanstack start
|
||||||
nitropack: "^2.12.4",
|
nitropack: "^2.12.4",
|
||||||
|
|
||||||
|
|||||||
@@ -76,11 +76,12 @@ export async function createProject(options: ProjectConfig) {
|
|||||||
|
|
||||||
await handleExtras(projectDir, options);
|
await handleExtras(projectDir, options);
|
||||||
|
|
||||||
|
await setupEnvironmentVariables(options);
|
||||||
|
await updatePackageConfigurations(projectDir, options);
|
||||||
|
|
||||||
await setupWebDeploy(options);
|
await setupWebDeploy(options);
|
||||||
await setupServerDeploy(options);
|
await setupServerDeploy(options);
|
||||||
|
|
||||||
await setupEnvironmentVariables(options);
|
|
||||||
await updatePackageConfigurations(projectDir, options);
|
|
||||||
await createReadme(projectDir, options);
|
await createReadme(projectDir, options);
|
||||||
|
|
||||||
await writeBtsConfig(options);
|
await writeBtsConfig(options);
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ function generateReadmeContent(options: ProjectConfig): string {
|
|||||||
frontend = ["tanstack-router"],
|
frontend = ["tanstack-router"],
|
||||||
backend = "hono",
|
backend = "hono",
|
||||||
api = "trpc",
|
api = "trpc",
|
||||||
|
webDeploy,
|
||||||
|
serverDeploy,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const isConvex = backend === "convex";
|
const isConvex = backend === "convex";
|
||||||
@@ -103,6 +105,7 @@ Follow the prompts to create a new Convex project and connect it to your applica
|
|||||||
packageManagerRunCmd,
|
packageManagerRunCmd,
|
||||||
orm,
|
orm,
|
||||||
options.dbSetup,
|
options.dbSetup,
|
||||||
|
options.serverDeploy,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +123,8 @@ ${
|
|||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
${generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeploy)}
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
\`\`\`
|
\`\`\`
|
||||||
@@ -475,6 +480,7 @@ function generateDatabaseSetup(
|
|||||||
packageManagerRunCmd: string,
|
packageManagerRunCmd: string,
|
||||||
orm: ORM,
|
orm: ORM,
|
||||||
dbSetup: DatabaseSetup,
|
dbSetup: DatabaseSetup,
|
||||||
|
serverDeploy?: string,
|
||||||
): string {
|
): string {
|
||||||
if (database === "none") {
|
if (database === "none") {
|
||||||
return "";
|
return "";
|
||||||
@@ -494,7 +500,9 @@ function generateDatabaseSetup(
|
|||||||
1. Start the local SQLite database:
|
1. Start the local SQLite database:
|
||||||
${
|
${
|
||||||
dbSetup === "d1"
|
dbSetup === "d1"
|
||||||
? "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command."
|
? serverDeploy === "alchemy"
|
||||||
|
? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy."
|
||||||
|
: "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command."
|
||||||
: `\`\`\`bash
|
: `\`\`\`bash
|
||||||
cd apps/server && ${packageManagerRunCmd} db:local
|
cd apps/server && ${packageManagerRunCmd} db:local
|
||||||
\`\`\`
|
\`\`\`
|
||||||
@@ -632,3 +640,51 @@ function generateScriptsList(
|
|||||||
|
|
||||||
return scripts;
|
return scripts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateDeploymentCommands(
|
||||||
|
packageManagerRunCmd: string,
|
||||||
|
webDeploy?: string,
|
||||||
|
serverDeploy?: string,
|
||||||
|
): string {
|
||||||
|
const lines: string[] = [];
|
||||||
|
|
||||||
|
if (webDeploy === "alchemy" || serverDeploy === "alchemy") {
|
||||||
|
lines.push("## Deployment (Alchemy)");
|
||||||
|
if (webDeploy === "alchemy" && serverDeploy !== "alchemy") {
|
||||||
|
lines.push(
|
||||||
|
`- Web dev: cd apps/web && ${packageManagerRunCmd} dev`,
|
||||||
|
`- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`,
|
||||||
|
`- Web destroy: cd apps/web && ${packageManagerRunCmd} destroy`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (serverDeploy === "alchemy" && webDeploy !== "alchemy") {
|
||||||
|
lines.push(
|
||||||
|
`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`,
|
||||||
|
`- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`,
|
||||||
|
`- Server destroy: cd apps/server && ${packageManagerRunCmd} destroy`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (webDeploy === "alchemy" && serverDeploy === "alchemy") {
|
||||||
|
lines.push(
|
||||||
|
`- Dev: ${packageManagerRunCmd} dev`,
|
||||||
|
`- Deploy: ${packageManagerRunCmd} deploy`,
|
||||||
|
`- Destroy: ${packageManagerRunCmd} destroy`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webDeploy === "wrangler" || serverDeploy === "wrangler") {
|
||||||
|
lines.push("\n## Deployment (Cloudflare Wrangler)");
|
||||||
|
if (webDeploy === "wrangler") {
|
||||||
|
lines.push(`- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`);
|
||||||
|
}
|
||||||
|
if (serverDeploy === "wrangler") {
|
||||||
|
lines.push(
|
||||||
|
`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`,
|
||||||
|
`- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.length ? `\n${lines.join("\n")}\n` : "";
|
||||||
|
}
|
||||||
|
|||||||
@@ -412,15 +412,15 @@ function getAlchemyDeployInstructions(
|
|||||||
|
|
||||||
if (webDeploy === "alchemy" && serverDeploy !== "alchemy") {
|
if (webDeploy === "alchemy" && serverDeploy !== "alchemy") {
|
||||||
instructions.push(
|
instructions.push(
|
||||||
`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} alchemy:dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`,
|
`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`,
|
||||||
);
|
);
|
||||||
} else if (serverDeploy === "alchemy" && webDeploy !== "alchemy") {
|
} else if (serverDeploy === "alchemy" && webDeploy !== "alchemy") {
|
||||||
instructions.push(
|
instructions.push(
|
||||||
`${pc.bold("Deploy server with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/server && ${runCmd} alchemy:dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/server && ${runCmd} destroy`}`,
|
`${pc.bold("Deploy server with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/server && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/server && ${runCmd} destroy`}`,
|
||||||
);
|
);
|
||||||
} else if (webDeploy === "alchemy" && serverDeploy === "alchemy") {
|
} else if (webDeploy === "alchemy" && serverDeploy === "alchemy") {
|
||||||
instructions.push(
|
instructions.push(
|
||||||
`${pc.bold("Deploy with Alchemy:")}\n${pc.cyan("•")} Dev: ${`${runCmd} alchemy:dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`,
|
`${pc.bold("Deploy with Alchemy:")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -835,12 +835,6 @@ export async function setupDeploymentTemplates(
|
|||||||
serverAppDir,
|
serverAppDir,
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
await processAndCopyFiles(
|
|
||||||
"wrangler.jsonc.hbs",
|
|
||||||
alchemyTemplateSrc,
|
|
||||||
serverAppDir,
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -885,12 +879,6 @@ export async function setupDeploymentTemplates(
|
|||||||
serverAppDir,
|
serverAppDir,
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
await processAndCopyFiles(
|
|
||||||
"wrangler.jsonc.hbs",
|
|
||||||
alchemyTemplateSrc,
|
|
||||||
serverAppDir,
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export async function setupCombinedAlchemyDeploy(
|
|||||||
...pkg.scripts,
|
...pkg.scripts,
|
||||||
deploy: "alchemy deploy",
|
deploy: "alchemy deploy",
|
||||||
destroy: "alchemy destroy",
|
destroy: "alchemy destroy",
|
||||||
"alchemy:dev": "alchemy dev",
|
dev: "alchemy dev",
|
||||||
};
|
};
|
||||||
await fs.writeJson(rootPkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(rootPkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
@@ -49,18 +49,32 @@ export async function setupCombinedAlchemyDeploy(
|
|||||||
const isSolid = frontend.includes("solid");
|
const isSolid = frontend.includes("solid");
|
||||||
|
|
||||||
if (isNext) {
|
if (isNext) {
|
||||||
await setupNextAlchemyDeploy(projectDir, packageManager);
|
await setupNextAlchemyDeploy(projectDir, packageManager, {
|
||||||
|
skipAppScripts: true,
|
||||||
|
});
|
||||||
} else if (isNuxt) {
|
} else if (isNuxt) {
|
||||||
await setupNuxtAlchemyDeploy(projectDir, packageManager);
|
await setupNuxtAlchemyDeploy(projectDir, packageManager, {
|
||||||
|
skipAppScripts: true,
|
||||||
|
});
|
||||||
} else if (isSvelte) {
|
} else if (isSvelte) {
|
||||||
await setupSvelteAlchemyDeploy(projectDir, packageManager);
|
await setupSvelteAlchemyDeploy(projectDir, packageManager, {
|
||||||
|
skipAppScripts: true,
|
||||||
|
});
|
||||||
} else if (isTanstackStart) {
|
} else if (isTanstackStart) {
|
||||||
await setupTanStackStartAlchemyDeploy(projectDir, packageManager);
|
await setupTanStackStartAlchemyDeploy(projectDir, packageManager, {
|
||||||
|
skipAppScripts: true,
|
||||||
|
});
|
||||||
} else if (isTanstackRouter) {
|
} else if (isTanstackRouter) {
|
||||||
await setupTanStackRouterAlchemyDeploy(projectDir, packageManager);
|
await setupTanStackRouterAlchemyDeploy(projectDir, packageManager, {
|
||||||
|
skipAppScripts: true,
|
||||||
|
});
|
||||||
} else if (isReactRouter) {
|
} else if (isReactRouter) {
|
||||||
await setupReactRouterAlchemyDeploy(projectDir, packageManager);
|
await setupReactRouterAlchemyDeploy(projectDir, packageManager, {
|
||||||
|
skipAppScripts: true,
|
||||||
|
});
|
||||||
} else if (isSolid) {
|
} else if (isSolid) {
|
||||||
await setupSolidAlchemyDeploy(projectDir, packageManager);
|
await setupSolidAlchemyDeploy(projectDir, packageManager, {
|
||||||
|
skipAppScripts: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { addPackageDependency } from "../../../utils/add-package-deps";
|
|||||||
export async function setupNextAlchemyDeploy(
|
export async function setupNextAlchemyDeploy(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
_packageManager: PackageManager,
|
_packageManager: PackageManager,
|
||||||
|
options?: { skipAppScripts?: boolean },
|
||||||
) {
|
) {
|
||||||
const webAppDir = path.join(projectDir, "apps/web");
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
if (!(await fs.pathExists(webAppDir))) return;
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
@@ -19,12 +20,14 @@ export async function setupNextAlchemyDeploy(
|
|||||||
if (await fs.pathExists(pkgPath)) {
|
if (await fs.pathExists(pkgPath)) {
|
||||||
const pkg = await fs.readJson(pkgPath);
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
|
||||||
pkg.scripts = {
|
if (!options?.skipAppScripts) {
|
||||||
...pkg.scripts,
|
pkg.scripts = {
|
||||||
deploy: "alchemy deploy",
|
...pkg.scripts,
|
||||||
destroy: "alchemy destroy",
|
deploy: "alchemy deploy",
|
||||||
"alchemy:dev": "alchemy dev",
|
destroy: "alchemy destroy",
|
||||||
};
|
dev: "alchemy dev",
|
||||||
|
};
|
||||||
|
}
|
||||||
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { addPackageDependency } from "../../../utils/add-package-deps";
|
|||||||
export async function setupNuxtAlchemyDeploy(
|
export async function setupNuxtAlchemyDeploy(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
_packageManager: PackageManager,
|
_packageManager: PackageManager,
|
||||||
|
options?: { skipAppScripts?: boolean },
|
||||||
) {
|
) {
|
||||||
const webAppDir = path.join(projectDir, "apps/web");
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
if (!(await fs.pathExists(webAppDir))) return;
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
@@ -20,12 +21,14 @@ export async function setupNuxtAlchemyDeploy(
|
|||||||
if (await fs.pathExists(pkgPath)) {
|
if (await fs.pathExists(pkgPath)) {
|
||||||
const pkg = await fs.readJson(pkgPath);
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
|
||||||
pkg.scripts = {
|
if (!options?.skipAppScripts) {
|
||||||
...pkg.scripts,
|
pkg.scripts = {
|
||||||
deploy: "alchemy deploy",
|
...pkg.scripts,
|
||||||
destroy: "alchemy destroy",
|
deploy: "alchemy deploy",
|
||||||
"alchemy:dev": "alchemy dev",
|
destroy: "alchemy destroy",
|
||||||
};
|
dev: "alchemy dev",
|
||||||
|
};
|
||||||
|
}
|
||||||
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
import { IndentationText, Node, Project, QuoteKind } from "ts-morph";
|
|
||||||
import type { PackageManager } from "../../../types";
|
import type { PackageManager } from "../../../types";
|
||||||
import { addPackageDependency } from "../../../utils/add-package-deps";
|
import { addPackageDependency } from "../../../utils/add-package-deps";
|
||||||
|
|
||||||
export async function setupReactRouterAlchemyDeploy(
|
export async function setupReactRouterAlchemyDeploy(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
_packageManager: PackageManager,
|
_packageManager: PackageManager,
|
||||||
|
options?: { skipAppScripts?: boolean },
|
||||||
) {
|
) {
|
||||||
const webAppDir = path.join(projectDir, "apps/web");
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
if (!(await fs.pathExists(webAppDir))) return;
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
|
|
||||||
await addPackageDependency({
|
await addPackageDependency({
|
||||||
devDependencies: ["alchemy", "@cloudflare/vite-plugin", "dotenv"],
|
devDependencies: ["alchemy", "dotenv"],
|
||||||
projectDir: webAppDir,
|
projectDir: webAppDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,149 +20,14 @@ export async function setupReactRouterAlchemyDeploy(
|
|||||||
if (await fs.pathExists(pkgPath)) {
|
if (await fs.pathExists(pkgPath)) {
|
||||||
const pkg = await fs.readJson(pkgPath);
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
|
||||||
pkg.scripts = {
|
if (!options?.skipAppScripts) {
|
||||||
...pkg.scripts,
|
pkg.scripts = {
|
||||||
deploy: "alchemy deploy",
|
...pkg.scripts,
|
||||||
destroy: "alchemy destroy",
|
deploy: "alchemy deploy",
|
||||||
"alchemy:dev": "alchemy dev",
|
destroy: "alchemy destroy",
|
||||||
};
|
dev: "alchemy dev",
|
||||||
|
};
|
||||||
|
}
|
||||||
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const viteConfigPath = path.join(webAppDir, "vite.config.ts");
|
|
||||||
if (await fs.pathExists(viteConfigPath)) {
|
|
||||||
try {
|
|
||||||
const project = new Project({
|
|
||||||
manipulationSettings: {
|
|
||||||
indentationText: IndentationText.TwoSpaces,
|
|
||||||
quoteKind: QuoteKind.Double,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
project.addSourceFileAtPath(viteConfigPath);
|
|
||||||
const sourceFile = project.getSourceFileOrThrow(viteConfigPath);
|
|
||||||
|
|
||||||
const alchemyImport = sourceFile.getImportDeclaration(
|
|
||||||
"alchemy/cloudflare/react-router",
|
|
||||||
);
|
|
||||||
if (!alchemyImport) {
|
|
||||||
sourceFile.addImportDeclaration({
|
|
||||||
moduleSpecifier: "alchemy/cloudflare/react-router",
|
|
||||||
defaultImport: "alchemy",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const exportAssignment = sourceFile.getExportAssignment(
|
|
||||||
(d) => !d.isExportEquals(),
|
|
||||||
);
|
|
||||||
if (!exportAssignment) return;
|
|
||||||
|
|
||||||
const defineConfigCall = exportAssignment.getExpression();
|
|
||||||
if (
|
|
||||||
!Node.isCallExpression(defineConfigCall) ||
|
|
||||||
defineConfigCall.getExpression().getText() !== "defineConfig"
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let configObject = defineConfigCall.getArguments()[0];
|
|
||||||
if (!configObject) {
|
|
||||||
configObject = defineConfigCall.addArgument("{}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Node.isObjectLiteralExpression(configObject)) {
|
|
||||||
const pluginsProperty = configObject.getProperty("plugins");
|
|
||||||
if (pluginsProperty && Node.isPropertyAssignment(pluginsProperty)) {
|
|
||||||
const initializer = pluginsProperty.getInitializer();
|
|
||||||
if (Node.isArrayLiteralExpression(initializer)) {
|
|
||||||
const hasCloudflarePlugin = initializer
|
|
||||||
.getElements()
|
|
||||||
.some((el) => el.getText().includes("cloudflare("));
|
|
||||||
|
|
||||||
if (!hasCloudflarePlugin) {
|
|
||||||
initializer.addElement("alchemy()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!pluginsProperty) {
|
|
||||||
configObject.addPropertyAssignment({
|
|
||||||
name: "plugins",
|
|
||||||
initializer: "[alchemy()]",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await project.save();
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Failed to update vite.config.ts:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const reactRouterConfigPath = path.join(webAppDir, "react-router.config.ts");
|
|
||||||
if (await fs.pathExists(reactRouterConfigPath)) {
|
|
||||||
try {
|
|
||||||
const project = new Project({
|
|
||||||
manipulationSettings: {
|
|
||||||
indentationText: IndentationText.TwoSpaces,
|
|
||||||
quoteKind: QuoteKind.Double,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
project.addSourceFileAtPath(reactRouterConfigPath);
|
|
||||||
const sourceFile = project.getSourceFileOrThrow(reactRouterConfigPath);
|
|
||||||
|
|
||||||
const exportAssignment = sourceFile.getExportAssignment(
|
|
||||||
(d) => !d.isExportEquals(),
|
|
||||||
);
|
|
||||||
if (!exportAssignment) return;
|
|
||||||
|
|
||||||
const configExpression = exportAssignment.getExpression();
|
|
||||||
let configObject: Node | undefined;
|
|
||||||
|
|
||||||
if (Node.isObjectLiteralExpression(configExpression)) {
|
|
||||||
configObject = configExpression;
|
|
||||||
} else if (Node.isSatisfiesExpression(configExpression)) {
|
|
||||||
const expression = configExpression.getExpression();
|
|
||||||
if (Node.isObjectLiteralExpression(expression)) {
|
|
||||||
configObject = expression;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!configObject || !Node.isObjectLiteralExpression(configObject))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const futureProperty = configObject.getProperty("future");
|
|
||||||
|
|
||||||
if (!futureProperty) {
|
|
||||||
configObject.addPropertyAssignment({
|
|
||||||
name: "future",
|
|
||||||
initializer: `{
|
|
||||||
unstable_viteEnvironmentApi: true,
|
|
||||||
}`,
|
|
||||||
});
|
|
||||||
} else if (Node.isPropertyAssignment(futureProperty)) {
|
|
||||||
const futureInitializer = futureProperty.getInitializer();
|
|
||||||
|
|
||||||
if (Node.isObjectLiteralExpression(futureInitializer)) {
|
|
||||||
const viteEnvApiProp = futureInitializer.getProperty(
|
|
||||||
"unstable_viteEnvironmentApi",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!viteEnvApiProp) {
|
|
||||||
futureInitializer.addPropertyAssignment({
|
|
||||||
name: "unstable_viteEnvironmentApi",
|
|
||||||
initializer: "true",
|
|
||||||
});
|
|
||||||
} else if (Node.isPropertyAssignment(viteEnvApiProp)) {
|
|
||||||
const value = viteEnvApiProp.getInitializer()?.getText();
|
|
||||||
if (value === "false") {
|
|
||||||
viteEnvApiProp.setInitializer("true");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await project.save();
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Failed to update react-router.config.ts:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { addPackageDependency } from "../../../utils/add-package-deps";
|
|||||||
export async function setupSolidAlchemyDeploy(
|
export async function setupSolidAlchemyDeploy(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
_packageManager: PackageManager,
|
_packageManager: PackageManager,
|
||||||
|
options?: { skipAppScripts?: boolean },
|
||||||
) {
|
) {
|
||||||
const webAppDir = path.join(projectDir, "apps/web");
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
if (!(await fs.pathExists(webAppDir))) return;
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
@@ -19,12 +20,14 @@ export async function setupSolidAlchemyDeploy(
|
|||||||
if (await fs.pathExists(pkgPath)) {
|
if (await fs.pathExists(pkgPath)) {
|
||||||
const pkg = await fs.readJson(pkgPath);
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
|
||||||
pkg.scripts = {
|
if (!options?.skipAppScripts) {
|
||||||
...pkg.scripts,
|
pkg.scripts = {
|
||||||
deploy: "alchemy deploy",
|
...pkg.scripts,
|
||||||
destroy: "alchemy destroy",
|
deploy: "alchemy deploy",
|
||||||
"alchemy:dev": "alchemy dev",
|
destroy: "alchemy destroy",
|
||||||
};
|
dev: "alchemy dev",
|
||||||
|
};
|
||||||
|
}
|
||||||
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { addPackageDependency } from "../../../utils/add-package-deps";
|
|||||||
export async function setupSvelteAlchemyDeploy(
|
export async function setupSvelteAlchemyDeploy(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
_packageManager: PackageManager,
|
_packageManager: PackageManager,
|
||||||
|
options?: { skipAppScripts?: boolean },
|
||||||
) {
|
) {
|
||||||
const webAppDir = path.join(projectDir, "apps/web");
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
if (!(await fs.pathExists(webAppDir))) return;
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
@@ -20,12 +21,15 @@ export async function setupSvelteAlchemyDeploy(
|
|||||||
if (await fs.pathExists(pkgPath)) {
|
if (await fs.pathExists(pkgPath)) {
|
||||||
const pkg = await fs.readJson(pkgPath);
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
|
||||||
pkg.scripts = {
|
if (!options?.skipAppScripts) {
|
||||||
...pkg.scripts,
|
pkg.scripts = {
|
||||||
deploy: "alchemy deploy",
|
...pkg.scripts,
|
||||||
destroy: "alchemy destroy",
|
deploy: "alchemy deploy",
|
||||||
"alchemy:dev": "alchemy dev",
|
destroy: "alchemy destroy",
|
||||||
};
|
dev: "alchemy dev",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { addPackageDependency } from "../../../utils/add-package-deps";
|
|||||||
export async function setupTanStackRouterAlchemyDeploy(
|
export async function setupTanStackRouterAlchemyDeploy(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
_packageManager: PackageManager,
|
_packageManager: PackageManager,
|
||||||
|
options?: { skipAppScripts?: boolean },
|
||||||
) {
|
) {
|
||||||
const webAppDir = path.join(projectDir, "apps/web");
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
if (!(await fs.pathExists(webAppDir))) return;
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
@@ -19,12 +20,15 @@ export async function setupTanStackRouterAlchemyDeploy(
|
|||||||
if (await fs.pathExists(pkgPath)) {
|
if (await fs.pathExists(pkgPath)) {
|
||||||
const pkg = await fs.readJson(pkgPath);
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
|
||||||
pkg.scripts = {
|
if (!options?.skipAppScripts) {
|
||||||
...pkg.scripts,
|
pkg.scripts = {
|
||||||
deploy: "alchemy deploy",
|
...pkg.scripts,
|
||||||
destroy: "alchemy destroy",
|
deploy: "alchemy deploy",
|
||||||
"alchemy:dev": "alchemy dev",
|
destroy: "alchemy destroy",
|
||||||
};
|
dev: "alchemy dev",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { addPackageDependency } from "../../../utils/add-package-deps";
|
|||||||
export async function setupTanStackStartAlchemyDeploy(
|
export async function setupTanStackStartAlchemyDeploy(
|
||||||
projectDir: string,
|
projectDir: string,
|
||||||
_packageManager: PackageManager,
|
_packageManager: PackageManager,
|
||||||
|
options?: { skipAppScripts?: boolean },
|
||||||
) {
|
) {
|
||||||
const webAppDir = path.join(projectDir, "apps/web");
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
if (!(await fs.pathExists(webAppDir))) return;
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
@@ -20,12 +21,15 @@ export async function setupTanStackStartAlchemyDeploy(
|
|||||||
if (await fs.pathExists(pkgPath)) {
|
if (await fs.pathExists(pkgPath)) {
|
||||||
const pkg = await fs.readJson(pkgPath);
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
|
||||||
pkg.scripts = {
|
if (!options?.skipAppScripts) {
|
||||||
...pkg.scripts,
|
pkg.scripts = {
|
||||||
deploy: "alchemy deploy",
|
...pkg.scripts,
|
||||||
destroy: "alchemy destroy",
|
deploy: "alchemy deploy",
|
||||||
"alchemy:dev": "alchemy dev",
|
destroy: "alchemy destroy",
|
||||||
};
|
dev: "alchemy dev",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,11 +99,9 @@ export async function setupAlchemyServerDeploy(
|
|||||||
|
|
||||||
packageJson.scripts = {
|
packageJson.scripts = {
|
||||||
...packageJson.scripts,
|
...packageJson.scripts,
|
||||||
dev: "wrangler dev --port=3000",
|
dev: "alchemy dev",
|
||||||
build: "wrangler deploy --dry-run",
|
|
||||||
deploy: "alchemy deploy",
|
deploy: "alchemy deploy",
|
||||||
destroy: "alchemy destroy",
|
destroy: "alchemy destroy",
|
||||||
"alchemy:dev": "alchemy dev",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ export async function getDeploymentChoice(
|
|||||||
return "none";
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasIncompatibleFrontend = frontend.some(
|
const hasIncompatibleFrontend = frontend.some((f) => f === "next");
|
||||||
(f) => f === "next" || f === "react-router",
|
|
||||||
);
|
|
||||||
const availableDeployments = hasIncompatibleFrontend
|
const availableDeployments = hasIncompatibleFrontend
|
||||||
? ["wrangler", "none"]
|
? ["wrangler", "none"]
|
||||||
: ["wrangler", "alchemy", "none"];
|
: ["wrangler", "alchemy", "none"];
|
||||||
@@ -84,9 +82,7 @@ export async function getDeploymentToAdd(
|
|||||||
return "none";
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasIncompatibleFrontend = frontend.some(
|
const hasIncompatibleFrontend = frontend.some((f) => f === "next");
|
||||||
(f) => f === "next" || f === "react-router",
|
|
||||||
);
|
|
||||||
|
|
||||||
const options: DeploymentOption[] = [];
|
const options: DeploymentOption[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -324,9 +324,7 @@ export function validateAlchemyCompatibility(
|
|||||||
const isAlchemyServerDeploy = serverDeploy === "alchemy";
|
const isAlchemyServerDeploy = serverDeploy === "alchemy";
|
||||||
|
|
||||||
if (isAlchemyWebDeploy || isAlchemyServerDeploy) {
|
if (isAlchemyWebDeploy || isAlchemyServerDeploy) {
|
||||||
const incompatibleFrontends = frontends.filter(
|
const incompatibleFrontends = frontends.filter((f) => f === "next");
|
||||||
(f) => f === "next" || f === "react-router",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (incompatibleFrontends.length > 0) {
|
if (incompatibleFrontends.length > 0) {
|
||||||
const deployType =
|
const deployType =
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { Vite } from "alchemy/cloudflare";
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq serverDeploy "alchemy")}}
|
{{#if (eq serverDeploy "alchemy")}}
|
||||||
import { Worker, WranglerJson } from "alchemy/cloudflare";
|
import { Worker } from "alchemy/cloudflare";
|
||||||
{{#if (eq dbSetup "d1")}}
|
{{#if (eq dbSetup "d1")}}
|
||||||
import { D1Database } from "alchemy/cloudflare";
|
import { D1Database } from "alchemy/cloudflare";
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -44,7 +44,6 @@ await Exec("db-generate", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const db = await D1Database("database", {
|
const db = await D1Database("database", {
|
||||||
name: `${app.name}-${app.stage}-db`,
|
|
||||||
migrationsDir: "apps/server/src/db/migrations",
|
migrationsDir: "apps/server/src/db/migrations",
|
||||||
});
|
});
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -53,7 +52,6 @@ const db = await D1Database("database", {
|
|||||||
{{#if (includes frontend "next")}}
|
{{#if (includes frontend "next")}}
|
||||||
export const web = await Next("web", {
|
export const web = await Next("web", {
|
||||||
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
||||||
name: `${app.name}-${app.stage}-web`,
|
|
||||||
bindings: {
|
bindings: {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL || "",
|
NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL || "",
|
||||||
@@ -68,7 +66,6 @@ export const web = await Next("web", {
|
|||||||
{{else if (includes frontend "nuxt")}}
|
{{else if (includes frontend "nuxt")}}
|
||||||
export const web = await Nuxt("web", {
|
export const web = await Nuxt("web", {
|
||||||
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
||||||
name: `${app.name}-${app.stage}-web`,
|
|
||||||
bindings: {
|
bindings: {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
NUXT_PUBLIC_CONVEX_URL: process.env.NUXT_PUBLIC_CONVEX_URL || "",
|
NUXT_PUBLIC_CONVEX_URL: process.env.NUXT_PUBLIC_CONVEX_URL || "",
|
||||||
@@ -83,7 +80,6 @@ export const web = await Nuxt("web", {
|
|||||||
{{else if (includes frontend "svelte")}}
|
{{else if (includes frontend "svelte")}}
|
||||||
export const web = await SvelteKit("web", {
|
export const web = await SvelteKit("web", {
|
||||||
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
||||||
name: `${app.name}-${app.stage}-web`,
|
|
||||||
bindings: {
|
bindings: {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
PUBLIC_CONVEX_URL: process.env.PUBLIC_CONVEX_URL || "",
|
PUBLIC_CONVEX_URL: process.env.PUBLIC_CONVEX_URL || "",
|
||||||
@@ -98,7 +94,6 @@ export const web = await SvelteKit("web", {
|
|||||||
{{else if (includes frontend "tanstack-start")}}
|
{{else if (includes frontend "tanstack-start")}}
|
||||||
export const web = await TanStackStart("web", {
|
export const web = await TanStackStart("web", {
|
||||||
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
||||||
name: `${app.name}-${app.stage}-web`,
|
|
||||||
bindings: {
|
bindings: {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
|
VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
|
||||||
@@ -113,7 +108,6 @@ export const web = await TanStackStart("web", {
|
|||||||
{{else if (includes frontend "tanstack-router")}}
|
{{else if (includes frontend "tanstack-router")}}
|
||||||
export const web = await Vite("web", {
|
export const web = await Vite("web", {
|
||||||
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
||||||
name: `${app.name}-${app.stage}-web`,
|
|
||||||
assets: "dist",
|
assets: "dist",
|
||||||
bindings: {
|
bindings: {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
@@ -129,7 +123,6 @@ export const web = await Vite("web", {
|
|||||||
{{else if (includes frontend "react-router")}}
|
{{else if (includes frontend "react-router")}}
|
||||||
export const web = await ReactRouter("web", {
|
export const web = await ReactRouter("web", {
|
||||||
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
||||||
name: `${app.name}-${app.stage}-web`,
|
|
||||||
bindings: {
|
bindings: {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
|
VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
|
||||||
@@ -144,7 +137,6 @@ export const web = await ReactRouter("web", {
|
|||||||
{{else if (includes frontend "solid")}}
|
{{else if (includes frontend "solid")}}
|
||||||
export const web = await Vite("web", {
|
export const web = await Vite("web", {
|
||||||
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
||||||
name: `${app.name}-${app.stage}-web`,
|
|
||||||
assets: "dist",
|
assets: "dist",
|
||||||
bindings: {
|
bindings: {
|
||||||
{{#if (eq backend "convex")}}
|
{{#if (eq backend "convex")}}
|
||||||
@@ -163,7 +155,6 @@ export const web = await Vite("web", {
|
|||||||
{{#if (eq serverDeploy "alchemy")}}
|
{{#if (eq serverDeploy "alchemy")}}
|
||||||
export const server = await Worker("server", {
|
export const server = await Worker("server", {
|
||||||
{{#if (eq webDeploy "alchemy")}}cwd: "apps/server",{{/if}}
|
{{#if (eq webDeploy "alchemy")}}cwd: "apps/server",{{/if}}
|
||||||
name: `${app.name}-${app.stage}`,
|
|
||||||
entrypoint: "src/index.ts",
|
entrypoint: "src/index.ts",
|
||||||
compatibility: "node",
|
compatibility: "node",
|
||||||
bindings: {
|
bindings: {
|
||||||
@@ -188,14 +179,8 @@ export const server = await Worker("server", {
|
|||||||
port: 3000,
|
port: 3000,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await WranglerJson("wrangler", {
|
|
||||||
worker: server,
|
|
||||||
});
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{{#if (and (eq webDeploy "alchemy") (eq serverDeploy "alchemy"))}}
|
{{#if (and (eq webDeploy "alchemy") (eq serverDeploy "alchemy"))}}
|
||||||
console.log(`Web -> ${web.url}`);
|
console.log(`Web -> ${web.url}`);
|
||||||
console.log(`Server -> ${server.url}`);
|
console.log(`Server -> ${server.url}`);
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
// This is a temporary wrangler.jsonc file that will be overwritten by alchemy
|
|
||||||
// It's only here so that `wrangler dev` can work or use alchemy dev instead
|
|
||||||
{
|
|
||||||
"name": "{{projectName}}",
|
|
||||||
"main": "src/index.ts",
|
|
||||||
"compatibility_date": "2025-08-16",
|
|
||||||
"compatibility_flags": [
|
|
||||||
"nodejs_compat",
|
|
||||||
"nodejs_compat_populate_process_env"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -2804,27 +2804,8 @@ describe("create-better-t-stack smoke", () => {
|
|||||||
consola.success(`${dirName} built successfully`);
|
consola.success(`${dirName} built successfully`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scripts["check-types"]) {
|
if (!scripts.build) {
|
||||||
consola.start(`Type checking ${dirName}...`);
|
consola.info(`No build script for ${dirName}, skipping`);
|
||||||
const typeRes = await runScript(
|
|
||||||
pm,
|
|
||||||
projectDir,
|
|
||||||
"check-types",
|
|
||||||
[],
|
|
||||||
120_000,
|
|
||||||
);
|
|
||||||
expect(typeRes.exitCode).toBe(0);
|
|
||||||
consola.success(`${dirName} type check passed`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!scripts.build && !scripts["check-types"]) {
|
|
||||||
consola.info(
|
|
||||||
`No build or check-types script for ${dirName}, skipping`,
|
|
||||||
);
|
|
||||||
} else if (!scripts.build && scripts["check-types"]) {
|
|
||||||
consola.info(
|
|
||||||
`Only check-types script available for ${dirName}, type checking will be performed`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
consola.error(`${dirName} failed`, error);
|
consola.error(`${dirName} failed`, error);
|
||||||
|
|||||||
@@ -1005,7 +1005,7 @@ const analyzeStackCompatibility = (stack: StackState): CompatibilityResult => {
|
|||||||
|
|
||||||
if (isAlchemyWebDeploy || isAlchemyServerDeploy) {
|
if (isAlchemyWebDeploy || isAlchemyServerDeploy) {
|
||||||
const incompatibleFrontends = nextStack.webFrontend.filter(
|
const incompatibleFrontends = nextStack.webFrontend.filter(
|
||||||
(f) => f === "next" || f === "react-router",
|
(f) => f === "next",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (incompatibleFrontends.length > 0) {
|
if (incompatibleFrontends.length > 0) {
|
||||||
@@ -1029,9 +1029,7 @@ const analyzeStackCompatibility = (stack: StackState): CompatibilityResult => {
|
|||||||
notes.webDeploy.hasIssue = true;
|
notes.webDeploy.hasIssue = true;
|
||||||
notes.serverDeploy.hasIssue = true;
|
notes.serverDeploy.hasIssue = true;
|
||||||
|
|
||||||
nextStack.webFrontend = nextStack.webFrontend.filter(
|
nextStack.webFrontend = nextStack.webFrontend.filter((f) => f !== "next");
|
||||||
(f) => f !== "next" && f !== "react-router",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (nextStack.webFrontend.length === 0) {
|
if (nextStack.webFrontend.length === 0) {
|
||||||
nextStack.webFrontend = ["tanstack-router"];
|
nextStack.webFrontend = ["tanstack-router"];
|
||||||
@@ -1632,10 +1630,7 @@ const StackBuilder = () => {
|
|||||||
const { adjustedStack } = analyzeStackCompatibility(simulatedStack);
|
const { adjustedStack } = analyzeStackCompatibility(simulatedStack);
|
||||||
const finalStack = adjustedStack ?? simulatedStack;
|
const finalStack = adjustedStack ?? simulatedStack;
|
||||||
|
|
||||||
if (
|
if (category === "webFrontend" && optionId === "next") {
|
||||||
category === "webFrontend" &&
|
|
||||||
(optionId === "next" || optionId === "react-router")
|
|
||||||
) {
|
|
||||||
const isAlchemyWebDeploy = finalStack.webDeploy === "alchemy";
|
const isAlchemyWebDeploy = finalStack.webDeploy === "alchemy";
|
||||||
const isAlchemyServerDeploy = finalStack.serverDeploy === "alchemy";
|
const isAlchemyServerDeploy = finalStack.serverDeploy === "alchemy";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user