UNPKG

@serpent/common-cli

Version:

通用的 cli 相关的函数

559 lines (507 loc) 16.2 kB
'use strict'; var fs$3 = require('fs'); var path$4 = require('path'); var assert = require('assert'); var _commonjsHelpers = require('./_commonjsHelpers-ed042b00.cjs'); var exists$1 = require('./exists-4a19b288.cjs'); var require$$1 = require('os'); var findup = {exports: {}}; /** * @module libs/fs/findup * @createdAt 2016-06-30 * * @copyright Copyright (c) 2016 Zhonglei Qiu * @license Licensed under the MIT license. */ (function (module, exports) { var fs = fs$3; var path = path$4; var exists = exists$1.existsExports; /** * * 递归向上查找满足条件的文件夹 * * @param {String} dir 起始查找目录 * @param {String|Function} iteratorSync 要查找到文件名,或者返回 Boolean 值的函数, * 如果此参数是函数,那么它会接收到参数是当前递归所在的目录 * @param {Object} [options] 配置选项 * * - allowTypes: {String|Array<String>} 要查找的文件所属类型, 参考 {@link module:libs/fs/exists} 函数的第二个参数 * - maxdepth: {Number} 递归的深度,1:表示只会查找当前文件夹下的文件,2:表示查找当前文件夹和上一个文件夹 ... * * @throws {Error} 如果没有找到任何满足条件的文件夹 * @return {String} 查找到的满足条件的文件夹路径 * * @author Zhongle Qiu * @since 2.0.0 * */ module.exports = function(dir, iteratorSync, options) { dir = path.normalize(dir); options = options || {}; if (typeof iteratorSync === 'string') { var file = iteratorSync; iteratorSync = function(dir) { return exists(path.join(dir, file), options.allowTypes) }; } var currentDepth = 0; while (dir !== path.resolve(dir, '..')) { if (typeof options.maxdepth === 'number' && options.maxdepth >= 0 && currentDepth >= options.maxdepth) { break } currentDepth++; if (iteratorSync(dir)) return dir dir = path.resolve(dir, '..'); } throw new Error('Not found') }; exports = module.exports; function _find(root, file, allowTypes) { if (file == null) { file = root; root = process.cwd(); } var dir = exports(root, file, {allowTypes: allowTypes}); return path.resolve(path.join(dir, file)) } /** * 递归向上查找指定的文件 * * @param {String} [root] 起始查找目录(如果没有指定,则从当前路径开始) * @param {String} file 要查找的文件名 * @throws {Error} 如果没有找到满足条件的文件 * @return {String} 返回查到的文件路径 * * @author Zhongle Qiu * @since 1.5.0 */ exports.file = function(root, file) { return _find(root, file, 'File') }; /** * 递归向上查找指定的文件夹 * * @param {String} [root] 起始查找目录(如果没有指定,则从当前路径开始) * @param {String} dir 要查找的文件夹名 * @throws {Error} 如果没有找到满足条件的文件夹 * @return {String} 返回查到的文件夹路径 * * @author Zhongle Qiu * @since 1.5.0 */ exports.dir = function(root, dir) { return _find(root, dir, 'Directory') }; /** * 递归向上查找 package.json 文件 * * @param {String} [root] 起始查找目录(如果没有指定,则从当前路径开始) * @throws {Error} 如果没有找到 package.json 文件 * @return {String} 返回查到的 package.json 的路径 * * @author Zhongle Qiu * @since 1.5.0 */ exports.pkg = function(root) { return exports.file(root || process.cwd(), 'package.json') }; /** * 递归向上查找 .git 文件夹 * * @param {String} [root] 起始查找目录(如果没有指定,则从当前路径开始) * @throws {Error} 如果没有找到 .git 文件夹 * @return {String} 返回查到的 .git 文件夹的路径 * * @author Zhongle Qiu * @since 1.5.0 */ exports.git = function(root) { var dir = _find(root || process.cwd(), '.git', ['File', 'Directory']); var stats = fs.statSync(dir); if (!stats.isDirectory()) { // .git 可能是一个文件,而不是文件夹 return fs.readFileSync(dir, 'utf8').substring('gitdir: '.length).trim() } return dir }; } (findup, findup.exports)); var findupExports = findup.exports; var _findup = /*@__PURE__*/_commonjsHelpers.getDefaultExportFromCjs(findupExports); /** * * @module libs/fs/mkdirp * @createdAt 2016-08-05 * * @copyright Copyright (c) 2016 Zhonglei Qiu * @license Licensed under the MIT license. */ var fs$2 = fs$3; var path$3 = path$4; var o777 = parseInt('0777', 8); /** * 创建目录 * * 如果上级目录不存在,也会创建,类似于 Linux 的 mkdirp * @param {String} p 要创建的目录 * @param {Object|Number} opts 配置或者直接指定要创建的目录的 * @param {Number} opts.mode * @param {Object} opts.fs * @return {String} */ var mkdirp$1 = function mkdirp(p, opts, made) { if (!opts || typeof opts !== 'object') { opts = { mode: opts }; } var mode = opts.mode; var xfs = opts.fs || fs$2; if (mode === undefined) { mode = o777 & (~process.umask()); } if (!made) made = null; p = path$3.resolve(p); try { xfs.mkdirSync(p, mode); made = made || p; } catch (err0) { switch (err0.code) { case 'ENOENT': /* istanbul ignore if */ if (path$3.dirname(p) === p) throw err0 made = mkdirp(path$3.dirname(p), opts, made); mkdirp(p, opts, made); break // In the case of any other error, just see if there's a dir // there already. If so, then hooray! If not, then something // is borked. default: var stat; try { stat = xfs.statSync(p); } catch (err1) { /* istanbul ignore next */ throw err0 } /* istanbul ignore else */ if (!stat.isDirectory()) throw err0 } } return made }; var mkdirp$2 = /*@__PURE__*/_commonjsHelpers.getDefaultExportFromCjs(mkdirp$1); /** * * @module libs/fs/ospath * @createdAt 2017-07-14 * * @copyright Copyright (c) 2017 Zhonglei Qiu * @license Licensed under the MIT license. * @see https://github.com/jprichardson/ospath/blob/1.2.2/index.js */ var path$2 = path$4; var os = require$$1; function data() { switch (this.__platform || /* istanbul ignore next */ process.platform) { case 'win32': return path$2.resolve(process.env.APPDATA) case 'darwin': return path$2.resolve(path$2.join(home.call(this), 'Library/Application Support/')) default: return process.env.XDG_CONFIG_HOME ? path$2.resolve(process.env.XDG_CONFIG_HOME) : path$2.resolve(path$2.join(home.call(this), '.config/')) } } function desktop() { return path$2.join(home.call(this), 'Desktop') } function home() { /* istanbul ignore else */ if ('homedir' in os) return os.homedir() // io.js >= 2.3 /* istanbul ignore next */ switch (this.__platform || process.platform) { case 'win32': return path$2.resolve(process.env.USERPROFILE) default: return path$2.resolve(process.env.HOME) } } function tmp() { switch (this.__platform || /* istanbul ignore next */ process.platform) { case 'win32': return path$2.resolve(process.env.TEMP) default: return path$2.resolve('/tmp') } } var ospath$1 = { __platform: process.platform, data: data, desktop: desktop, home: home, tmp: tmp }; var ospath_1 = ospath$1; var _ospath = /*@__PURE__*/_commonjsHelpers.getDefaultExportFromCjs(ospath_1); /** * 递归删除指定的文件夹或文件 * * @module libs/fs/rm * @createdAt 2016-08-05 * * @copyright Copyright (c) 2016 Zhonglei Qiu * @license Licensed under the MIT license. */ var fs$1 = fs$3; var path$1 = path$4; /** * 递归遍历删除指定的文件或文件夹 * @param {String} file 要删除的文件的路径 */ function rm$1(file) { var stat; try { stat = fs$1.statSync(file); } catch (e) { /* istanbul ignore else */ if (e.message.indexOf('ENOENT') === 0) { return false } /* istanbul ignore next */ throw e } if (stat.isDirectory()) { return rmDir(file) } else { return rmFile(file) } } function rmFile(file) { return fs$1.unlinkSync(file) } function rmDir(dir) { fs$1.readdirSync(dir).forEach(function(item) { rm$1(path$1.join(dir, item)); }); return fs$1.rmdirSync(dir) } var rm_1 = rm$1; var _rm = /*@__PURE__*/_commonjsHelpers.getDefaultExportFromCjs(rm_1); var fs = fs$3; var path = path$4; function walk$1(rootDir, callback) { fs.readdirSync(rootDir).forEach(function(fileName) { var fileFullPath = path.join(rootDir, fileName); var fileStat = fs.statSync(fileFullPath); if (callback(rootDir, fileName, fileFullPath, fileStat) !== false) { if (fileStat.isDirectory()) { walk$1(fileFullPath, callback); } } }); } var walk_1 = walk$1; var _walk = /*@__PURE__*/_commonjsHelpers.getDefaultExportFromCjs(walk_1); /** * 将文件路径转化成操作系统相关的路径 * @param filePath 文件路径 */ function toOSPath(filePath, sep) { if (sep === void 0) { sep = path$4.sep; } return filePath.split(/[\\/]/).join(sep); } /** * 将文件路径转化成 posix 系统相关的路径 * @param filePath 文件路径 */ function toPosixPath(filePath) { return toOSPath(filePath, path$4.posix.sep); } /** * 将文件路径转化成 win32 系统相关的路径 * @param filePath 文件路径 */ function toWin32Path(filePath) { return toOSPath(filePath, path$4.win32.sep); } /** 向上递归查找指定的文件 */ function findupFile(name, refRootPath) { var ref = refRootPath || process.cwd(); try { return _findup.file(ref, name); } catch (e) { throw new Error("can't found up file whose name is \"".concat(name, "\" from directory ").concat(ref, " ")); } } /** 向上递归查找指定名称的文件夹 */ function findupDir(name, refRootPath) { var ref = refRootPath || process.cwd(); try { return _findup.dir(ref, name); } catch (e) { throw new Error("can't found up directory whose name is \"".concat(name, "\" from directory ").concat(ref, " ")); } } /** * 向上递归查找有效的 package.json 文件 * * @testing-library/user-event 项目在生成的 dist 文件下还有 package.json 目录,这种情况会避免返回错误的路径, * 处理方法: 如果有 node_modules,则 package.json 目录前不应该出现三层结构,会根据层级结构优化 */ function findupPackage(refRootPath) { var ref = refRootPath || process.cwd(); try { var result = _findup.pkg(ref); var NM = 'node_modules'; // result 示例: xx/node_modules/@testing-library/user-event/dist/cjs if (result.includes(NM)) { var splitIndex = result.lastIndexOf(NM) + NM.length + 1; // prefix 示例: xx/node_modules/ // suffix 示例: @testing-library/user-event/dist/cjs var prefix = result.substring(0, splitIndex); var suffix = result.substring(splitIndex); var parts = suffix.split(/[/\\]/); var tmp = void 0; if (suffix[0] === '@') { tmp = parts.length === 2 ? result : path$4.join(prefix, parts[0], parts[1]); } else { tmp = parts.length === 1 ? result : path$4.join(prefix, parts[0]); } tmp = path$4.join(tmp, 'package.json'); return existsFile(tmp) ? tmp : result; } return result; } catch (e) { throw new Error("can't found up \"package.json\" in directory ".concat(ref)); } } /** 向上递归查找包含 package.json 的目录 */ function findupPackageRoot(refRootPath) { return path$4.dirname(findupPackage(refRootPath)); } /** 递归删除指定路径上的内容 */ function rm(absPath) { return _rm(absPath); } /** 遍历指定目录上的内容 */ function walk(absDir, callback) { return _walk(absDir, callback); } var ospath = { __platform: _ospath.__platform, /** * 获取系统存放数据的目录,优先读取 XDG_DATA_HOME 环境变量 */ data: makeSystemDir('data', 'XDG_DATA_HOME'), /** * 获取系统桌面目录 */ desktop: makeSystemDir('desktop'), /** * 获取系统的当前用户目录 */ home: makeSystemDir('home'), /** * 获取系统的临时目录 */ tmp: makeSystemDir('tmp'), /** * 获取系统的缓存目录,优先读取 XDG_CACHE_HOME 环境变量,其次 "$HOME/.cache" */ cache: makeCustomDir('.cache', 'XDG_CACHE_HOME'), /** * 获取系统的配置目录,优先读取 XDG_CONFIG_HOME 环境变量,其次 "$HOME/.config" */ config: makeCustomDir('.config', 'XDG_CONFIG_HOME'), }; function makeCustomDir(custom, envKey) { return function (subpath) { return getDir(envKey && process.env[envKey] || path$4.join(_ospath.home(), custom), subpath); }; } function makeSystemDir(key, envKey) { return function (subpath) { return getDir(envKey && process.env[envKey] || _ospath[key](), subpath); }; } function getDir(root, subpath) { return subpath ? path$4.resolve(root, toOSPath(subpath)) : root; } /** 递归创建文件夹 */ function mkdirp(absDir) { return mkdirp$2(absDir); } /** 确保文件夹存在 */ function ensureDir(absDir) { mkdirp(absDir); } /** 确保文件存在 */ function ensureFile(absPath) { if (!existsFile(absPath)) { ensureDir(path$4.dirname(absPath)); fs$3.writeFileSync(absPath, ''); } } /** 判断指定路径上是否存在内容 */ function exists(absPath) { return !!tryStat(absPath); } /** 判断指定路径上是否存在文件 */ function existsFile(absFile) { return tryStatExists(absFile, 'isFile'); } /** 判断指定路径上是否存在非文件的内容 */ function existsNotFile(absPath) { return tryStatExists(absPath, 'isFile', true); } /** 判断文件是否存在,不存在则抛出异常 */ function assertFile(absFile, message) { assert.ok(existsFile(absFile), message || "file \"".concat(absFile, "\" is not exists")); } /** 判断指定路径上是否存在文件夹 */ function existsDir(absDir) { return tryStatExists(absDir, 'isDirectory'); } /** 判断指定路径上是否存在非文件夹的内容 */ function existsNotDir(absPath) { return tryStatExists(absPath, 'isDirectory', true); } /** 判断文件是否存在,不存在则抛出异常 */ function assertDir(absDir, message) { assert.ok(existsDir(absDir), message || "directory \"".concat(absDir, "\" is not exists")); } /** 获取文件的 stats 对象 */ function stat(absPath) { return fs$3.statSync(absPath); } /** 尝试获取文件的 stats 对象,如果不存在返回 undefined */ function tryStat(absPath) { try { return stat(absPath); } catch (e) { return; } } function tryStatExists(absPath, fnKey, reverse) { var stats = tryStat(absPath); if (!stats) return false; var res = stats[fnKey](); return reverse ? !res : res; } exports.assertDir = assertDir; exports.assertFile = assertFile; exports.ensureDir = ensureDir; exports.ensureFile = ensureFile; exports.exists = exists; exports.existsDir = existsDir; exports.existsFile = existsFile; exports.existsNotDir = existsNotDir; exports.existsNotFile = existsNotFile; exports.findupDir = findupDir; exports.findupFile = findupFile; exports.findupPackage = findupPackage; exports.findupPackageRoot = findupPackageRoot; exports.mkdirp = mkdirp; exports.mkdirp$1 = mkdirp$2; exports.ospath = ospath; exports.rm = rm; exports.stat = stat; exports.toOSPath = toOSPath; exports.toPosixPath = toPosixPath; exports.toWin32Path = toWin32Path; exports.tryStat = tryStat; exports.walk = walk;