UNPKG

zcatalyst-cli

Version:

Command Line Tool for CATALYST

314 lines (313 loc) 16.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const prompt_1 = __importDefault(require("../../../prompt")); const logger_1 = require("../../../util_modules/logger"); const endpoints_1 = require("../../../endpoints"); const archiver_1 = __importDefault(require("../../../archiver")); const option_1 = require("../../../util_modules/option"); const path_1 = __importStar(require("path")); const runtime_store_1 = __importDefault(require("../../../runtime-store")); const fs_1 = require("../../../util_modules/fs"); const ansi_colors_1 = require("ansi-colors"); const config_1 = require("../../../util_modules/config"); const console_1 = require("console"); const error_1 = __importDefault(require("../../../error")); const constants_1 = require("../../../util_modules/constants"); const project_1 = require("../../../util_modules/project"); const toml_1 = require("../../../util_modules/parser/toml"); const async_1 = require("../../../util_modules/fs/lib/async"); function getFrameworkOption(frameworks, source) { return __awaiter(this, void 0, void 0, function* () { let frameworkOpt = (0, option_1.getOptionValue)('framework'); if (frameworkOpt && frameworks.findIndex((framework) => framework.name === frameworkOpt) === -1) { (0, logger_1.warning)('Given framework is not supported in Slate.'); frameworkOpt = ''; } if (!frameworkOpt) { const filteredFrameworks = frameworks.filter((framework) => framework.name !== 'other'); const { selectedFramework } = yield prompt_1.default.ask(prompt_1.default.question('selectedFramework', 'Select a framework to start with: ', { type: 'list', choices: filteredFrameworks.map(({ label, name }) => prompt_1.default.choice(label, { value: name, short: label })) })); frameworkOpt = selectedFramework; } return { name: frameworkOpt, source }; }); } function validateAppName(appName) { if (appName.length === 0) { return 'App name cannot be empty'; } if (appName.length > 45) { return 'App name cannot be more than 45 characters'; } if (!appName.match(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/)) { return 'App name must be alphanumeric and contain only a single hyphen in the middle.'; } return true; } function getAppName(existingSlates, frameworkOpt) { return __awaiter(this, void 0, void 0, function* () { let appName = (0, option_1.getOptionValue)('name'); if (!appName) { const { name } = yield prompt_1.default.ask(prompt_1.default.question('name', 'Please provide the name for your app:', { type: 'input', default: frameworkOpt, validate: (name) => { if (existingSlates.findIndex((targ) => targ.name === name) !== -1) return 'Slate already configured with this name.'; return validateAppName(name); } })); appName = name; } else { if (existingSlates.findIndex((targ) => targ.name === appName) !== -1) { throw new error_1.default('Slate already configured with this name.'); } else { const isValidApp = validateAppName(appName); if (isValidApp !== true) { throw new error_1.default(isValidApp + ''); } } } return appName; }); } function handleTemplate(appName, { templateName, frameworkName } = {}) { return __awaiter(this, void 0, void 0, function* () { const projectRoot = (0, project_1.getProjectRoot)(); const appPath = path_1.default.join(projectRoot, appName); const folderExists = yield fs_1.ASYNC.dirExists(appPath); const overwriteAns = folderExists ? yield prompt_1.default.ask(prompt_1.default.question('overwrite', `Directory ${(0, ansi_colors_1.underline)(appPath)} already exists. Overwrite?`, { type: 'confirm', default: false })) : { overwrite: true }; if (!overwriteAns.overwrite) { (0, logger_1.warning)('Skipping slate template setup'); return appPath; } yield fs_1.ASYNC.deleteDir(appPath).catch(console_1.error); const templatePath = 'slate-main' + (templateName ? `/templates/${templateName}` : `/examples/${frameworkName}`); const responseZip = (yield (yield (0, endpoints_1.slateAPI)()).downloadTemplate()); yield new archiver_1.default() .load(responseZip) .extract(appPath, templatePath, { ignoreLevel: 3 }) .finalize(); return appPath; }); } function addExistingSlate(existingSlates) { return __awaiter(this, void 0, void 0, function* () { yield prompt_1.default.register('file-path'); const projectRoot = (0, project_1.getProjectRoot)(); const { sourcePath } = yield prompt_1.default.ask(prompt_1.default.question('sourcePath', 'Please provide the source path of your slate service: ', { type: 'file-path', validate: (pth) => __awaiter(this, void 0, void 0, function* () { const buildPath = (0, path_1.resolve)(projectRoot, pth.value); if (existingSlates.findIndex((targ) => targ.source === buildPath) !== -1) return 'Path is already linked.'; if (yield fs_1.ASYNC.dirExists(buildPath)) { return true; } return 'Path does not exist'; }), depth: 5, empTxt: ' ', rootPath: projectRoot, ignoreFiles: true, excludeDir: true, exclude: ['**/node_modules', '**/.git', '**/.catalyst'] })); prompt_1.default.deregister('file-path'); return sourcePath; }); } function detectFramework(source, frameworkList) { return __awaiter(this, void 0, void 0, function* () { const frameworkOpt = (0, option_1.getOptionValue)('framework'); if (frameworkOpt && frameworkList.findIndex((framework) => framework.name === frameworkOpt) === -1) { return { name: frameworkOpt, source }; } const packageJsonPath = (0, path_1.join)(source, constants_1.FILENAME.package_json); const packageJsonExists = yield fs_1.ASYNC.fileExists(packageJsonPath); if (!packageJsonExists) { (0, logger_1.warning)('Unable to find the package.json file at the given source path'); return getFrameworkOption(frameworkList, source); } const data = yield fs_1.ASYNC.readJSONFile(packageJsonPath); const dependencies = Object.assign(Object.assign({}, data === null || data === void 0 ? void 0 : data.dependencies), data === null || data === void 0 ? void 0 : data.devDependencies); if (!dependencies) { (0, logger_1.warning)('The package.json file does not contain dependencies'); return getFrameworkOption(frameworkList, source); } const isReact = dependencies['react'] !== undefined && dependencies['react-dom'] !== undefined; const isVite = dependencies['vite'] !== undefined || dependencies['@vitejs/plugin-react'] !== undefined; if (isReact && isVite) { return { name: 'react-vite', source }; } const isNextJs = dependencies['react'] !== undefined && dependencies['next'] !== undefined; if (isNextJs) { return { name: 'nextjs', source }; } frameworkList = frameworkList.filter((framework) => !['static', 'react-vite', 'nextjs'].includes(framework.name)); const framework = frameworkList.find(({ keywords }) => keywords.every((keyword) => dependencies[keyword] !== undefined)); if (!framework) { (0, logger_1.warning)('No matching framework found in package.json dependencies'); return getFrameworkOption(frameworkList); } return { name: framework.name, source }; }); } function getConfigDetails(frameworkOpt, frameworks) { return __awaiter(this, void 0, void 0, function* () { const slateConfigs = frameworks.find((framework) => frameworkOpt.toLowerCase() === framework.name); if (frameworkOpt === 'static') { return { framework: 'static' }; } const slateConfigDetails = { framework: frameworkOpt, install_command: slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings.install_command.value, build_path: slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings.output_dir.value, build_command: slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings.build_command.value, root_path: './' }; let editDefaultConfig; if (!(0, option_1.getOptionValue)('default')) { if (slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings) { (0, console_1.log)(`Auto-detected App Configuration (${(0, ansi_colors_1.bold)(frameworkOpt)}):\n` + `${(0, ansi_colors_1.grey)((0, ansi_colors_1.bold)('Install Command: ') + (slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings.install_command.placeholder))}\n` + `${(0, ansi_colors_1.grey)((0, ansi_colors_1.bold)('Build Command: ') + (slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings.build_command.placeholder))}\n` + `${(0, ansi_colors_1.grey)((0, ansi_colors_1.bold)('Build Path: ') + (slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings.output_dir.placeholder))}`); editDefaultConfig = yield prompt_1.default.ask(prompt_1.default.question('config', 'Do you want to modify these default configurations?', { type: 'confirm', default: false })); } else { (0, logger_1.warning)('Unable to detect the app configuration for the selected framework.'); } } if (!(slateConfigs === null || slateConfigs === void 0 ? void 0 : slateConfigs.settings) || (editDefaultConfig === null || editDefaultConfig === void 0 ? void 0 : editDefaultConfig.config)) { const config = yield prompt_1.default.ask(prompt_1.default.question('installCommand', 'Provide your Install Command:', { type: 'input', validate: (value) => __awaiter(this, void 0, void 0, function* () { value = value.trim(); if (value === '') return 'Please provide a valid install command'; else if (value.length > 50) return 'Cannot exceed 50 characters.'; return true; }) }), prompt_1.default.question('buildCommand', 'Provide your Build Command:', { type: 'input', validate: (value) => __awaiter(this, void 0, void 0, function* () { value = value.trim(); if (value === '') return 'Please provide a valid build command'; else if (value.length > 50) return 'Cannot exceed 50 characters.'; return true; }) }), prompt_1.default.question('buildPath', 'Provide your Build Path:', { type: 'input', validate: (value) => __awaiter(this, void 0, void 0, function* () { value = value.trim(); if (value === '') return 'Please provide a valid build path'; else if (/[#%*$@?]/.test(value)) return 'Build path containing invalid characters.'; else if (value.length > 50) return 'Cannot exceed 50 characters.'; return true; }) })); (slateConfigDetails.install_command = config.installCommand), (slateConfigDetails.build_path = config.buildPath), (slateConfigDetails.build_command = config.buildCommand); } return slateConfigDetails || {}; }); } exports.default = (add) => __awaiter(void 0, void 0, void 0, function* () { const frameworks = yield (yield (0, endpoints_1.slateAPI)()).getFrameworks(); const templateName = (0, option_1.getOptionValue)('template'); const frameworkOpt = add ? yield detectFramework(yield addExistingSlate(config_1.slateConfig.raw() || []), frameworks) : yield getFrameworkOption(frameworks); const appName = yield getAppName(config_1.slateConfig.raw() || [], frameworkOpt.name); const payload = { name: appName, source: frameworkOpt.source || (yield handleTemplate(appName, { templateName, frameworkName: frameworkOpt.name })) }; const slateConfigDetails = yield getConfigDetails(frameworkOpt.name, frameworks); if (frameworkOpt.name !== 'static') { const slateRunConfig = yield prompt_1.default.ask(prompt_1.default.question('devCommand', 'Please provide your Development Command:', { type: 'input', default: 'npm start', validate: (value) => __awaiter(void 0, void 0, void 0, function* () { value = value.trim(); if (value === '') return 'Please provide a valid development command'; else if (value.length > 50) return 'Cannot exceed 50 characters.'; return true; }) })); yield fs_1.ASYNC.writeJSONFile((0, path_1.join)(payload.source, constants_1.FILENAME.cli_config), { slate: { dev_command: slateRunConfig.devCommand } }); } const pth = path_1.default.join(payload.source, '.catalyst', constants_1.FILENAME.slate_config); const warnContent = '# ⚠️ This file is automatically generated by the Catalyst CLI when you link or create a Slate app,and is used only for the initial deployment to the Catalyst console. \ \n# ⚠️ Please do not modify this file, as it is fully managed by the CLI.\n'; yield (0, async_1.ensureFile)(pth, true); fs_1.ASYNC.writeFile(pth, warnContent + '\n' + (0, toml_1.convertTOML)(slateConfigDetails)); runtime_store_1.default.set('payload.slate.targets', [payload]); });