UNPKG

@winner-fed/deploy-cli

Version:

CLI tool for deploy.

650 lines (633 loc) 20 kB
/* * @winner-fed/deploy-cli * @Author: whaleFE * @Version: 1.0.0 * @Description: CLI tool for deploy. * @Date: Build time 2025/7/11 13:19:21 */ "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // package.json var require_package = __commonJS({ "package.json"(exports2, module2) { module2.exports = { name: "@winner-fed/deploy-cli", version: "1.0.0", description: "CLI tool for deploy.", main: "dist/index.js", types: "dist/index.d.ts", bin: { "deploy-cli": "bin/deploy.js" }, files: [ "dist", "bin" ], keywords: [ "depoly", "deploy-cli", "ftp", "see" ], scripts: { prepublishOnly: "npm run build", dev: "tsup --watch", build: "tsup", typecheck: "tsc --noEmit" }, dependencies: { "@winner-fed/winner-deploy": "workspace:^", "@winner-fed/ftp-deploy": "workspace:^", cac: "^6.7.12", colorette: "^2.0.19", chokidar: "^3.5.3", "fs-extra": "^10.1.0", "strip-json-comments": "3.1.1", jiti: "^1.21.0", joycon: "^3.0.1", deepmerge: "^4.2.2" }, devDependencies: { "@types/fs-extra": "^9.0.13", tslib: "^2.4.0", tsup: "^8.5.0" }, engines: { node: ">=14" }, license: "ISC" }; } }); // src/index.ts var index_exports = {}; __export(index_exports, { cli: () => cli, copyDistToDocker: () => copyDistToDocker, defineConfig: () => defineConfig, formatDate: () => formatDate, generateGUID: () => generateGUID, generateSeePackageInfo: () => generateSeePackageInfo, getGitHash: () => getGitHash, isGitSync: () => isGitSync, transformTime: () => transformTime }); module.exports = __toCommonJS(index_exports); // src/cli.ts var import_cac = require("cac"); // src/command.ts var import_deepmerge = __toESM(require("deepmerge")); // src/load.ts var import_fs = __toESM(require("fs")); var import_joycon = __toESM(require("joycon")); var import_path = __toESM(require("path")); var import_jiti = __toESM(require("jiti")); // src/jsoncParse.ts var import_strip_json_comments = __toESM(require("strip-json-comments")); function jsoncParse(data) { try { return new Function("return " + (0, import_strip_json_comments.default)(data).trim())(); } catch (e) { return {}; } } // src/load.ts var joycon = new import_joycon.default(); var loadJson = (filepath) => __async(null, null, function* () { try { return jsoncParse(yield import_fs.default.promises.readFile(filepath, "utf8")); } catch (error) { if (error instanceof Error) { throw new Error(`Failed to parse ${import_path.default.relative(process.cwd(), filepath)}: ${error.message}`); } else { throw error; } } }); var jsonLoader = { test: /\.json$/, load(filepath) { return loadJson(filepath); } }; joycon.addLoader(jsonLoader); function loadUserConfig(cwd, configFile) { return __async(this, null, function* () { const configJoycon = new import_joycon.default(); const configPath = yield configJoycon.resolve({ files: configFile ? [configFile] : [ `deploy.config.ts`, `deploy.config.js`, `deploy.config.cjs`, `deploy.config.mjs`, `deploy.config.json`, "package.json" ], cwd, stopDir: import_path.default.parse(cwd).root, packageKey: `deploy` }); if (configPath) { if (configPath.endsWith(".json")) { let data = yield loadJson(configPath); if (configPath.endsWith("package.json")) { data = data.deploy; } if (data) { return { path: configPath, data }; } return {}; } const jiti = (0, import_jiti.default)(configPath, { cache: true, debug: process.env.NODE_ENV === "development" }); try { const configModule = jiti(configPath); return { path: configPath, data: configModule.deploy || configModule.default || configModule }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to load config from ${import_path.default.relative(process.cwd(), configPath)}: ${error.message}`); } else { throw error; } } } return {}; }); } function loadPkg(cwd) { return __async(this, null, function* () { const { data } = yield joycon.load(["package.json"], cwd, import_path.default.dirname(cwd)); return data || {}; }); } // src/command.ts var mergeDeployConfig = (defaultAppConfig) => __async(null, null, function* () { var _a; const userConfig = (_a = yield loadUserConfig(defaultAppConfig.source, defaultAppConfig.config)) == null ? void 0 : _a.data; return (0, import_deepmerge.default)(defaultAppConfig, userConfig); }); // src/see.ts var import_fs_extra2 = __toESM(require("fs-extra")); var import_path3 = __toESM(require("path")); // src/util.ts var import_path2 = __toESM(require("path")); var import_fs_extra = __toESM(require("fs-extra")); // src/log.ts var colors = __toESM(require("colorette")); var colorize = (type, data, onlyImportant = false) => { if (onlyImportant && (type === "info" || type === "success")) return data; const color = type === "info" ? "blue" : type === "error" ? "red" : type === "warn" ? "yellow" : "green"; return colors[color](data); }; var makeLabel = (name, input, type) => { return [name && `${colors.dim("[")}${name.toUpperCase()}${colors.dim("]")}`, colorize(type, input)].filter(Boolean).join(" "); }; var silent = false; var createLogger = (name) => { return { setName(_name) { name = _name; }, success(label, ...args) { return this.log(label, "success", ...args); }, info(label, ...args) { return this.log(label, "info", ...args); }, error(label, ...args) { return this.log(label, "error", ...args); }, warn(label, ...args) { return this.log(label, "warn", ...args); }, log(label, type, ...data) { switch (type) { case "error": { return console.error(makeLabel(name, label, type), ...data.map((item) => colorize(type, item, true))); } default: if (silent) return; console.log(makeLabel(name, label, type), ...data.map((item) => colorize(type, item, true))); } } }; }; // src/util.ts var logger = createLogger(); function generateGUID() { var d = Date.now(); var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c === "x" ? r : r & 7 | 8).toString(16); }); return uuid; } function formatDate(date, fmt) { if (date === void 0) date = /* @__PURE__ */ new Date(); if (fmt === void 0) fmt = "yyyy-MM-dd HH:mm:ss"; if (typeof date === "string" || typeof date === "number") { date = new Date(date); } const o = { "M+": date.getMonth() + 1, // 月份 "d+": date.getDate(), // 日 "h+": date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, // 小时 "H+": date.getHours(), // 小时 "m+": date.getMinutes(), // 分 "s+": date.getSeconds(), // 秒 "q+": Math.floor((date.getMonth() + 3) / 3), // 季度 S: date.getMilliseconds() // 毫秒 }; const week = { "0": "\u65E5", "1": "\u4E00", "2": "\u4E8C", "3": "\u4E09", "4": "\u56DB", "5": "\u4E94", "6": "\u516D" }; if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); } if (/(E+)/.test(fmt)) { const dayKey = date.getDay().toString(); fmt = fmt.replace( RegExp.$1, (RegExp.$1.length > 1 ? RegExp.$1.length > 2 ? "\u661F\u671F" : "\u5468" : "") + (week[dayKey] || "") ); } for (var k in o) { if (new RegExp("(" + k + ")").test(fmt)) { const value = o[k]; fmt = fmt.replace( RegExp.$1, RegExp.$1.length === 1 ? value.toString() : ("00" + value).substr(("" + value).length) ); } } return fmt; } var isGitSync = function isGitSync2(dir) { let currentDir = import_path2.default.resolve(dir); let gitRoot; while (currentDir !== import_path2.default.dirname(currentDir)) { const gitPath = import_path2.default.join(currentDir, ".git"); if (import_fs_extra.default.existsSync(gitPath)) { gitRoot = currentDir; break; } currentDir = import_path2.default.dirname(currentDir); } return { isGit: !!gitRoot, gitRoot }; }; var getGitHash = function getGitHash2(gitRoot) { let rev; try { const gitHeadPath = gitRoot ? import_path2.default.join(gitRoot, ".git/HEAD") : ".git/HEAD"; rev = import_fs_extra.default.readFileSync(gitHeadPath).toString().trim().split(/.*[: ]/).slice(-1)[0]; } catch (error) { rev = generateGUID().slice(0, 8); } if (rev.indexOf("/") === -1) { return rev; } else { try { const gitRefPath = gitRoot ? import_path2.default.join(gitRoot, ".git", rev) : `.git/${rev}`; return import_fs_extra.default.readFileSync(gitRefPath).toString().trim(); } catch (error) { logger.error(".git/refs/heads/master \u8BBF\u95EE\u5931\u8D25\uFF0C\u8FD8\u6CA1\u6709\u8FDB\u884C\u8FC7\u7B2C\u4E00\u6B21\u63D0\u4EA4\u3002\u9ED8\u8BA4\u53D6\u503C\u4E3A guid\u3002"); return generateGUID().slice(0, 8); } } }; var transformTime = function transformTime2(cwd) { const gitResult = isGitSync(cwd); if (gitResult.isGit) { return `${formatDate(Date.now(), "yyyyMMddHHmmss")}.${getGitHash(gitResult.gitRoot).substring(0, 8)}`; } else { return `${formatDate(Date.now(), "yyyyMMddHHmmss")}.${generateGUID().slice(0, 8)}`; } }; function generateSeePackageInfo(source, { system, type, version, name, description, outputName, configName, isDocker, buildVersion, isProduction, variables, configTemplate }) { let seePackageName = `${system}-${name}-web`; const templateFunc = () => { if (configTemplate) return configTemplate; if (type === "bizframe") { return `./${outputName}/${configName}.js`; } return `./${outputName}/${name}/sysconfig.js`; }; const variablesFunc = () => { try { return variables || []; } catch (error) { console.error(error); return []; } }; const seePackageOptions = { system, type, name, version, templateFunc, variablesFunc, description, seePackageType: "web" }; if (isDocker) { seePackageName += "-docker"; seePackageOptions.seePackageType = "docker"; } function generateSeePackageNameAndVersion() { let appVersion2 = version.replace("-patch", ".") || `1.0.0`; const appVersionArray = appVersion2.split("."); appVersion2 = appVersionArray.length === 3 ? appVersion2 + ".0" : appVersion2; const cloneBuildVersion = buildVersion || appVersion2; seePackageName += `-${cloneBuildVersion}`; if (!isProduction) { appVersion2 = `${appVersion2}-${transformTime(source)}`; seePackageName += `-${transformTime(source)}`; } return { appVersion: appVersion2 }; } const { appVersion } = generateSeePackageNameAndVersion(); seePackageOptions.version = appVersion || version; return { seePackageOptions, defaultSeePackageName: seePackageName }; } function copyDistToDocker(cwd, outputName = "dist") { const dockerHtmlPath = import_path2.default.resolve(cwd, "docker/html"); import_fs_extra.default.remove(dockerHtmlPath, (err) => { if (err) return; import_fs_extra.default.copy(import_path2.default.resolve(cwd, outputName), dockerHtmlPath, (err2) => { if (err2) { logger.error("\u62F7\u8D1D dist \u81F3 docker/html \u5931\u8D25\uFF01\uFF01\uFF01"); } }); }); } // src/see.ts var import_winner_deploy = require("@winner-fed/winner-deploy"); function seeBuild(source, seeConfig) { return __async(this, null, function* () { const projectPkg = yield loadPkg(source); let _a = seeConfig, { name = projectPkg.name, version = projectPkg.version, description = projectPkg.description, system, type, appType = projectPkg.name, configName, buildVersion = projectPkg.buildVersion, outputName, isDocker, variables, isProduction, seePackageName, dockerImage, configTemplate, seePackagePath, cb } = _a, restArgs = __objRest(_a, [ "name", "version", "description", "system", "type", "appType", "configName", "buildVersion", "outputName", "isDocker", "variables", "isProduction", "seePackageName", "dockerImage", "configTemplate", "seePackagePath", "cb" ]); seePackagePath = seePackagePath || "package"; if (!system) { throw new Error("system \u4E0D\u80FD\u4E3A\u7A7A\uFF01\u6839\u636E\u5B9E\u9645\u9879\u76EE\u9700\u6C42\u8FDB\u884C\u547D\u540D\uFF01"); } const { defaultSeePackageName, seePackageOptions } = generateSeePackageInfo(source, { system, type, version, name, description, outputName, configName, isDocker, buildVersion, isProduction, variables, configTemplate }); if (!seePackageName) { seePackageName = defaultSeePackageName; } if (seePackagePath && seePackagePath !== "/") { import_fs_extra2.default.removeSync(import_path3.default.join(source, seePackagePath)); } if (seePackageOptions.seePackageType === "docker") { (0, import_winner_deploy.generateSeePackageZip)( __spreadValues(__spreadProps(__spreadValues({}, seePackageOptions), { appType, configName, outputName, seePackageName, dockerImage, seePackagePath }), restArgs), function() { copyDistToDocker(source, outputName); (0, import_winner_deploy.generateSeePackageZip)( __spreadValues(__spreadProps(__spreadValues({}, seePackageOptions), { appType, seePackageType: "web", configName, outputName, seePackageName: seePackageName == null ? void 0 : seePackageName.replace("-docker", ""), scriptsType: "bash", seePackagePath }), restArgs), () => { typeof cb === "function" && cb(); } ); } ); return; } (0, import_winner_deploy.generateSeePackageZip)( __spreadValues(__spreadProps(__spreadValues({}, seePackageOptions), { appType, configName, outputName, seePackageName, scriptsType: "bash", seePackagePath }), restArgs), () => { typeof cb === "function" && cb(); } ); }); } // src/ftp.ts var import_ftp_deploy = require("@winner-fed/ftp-deploy"); var logger2 = createLogger(); function ftpBuild(source, ftpConfig) { const ftpDeploy = new import_ftp_deploy.FtpDeployer(); logger2.info("Start uploading..."); ftpDeploy.deploy(ftpConfig).then((res) => logger2.info("upload finished:", res)).catch((err) => logger2.error(err)); } // src/cli.ts var cli = (defaultAppConfig) => { const program = (0, import_cac.cac)("@winner-fed/deploy-cli"); const versionCli = require_package().version; program.version(`@winner-fed/cli@${versionCli}`); program.help(); program.command("see [project]", "Build see package").option("--config <filename>", "Use a custom config file").action((filename, options) => __async(null, null, function* () { Object.assign(defaultAppConfig, __spreadValues({}, options)); const { source, seeConfig } = yield mergeDeployConfig(defaultAppConfig); yield seeBuild(source, seeConfig); })); program.command("ftp [project]", "FTP uploads local files to the target server").option("--config <filename>", "Use a custom config file").action((filename, options) => __async(null, null, function* () { Object.assign(defaultAppConfig, __spreadValues({}, options)); const { source, ftpConfig } = yield mergeDeployConfig(defaultAppConfig); yield ftpBuild(source, ftpConfig); })); program.parse(process.argv); }; // src/defineConfig.ts var defineConfig = (config) => config; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { cli, copyDistToDocker, defineConfig, formatDate, generateGUID, generateSeePackageInfo, getGitHash, isGitSync, transformTime });