@veecode-platform/safira-cli
Version:
Generate a microservice project from your spec.
355 lines (354 loc) • 18.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const color_1 = tslib_1.__importDefault(require("@oclif/color"));
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
const database_enum_1 = require("../../database/database-enum");
const database_utils_1 = require("../../database/database-utils");
const spec_discovery_exception_1 = require("../../exception/spec-discovery-exception");
const generate_project_1 = require("../../generate/generate-project");
const java_framework_enum_1 = require("../../generate/java/java-framework-enum");
const java_version_1 = require("../../generate/java/java-version");
const package_manager_enum_1 = require("../../generate/java/package-manager-enum");
const git_commands_1 = require("../../git/git-commands");
const language_support_1 = require("../../language-support");
const properties = tslib_1.__importStar(require("../../properties.json"));
const spec_discovery_1 = require("../../safira-globals/spec-discovery");
const safira_utils_1 = require("../../safira-project/safira-utils");
const constants_1 = require("../../utils/commands/constants");
const file_system_utils_1 = require("../../utils/file-system-utils");
const url_utils_1 = require("../../utils/url-utils");
const code_quarkus_service_1 = require("../../generate/java/quarkus/code-quarkus-service");
const exit_codes_1 = require("../../command/exit-codes");
class ProjectNew extends core_1.Command {
async run() {
const { args, flags } = await this.parse(ProjectNew);
const currentPath = file_system_utils_1.FileSystemUtils.getCurrentPath();
const projectName = file_system_utils_1.FileSystemUtils.getHighFolderFromPath(currentPath);
if (projectName !== projectName.toLocaleLowerCase()) {
console.log(color_1.default.bold.yellow("Consider rename your project to lowercase letters, provide it and try again."));
process.exit(exit_codes_1.ExitCode.operationNotPermitted);
}
safira_utils_1.SafiraUtils.init();
let openApiFile = "";
try {
openApiFile = await spec_discovery_1.SpecDiscovery.discoverSpecs({ projectPath: currentPath });
}
catch (error) {
if (error instanceof spec_discovery_exception_1.SpecDiscoveryNotFoundException) {
console.log(color_1.default.yellow("Insomnia workspace or openapi-swagger.yaml not found in current path."));
const importAnswer = await inquirer_1.default.prompt([{
type: "list",
name: "import",
message: "Do you want to import it?",
choices: constants_1.yesNoList,
default: "yes",
},
{
when: (answers) => answers.import === "yes",
type: "input",
name: "openapi-file-path",
message: "Path to the OpenAPI file:",
default: "./openapi-swagger.yaml",
validate: (value) => file_system_utils_1.FileSystemUtils.exists(file_system_utils_1.FileSystemUtils.fullPath(value)) ? true : "Please enter a valid path to openapi file",
}]);
if (importAnswer.import === "no") {
console.log(color_1.default.yellow("Please, provide it and try again."));
return;
}
file_system_utils_1.FileSystemUtils.copyFileSync(importAnswer["openapi-file-path"], `${properties.openapi["spec-name"]}.${properties.openapi.extension}`);
openApiFile = `${properties.openapi["spec-name"]}.${properties.openapi.extension}`;
}
}
let answers = await this.showCommonQuestions(args, flags);
if (answers["confirm-spec-kong-kubernetes"] === "no") {
answers["kong-kubernetes"] = "no";
console.log(color_1.default.yellowBright("The spec does not have Kong for Kubernetes configuration, the configuration will not be generated."));
}
const dataBaseAnswer = await this.showDataBaseQuestions(args, flags);
if (answers["pull-insomnia-workspace"] === "yes") {
try {
await git_commands_1.GitCommand.instance.pull(file_system_utils_1.FileSystemUtils.fullPath(answers["insomnia-workspace"]));
console.log("pull works");
}
catch (error) {
this.error(color_1.default.red(error.message));
}
}
const languageAnswer = Object.keys(language_support_1.LanguageSupportEnum).length > 1 ? await inquirer_1.default.prompt([
{
when: !flags.language,
type: "list",
name: "language",
message: "language to use",
default: language_support_1.LanguageSupportEnum.java,
choices: Object.keys(language_support_1.LanguageSupportEnum),
},
]) : { language: language_support_1.LanguageSupportEnum.java };
if (flags.framework && !flags.language && ["quarkus", "springboot"].includes(flags.framework)) {
languageAnswer.language = "java";
}
answers = { ...answers, ...languageAnswer };
const language = language_support_1.LanguageSupportEnumHelper.parse(answers.language);
const frameworkAnswer = await inquirer_1.default.prompt([
{
when: !flags.framework,
type: "list",
name: "framework",
message: "framework to use",
choices: language_support_1.LanguageSupportEnumHelper.getLanguageFrameworks(language),
},
]);
answers = { ...answers, ...frameworkAnswer, ...dataBaseAnswer };
if (language === language_support_1.LanguageSupportEnum.java) {
const framework = java_framework_enum_1.JavaFrameworksEnumHelper.getJavaFrameworksEnumFromString(answers.framework || flags.framework);
switch (framework) {
case java_framework_enum_1.JavaFrameworksEnum.springboot:
answers = { ...answers, ...await this.showSpringBootQuestions(args, flags) };
break;
case java_framework_enum_1.JavaFrameworksEnum.quarkus:
answers = { ...answers, ...await this.showQuarkusQuestions(args, flags) };
break;
default:
break;
}
}
const rootProjectPath = (flags["new-project-root"] || answers["new-project-root"] || currentPath)?.trim();
try {
core_1.CliUx.ux.action.start("Generating project");
const insomniaPath = (flags["insomnia-workspace"] || answers["insomnia-workspace"])?.trim();
await new generate_project_1.GenerateProjectImpl().newProject({
projectName: projectName,
newProjectRoot: rootProjectPath,
openapiFilePath: openApiFile,
projectDescription: flags["project-description"] || answers["project-description"],
language: flags.language || answers.language,
framework: flags.framework || answers.framework,
javaManagement: package_manager_enum_1.PackageManager[flags["java-pack-manager"] || answers["java-pack-manager"]],
javaSpringbootVersion: flags["java-springboot-version"] || answers["java-springboot-version"],
javaPackage: (flags["java-package"] || answers["java-package"])?.trim(),
javaVersion: flags["java-version"] || answers["java-version"],
applicationPort: flags["application-port"] || answers["application-port"],
kongKubernetes: (flags["kong-kubernetes"] || answers["kong-kubernetes"]) === "yes",
useDataBase: (flags["use-database"] || answers["use-database"]) === "yes",
dataBase: database_enum_1.DatabaseEnum[flags.database || answers.database],
dataBaseUrl: flags["database-url"] || answers["database-url"],
dataBaseUser: flags["database-user"] || answers["database-user"],
dataBasePassword: flags["database-password"] || answers["database-password"],
quarkusVersion: flags["quarkus-version"] || answers["quarkus-version"],
});
}
catch (error) {
this.log(color_1.default.red(error.message));
core_1.CliUx.ux.action.stop("Failed");
return;
}
finally {
safira_utils_1.SafiraUtils.deleteTmpFolder();
if (core_1.CliUx.ux.action.running) {
core_1.CliUx.ux.action.stop();
}
}
}
showCommonQuestions(args, flags) {
return inquirer_1.default.prompt([
{
when: !flags["project-description"],
type: "input",
name: "project-description",
message: "The description of the new project:",
default: "A new project",
validate: (value) => value.length > 0 ? true : "Please enter a valid description",
},
{
when: !flags["application-port"],
type: "input",
name: "application-port",
message: "Application port:",
default: "8080",
validate: (value) => value > 0 ? true : "Please enter a valid port",
},
{
when: !flags["kong-kubernetes"],
type: "list",
name: "kong-kubernetes",
message: "Generate Kong for Kubernetes configuration?",
choices: constants_1.yesNoList,
},
{
when: (answers) => (flags["kong-kubernetes"] === "yes" || answers["kong-kubernetes"] === "yes"),
type: "list",
name: "confirm-spec-kong-kubernetes",
message: "The spec have Kong for Kubernetes configuration?",
choices: constants_1.yesNoList,
},
]);
}
showDataBaseQuestions(args, flags) {
const choices = database_utils_1.DatabaseUtils.getEnumKeyValueList();
return inquirer_1.default.prompt([
{
when: !flags["use-database"],
type: "list",
name: "use-database",
message: "Use database?",
choices: constants_1.yesNoList,
},
{
when: (answers) => (flags["use-database"] === "yes" || answers["use-database"] === "yes") && !flags.database,
type: "list",
name: "database",
message: "Database:",
choices: choices,
},
{
when: (answers) => (flags["use-database"] === "yes" || answers["use-database"] === "yes") && !flags["database-url"],
type: "string",
name: "database-url",
message: "Database URL:",
default: "localhost:5432/database",
validate: (value) => this._validateDataBaseUrl(value),
},
{
when: (answers) => (flags["use-database"] === "yes" || answers["use-database"] === "yes") && !flags["database-user"],
type: "string",
name: "database-user",
message: "Database User:",
validate: (value) => value.length > 0 ? true : "Please enter a valid user",
},
{
when: (answers) => (flags["use-database"] === "yes" || answers["use-database"] === "yes") && !flags["database-password"],
type: "string",
name: "database-password",
message: "Database Password:",
},
]);
}
_validateDataBaseUrl(url) {
url = url_utils_1.UrlUtils.removeProtocol(url);
const splittedInTwo = url.split(":");
const verifyLocal = splittedInTwo[0];
if (verifyLocal.length === 0 || splittedInTwo.length !== 2) {
return "Please enter a valid database URL";
}
const splittedInTwoAgain = splittedInTwo[1].split("/");
if (splittedInTwoAgain.length !== 2) {
return "Please enter a valid database URL with a port and a database";
}
const verifyPort = splittedInTwoAgain[0];
const verifyDataBase = splittedInTwoAgain[1];
if (verifyPort.length === 0) {
return "Please enter a valid database URL with a valid port ";
}
if (verifyDataBase.length === 0) {
return "Please enter a valid database URL pointing to a database";
}
return true;
}
showSpringBootQuestions(args, flags) {
return inquirer_1.default.prompt([
{
when: !flags.language,
type: "list",
name: "java-version",
message: "Java version to use",
default: `java${java_version_1.JavaVersion.java11}`,
choices: Object.keys(java_version_1.JavaVersion),
},
{
when: !flags["java-pack-manager"],
type: "list",
name: "java-pack-manager",
message: "java package manager",
choices: Object.keys(package_manager_enum_1.PackageManager),
},
{
when: !flags["java-springboot-version"],
type: "input",
name: "java-springboot-version",
message: "spring boot version",
default: "2.5.13",
validate: (value) => value.length > 0 ? true : "Please enter a valid Springboot version",
},
{
when: !flags["java-package"],
type: "input",
name: "java-package",
message: "java package",
default: "com.safira.demo",
validate: (value) => value.length > 0 ? true : "Please enter a valid Java package",
},
]);
}
async showQuarkusQuestions(args, flags) {
let quarkusVersions = [];
try {
quarkusVersions = (await code_quarkus_service_1.CodeQuarkusService.instance.getPublicVersions()).map(v => v.key.split(":")[1]);
}
catch { }
return inquirer_1.default.prompt([
{
when: !flags["quarkus-version"] && quarkusVersions.length > 0,
type: "list",
name: "quarkus-version",
message: "quarkus version",
choices: quarkusVersions,
},
{
when: !flags.language,
type: "list",
name: "java-version",
message: "Java version to use",
default: `java${java_version_1.JavaVersion.java11}`,
choices: [java_version_1.JavaVersion.java11, java_version_1.JavaVersion.java17],
},
{
when: !flags["java-package"],
type: "input",
name: "java-package",
message: "java package",
default: "com.safira.demo",
validate: (value) => value.length > 0 ? true : "Please enter a valid Java package",
},
{
when: !flags["java-pack-manager"],
type: "list",
name: "java-pack-manager",
message: "java management",
choices: Object.keys(package_manager_enum_1.PackageManager),
default: "maven",
},
]);
}
}
exports.default = ProjectNew;
ProjectNew.hidden = true;
ProjectNew.description = "Create a new project";
ProjectNew.argDescription = "Use '.' to create project into current folder or name of the project to create a new folder.User lowercase letters for the project name.";
ProjectNew.examples = [
"<%= config.bin %> <%= command.id %>",
"<%= config.bin %> <%= command.id %> app-name",
"<%= config.bin %> <%= command.id %> app-name --language java11 --java-pack-manager gradle --application-port 8090",
"<%= config.bin %> <%= command.id %> . -create a project in the current folder",
];
ProjectNew.flags = {
help: core_1.Flags.help({}),
language: core_1.Flags.string({ char: "l", description: "Programming language to use", helpValue: "java" }),
framework: core_1.Flags.enum({ char: "f", description: "", options: ["springboot", "quarkus"] }),
"project-description": core_1.Flags.string({ description: "The description of the new project." }),
"java-pack-manager": core_1.Flags.enum({ description: "Java package management", options: Object.keys(package_manager_enum_1.PackageManager) }),
"java-springboot-version": core_1.Flags.string({ description: "Springboot version", helpValue: "2.5.13" }),
"java-package": core_1.Flags.string({ description: "Java package", helpValue: "com.safira.demo" }),
"java-version": core_1.Flags.enum({ description: "Java version", options: Object.keys(java_version_1.JavaVersion) }),
"application-port": core_1.Flags.integer({ description: "Application port", helpValue: "8080" }),
"kong-kubernetes": core_1.Flags.enum({ description: "Generate Kong for Kubernetes configuration", options: constants_1.yesNoList }),
"use-database": core_1.Flags.enum({ description: "Use database", options: constants_1.yesNoList }),
database: core_1.Flags.enum({ description: "The database provider", options: Object.keys(database_enum_1.DatabaseEnum) }),
"database-url": core_1.Flags.string({ description: "The url of the database", helpValue: "localhost:5432/database" }),
"database-user": core_1.Flags.string({ description: "The user of the database", helpValue: "User" }),
"database-password": core_1.Flags.string({ description: "The password of the database", helpValue: "password123" }),
"export-spec": core_1.Flags.enum({ description: "Export spec", options: constants_1.yesNoList }),
"quarkus-version": core_1.Flags.string({ description: "Quarkus version" }),
};
ProjectNew.args = [];