Files
create-better-t-stack/apps/cli/src/helpers/core/add-deployment.ts
2025-08-29 00:21:08 +05:30

122 lines
3.6 KiB
TypeScript

import path from "node:path";
import { log } from "@clack/prompts";
import pc from "picocolors";
import type {
AddInput,
ProjectConfig,
ServerDeploy,
WebDeploy,
} from "../../types";
import { updateBtsConfig } from "../../utils/bts-config";
import { exitWithError } from "../../utils/errors";
import { setupServerDeploy } from "../deployment/server-deploy-setup";
import { setupWebDeploy } from "../deployment/web-deploy-setup";
import {
detectProjectConfig,
isBetterTStackProject,
} from "./detect-project-config";
import { installDependencies } from "./install-dependencies";
import { setupDeploymentTemplates } from "./template-manager";
export async function addDeploymentToProject(
input: AddInput & {
webDeploy?: WebDeploy;
serverDeploy?: ServerDeploy;
suppressInstallMessage?: boolean;
},
) {
try {
const projectDir = input.projectDir || process.cwd();
const isBetterTStack = await isBetterTStackProject(projectDir);
if (!isBetterTStack) {
exitWithError(
"This doesn't appear to be a Better-T Stack project. Please run this command from the root of a Better-T Stack project.",
);
}
const detectedConfig = await detectProjectConfig(projectDir);
if (!detectedConfig) {
exitWithError(
"Could not detect the project configuration. Please ensure this is a valid Better-T Stack project.",
);
}
if (input.webDeploy && detectedConfig.webDeploy === input.webDeploy) {
exitWithError(
`${input.webDeploy} web deployment is already configured for this project.`,
);
}
if (
input.serverDeploy &&
detectedConfig.serverDeploy === input.serverDeploy
) {
exitWithError(
`${input.serverDeploy} server deployment is already configured for this project.`,
);
}
const config: ProjectConfig = {
projectName: detectedConfig.projectName || path.basename(projectDir),
projectDir,
relativePath: ".",
database: detectedConfig.database || "none",
orm: detectedConfig.orm || "none",
backend: detectedConfig.backend || "none",
runtime: detectedConfig.runtime || "none",
frontend: detectedConfig.frontend || [],
addons: detectedConfig.addons || [],
examples: detectedConfig.examples || [],
auth: detectedConfig.auth || "none",
git: false,
packageManager:
input.packageManager || detectedConfig.packageManager || "npm",
install: input.install || false,
dbSetup: detectedConfig.dbSetup || "none",
api: detectedConfig.api || "none",
webDeploy: input.webDeploy || detectedConfig.webDeploy || "none",
serverDeploy: input.serverDeploy || detectedConfig.serverDeploy || "none",
};
if (input.webDeploy && input.webDeploy !== "none") {
log.info(
pc.green(
`Adding ${input.webDeploy} web deployment to ${config.frontend.join("/")}`,
),
);
}
if (input.serverDeploy && input.serverDeploy !== "none") {
log.info(pc.green(`Adding ${input.serverDeploy} server deployment`));
}
await setupDeploymentTemplates(projectDir, config);
await setupWebDeploy(config);
await setupServerDeploy(config);
await updateBtsConfig(projectDir, {
webDeploy: input.webDeploy || config.webDeploy,
serverDeploy: input.serverDeploy || config.serverDeploy,
});
if (config.install) {
await installDependencies({
projectDir,
packageManager: config.packageManager,
});
} else if (!input.suppressInstallMessage) {
log.info(
pc.yellow(
`Run ${pc.bold(
`${config.packageManager} install`,
)} to install dependencies`,
),
);
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
exitWithError(`Error adding deployment: ${message}`);
}
}