@tarojs/helper
Version:
Taro Helper
692 lines • 26.3 kB
JavaScript
;
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 });
exports.babelKit = exports.fs = exports.removePathPrefix = exports.readConfig = exports.readPageConfig = exports.removeHeadSlash = exports.getModuleDefaultExport = exports.addPlatforms = exports.extnameExpRegOf = exports.readDirWithFileTypes = exports.getAllFilesInFolder = exports.applyArrayedVisitors = exports.mergeVisitors = exports.recursiveMerge = exports.getInstalledNpmPkgVersion = exports.getInstalledNpmPkgPath = exports.pascalCase = exports.emptyDirectory = exports.cssImports = exports.generateConstantsList = exports.getNpmPackageAbsolutePath = exports.generateEnvList = exports.resolveScriptPath = exports.resolveMainFilePath = exports.resolveSync = exports.isEmptyObject = exports.shouldUseCnpm = exports.shouldUseYarn = exports.getSystemUsername = exports.getHash = exports.getConfig = exports.getTaroPath = exports.getUserHomeDir = exports.recursiveFindNodeModules = exports.printLog = exports.resolveStylePath = exports.promoteRelativePath = exports.replaceAliasPath = exports.isAliasPath = exports.isQuickAppPkg = exports.isNpmPkg = exports.isNodeModule = exports.normalizePath = void 0;
const child_process = __importStar(require("node:child_process"));
const node_crypto_1 = require("node:crypto");
const os = __importStar(require("node:os"));
const path = __importStar(require("node:path"));
const babel = __importStar(require("@babel/core"));
const generator_1 = __importDefault(require("@babel/generator"));
const babelParser = __importStar(require("@babel/parser"));
const traverse_1 = __importDefault(require("@babel/traverse"));
const t = __importStar(require("@babel/types"));
const fs = __importStar(require("fs-extra"));
exports.fs = fs;
const lodash_1 = require("lodash");
const constants_1 = require("./constants");
const esbuild_1 = require("./esbuild");
const terminal_1 = require("./terminal");
const execSync = child_process.execSync;
function normalizePath(path) {
return path.replace(/\\/g, '/').replace(/\/{2,}/g, '/');
}
exports.normalizePath = normalizePath;
const isNodeModule = (filename) => constants_1.REG_NODE_MODULES.test(filename);
exports.isNodeModule = isNodeModule;
function isNpmPkg(name) {
if (/^(\.|\/)/.test(name)) {
return false;
}
return true;
}
exports.isNpmPkg = isNpmPkg;
function isQuickAppPkg(name) {
return /^@(system|service)\.[a-zA-Z]{1,}/.test(name);
}
exports.isQuickAppPkg = isQuickAppPkg;
function isAliasPath(name, pathAlias = {}) {
const prefixes = Object.keys(pathAlias);
if (prefixes.length === 0) {
return false;
}
return prefixes.includes(name) || new RegExp(`^(${prefixes.join('|')})/`).test(name);
}
exports.isAliasPath = isAliasPath;
function replaceAliasPath(filePath, name, pathAlias = {}) {
// 后续的 path.join 在遇到符号链接时将会解析为真实路径,如果
// 这里的 filePath 没有做同样的处理,可能会导致 import 指向
// 源代码文件,导致文件被意外修改
filePath = fs.realpathSync(filePath);
const prefixes = Object.keys(pathAlias);
if (prefixes.includes(name)) {
return promoteRelativePath(path.relative(filePath, fs.realpathSync(resolveScriptPath(pathAlias[name]))));
}
const reg = new RegExp(`^(${prefixes.join('|')})/(.*)`);
name = name.replace(reg, function (_m, $1, $2) {
return promoteRelativePath(path.relative(filePath, path.join(pathAlias[$1], $2)));
});
return name;
}
exports.replaceAliasPath = replaceAliasPath;
function promoteRelativePath(fPath) {
const fPathArr = fPath.split(path.sep);
let dotCount = 0;
fPathArr.forEach((item) => {
if (item.indexOf('..') >= 0) {
dotCount++;
}
});
if (dotCount === 1) {
fPathArr.splice(0, 1, '.');
return fPathArr.join('/');
}
if (dotCount > 1) {
fPathArr.splice(0, 1);
return fPathArr.join('/');
}
return normalizePath(fPath);
}
exports.promoteRelativePath = promoteRelativePath;
function resolveStylePath(p) {
const realPath = p;
const removeExtPath = p.replace(path.extname(p), '');
const taroEnv = process.env.TARO_ENV;
for (let i = 0; i < constants_1.CSS_EXT.length; i++) {
const item = constants_1.CSS_EXT[i];
if (taroEnv) {
if (fs.existsSync(`${removeExtPath}.${taroEnv}${item}`)) {
return `${removeExtPath}.${taroEnv}${item}`;
}
}
if (fs.existsSync(`${p}${item}`)) {
return `${p}${item}`;
}
}
return realPath;
}
exports.resolveStylePath = resolveStylePath;
function printLog(type, tag, filePath) {
const typeShow = constants_1.processTypeMap[type];
const tagLen = tag.replace(/[\u0391-\uFFE5]/g, 'aa').length;
const tagFormatLen = 8;
if (tagLen < tagFormatLen) {
const rightPadding = new Array(tagFormatLen - tagLen + 1).join(' ');
tag += rightPadding;
}
const padding = '';
filePath = filePath || '';
if (typeof typeShow.color === 'string') {
console.log(terminal_1.chalk[typeShow.color](typeShow.name), padding, tag, padding, filePath);
}
else {
console.log(typeShow.color(typeShow.name), padding, tag, padding, filePath);
}
}
exports.printLog = printLog;
function recursiveFindNodeModules(filePath, lastFindPath) {
const findWorkspaceRoot = require('find-yarn-workspace-root');
if (lastFindPath && normalizePath(filePath) === normalizePath(lastFindPath)) {
return filePath;
}
const dirname = path.dirname(filePath);
const workspaceRoot = findWorkspaceRoot(dirname);
const nodeModules = path.join(workspaceRoot || dirname, 'node_modules');
if (fs.existsSync(nodeModules)) {
return nodeModules;
}
if (dirname.split(path.sep).length <= 1) {
printLog("error" /* processTypeEnum.ERROR */, `在${dirname}目录下`, '未找到node_modules文件夹,请先安装相关依赖库!');
return nodeModules;
}
return recursiveFindNodeModules(dirname, filePath);
}
exports.recursiveFindNodeModules = recursiveFindNodeModules;
function getUserHomeDir() {
function homedir() {
var _a;
const env = process.env;
const home = env.HOME;
const user = env.LOGNAME || env.USER || env.LNAME || env.USERNAME;
if (process.platform === 'win32') {
return env.USERPROFILE || '' + env.HOMEDRIVE + env.HOMEPATH || home || '';
}
if (process.platform === 'darwin') {
return home || (user ? '/Users/' + user : '');
}
if (process.platform === 'linux') {
return home || (((_a = process.getuid) === null || _a === void 0 ? void 0 : _a.call(process)) === 0 ? '/root' : user ? '/home/' + user : '');
}
return home || '';
}
return typeof os.homedir === 'function' ? os.homedir() : homedir();
}
exports.getUserHomeDir = getUserHomeDir;
function getTaroPath() {
const taroPath = path.join(getUserHomeDir(), constants_1.TARO_CONFIG_FOLDER);
if (!fs.existsSync(taroPath)) {
fs.ensureDirSync(taroPath);
}
return taroPath;
}
exports.getTaroPath = getTaroPath;
function getConfig() {
const configPath = path.join(getTaroPath(), 'config.json');
if (fs.existsSync(configPath)) {
return require(configPath);
}
return {};
}
exports.getConfig = getConfig;
function getHash(text) {
return (0, node_crypto_1.createHash)('sha256').update(text).digest('hex').substring(0, 8);
}
exports.getHash = getHash;
function getSystemUsername() {
const userHome = getUserHomeDir();
const systemUsername = process.env.USER || path.basename(userHome);
return systemUsername;
}
exports.getSystemUsername = getSystemUsername;
function shouldUseYarn() {
try {
execSync('yarn --version', { stdio: 'ignore' });
return true;
}
catch (e) {
return false;
}
}
exports.shouldUseYarn = shouldUseYarn;
function shouldUseCnpm() {
try {
execSync('cnpm --version', { stdio: 'ignore' });
return true;
}
catch (e) {
return false;
}
}
exports.shouldUseCnpm = shouldUseCnpm;
function isEmptyObject(obj) {
if (obj == null) {
return true;
}
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
return false;
}
}
return true;
}
exports.isEmptyObject = isEmptyObject;
function resolveSync(id, opts = {}) {
try {
const resolve = require('resolve').sync;
return resolve(id, Object.assign(Object.assign({}, opts), { packageFilter(pkg, pkgfile, dir) {
var _a;
if (opts.packageFilter) {
pkg = opts.packageFilter(pkg, pkgfile, dir);
}
else if ((_a = opts.mainFields) === null || _a === void 0 ? void 0 : _a.length) {
pkg.main = pkg[opts.mainFields.find((field) => pkg[field] && typeof pkg[field] === 'string') || 'main'];
}
return pkg;
} }));
}
catch (error) {
return null;
}
}
exports.resolveSync = resolveSync;
function resolveMainFilePath(p, extArrs = constants_1.SCRIPT_EXT) {
if (p.startsWith('pages/') || p === 'app.config') {
return p;
}
const realPath = p;
const taroEnv = process.env.TARO_ENV;
for (let i = 0; i < extArrs.length; i++) {
const item = extArrs[i];
if (taroEnv) {
if (fs.existsSync(`${p}.${taroEnv}${item}`)) {
return `${p}.${taroEnv}${item}`;
}
if (fs.existsSync(`${p}${path.sep}index.${taroEnv}${item}`)) {
return `${p}${path.sep}index.${taroEnv}${item}`;
}
if (fs.existsSync(`${p.replace(/\/index$/, `.${taroEnv}/index`)}${item}`)) {
return `${p.replace(/\/index$/, `.${taroEnv}/index`)}${item}`;
}
}
if (fs.existsSync(`${p}${item}`)) {
return `${p}${item}`;
}
if (fs.existsSync(`${p}${path.sep}index${item}`)) {
return `${p}${path.sep}index${item}`;
}
}
// 存在多端页面但是对应的多端页面配置不存在时,使用该页面默认配置
if (taroEnv && path.parse(p).base.endsWith(`.${taroEnv}.config`)) {
const idx = p.lastIndexOf(`.${taroEnv}.config`);
return resolveMainFilePath(p.slice(0, idx) + '.config');
}
return realPath;
}
exports.resolveMainFilePath = resolveMainFilePath;
function resolveScriptPath(p) {
return resolveMainFilePath(p);
}
exports.resolveScriptPath = resolveScriptPath;
function generateEnvList(env) {
const res = {};
if (env && !isEmptyObject(env)) {
for (const key in env) {
try {
res[`process.env.${key}`] = JSON.parse(env[key]);
}
catch (err) {
res[`process.env.${key}`] = env[key];
}
}
}
return res;
}
exports.generateEnvList = generateEnvList;
/**
* 获取 npm 文件或者依赖的绝对路径
*
* @param {string} 参数 1 - 组件路径
* @param {string} 参数 2 - 文件扩展名
* @returns {string} npm 文件绝对路径
*/
function getNpmPackageAbsolutePath(npmPath, defaultFile = 'index') {
try {
let packageName = '';
let componentRelativePath = '';
const packageParts = npmPath.split(path.sep);
// 获取 npm 包名和指定的包文件路径
// taro-loader/path/index => packageName = taro-loader, componentRelativePath = path/index
// @tarojs/runtime/path/index => packageName = @tarojs/runtime, componentRelativePath = path/index
if (npmPath.startsWith('@')) {
packageName = packageParts.slice(0, 2).join(path.sep);
componentRelativePath = packageParts.slice(2).join(path.sep);
}
else {
packageName = packageParts[0];
componentRelativePath = packageParts.slice(1).join(path.sep);
}
// 没有指定的包文件路径统一使用 defaultFile
componentRelativePath || (componentRelativePath = defaultFile);
// require.resolve 解析的路径会包含入口文件路径,通过正则过滤一下
const match = require.resolve(packageName).match(new RegExp('.*' + packageName));
if (!(match === null || match === void 0 ? void 0 : match.length))
return null;
const packagePath = match[0];
return path.join(packagePath, `./${componentRelativePath}`);
}
catch (error) {
return null;
}
}
exports.getNpmPackageAbsolutePath = getNpmPackageAbsolutePath;
function generateConstantsList(constants) {
const res = {};
if (constants && !isEmptyObject(constants)) {
for (const key in constants) {
if ((0, lodash_1.isPlainObject)(constants[key])) {
res[key] = generateConstantsList(constants[key]);
}
else {
try {
res[key] = JSON.parse(constants[key]);
}
catch (err) {
res[key] = constants[key];
}
}
}
}
return res;
}
exports.generateConstantsList = generateConstantsList;
function cssImports(content) {
const results = [];
const cssImportRegx = new RegExp(constants_1.REG_CSS_IMPORT);
let match;
content = String(content).replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');
while ((match = cssImportRegx.exec(content))) {
results.push(match[2]);
}
return results;
}
exports.cssImports = cssImports;
/*eslint-disable*/
const retries = process.platform === 'win32' ? 100 : 1;
function emptyDirectory(dirPath, opts = { excludes: [] }) {
if (fs.existsSync(dirPath)) {
fs.readdirSync(dirPath).forEach((file) => {
const curPath = path.join(dirPath, file);
if (fs.lstatSync(curPath).isDirectory()) {
let removed = false;
let i = 0; // retry counter
do {
try {
const excludes = Array.isArray(opts.excludes) ? opts.excludes : [opts.excludes];
const canRemove = !excludes.length ||
!excludes.some((item) => typeof item === 'string' ? curPath.indexOf(item) >= 0 : item.test(curPath));
if (canRemove) {
emptyDirectory(curPath);
fs.rmdirSync(curPath);
}
removed = true;
}
catch (e) {
}
finally {
if (++i < retries) {
continue;
}
}
} while (!removed);
}
else {
fs.unlinkSync(curPath);
}
});
}
}
exports.emptyDirectory = emptyDirectory;
/* eslint-enable */
const pascalCase = (str) => str.charAt(0).toUpperCase() + (0, lodash_1.camelCase)(str.substr(1));
exports.pascalCase = pascalCase;
function getInstalledNpmPkgPath(pkgName, basedir) {
try {
const resolve = require('resolve').sync;
return resolve(`${pkgName}/package.json`, { basedir });
}
catch (err) {
return null;
}
}
exports.getInstalledNpmPkgPath = getInstalledNpmPkgPath;
function getInstalledNpmPkgVersion(pkgName, basedir) {
const pkgPath = getInstalledNpmPkgPath(pkgName, basedir);
if (!pkgPath) {
return null;
}
return fs.readJSONSync(pkgPath).version;
}
exports.getInstalledNpmPkgVersion = getInstalledNpmPkgVersion;
const recursiveMerge = (src, ...args) => {
return (0, lodash_1.mergeWith)(src, ...args, (value, srcValue) => {
const typeValue = typeof value;
const typeSrcValue = typeof srcValue;
if (typeValue !== typeSrcValue)
return;
if (Array.isArray(value) && Array.isArray(srcValue)) {
return value.concat(srcValue);
}
if (typeValue === 'object') {
return (0, exports.recursiveMerge)(value, srcValue);
}
});
};
exports.recursiveMerge = recursiveMerge;
const mergeVisitors = (src, ...args) => {
const validFuncs = ['exit', 'enter'];
return (0, lodash_1.mergeWith)(src, ...args, (value, srcValue, key, object, srcObject) => {
if (!object.hasOwnProperty(key) || !srcObject.hasOwnProperty(key)) {
return undefined;
}
const shouldMergeToArray = validFuncs.indexOf(key) > -1;
if (shouldMergeToArray) {
return (0, lodash_1.flatMap)([value, srcValue]);
}
const [newValue, newSrcValue] = [value, srcValue].map((v) => {
if (typeof v === 'function') {
return {
enter: v,
};
}
else {
return v;
}
});
return (0, exports.mergeVisitors)(newValue, newSrcValue);
});
};
exports.mergeVisitors = mergeVisitors;
const applyArrayedVisitors = (obj) => {
let key;
for (key in obj) {
const funcs = obj[key];
if (Array.isArray(funcs)) {
obj[key] = (astPath, ...args) => {
funcs.forEach((func) => {
func(astPath, ...args);
});
};
}
else if (typeof funcs === 'object') {
(0, exports.applyArrayedVisitors)(funcs);
}
}
return obj;
};
exports.applyArrayedVisitors = applyArrayedVisitors;
const getAllFilesInFolder = (folder_1, ...args_1) => __awaiter(void 0, [folder_1, ...args_1], void 0, function* (folder, filter = []) {
let files = [];
const list = readDirWithFileTypes(folder);
yield Promise.all(list.map((item) => __awaiter(void 0, void 0, void 0, function* () {
const itemPath = path.join(folder, item.name);
if (item.isDirectory) {
const _files = yield (0, exports.getAllFilesInFolder)(itemPath, filter);
files = [...files, ..._files];
}
else if (item.isFile) {
if (!filter.find((rule) => rule === item.name))
files.push(itemPath);
}
})));
return files;
});
exports.getAllFilesInFolder = getAllFilesInFolder;
function readDirWithFileTypes(folder) {
const list = fs.readdirSync(folder);
const res = list.map((name) => {
const stat = fs.statSync(path.join(folder, name));
return {
name,
isDirectory: stat.isDirectory(),
isFile: stat.isFile(),
};
});
return res;
}
exports.readDirWithFileTypes = readDirWithFileTypes;
function extnameExpRegOf(filePath) {
return new RegExp(`${path.extname(filePath)}$`);
}
exports.extnameExpRegOf = extnameExpRegOf;
function addPlatforms(platform) {
const upperPlatform = platform.toLocaleUpperCase();
if (constants_1.PLATFORMS[upperPlatform])
return;
constants_1.PLATFORMS[upperPlatform] = platform;
}
exports.addPlatforms = addPlatforms;
const getModuleDefaultExport = (exports) => (exports.__esModule ? exports.default : exports);
exports.getModuleDefaultExport = getModuleDefaultExport;
function removeHeadSlash(str) {
return str.replace(/^(\/|\\)/, '');
}
exports.removeHeadSlash = removeHeadSlash;
// converts ast nodes to js object
function exprToObject(node) {
const types = ['BooleanLiteral', 'StringLiteral', 'NumericLiteral'];
if (types.includes(node.type)) {
return node.value;
}
if (node.name === 'undefined' && !node.value) {
return undefined;
}
if (node.type === 'NullLiteral') {
return null;
}
if (node.type === 'ObjectExpression') {
return genProps(node.properties);
}
if (node.type === 'ArrayExpression') {
return node.elements.reduce((acc, el) => [
...acc,
...(el.type === 'SpreadElement' ? exprToObject(el.argument) : [exprToObject(el)]),
], []);
}
}
// converts ObjectExpressions to js object
function genProps(props) {
return props.reduce((acc, prop) => {
if (prop.type === 'SpreadElement') {
return Object.assign(Object.assign({}, acc), exprToObject(prop.argument));
}
else if (prop.type !== 'ObjectMethod') {
const v = exprToObject(prop.value);
if (v !== undefined) {
return Object.assign(Object.assign({}, acc), { [prop.key.name || prop.key.value]: v });
}
}
return acc;
}, {});
}
// read page config from a sfc file instead of the regular config file
function readSFCPageConfig(configPath) {
var _a;
if (!fs.existsSync(configPath))
return {};
const sfcSource = fs.readFileSync(configPath, 'utf8');
const dpcReg = /definePageConfig\(\{[\w\W]+?\}\)/g;
const matches = sfcSource.match(dpcReg);
let result = {};
if (matches && matches.length === 1) {
const callExprHandler = (p) => {
const { callee } = p.node;
if (!callee.name)
return;
if (callee.name && callee.name !== 'definePageConfig')
return;
const configNode = p.node.arguments[0];
result = exprToObject(configNode);
p.stop();
};
const configSource = matches[0];
const program = (_a = (babel.parse(configSource, { filename: '' }))) === null || _a === void 0 ? void 0 : _a.program;
program && babel.traverse(program, { CallExpression: callExprHandler });
}
return result;
}
function readPageConfig(configPath) {
let result = {};
const extNames = ['.js', '.jsx', '.ts', '.tsx', '.vue'];
// check source file extension
extNames.some((ext) => {
const tempPath = configPath.replace('.config', ext);
if (fs.existsSync(tempPath)) {
try {
result = readSFCPageConfig(tempPath);
}
catch (error) {
result = {};
}
return true;
}
});
return result;
}
exports.readPageConfig = readPageConfig;
function readConfig(configPath, options = {}) {
let result = {};
if (fs.existsSync(configPath)) {
if (constants_1.REG_JSON.test(configPath)) {
result = fs.readJSONSync(configPath);
}
else {
result = (0, esbuild_1.requireWithEsbuild)(configPath, {
customConfig: {
alias: options.alias || {},
define: (0, lodash_1.defaults)({}, options.defineConstants || {}, {
define: 'define', // Note: 该场景下不支持 AMD 导出,这会导致 esbuild 替换 babel 的 define 方法
}),
},
customSwcConfig: {
jsc: {
parser: {
syntax: 'typescript',
decorators: true,
},
transform: {
legacyDecorator: true,
},
experimental: {
plugins: [
[path.resolve(__dirname, '../swc/swc_plugin_define_config.wasm'), {}]
]
}
},
module: {
type: 'commonjs',
},
},
});
}
result = (0, exports.getModuleDefaultExport)(result);
}
else {
result = readPageConfig(configPath);
}
return result;
}
exports.readConfig = readConfig;
// 去除路径前缀,比如 /, ./
function removePathPrefix(filePath = '') {
const normalizedPath = path.normalize(filePath);
const parsedPath = path.parse(normalizedPath);
const { root, dir, base } = parsedPath;
let result = path.join(dir, base);
if (result.startsWith(root)) {
result = result.slice(root.length);
}
return result;
}
exports.removePathPrefix = removePathPrefix;
// 集中引入 babel 工具箱,供编译时使用
exports.babelKit = {
types: t,
parse: babelParser.parse,
generate: generator_1.default,
traverse: traverse_1.default,
};
//# sourceMappingURL=utils.js.map