@vxrn/takeout-cli
Version:
CLI tools for Takeout starter kit - interactive onboarding and project setup
150 lines (149 loc) • 6.84 kB
JavaScript
import { defineCommand } from "citty";
import { execSync } from "node:child_process";
import {
copyEnvFile,
createEnvLocal,
envFileExists,
generateSecret,
updateEnvVariable
} from "../utils/env";
import { markOnboarded, updateAppConfig, updatePackageJson } from "../utils/files";
import { checkAllPorts, getConflictingPorts } from "../utils/ports";
import { checkAllPrerequisites, hasRequiredPrerequisites } from "../utils/prerequisites";
import {
confirmContinue,
displayOutro,
displayPortConflicts,
displayPrerequisites,
displayWelcome,
promptText,
showError,
showInfo,
showSpinner,
showStep,
showSuccess,
showWarning
} from "../utils/prompts";
const onboardCommand = defineCommand({
meta: {
name: "onboard",
description: "Interactive onboarding for Takeout starter kit"
},
args: {
skip: {
type: "boolean",
description: "Skip interactive prompts",
default: !1
}
},
async run({ args }) {
const cwd = process.cwd();
if (args.skip) {
showInfo("Skipping onboarding (--skip flag)");
return;
}
displayWelcome(), showStep("Checking prerequisites..."), console.info();
const checks = checkAllPrerequisites();
if (displayPrerequisites(checks), !hasRequiredPrerequisites(checks) && (showWarning(
"Some required prerequisites are missing. You can continue, but setup may fail."
), !await confirmContinue("Continue anyway?", !1))) {
displayOutro("Setup cancelled. Install prerequisites and try again.");
return;
}
console.info(), showStep("Setting up environment files..."), console.info(), envFileExists(cwd, ".env") ? (showInfo(".env file already exists"), await confirmContinue("Reconfigure environment?", !1) ? await setupEnvironment(cwd) : showInfo("Skipping environment setup")) : await setupEnvironment(cwd), console.info(), showStep("Configuring project identity..."), console.info(), await confirmContinue(
"Customize project name and bundle identifier?",
!1
) ? await customizeProject(cwd) : showInfo("Keeping default project configuration"), console.info(), showStep("Starting development services..."), console.info();
const portChecks = checkAllPorts(), conflicts = getConflictingPorts(portChecks);
if (conflicts.length > 0 && (displayPortConflicts(conflicts), showWarning("Some ports are already in use. You may need to stop other services.")), await confirmContinue(
"Start Docker services (PostgreSQL, Zero, MinIO)?",
!0
) ? await startServices(cwd) : (showInfo("Skipping service startup"), showInfo("Run 'bun backend' to start services later")), console.info(), showStep("Setup complete!"), console.info(), showSuccess("\u2713 Environment configured"), showSuccess("\u2713 Project ready for development"), markOnboarded(cwd), console.info(), showInfo("Next steps:"), console.info(), console.info(" bun dev # Start development server"), console.info(" bun ios # Run iOS simulator"), console.info(" bun android # Run Android emulator"), console.info(), console.info("Documentation: /docs"), console.info(), await confirmContinue("Start development server now?", !0)) {
console.info(), showInfo("Starting development server..."), console.info();
try {
execSync("bun dev", { stdio: "inherit", cwd });
} catch {
showInfo("Development server stopped");
}
}
displayOutro("Happy coding! \u{1F680}");
}
});
async function setupEnvironment(cwd) {
const copyResult = copyEnvFile(cwd, ".env.development", ".env");
if (!copyResult.success) {
showError(`Failed to create .env: ${copyResult.error}`);
return;
}
if (showSuccess("Created .env from .env.development"), !await confirmContinue(
"Use existing BETTER_AUTH_SECRET from .env.development?",
!0
)) {
const secret = generateSecret();
updateEnvVariable(cwd, "BETTER_AUTH_SECRET", secret), showSuccess("Generated new BETTER_AUTH_SECRET");
}
if (await confirmContinue("Set up GitHub OAuth?", !1)) {
const clientId = await promptText(
"GitHub Client ID:",
void 0,
"Iv23liNaYfNSauaySodL"
);
clientId && updateEnvVariable(cwd, "ONECHAT_GITHUB_CLIENT_ID", clientId);
const clientSecret = await promptText(
"GitHub Client Secret (optional):",
void 0,
"Leave empty to skip"
);
clientSecret && updateEnvVariable(cwd, "ONECHAT_GITHUB_CLIENT_SECRET", clientSecret);
}
createEnvLocal(cwd), showSuccess("Created .env.local for personal overrides");
}
async function customizeProject(cwd) {
const projectName = await promptText("Project name:", "takeout", "my-awesome-app"), slug = await promptText(
"Project slug (URL-friendly):",
projectName.toLowerCase().replace(/\s+/g, "-"),
"my-awesome-app"
), bundleId = await promptText(
"Bundle identifier:",
`com.${slug}.app`,
"com.example.app"
), domain = await promptText(
"Development domain:",
"localhost:8081",
"localhost:8081"
), pkgResult = updatePackageJson(cwd, {
name: projectName,
description: `${projectName} - Built with Takeout starter kit`
});
pkgResult.success ? showSuccess("Updated package.json") : showError(`Failed to update package.json: ${pkgResult.error}`);
const configResult = updateAppConfig(cwd, {
name: projectName,
slug,
bundleId
});
configResult.success ? showSuccess("Updated app.config.ts") : showError(`Failed to update app.config.ts: ${configResult.error}`);
const serverUrl = `http://${domain}`;
updateEnvVariable(cwd, "BETTER_AUTH_URL", serverUrl), updateEnvVariable(cwd, "ONE_SERVER_URL", serverUrl), showSuccess("Updated environment URLs");
}
async function startServices(cwd) {
const spinner = showSpinner("Starting Docker services...");
try {
if (execSync("bun backend", {
stdio: "ignore",
cwd
}), await new Promise((resolve) => setTimeout(resolve, 3e3)), spinner.stop("Docker services started"), showSuccess("\u2713 PostgreSQL running on port 5432"), showSuccess("\u2713 Zero sync running on port 4848"), showSuccess("\u2713 MinIO (S3) running on port 9090"), await confirmContinue("Run database migrations?", !0)) {
const migrateSpinner = showSpinner("Running migrations...");
try {
execSync("bun migrate", { stdio: "ignore", cwd }), migrateSpinner.stop("Database migrated"), showSuccess("\u2713 Database migrations complete");
} catch {
migrateSpinner.stop("Migration failed"), showError("Failed to run migrations"), showInfo("Try running 'bun migrate' manually");
}
}
} catch (error) {
spinner.stop("Failed to start services"), showError(error instanceof Error ? error.message : "Unknown error"), showInfo("Try running 'bun backend' manually");
}
}
export {
onboardCommand
};
//# sourceMappingURL=onboard.js.map