UNPKG

spring-boot-cli

Version:
185 lines (184 loc) 9.08 kB
import { Command } from "commander"; import inquirer from "inquirer"; import { isValidMavenArtifactId, isValidMavenGroupId, isValidProjectName } from "../utils/validator.utils.mjs"; import chalk from "chalk"; import path from "node:path"; import crypto from "crypto"; import { copyFiles, createFolder, deleteFolder, getJavaFiles, readFile, renameFile, writeFile } from "../utils/file-manager.utils.mjs"; import { cloneStarterPack, commitInitialProject } from "../utils/git.utils.mjs"; import ora from "ora"; import { parseObjectToXmlString, parseStringToXml } from "../utils/xml.utils.mjs"; import { parseObjectToYamlString, parseStringToYaml } from "../utils/yaml.utils.mjs"; const createCommand = new Command("create") .command("create") .alias("c") .description("Create a new spring boot project with starter pack") .argument("<name>", "Name of the project") .action(async (name) => { // ========================================= // Validate parameters // ========================================= if (!validateName(name)) { console.error(chalk.red("Please enter a valid project name")); process.exit(1); } const groupId = await getGroupId(); const artifactId = await getArtifactId(); // ========================================= // Loading spinner // ========================================= const spinner = ora(`Creating project folder...\n`).start(); // Start the spinner // ========================================= // Create project folder // ========================================= spinner.start(`Creating project folder...`); const projectPath = path.join(process.cwd(), name); createFolder(projectPath); spinner.info(`Project folder created at ${projectPath}`); // ========================================= // Clone starter pack from git // ========================================= spinner.start(`Cloning starter pack...`); await cloneStarterPack(projectPath); deleteFolder(path.join(projectPath, ".git")); spinner.info(`Starter pack cloned at ${projectPath}`); // ========================================= // Edit pom.xml // ========================================= spinner.start(`Generating project...`); const pomPath = path.join(projectPath, "pom.xml"); const pom = readFile(pomPath); let pomXml = await parseStringToXml(pom); pomXml = editPom(pomXml, groupId, artifactId, name); const pomString = await parseObjectToXmlString(pomXml); writeFile(pomPath, pomString); // ========================================= // Replace imports in java files with groupId // ========================================= const javaFilePattern = path.posix.join(projectPath, "src", "main", "java", "**", "*.java"); const javaTestFilePattern = path.posix.join(projectPath, "src", "test", "java", "**", "*.java"); let javaFiles = getJavaFiles(javaFilePattern); let javaTestFiles = getJavaFiles(javaTestFilePattern); javaFiles.push(...javaTestFiles); javaFiles.forEach((file) => { let fileContent = readFile(file); fileContent = fileContent.replaceAll("it.theapplegeek.spring_starter_pack", `${groupId.replaceAll("-", "_")}.${artifactId.replaceAll("-", "_")}`); writeFile(file, fileContent); }); // ========================================= // Rename main application class // ========================================= const mainApplicationPath = path.join(projectPath, "src", "main", "java", "it", "theapplegeek", "spring_starter_pack", "Application.java"); let mainApplicationContent = readFile(mainApplicationPath); const artifactIdCamelCase = artifactId.split(/[.-]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(""); mainApplicationContent = mainApplicationContent.replaceAll("class Application", `class ${artifactIdCamelCase}Application`); mainApplicationContent = mainApplicationContent.replaceAll("Application.class", `${artifactIdCamelCase}Application.class`); writeFile(mainApplicationPath, mainApplicationContent); const mainApplicationNewPath = path.join(projectPath, "src", "main", "java", "it", "theapplegeek", "spring_starter_pack", `${artifactIdCamelCase}Application.java`); renameFile(mainApplicationPath, mainApplicationNewPath); // ========================================= // Edit application.yml // ========================================= const applicationYmlPath = path.join(projectPath, "src", "main", "resources", "application.yml"); const applicationYmlFile = readFile(applicationYmlPath); let applicationYmlContent = parseStringToYaml(applicationYmlFile); applicationYmlContent.spring.application.name = artifactId.split(/[.-]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" "); const secretKeyHex = crypto.randomBytes(32).toString('hex'); applicationYmlContent.application.security.jwt['secret-key'] = Buffer.from(secretKeyHex).toString('base64'); applicationYmlContent = parseObjectToYamlString(applicationYmlContent); writeFile(applicationYmlPath, applicationYmlContent); // ========================================= // Replace package path with groupId and artifactId // ========================================= const groupIdSplit = groupId.replaceAll("-", "_").split("."); const artifactIdSplit = artifactId.replaceAll("-", "_").split("."); const defaultFolderPath = path.join(projectPath, "src", "main", "java", "it", "theapplegeek", "spring_starter_pack"); const newFolderPath = path.join(projectPath, "src", "main", "java", ...groupIdSplit, ...artifactIdSplit); createFolder(newFolderPath, false); copyFiles(defaultFolderPath, newFolderPath); const defaultTestFolderPath = path.join(projectPath, "src", "test", "java", "it", "theapplegeek", "spring_starter_pack"); const newTestFolderPath = path.join(projectPath, "src", "test", "java", ...groupIdSplit, ...artifactIdSplit); createFolder(newTestFolderPath, false); copyFiles(defaultTestFolderPath, newTestFolderPath); deleteDefaultFolder(groupId, artifactId, projectPath); spinner.info(`Project created at ${projectPath}`); // ========================================= // Commit initial project // ========================================= spinner.start(`Initializing git...`); await commitInitialProject(projectPath); spinner.info(`Git initialized`); spinner.succeed(chalk.green(`Project created successfully!`)); console.log(`\nNext steps:`); console.log(`1. cd ${name}`); console.log(`2. open the project in your favorite IDE`); }); const validateName = (input) => { if (input === "") return false; else if (!isValidProjectName(input)) return false; return true; }; const getGroupId = async () => { return inquirer.prompt({ type: "input", name: "groupId", message: "Enter the group ID: ", validate: (input) => { if (input === "") { return "Please enter a group ID"; } else if (!isValidMavenGroupId(input)) { return "Please enter a valid group ID"; } return true; } }).then((answers) => { return answers.groupId; }); }; const getArtifactId = async () => { return inquirer.prompt({ type: "input", name: "artifactId", message: "Enter the artifact ID: ", validate: (input) => { if (input === "") { return "Please enter an artifact ID"; } else if (!isValidMavenArtifactId(input)) { return "Please enter a valid artifact ID"; } return true; } }).then((answers) => { return answers.artifactId; }); }; const editPom = (pom, groupId, artifactId, name) => { pom.project.groupId[0] = groupId; pom.project.artifactId[0] = artifactId; pom.project.name[0] = name; pom.project.description[0] = 'Insert project description here'; delete pom.project.licenses[0]; delete pom.project.developers[0]; return pom; }; const deleteDefaultFolder = (groupId, artifactId, projectPath) => { if (groupId === "it.theapplegeek" && artifactId === "spring-starter-pack") return; if (groupId === "it.theapplegeek") { deleteFolder(path.join(projectPath, "src", "main", "java", "it", "theapplegeek", "spring_starter_pack")); deleteFolder(path.join(projectPath, "src", "test", "java", "it", "theapplegeek", "spring_starter_pack")); } else if (groupId.startsWith("it.")) { deleteFolder(path.join(projectPath, "src", "main", "java", "it", "theapplegeek")); deleteFolder(path.join(projectPath, "src", "test", "java", "it", "theapplegeek")); } else { deleteFolder(path.join(projectPath, "src", "main", "java", "it")); deleteFolder(path.join(projectPath, "src", "test", "java", "it")); } }; export { createCommand };