UNPKG

constatic

Version:

Constatic is a CLI for creating and managing modern TypeScript projects, providing an organized structure and features that streamline development.

219 lines (218 loc) 7.13 kB
// src/actions/bot/init.ts import { actions } from "#actions/index.js"; import { byeMessage, divider, getCdPath, json, log, modifyObjArg, toNpmName, uiMessage } from "#helpers"; import { KeyValueFile } from "#lib/kvf.js"; import { applyScriptPresets } from "#shared/presets/scripts/apply.js"; import ck from "chalk"; import { copy } from "fs-extra"; import merge from "lodash.merge"; import { cp, readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import ora from "ora"; import { readPackageJSON } from "pkg-types"; import { Project } from "ts-morph"; async function initBotAction(cli, data) { const distJoin = (...paths) => path.join(data.dist, ...paths); const templateJoin = (...paths) => path.join(cli.templates.botPath, ...paths); const isDistRoot = data.dist === process.cwd(); const generating = ora(); generating.start(uiMessage({ "en-US": "The project is being generated! Please wait...", "pt-BR": "O projeto está sendo gerado! Aguarde..." })); await copyProject(path.join(cli.templates.botPath, "project"), distJoin()); const project = new Project({ tsConfigFilePath: distJoin("tsconfig.json") }); const projectFiles = { envSchema: project.addSourceFileAtPath(distJoin("src/env.ts")), index: project.addSourceFileAtPath(distJoin("src/index.ts")) }; const envFile = new KeyValueFile(distJoin("./.env")); await envFile.read(); generating.text = uiMessage({ "en-US": "Creating environment variables manager", "pt-BR": "Criando gerenciador de variáveis de ambiente" }); const pkg = await readPackageJSON(distJoin("package.json")); pkg.name = toNpmName(path.basename(path.resolve(data.dist))); const database = cli.templates.bot.presets.databases[data.database ?? ""]; if (database) { generating.text = uiMessage({ "en-US": "Setting up the database", "pt-BR": "Configurando o banco de dados" }); await actions.bot.add.database({ database, pkg, envFile, envSchema: projectFiles.envSchema, cli, dist: distJoin() }); } const server = cli.templates.bot.presets.servers[data.server ?? ""]; if (server) { generating.text = uiMessage({ "en-US": "Setting up the API Server...", "pt-BR": "Configurando Servidor de API..." }); await actions.bot.add.server({ server, pkg, envFile, cli, dist: distJoin(), ...projectFiles }); } const token = cli.config.getToken(data.token ?? ""); if (token) { generating.text = uiMessage({ "en-US": "Writing the token to the .env file...", "pt-BR": "Escrevendo o token no arquivo .env..." }); envFile.set("BOT_TOKEN", token.token); } await copy(templateJoin("extras", "gitignore.txt"), distJoin(".gitignore")); if (data.extras?.includes("discloud")) { const dir = templateJoin("extras", cli.shell.isBun ? "bun" : "discloud"); await copy(path.join(dir, "discloud.ignore.txt"), distJoin(".discloudignore")); await copy(path.join(dir, "discloud.config.txt"), distJoin("discloud.config")); const discloudFile = new KeyValueFile(distJoin("discloud.config")); await discloudFile.read(); discloudFile.set("NAME", pkg.name); if (cli.shell.isBun) { discloudFile.set("MAIN", "Dockerfile"); } if (cli.shell.isBun) { await copy(path.join(dir, "Dockerfile"), distJoin("Dockerfile")); } await discloudFile.write(); } if (data.extras?.includes("tsup")) { await actions.bot.add.tsup({ cli, pkg, distdir: distJoin() }); } const baseVersionPath = distJoin("src/discord/base/base.version.ts"); await readFile(baseVersionPath, "utf-8").then((content) => content.replace("{{baseVersion}}", cli.pkg.version)).then((content) => writeFile(baseVersionPath, content, "utf-8")).catch(() => null); pkg.baseVersion = cli.pkg.version; if (data.scripts && data.scripts.length >= 1) { const presets = cli.config.get("presets.scripts", []); const selected = presets.filter((p) => data.scripts?.includes(p.name) || data.scripts?.includes(p.alias ?? "")); await applyScriptPresets(cli, { pkg, dist: data.dist, presets: selected }); } if (cli.shell.isBun) { const bunPkgJson = await readPackageJSON(templateJoin("extras", "bun/package.json")); merge(pkg, bunPkgJson); pkg.devDependencies ??= {}; delete pkg.devDependencies["tsx"]; delete pkg.devDependencies["@types/node"]; } await json.write(distJoin("package.json"), pkg); await project.save(); await envFile.write(); await envFile.write(distJoin(".env.example"), true); if (data.install) { generating.text = uiMessage({ "en-US": "Installing the dependencies...", "pt-BR": "Instalando as dependências..." }); const result = await cli.shell.run(distJoin(), "install"); generating.stop(); if (result.success) { log.success(uiMessage({ "en-US": "✅ Dependencies installed successfully!", "pt-BR": "✅ Dependências instaladas com sucesso!" })); } else { const command = `${cli.shell.agent} install`; log.fail(uiMessage({ "en-US": [ "❌ Unable to install dependencies!", `Install manually using ${command}` ].join(` `), "pt-BR": [ "❌ Não foi possível instalar dependências!", `Instale manualmente usando ${command}` ].join(` `) })); } divider(); } generating.stop(); log.success(uiMessage({ "en-US": "Project generate successfully!", "pt-BR": "Projeto gerado com sucesso!" })); divider(); if (!isDistRoot) { log.custom(ck.green("➞"), uiMessage({ "en-US": `Use: ${getCdPath(data.dist)}`, "pt-BR": `Use: ${getCdPath(data.dist)}` })); } if (!data.install) { log.custom(ck.green("➞"), uiMessage({ "en-US": "Install the dependencies", "pt-BR": "Instale as dependências" })); } log.custom(ck.green("➞"), uiMessage({ "en-US": `Run ${ck.underline("dev")} script`, "pt-BR": `Execute o script ${ck.underline("dev")}` })); divider(); console.log(byeMessage); divider(); } async function copyProject(src, dist) { const items = [ "node_modules", "package-lock.json", "build", "dist", "deprecated" ]; const extensions = [ ".env.dev", ".env.development", ".development.json", ".dev.json" ]; await cp(src, dist, { recursive: true, force: true, filter(source) { const basename = path.basename(source); if (items.includes(basename)) return false; if (extensions.some((ext) => basename.endsWith(ext))) return false; return true; } }); } async function updateEnv(sourceFile, envManager, schema) { await modifyObjArg({ callname: "z.looseObject", source: sourceFile, modify: (arg) => arg.addPropertyAssignments(schema.map(([name, initializer]) => ({ name, initializer }))) }); for (const [key, _, value] of schema) { envManager.set(key, value); } } export { updateEnv, initBotAction };