UNPKG

@lakutata/cli

Version:
180 lines (179 loc) 8.78 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Creator = void 0; const Information_js_1 = require("./Information.js"); const DeGitPuller_js_1 = require("../components/DeGitPuller.js"); const Spinner_js_1 = require("../components/Spinner.js"); const CreateProjectOptions_js_1 = require("../../options/CreateProjectOptions.js"); const node_path_1 = __importDefault(require("node:path")); const promises_1 = require("node:fs/promises"); const SpecialChar_js_1 = require("../SpecialChar.js"); const lakutata_1 = require("lakutata"); const di_1 = require("lakutata/decorator/di"); const logger_1 = require("lakutata/com/logger"); const helper_1 = require("lakutata/helper"); const dto_1 = require("lakutata/decorator/dto"); const ansis_1 = __importDefault(require("ansis")); const cli_table3_1 = __importDefault(require("cli-table3")); const OnlineLatestVersion_1 = require("./OnlineLatestVersion"); class Creator extends lakutata_1.Provider { /** * Check if the target path exists * @param targetDirectory * @param initOnly * @protected */ async checkTargetPathExistence(targetDirectory, initOnly) { const exists = await (0, helper_1.IsExists)(targetDirectory); if (!exists && initOnly) { this.log.error(`${SpecialChar_js_1.charCross} The target path does not exist.`); return this.app.exit(1); } await (0, promises_1.mkdir)(targetDirectory, { recursive: true }); this.log.info(`${SpecialChar_js_1.charCheck} The target path does not exist.`); } /** * Check target path is a valid directory * @param targetDirectory * @protected */ async checkTargetPathIsDirectory(targetDirectory) { const targetInfo = await (0, promises_1.stat)(targetDirectory); if (!targetInfo.isDirectory()) { this.log.error(`${SpecialChar_js_1.charCross} The target path is not a valid directory.`); return this.app.exit(1); } this.log.info(`${SpecialChar_js_1.charCheck} The target path is a valid directory.`); } /** * Check target directory is empty, if the target directory is not empty, throw error and exit * @param targetDirectory * @param initOnly * @protected */ async checkTargetDirectoryIsEmpty(targetDirectory, initOnly) { const files = await (0, promises_1.readdir)(targetDirectory); if (files.length && !initOnly) { this.log.error(`${SpecialChar_js_1.charCross} The target directory is not empty.`); return this.app.exit(1); } this.log.info(`${SpecialChar_js_1.charCheck} The target directory is empty.`); } /** * project information filling * @protected */ async projectInformationFilling(targetPath, fields) { const items = await (0, helper_1.Glob)(node_path_1.default.resolve(targetPath, '**/*')); for (const item of items) { const stats = await (0, promises_1.stat)(item); if (!stats.isFile()) continue; const rawContent = await (0, promises_1.readFile)(item, { encoding: 'utf-8' }); const filledContent = (0, helper_1.Templating)(rawContent, fields, { ignoreMissing: true }); if (rawContent !== filledContent) await (0, promises_1.writeFile)(item, filledContent, { flag: 'w' }); } } /** * Exec create * @param options */ async create(options) { const appName = options.name; const appId = options.id; const appDescription = options.description; const authorName = options.author; const licenseName = options.license; const appTemplate = options.template; const targetPath = options.overwrite ? node_path_1.default.resolve(options.path) : node_path_1.default.resolve(options.path, options.name); const table = new cli_table3_1.default(); table.push([{ content: ansis_1.default.bold.cyan('Project Creation Information'), colSpan: 2, hAlign: 'center' }], [ansis_1.default.blue('APP ID & Project Name'), appId], [ansis_1.default.blue('APP Name'), appName], [ansis_1.default.blue('APP Description'), appDescription], [ansis_1.default.blue('Project Create Target Path'), targetPath], [ansis_1.default.blue('Project Create Mode'), options.overwrite ? ansis_1.default.yellow('Initialize project in an existing directory') : ansis_1.default.green('Create a new folder for the project')], [ansis_1.default.blue('Project Author Name'), authorName], [ansis_1.default.blue('Project License'), licenseName], [ansis_1.default.blue('Project Template Repository'), this.puller.getGitSource(appTemplate)]); console.log(table.toString()); await new Promise(resolve => { let timeLeft = 10; const interval = setInterval(() => { timeLeft -= 1; if (!timeLeft) { clearInterval(interval); this.spinner.stop(); return resolve(); } }, 1000); this.spinner.start(() => `Please confirm the project creation information; the creation process will commence in ${timeLeft} seconds.`); }); await this.checkTargetPathExistence(targetPath, options.overwrite); await this.checkTargetPathIsDirectory(targetPath); await this.checkTargetDirectoryIsEmpty(targetPath, options.overwrite); this.spinner.start('Pulling'); await this.puller.pull(appTemplate, targetPath); this.spinner.stop(); this.log.info(`${SpecialChar_js_1.charCheck} Template pulled.`); this.spinner.start('Filling information'); await this.projectInformationFilling(targetPath, { $APP_NAME: appName, $APP_ID: appId, $APP_DESC: appDescription, $APP_AUTHOR: authorName, $APP_LICENSE: licenseName }); this.spinner.stop(); this.log.info(`${SpecialChar_js_1.charCheck} Project information filling completed.`); this.spinner.start('Installing'); const { execa } = await import('execa'); await execa('npm', ['install'], { cwd: targetPath }); await execa('npm', ['install', `${this.onlineVersion.getName()}@${await this.onlineVersion.getVersion()}`], { cwd: targetPath }); this.spinner.stop(); this.log.info(`${SpecialChar_js_1.charCheck} Project has been successfully created.`); } } exports.Creator = Creator; __decorate([ (0, di_1.Inject)(lakutata_1.Application), __metadata("design:type", lakutata_1.Application) ], Creator.prototype, "app", void 0); __decorate([ (0, di_1.Inject)('log'), __metadata("design:type", logger_1.Logger) ], Creator.prototype, "log", void 0); __decorate([ (0, di_1.Inject)('spinner'), __metadata("design:type", Spinner_js_1.Spinner) ], Creator.prototype, "spinner", void 0); __decorate([ (0, di_1.Inject)('puller'), __metadata("design:type", DeGitPuller_js_1.DeGitPuller) ], Creator.prototype, "puller", void 0); __decorate([ (0, di_1.Inject)('info'), __metadata("design:type", Information_js_1.Information) ], Creator.prototype, "frameworkInfo", void 0); __decorate([ (0, di_1.Inject)('onlineVersion'), __metadata("design:type", OnlineLatestVersion_1.OnlineLatestVersion /** * Check if the target path exists * @param targetDirectory * @param initOnly * @protected */ ) ], Creator.prototype, "onlineVersion", void 0); __decorate([ (0, dto_1.Accept)(CreateProjectOptions_js_1.CreateProjectOptions.required()), __metadata("design:type", Function), __metadata("design:paramtypes", [CreateProjectOptions_js_1.CreateProjectOptions]), __metadata("design:returntype", Promise) ], Creator.prototype, "create", null);