diff --git a/README.MD b/README.MD index 244a6fd..938d53e 100644 --- a/README.MD +++ b/README.MD @@ -1,5 +1,19 @@ # @noderun/pp +### 安装 +```bash +npm i @noderun/pp -h +``` +### 帮助 +```bash +pp -h +``` +### 查询 +```bash +pp list # 查询已存在的模板列表 +pp list -a # 包含仓库地址 +``` + 命令行管理模板项目 * [x] 增删查模板列表 diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..e4966ce --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,6 @@ +// Generated by dts-bundle v0.7.3 + +declare module '@noderun/pp' { + export {}; +} + diff --git a/dist/pp.cjs.js b/dist/pp.cjs.js index ca52ec7..0ceeb20 100755 --- a/dist/pp.cjs.js +++ b/dist/pp.cjs.js @@ -3,31 +3,150 @@ var commander = require('commander'); var tslib = require('tslib'); +var path = require('path'); +var os = require('os'); +var ini = require('ini'); var fs = require('fs-extra'); var chalk = require('chalk'); var uuid = require('uuid'); -var path = require('path'); -var os = require('os'); var download = require('download-git-repo'); var ejs = require('ejs'); -var ini = require('ini'); +var fetch = require('node-fetch'); +var qs = require('qs'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } +var path__default = /*#__PURE__*/_interopDefaultLegacy(path); +var os__default = /*#__PURE__*/_interopDefaultLegacy(os); +var ini__default = /*#__PURE__*/_interopDefaultLegacy(ini); var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk); var uuid__default = /*#__PURE__*/_interopDefaultLegacy(uuid); -var path__default = /*#__PURE__*/_interopDefaultLegacy(path); -var os__default = /*#__PURE__*/_interopDefaultLegacy(os); var download__default = /*#__PURE__*/_interopDefaultLegacy(download); var ejs__default = /*#__PURE__*/_interopDefaultLegacy(ejs); -var ini__default = /*#__PURE__*/_interopDefaultLegacy(ini); +var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch); +var qs__default = /*#__PURE__*/_interopDefaultLegacy(qs); var config = { dir: path__default["default"].join(os__default["default"].homedir(), '.pp'), - configPath: path__default["default"].join(os__default["default"].homedir(), '.pp', '.pprc') + configPath: path__default["default"].join(os__default["default"].homedir(), '.pp', '.pprc'), + listPath: path__default["default"].join(os__default["default"].homedir(), '.pp', '.listrc') }; +function writeErrorFile(content, path) { + if (path === void 0) { path = "pp.error.log"; } + if (typeof content == 'string') + syncWriteFile(path, content); + if (typeof content == "object" && content.toString) + syncWriteFile(path, content.toString()); + if (typeof content == "object" && content.toLocaleString) + syncWriteFile(path, content.toLocaleString()); +} +function syncWriteFile(path, content, encoding) { + if (encoding === void 0) { encoding = "utf-8"; } + return fs__default["default"].writeFileSync(path, content, encoding); +} +function readIniFile(path, encoding) { + if (encoding === void 0) { encoding = "utf-8"; } + return ini__default["default"].parse(fs__default["default"].readFileSync(path, encoding)); +} +function writeIniFile(path, data) { + fs__default["default"].writeFileSync(path, ini__default["default"].stringify(data)); +} + +var dataPath = config.listPath; +var Lists = readIniFile(dataPath); +var Data = (function () { + function Data() { + } + Data.getInstance = function () { + if (!Data.instance) { + Data.instance = new Data(); + } + return Data.instance; + }; + Data.prototype.getData = function () { + if (!Lists) { + Lists = {}; + } + return Lists; + }; + Data.prototype.sync = function () { + writeIniFile(dataPath, Lists); + }; + Data.prototype.remove = function (name) { + var data = this.getData(); + if (data[name]) { + delete data[name]; + this.sync(); + return true; + } + return false; + }; + Data.prototype.findOne = function (name) { + var data = this.getData(); + return data[name]; + }; + Data.prototype.addUrl = function (opts) { + var data = this.getData(); + if (!data[opts.name]) { + var _data = Object.assign({}, opts); + delete _data.name; + data[opts.name] = _data; + } + this.sync(); + }; + return Data; +}()); + +var configPath = config.configPath; +var configData = readIniFile(configPath); +var Config = (function () { + function Config() { + } + Config.getInstance = function () { + if (!Config.instance) { + Config.instance = new Config(); + } + return Config.instance; + }; + Config.prototype.getData = function () { + if (!configData) { + configData = {}; + } + return configData; + }; + Config.prototype.sync = function () { + writeIniFile(configPath, configData); + }; + Config.prototype.setGiteeToken = function (token) { + var gitee = this.getGitee(); + gitee.token = token; + this.sync(); + }; + Config.prototype.reomveGitee = function () { + var config = this.getData(); + delete config.gitee; + this.sync(); + }; + Config.prototype.getGitee = function () { + var config = this.getData(); + if (!config.gitee) + config.gitee = {}; + return config.gitee; + }; + return Config; +}()); + +try { + fs__default["default"].ensureDirSync(config.dir); + fs__default["default"].ensureFileSync(config.configPath); + fs__default["default"].ensureFileSync(config.listPath); +} +catch (e) { + throw e; +} + function walkDir(dir, cb) { function _walk(_dir) { if (_dir === void 0) { _dir = '.'; } @@ -46,7 +165,7 @@ function walkDir(dir, cb) { return _walk(); } function isExist(file) { - var result = false; + var result; try { fs__default["default"].accessSync(file, fs__default["default"].constants.F_OK | fs__default["default"].constants.R_OK | fs__default["default"].constants.W_OK); result = true; @@ -71,6 +190,8 @@ function writefile(fromDir, toDir, opts, force) { console.log(chalk__default["default"].red("安全起见,不覆写已存在的目录")); return; } + var errorFile = []; + var errors = []; walkDir(fromDir, function (file) { var fromRes = path__default["default"].resolve(fromDir, file); var toRes = path__default["default"].resolve(toDir, file); @@ -78,66 +199,111 @@ function writefile(fromDir, toDir, opts, force) { var originRoot = fs__default["default"].readFileSync(fromRes, { encoding: "utf8", }); - var html = ejs__default["default"].render(originRoot, opts); - fs__default["default"].writeFileSync(toRes, html); + try { + var html = ejs__default["default"].render(originRoot, opts); + fs__default["default"].writeFileSync(toRes, html); + } + catch (e) { + errorFile.push(toRes); + errors.push(e); + } }); + console.log(chalk__default["default"].green("写入完成")); + if (errorFile.length) { + console.log(chalk__default["default"].red('以下文件写入失败:')); + var errorInfo_1 = '错误如下:\n\n'; + errorFile.forEach(function (errFile, index) { + console.log(chalk__default["default"].red(errFile)); + errorInfo_1 += "=========================" + '\n'; + errorInfo_1 += errFile + '\n\n'; + errorInfo_1 += errors[index].toString() + '\n'; + errorInfo_1 += "=========================" + '\n'; + }); + var errorPath = path__default["default"].resolve(toDir, "./.pp.error.log"); + writeErrorFile(errorInfo_1, errorPath); + console.log(chalk__default["default"].red("详情请查看: " + errorPath)); + } } -function readFile(path, encoding) { - if (encoding === void 0) { encoding = "utf-8"; } - return fs__default["default"].readFileSync(path, encoding); -} -function readIniFile(path, encoding) { - if (encoding === void 0) { encoding = "utf-8"; } - return ini__default["default"].parse(fs__default["default"].readFileSync(path, encoding)); -} -function writeIniFile(path, data) { - fs__default["default"].writeFileSync(path, ini__default["default"].stringify(data)); -} - -try { - fs__default["default"].ensureDirSync(config.dir); - fs__default["default"].ensureFileSync(config.configPath); -} -catch (e) { - throw e; -} -var Opts = readIniFile(config.configPath); function onLogin(token) { - var result = Object.assign({}, Opts); - if (!result.token) - result.token = {}; - result.token.gitee = token; - writeIniFile(config.configPath, result); + Config.getInstance().setGiteeToken(token); console.log(chalk__default["default"].green("已保存gitee的私人令牌")); } +function onLogOut() { + Config.getInstance().reomveGitee(); + console.log(chalk__default["default"].green("已清除gitee")); +} function Whoami() { - console.log(chalk__default["default"].green("gitee token: ") + chalk__default["default"].greenBright(Opts.token.gitee)); + var giteeConfig = Config.getInstance().getGitee(); + var token = giteeConfig.token; + if (token) { + console.log(chalk__default["default"].green("gitee token: ") + chalk__default["default"].greenBright(token)); + } + else { + console.log(chalk__default["default"].green("您尚未保存gitee token")); + } +} +function sync() { + return tslib.__awaiter(this, void 0, void 0, function () { + var giteeConfig, token, params, requestInfo, res; + return tslib.__generator(this, function (_a) { + switch (_a.label) { + case 0: + giteeConfig = Config.getInstance().getGitee(); + token = giteeConfig.token; + params = qs__default["default"].stringify({ + access_token: token + }); + requestInfo = new fetch.Request('https://gitee.com/api/v5/gists?' + params, { + method: "GET" + }); + return [4, fetch__default["default"](requestInfo)]; + case 1: return [4, (_a.sent()).json()]; + case 2: + res = _a.sent(); + console.log(res); + return [2]; + } + }); + }); } function onList(opt) { - if (!Opts.list || !Object.keys(Opts.list).length) { + var data = Data.getInstance().getData(); + var keys = Object.keys(data); + if (!data || !keys.length) { console.log("暂无模板列表,请自行体添加"); return; } - Object.keys(Opts.list).forEach(function (key) { - var value = Opts.list[key]; + keys.forEach(function (key) { + var value = data[key]; if (opt === null || opt === void 0 ? void 0 : opt.all) { - console.log(value.name + (value.desc ? "(" + value.desc + ")" : "") + (": " + value.url)); + console.log(key + (value.desc ? "(" + value.desc + ")" : "") + (": " + value.url)); } else { - console.log(value.name + (value.desc ? "(" + value.desc + ")" : "")); + console.log(key + (value.desc ? "(" + value.desc + ")" : "")); } }); } -function onClone(target, opts) { - if (!Opts.list || !Opts.list[target]) { +function onCopy(templateDir, opts) { + if (!isExist(templateDir)) { + console.log(chalk__default["default"].red("请提供模板目录")); + return; + } + if (isExist(opts.targetDir)) { + console.log(chalk__default["default"].red("安全起见,不覆写已存在的目录,请先删除相同目录文件夹")); + return; + } + writefile(templateDir, opts.targetDir); +} +function onClone(name, opts) { + var item = Data.getInstance().findOne(name); + if (!item) { console.log("请先添加项目"); return; } - var data = Opts.list[target]; var tempPath = path__default["default"].join(os__default["default"].tmpdir(), "pp-" + uuid__default["default"].v4()); var to = opts.dir; - var git_url = "direct:" + data.url; + var git_url = "direct:" + item.url; if (isExist(to)) { console.log(chalk__default["default"].red("安全起见,不覆写已存在的目录,请先删除相同目录文件夹")); return; @@ -154,10 +320,8 @@ function onClone(target, opts) { }); } function onRemove(name) { - var result = Object.assign({}, Opts); - if (result.list && result.list[name]) { - delete result.list[name]; - writeIniFile(config.configPath, result); + var status = Data.getInstance().remove(name); + if (status) { console.log(chalk__default["default"].green("删除成功")); } else { @@ -165,26 +329,17 @@ function onRemove(name) { } } function onAdd(url, opt) { - var result = Object.assign({}, Opts); var http = /^(http|https)\:\/\//g; var git = /(git|root)\@/g; if (!git.test(url) && !http.test(url)) { console.error(chalk__default["default"].red("请添加正确的Git仓库地址")); return; } - if (!result.list) - result.list = {}; - if (result.list[opt.name]) { - console.error(chalk__default["default"].red("名字重复,当前存在:")); - onList(); - return; - } - result.list[opt.name] = tslib.__assign(tslib.__assign({}, opt), { url: url }); - writeIniFile(config.configPath, result); + Data.getInstance().addUrl(tslib.__assign(tslib.__assign({}, opt), { url: url })); console.log(chalk__default["default"].green("添加成功")); } function onCheck() { - console.log(readFile(config.configPath)); + console.log(JSON.stringify(Data.getInstance().getData())); } var program = new commander.Command(); @@ -193,6 +348,8 @@ program.helpOption("-h --help", "显示帮助信息"); program.showHelpAfterError("( pp -h 查看帮助信息)"); program.command("login ").description("本地保存Gitee的私人令牌").action(onLogin); program.command("whoami").description("查看私人令牌").action(Whoami); +program.command("logout").description("删除私人令牌").action(onLogOut); +program.command("sync").description("同步模板列表").action(sync); program.command("list").option('-a --all').description("查看所有模板列表").action(onList); program.command("check").description("查看配置文件").action(onCheck); program @@ -203,9 +360,10 @@ program .description("添加一个模板仓库") .action(onAdd); program - .command("rm ") + .command("remove ") .description("删除一个模板仓库") .action(onRemove); program.command("clone ").requiredOption("-d --dir ", "目标路径").description("克隆模板仓库").action(onClone); +program.command("copy ").requiredOption("-d --targetDir ", "目标路径").description("简单文件夹克隆").action(onCopy); program.parse(process.argv); //# sourceMappingURL=pp.cjs.js.map diff --git a/dist/pp.cjs.js.map b/dist/pp.cjs.js.map index 610c2d3..ff660dd 100644 --- a/dist/pp.cjs.js.map +++ b/dist/pp.cjs.js.map @@ -1 +1 @@ -{"version":3,"file":"pp.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} \ No newline at end of file +{"version":3,"file":"pp.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/package.json b/package.json index cfe1334..7da9708 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@types/ini": "^1.3.31", "@types/inquirer": "^8.1.3", "@types/node": "^15.12.5", + "@types/node-fetch": "2", "@types/qs": "^6.9.7", "@types/uuid": "^8.3.1", "chalk": "^4.1.2", @@ -62,6 +63,7 @@ "download-git-repo": "^3.0.2", "ejs": "^3.1.6", "ini": "^2.0.0", + "node-fetch": "2", "qs": "^6.10.1", "uuid": "^8.3.2" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1fad543..eb81f65 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,7 @@ specifiers: '@types/ini': ^1.3.31 '@types/inquirer': ^8.1.3 '@types/node': ^15.12.5 + '@types/node-fetch': '2' '@types/qs': ^6.9.7 '@types/uuid': ^8.3.1 chalk: ^4.1.2 @@ -23,6 +24,7 @@ specifiers: ini: ^2.0.0 inquirer: ^8.2.0 lodash: ^4.17.20 + node-fetch: '2' ora: 5.4.1 qs: ^6.10.1 rollup: ^2.26.3 @@ -37,6 +39,7 @@ dependencies: download-git-repo: 3.0.2 ejs: 3.1.6 ini: 2.0.0 + node-fetch: registry.npmmirror.com/node-fetch/2.6.6 qs: 6.10.1 uuid: 8.3.2 @@ -50,6 +53,7 @@ devDependencies: '@types/ini': 1.3.31 '@types/inquirer': registry.npmmirror.com/@types/inquirer/8.1.3 '@types/node': registry.npmmirror.com/@types/node/15.14.9 + '@types/node-fetch': registry.nlark.com/@types/node-fetch/2.5.12 '@types/qs': 6.9.7 '@types/uuid': 8.3.1 chalk: registry.nlark.com/chalk/4.1.2 @@ -275,7 +279,7 @@ packages: decompress-tarbz2: 4.1.1 decompress-targz: 4.1.1 decompress-unzip: 4.0.1 - graceful-fs: 4.2.8 + graceful-fs: registry.npmmirror.com/graceful-fs/4.2.8 make-dir: 1.3.0 pify: 2.3.0 strip-dirs: 2.1.0 @@ -334,7 +338,7 @@ packages: resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} engines: {node: '>=0.10.0'} dependencies: - mime-db: 1.51.0 + mime-db: registry.npmmirror.com/mime-db/1.51.0 dev: false /ext-name/5.0.0: @@ -411,14 +415,6 @@ packages: resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} dev: false - /fsevents/2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} @@ -488,9 +484,6 @@ packages: url-to-options: 1.0.1 dev: false - /graceful-fs/4.2.8: - resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==} - /has-flag/3.0.0: resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} engines: {node: '>=4'} @@ -626,11 +619,6 @@ packages: pify: 3.0.0 dev: false - /mime-db/1.51.0: - resolution: {integrity: sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==} - engines: {node: '>= 0.6'} - dev: false - /mimic-response/1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -977,6 +965,15 @@ packages: version: 3.0.5 dev: true + registry.nlark.com/@types/node-fetch/2.5.12: + resolution: {integrity: sha1-im93mx1OYLelf7b9SNhPtUW5zGY=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@types/node-fetch/download/@types/node-fetch-2.5.12.tgz} + name: '@types/node-fetch' + version: 2.5.12 + dependencies: + '@types/node': registry.npmmirror.com/@types/node/15.14.9 + form-data: registry.nlark.com/form-data/3.0.1 + dev: true + registry.nlark.com/@types/resolve/1.17.1: resolution: {integrity: sha1-Ov1q2JZ8d+Q3bFmKgt3Vj0bsRdY=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@types/resolve/download/@types/resolve-1.17.1.tgz} name: '@types/resolve' @@ -1018,6 +1015,12 @@ packages: color-convert: 2.0.1 dev: true + registry.nlark.com/asynckit/0.4.0: + resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/asynckit/download/asynckit-0.4.0.tgz} + name: asynckit + version: 0.4.0 + dev: true + registry.nlark.com/at-least-node/1.0.0: resolution: {integrity: sha1-YCzUtG6EStTv/JKoARo8RuAjjcI=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/at-least-node/download/at-least-node-1.0.0.tgz} name: at-least-node @@ -1116,6 +1119,15 @@ packages: engines: {node: '>=0.8'} dev: true + registry.nlark.com/combined-stream/1.0.8: + resolution: {integrity: sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/combined-stream/download/combined-stream-1.0.8.tgz} + name: combined-stream + version: 1.0.8 + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: registry.nlark.com/delayed-stream/1.0.0 + dev: true + registry.nlark.com/commondir/1.0.1: resolution: {integrity: sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/commondir/download/commondir-1.0.1.tgz} name: commondir @@ -1165,6 +1177,13 @@ packages: clone: registry.nlark.com/clone/1.0.4 dev: true + registry.nlark.com/delayed-stream/1.0.0: + resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/delayed-stream/download/delayed-stream-1.0.0.tgz} + name: delayed-stream + version: 1.0.0 + engines: {node: '>=0.4.0'} + dev: true + registry.nlark.com/detect-indent/0.2.0: resolution: {integrity: sha1-BCkUSYl5rC2fPHPk/z5od9O8krY=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/detect-indent/download/detect-indent-0.2.0.tgz} name: detect-indent @@ -1251,13 +1270,24 @@ packages: pkg-dir: registry.npmmirror.com/pkg-dir/4.2.0 dev: true + registry.nlark.com/form-data/3.0.1: + resolution: {integrity: sha1-69U3kbeDVqma+aMA1CgsTV65dV8=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/form-data/download/form-data-3.0.1.tgz?cache=0&sync_timestamp=1631521637683&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fform-data%2Fdownload%2Fform-data-3.0.1.tgz} + name: form-data + version: 3.0.1 + engines: {node: '>= 6'} + dependencies: + asynckit: registry.nlark.com/asynckit/0.4.0 + combined-stream: registry.nlark.com/combined-stream/1.0.8 + mime-types: registry.npmmirror.com/mime-types/2.1.34 + dev: true + registry.nlark.com/fs-extra/8.1.0: resolution: {integrity: sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/fs-extra/download/fs-extra-8.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffs-extra%2Fdownload%2Ffs-extra-8.1.0.tgz} name: fs-extra version: 8.1.0 engines: {node: '>=6 <7 || >=8'} dependencies: - graceful-fs: 4.2.8 + graceful-fs: registry.npmmirror.com/graceful-fs/4.2.8 jsonfile: registry.nlark.com/jsonfile/4.0.0 universalify: registry.nlark.com/universalify/0.1.2 dev: true @@ -1384,7 +1414,7 @@ packages: name: jsonfile version: 4.0.0 optionalDependencies: - graceful-fs: 4.2.8 + graceful-fs: registry.npmmirror.com/graceful-fs/4.2.8 dev: true registry.nlark.com/jsonfile/6.1.0: @@ -1394,7 +1424,7 @@ packages: dependencies: universalify: registry.nlark.com/universalify/2.0.0 optionalDependencies: - graceful-fs: 4.2.8 + graceful-fs: registry.npmmirror.com/graceful-fs/4.2.8 dev: true registry.nlark.com/locate-path/5.0.0: @@ -1791,6 +1821,12 @@ packages: defaults: registry.nlark.com/defaults/1.0.3 dev: true + registry.nlark.com/webidl-conversions/3.0.1: + resolution: {integrity: sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/webidl-conversions/download/webidl-conversions-3.0.1.tgz} + name: webidl-conversions + version: 3.0.1 + dev: false + registry.nlark.com/which/2.0.2: resolution: {integrity: sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=, registry: https://registry.npm.taobao.org/, tarball: https://registry.nlark.com/which/download/which-2.0.2.tgz} name: which @@ -1960,6 +1996,16 @@ packages: path-exists: registry.nlark.com/path-exists/4.0.0 dev: true + registry.npmmirror.com/fsevents/2.3.2: + resolution: {integrity: sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fsevents/download/fsevents-2.3.2.tgz} + name: fsevents + version: 2.3.2 + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + registry.npmmirror.com/glob/6.0.4: resolution: {integrity: sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/glob/download/glob-6.0.4.tgz} name: glob @@ -1989,7 +2035,6 @@ packages: resolution: {integrity: sha1-5BK40z9eAGWTy9PO5t+fLOu+gCo=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/graceful-fs/download/graceful-fs-4.2.8.tgz} name: graceful-fs version: 4.2.8 - dev: true registry.npmmirror.com/inquirer/8.2.0: resolution: {integrity: sha1-9E8AjdNEu/xLMAMfRdmE4DSjrDo=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/inquirer/download/inquirer-8.2.0.tgz} @@ -2021,6 +2066,21 @@ packages: has: 1.0.3 dev: true + registry.npmmirror.com/mime-db/1.51.0: + resolution: {integrity: sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/mime-db/download/mime-db-1.51.0.tgz} + name: mime-db + version: 1.51.0 + engines: {node: '>= 0.6'} + + registry.npmmirror.com/mime-types/2.1.34: + resolution: {integrity: sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/mime-types/download/mime-types-2.1.34.tgz} + name: mime-types + version: 2.1.34 + engines: {node: '>= 0.6'} + dependencies: + mime-db: registry.npmmirror.com/mime-db/1.51.0 + dev: true + registry.npmmirror.com/mkdirp/0.5.5: resolution: {integrity: sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/mkdirp/download/mkdirp-0.5.5.tgz} name: mkdirp @@ -2030,6 +2090,15 @@ packages: minimist: registry.nlark.com/minimist/1.2.5 dev: true + registry.npmmirror.com/node-fetch/2.6.6: + resolution: {integrity: sha1-F1GnwBg06OFpd1hzLp77burfr4k=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/node-fetch/download/node-fetch-2.6.6.tgz} + name: node-fetch + version: 2.6.6 + engines: {node: 4.x || >=6.0.0} + dependencies: + whatwg-url: registry.npmmirror.com/whatwg-url/5.0.0 + dev: false + registry.npmmirror.com/npm-run-path/4.0.1: resolution: {integrity: sha1-t+zR5e1T2o43pV4cImnguX7XSOo=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/npm-run-path/download/npm-run-path-4.0.1.tgz?cache=0&sync_timestamp=1633420537317&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fnpm-run-path%2Fdownload%2Fnpm-run-path-4.0.1.tgz} name: npm-run-path @@ -2081,7 +2150,7 @@ packages: engines: {node: '>=10.0.0'} hasBin: true optionalDependencies: - fsevents: 2.3.2 + fsevents: registry.npmmirror.com/fsevents/2.3.2 dev: true registry.npmmirror.com/rxjs/7.4.0: @@ -2118,6 +2187,12 @@ packages: ansi-regex: registry.nlark.com/ansi-regex/5.0.1 dev: true + registry.npmmirror.com/tr46/0.0.3: + resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tr46/download/tr46-0.0.3.tgz} + name: tr46 + version: 0.0.3 + dev: false + registry.npmmirror.com/type-fest/0.21.3: resolution: {integrity: sha1-0mCiSwGYQ24TP6JqUkptZfo7Ljc=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/type-fest/download/type-fest-0.21.3.tgz} name: type-fest @@ -2132,3 +2207,12 @@ packages: engines: {node: '>=4.2.0'} hasBin: true dev: true + + registry.npmmirror.com/whatwg-url/5.0.0: + resolution: {integrity: sha1-lmRU6HZUYuN2RNNib2dCzotwll0=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/whatwg-url/download/whatwg-url-5.0.0.tgz} + name: whatwg-url + version: 5.0.0 + dependencies: + tr46: registry.npmmirror.com/tr46/0.0.3 + webidl-conversions: registry.nlark.com/webidl-conversions/3.0.1 + dev: false diff --git a/src/config.ts b/src/config.ts index a7c721f..8602caf 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,5 +4,6 @@ import os from "os"; export default { //数据目录 dir: path.join(os.homedir(), '.pp'), - configPath: path.join(os.homedir(), '.pp','.pprc') + configPath: path.join(os.homedir(), '.pp','.pprc'), + listPath: path.join(os.homedir(), '.pp','.listrc') } diff --git a/src/data/config.ts b/src/data/config.ts new file mode 100644 index 0000000..7f48f38 --- /dev/null +++ b/src/data/config.ts @@ -0,0 +1,45 @@ + +import config from "@/config"; +import {readIniFile, writeIniFile} from "@/util"; + +const configPath = config.configPath + +/** + * 读取配置 + */ +let configData = readIniFile(configPath); + +export default class Config { + private static instance:Config; + static getInstance():Config{ + if(!Config.instance){ + Config.instance = new Config() + } + return Config.instance + } + getData(){ + if(!configData){ + configData = {} + } + return configData + } + sync(){ + writeIniFile(configPath, configData); + } + + setGiteeToken(token: string){ + let gitee = this.getGitee() + gitee.token = token; + this.sync() + } + reomveGitee(){ + let config = this.getData() + delete config.gitee + this.sync() + } + getGitee(){ + let config = this.getData() + if(!config.gitee) config.gitee = {} + return config.gitee + } +} diff --git a/src/data/data.ts b/src/data/data.ts new file mode 100644 index 0000000..697ded7 --- /dev/null +++ b/src/data/data.ts @@ -0,0 +1,59 @@ +/** + * 确保配置文件存在 + */ +import fs from "fs-extra"; +import config from "@/config"; +import {readIniFile, writeIniFile} from "@/util"; + +const dataPath = config.listPath + +/** + * 读取配置 + */ +let Lists = readIniFile(dataPath); + +export default class Data { + private static instance:Data; + static getInstance():Data{ + if(!Data.instance) { + Data.instance = new Data() + } + return Data.instance + } + + getData(){ + if(!Lists){ + Lists = {} + } + return Lists + } + + sync(){ + writeIniFile(dataPath, Lists); + } + + remove(name: string){ + let data = this.getData() + if(data[name]){ + delete data[name] + this.sync() + return true + } + return false + } + + findOne(name: string){ + let data = this.getData() + return data[name] + } + + addUrl(opts: { url: string, name: string, desc?:string, force?: boolean}){ + let data = this.getData() + if(!data[opts.name]){ + let _data: { url: string, name?: string, desc?:string, force?: boolean} = Object.assign({}, opts) + delete _data.name + data[opts.name] = _data + } + this.sync() + } +} diff --git a/src/data/index.ts b/src/data/index.ts new file mode 100644 index 0000000..ab98d95 --- /dev/null +++ b/src/data/index.ts @@ -0,0 +1,21 @@ + +import Data from "./data" +import Config from "./config" +/** + * 确保配置文件存在 + */ +import fs from "fs-extra"; +import config from "@/config"; + +try { + fs.ensureDirSync(config.dir); + fs.ensureFileSync(config.configPath); + fs.ensureFileSync(config.listPath); +} catch (e) { + throw e; +} + +export { + Config, + Data +} diff --git a/src/func.ts b/src/func.ts index e88aa17..a391cb2 100644 --- a/src/func.ts +++ b/src/func.ts @@ -1,63 +1,49 @@ -import fs from "fs-extra"; +import { Data,Config } from "./data" import chalk from "chalk"; -import uuid from "uuid"; import path from "path"; import os from "os"; -import qs from "qs"; -import https from "https"; -//https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#readable-named-exports -//不想用pure esm, 采用ora的5.4.1版本 -// import ora from "ora"; -// import * as inquirer from "inquirer"; -import config from "@/config"; +import uuid from "uuid"; import download from "download-git-repo"; -import writefile, { isExist } from "./writefile"; -import { readFile, readIniFile, writeIniFile } from "./util"; - -/** - * 确保配置文件存在 - */ -try { - fs.ensureDirSync(config.dir); - fs.ensureFileSync(config.configPath); -} catch (e) { - throw e; -} -/** - * 读取配置 - */ -const Opts = readIniFile(config.configPath); +import writefile, {isExist} from "@/writefile"; +import fs from "fs-extra"; +import fetch, {Request} from "node-fetch"; +import qs from "qs"; export function onLogin(token: string) { - const result = Object.assign({}, Opts); - if (!result.token) result.token = {}; - result.token.gitee = token; - writeIniFile(config.configPath, result); + Config.getInstance().setGiteeToken(token) console.log(chalk.green("已保存gitee的私人令牌")); } + +export function onLogOut() { + Config.getInstance().reomveGitee() + console.log(chalk.green("已清除gitee")); +} + export function Whoami() { - console.log( - chalk.green("gitee token: ") + chalk.greenBright(Opts.token.gitee) - ); + let giteeConfig = Config.getInstance().getGitee() + let token = giteeConfig.token + if(token){ + console.log( + chalk.green("gitee token: ") + chalk.greenBright(token) + ); + }else{ + console.log( + chalk.green("您尚未保存gitee token") + ); + } } -export function sync() { - // const options = { - // hostname: 'gitee.com', - // port: 443, - // path: '/api/v5/gists?'+qs.stringify({access_token:''}), - // method: 'GET' - // } - // const req = https.request(options, res => { - // console.log(`状态码: ${res.statusCode}`) - // res.on('data', d => { - // process.stdout.write(d) - // }) - // }) - // req.on('error', error => { - // console.error(error) - // }) - // req.end() +export async function sync() { + let giteeConfig = Config.getInstance().getGitee() + let token = giteeConfig.token + let params = qs.stringify({ + access_token: token + }) + const requestInfo = new Request('https://gitee.com/api/v5/gists?'+params,{ + method: "GET" + }); + const res = await (await fetch(requestInfo)).json() + console.log(res) } // export function onLogin() { @@ -90,31 +76,49 @@ export function sync() { * @param opt 参数: all:是否显示Git地址 */ export function onList(opt?: { all?: boolean }) { - if (!Opts.list || !Object.keys(Opts.list).length) { + const data = Data.getInstance().getData() + const keys = Object.keys(data) + if (!data || !keys.length) { console.log("暂无模板列表,请自行体添加"); return; } - Object.keys(Opts.list).forEach((key) => { - let value = Opts.list[key]; + keys.forEach((key) => { + const value = data[key] if (opt?.all) { console.log( - value.name + (value.desc ? `(${value.desc})` : "") + `: ${value.url}` + key + (value.desc ? `(${value.desc})` : "") + `: ${value.url}` ); } else { - console.log(value.name + (value.desc ? `(${value.desc})` : "")); + console.log(key + (value.desc ? `(${value.desc})` : "")); } }); } -export function onClone(target: string, opts: { dir: string }) { - if (!Opts.list || !Opts.list[target]) { +export function onCopy(templateDir: string, opts: { targetDir: string }){ + if(!isExist(templateDir)){ + console.log( + chalk.red("请提供模板目录") + ); + return; + } + if (isExist(opts.targetDir)) { + console.log( + chalk.red("安全起见,不覆写已存在的目录,请先删除相同目录文件夹") + ); + return; + } + writefile(templateDir, opts.targetDir); +} + +export function onClone(name: string, opts: { dir: string }) { + const item = Data.getInstance().findOne(name) + if (!item) { console.log("请先添加项目"); return; } - let data = Opts.list[target]; let tempPath = path.join(os.tmpdir(), "pp-" + uuid.v4()); let to = opts.dir; - let git_url = "direct:" + data.url; + let git_url = "direct:" + item.url; if (isExist(to)) { console.log( chalk.red("安全起见,不覆写已存在的目录,请先删除相同目录文件夹") @@ -133,10 +137,8 @@ export function onClone(target: string, opts: { dir: string }) { } export function onRemove(name: string) { - let result = Object.assign({}, Opts); - if (result.list && result.list[name]) { - delete result.list[name]; - writeIniFile(config.configPath, result); + const status = Data.getInstance().remove(name) + if (status) { console.log(chalk.green("删除成功")); } else { console.error(chalk.red("不存在该模板")); @@ -144,24 +146,16 @@ export function onRemove(name: string) { } export function onAdd(url: string, opt: { name: string; desc?: string }) { - const result = Object.assign({}, Opts); const http = /^(http|https)\:\/\//g; const git = /(git|root)\@/g; if (!git.test(url) && !http.test(url)) { console.error(chalk.red("请添加正确的Git仓库地址")); return; } - if (!result.list) result.list = {}; - if (result.list[opt.name]) { - console.error(chalk.red("名字重复,当前存在:")); - onList(); - return; - } - result.list[opt.name] = { ...opt, url }; - writeIniFile(config.configPath, result); + Data.getInstance().addUrl({...opt, url: url}); console.log(chalk.green("添加成功")); } export function onCheck() { - console.log(readFile(config.configPath)); + console.log(JSON.stringify(Data.getInstance().getData())); } diff --git a/src/index.ts b/src/index.ts index c6c1295..0343d9a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,8 +12,10 @@ program.showHelpAfterError("( pp -h 查看帮助信息)"); //Todo program.command("login ").description("本地保存Gitee的私人令牌").action(func.onLogin); -program.command("whoami").description("查看私人令牌").action(func.Whoami); - +program.command("whoami").description("查看私人令牌").action(func.Whoami); +program.command("logout").description("删除私人令牌").action(func.onLogOut); +program.command("sync").description("同步模板列表").action(func.sync); + program.command("list").option('-a --all').description("查看所有模板列表").action(func.onList); program.command("check").description("查看配置文件").action(func.onCheck); @@ -27,10 +29,11 @@ program .action(func.onAdd); program - .command("rm ") + .command("remove ") .description("删除一个模板仓库") .action(func.onRemove); program.command("clone ").requiredOption("-d --dir ", "目标路径").description("克隆模板仓库").action(func.onClone); +program.command("copy ").requiredOption("-d --targetDir ", "目标路径").description("简单文件夹克隆").action(func.onCopy); program.parse(process.argv); diff --git a/src/util.ts b/src/util.ts index 7a1cf13..6a4fce6 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,13 +1,23 @@ -import ini, {EncodeOptions } from "ini" +import ini from "ini" import fs from "fs-extra" -export function readFile(path:string, encoding: BufferEncoding="utf-8") { +export function syncReadFile(path:string, encoding: BufferEncoding="utf-8") { return fs.readFileSync(path, encoding) } + +export function writeErrorFile(content: any, path:string = "pp.error.log"){ + if(typeof content == 'string') syncWriteFile(path, content); + if(typeof content == "object" && content.toString) syncWriteFile(path, content.toString()); + if(typeof content == "object" && content.toLocaleString) syncWriteFile(path, content.toLocaleString()); +} + +export function syncWriteFile(path:string, content: string, encoding: BufferEncoding="utf-8") { + return fs.writeFileSync(path, content, encoding) +} export function readIniFile(path:string, encoding: BufferEncoding="utf-8") { return ini.parse(fs.readFileSync(path, encoding)) } export function writeIniFile(path:string, data: Object) { fs.writeFileSync(path, ini.stringify(data)) -} \ No newline at end of file +} diff --git a/src/writefile.ts b/src/writefile.ts index 45f2d8d..ba126c7 100644 --- a/src/writefile.ts +++ b/src/writefile.ts @@ -2,7 +2,7 @@ import fs from "fs-extra"; import ejs from "ejs"; import chalk from "chalk"; import path from "path"; -import execa from "execa"; +import {writeErrorFile} from "@/util"; function walkDir (dir: string, cb?: (file: string)=>void) { function _walk (_dir = '.') { @@ -21,7 +21,7 @@ function walkDir (dir: string, cb?: (file: string)=>void) { } export function isExist (file: string) { - let result = false + let result: boolean try { fs.accessSync(file, fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK); result = true // 文件可读写 @@ -44,6 +44,8 @@ export default function writefile (fromDir: string, toDir: string, opts = {}, fo console.log(chalk.red("安全起见,不覆写已存在的目录")) return } + const errorFile:any[] = [] + const errors: any[] = [] walkDir(fromDir, function (file) { let fromRes = path.resolve(fromDir, file) let toRes = path.resolve(toDir, file) @@ -51,7 +53,32 @@ export default function writefile (fromDir: string, toDir: string, opts = {}, fo const originRoot = fs.readFileSync(fromRes, { encoding: "utf8", }); - const html = ejs.render(originRoot, opts); - fs.writeFileSync(toRes, html); + try{ + const html = ejs.render(originRoot, opts); + fs.writeFileSync(toRes, html); + }catch (e) { + errorFile.push(toRes) + errors.push(e) + // throw e + } }) + console.log( + chalk.green("写入完成") + ); + if(errorFile.length){ + console.log(chalk.red('以下文件写入失败:')) + let errorInfo = '错误如下:\n\n' + errorFile.forEach((errFile, index)=>{ + console.log(chalk.red(errFile)) + errorInfo+="========================="+'\n' + errorInfo+=errFile+'\n\n' + errorInfo+=errors[index].toString()+'\n' + errorInfo+="========================="+'\n' + }) + let errorPath = path.resolve(toDir, "./.pp.error.log") + writeErrorFile(errorInfo, errorPath) + console.log( + chalk.red("详情请查看: "+errorPath) + ); + } } diff --git a/templates/a.txt b/templates/a.txt index e2d2667..20b8889 100644 --- a/templates/a.txt +++ b/templates/a.txt @@ -1 +1,2 @@ -asdad <%= name %> \ No newline at end of file +asdad + <%= name %> diff --git a/templates/啊倒萨/aaa.d b/templates/啊倒萨/aaa.d index e2d2667..d536f7a 100644 --- a/templates/啊倒萨/aaa.d +++ b/templates/啊倒萨/aaa.d @@ -1 +1 @@ -asdad <%= name %> \ No newline at end of file +asdad diff --git a/templates/啊倒萨/aas.txt b/templates/啊倒萨/aas.txt new file mode 100644 index 0000000..20b8889 --- /dev/null +++ b/templates/啊倒萨/aas.txt @@ -0,0 +1,2 @@ +asdad + <%= name %>