123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.cleanEmpty = exports.modifierHas = exports.isClass = exports.findExportNode = exports.loadTsConfig = exports.camelProp = exports.formatProp = exports.readJson5 = exports.readJson = exports.getPkgInfo = exports.parseJson = exports.extend = exports.requireFile = exports.moduleExist = exports.resolveModule = exports.removeSameNameJs = exports.toArray = exports.formatPath = exports.getModuleObjByPath = exports.cleanJs = exports.writeFileSync = exports.getImportStr = exports.log = exports.pickFields = exports.strToFn = exports.loadModules = exports.checkMaybeIsJsProj = exports.checkMaybeIsTsProj = exports.writeTsConfig = exports.writeJsConfig = exports.loadFiles = exports.isIdentifierName = exports.convertString = exports.getEggInfo = exports.TS_CONFIG = exports.JS_CONFIG = void 0;
- const tslib_1 = require("tslib");
- const fs_1 = tslib_1.__importDefault(require("fs"));
- const mkdirp_1 = tslib_1.__importDefault(require("mkdirp"));
- const globby_1 = tslib_1.__importDefault(require("globby"));
- const path_1 = tslib_1.__importDefault(require("path"));
- const typescript_1 = tslib_1.__importDefault(require("typescript"));
- const yn_1 = tslib_1.__importDefault(require("yn"));
- const config_1 = require("./config");
- const child_process_1 = require("child_process");
- const json5_1 = tslib_1.__importDefault(require("json5"));
- exports.JS_CONFIG = {
- include: ['**/*'],
- };
- exports.TS_CONFIG = {
- compilerOptions: {
- target: typescript_1.default.ScriptTarget.ES2017,
- module: typescript_1.default.ModuleKind.CommonJS,
- strict: true,
- noImplicitAny: false,
- experimentalDecorators: true,
- emitDecoratorMetadata: true,
- allowSyntheticDefaultImports: true,
- charset: 'utf8',
- allowJs: false,
- pretty: true,
- lib: ['es6'],
- noEmitOnError: false,
- noUnusedLocals: true,
- noUnusedParameters: true,
- allowUnreachableCode: false,
- allowUnusedLabels: false,
- strictPropertyInitialization: false,
- noFallthroughCasesInSwitch: true,
- skipLibCheck: true,
- skipDefaultLibCheck: true,
- inlineSourceMap: true,
- },
- };
- const cacheEggInfo = {};
- function getEggInfo(option) {
- const { cacheIndex, cwd, customLoader } = option;
- const cacheKey = cacheIndex ? `${cacheIndex}${cwd}` : undefined;
- const caches = cacheKey ? (cacheEggInfo[cacheKey] = cacheEggInfo[cacheKey] || {}) : undefined;
- const end = (json) => {
- if (caches) {
- caches.eggInfo = json;
- caches.cacheTime = Date.now();
- }
- if (option.callback) {
- return option.callback(json);
- }
- return json;
- };
- // check cache
- if (caches) {
- if (caches.cacheTime && (Date.now() - caches.cacheTime) < 1000) {
- return end(caches.eggInfo);
- }
- else if (caches.runningPromise) {
- return caches.runningPromise;
- }
- }
- // get egg info from customLoader
- if (customLoader) {
- return end({
- config: customLoader.config,
- plugins: customLoader.plugins,
- eggPaths: customLoader.eggPaths,
- });
- }
- // prepare options
- const cmd = 'node';
- const args = [path_1.default.resolve(__dirname, './scripts/eggInfo')];
- const opt = {
- cwd,
- env: Object.assign(Object.assign(Object.assign({}, process.env), { TS_NODE_TYPE_CHECK: 'false', TS_NODE_TRANSPILE_ONLY: 'true', TS_NODE_FILES: 'false', EGG_TYPESCRIPT: 'true', CACHE_REQUIRE_PATHS_FILE: path_1.default.resolve(config_1.tmpDir, './requirePaths.json') }), option.env),
- };
- if (option.async) {
- // cache promise
- caches.runningPromise = new Promise((resolve, reject) => {
- (0, child_process_1.execFile)(cmd, args, opt, err => {
- caches.runningPromise = null;
- if (err)
- reject(err);
- resolve(end(parseJson(fs_1.default.readFileSync(config_1.eggInfoPath, 'utf-8'))));
- });
- });
- return caches.runningPromise;
- }
- try {
- (0, child_process_1.execFileSync)(cmd, args, opt);
- return end(parseJson(fs_1.default.readFileSync(config_1.eggInfoPath, 'utf-8')));
- }
- catch (e) {
- return end({});
- }
- }
- exports.getEggInfo = getEggInfo;
- // convert string to same type with default value
- function convertString(val, defaultVal) {
- if (val === undefined)
- return defaultVal;
- switch (typeof defaultVal) {
- case 'boolean':
- return (0, yn_1.default)(val, { default: defaultVal });
- case 'number':
- const num = +val;
- return (isNaN(num) ? defaultVal : num);
- case 'string':
- return val;
- default:
- return defaultVal;
- }
- }
- exports.convertString = convertString;
- function isIdentifierName(s) {
- return /^[$A-Z_][0-9A-Z_$]*$/i.test(s);
- }
- exports.isIdentifierName = isIdentifierName;
- // load ts/js files
- function loadFiles(cwd, pattern) {
- pattern = pattern || '**/*.(js|ts)';
- pattern = Array.isArray(pattern) ? pattern : [pattern];
- const fileList = globby_1.default.sync(pattern.concat(['!**/*.d.ts']), { cwd });
- return fileList.filter(f => {
- // filter same name js/ts
- return !(f.endsWith('.js') &&
- fileList.includes(f.substring(0, f.length - 2) + 'ts'));
- });
- }
- exports.loadFiles = loadFiles;
- // write jsconfig.json to cwd
- function writeJsConfig(cwd) {
- const jsconfigUrl = path_1.default.resolve(cwd, './jsconfig.json');
- if (!fs_1.default.existsSync(jsconfigUrl)) {
- fs_1.default.writeFileSync(jsconfigUrl, JSON.stringify(exports.JS_CONFIG, null, 2));
- return jsconfigUrl;
- }
- }
- exports.writeJsConfig = writeJsConfig;
- // write tsconfig.json to cwd
- function writeTsConfig(cwd) {
- const tsconfigUrl = path_1.default.resolve(cwd, './tsconfig.json');
- if (!fs_1.default.existsSync(tsconfigUrl)) {
- fs_1.default.writeFileSync(tsconfigUrl, JSON.stringify(exports.TS_CONFIG, null, 2));
- return tsconfigUrl;
- }
- }
- exports.writeTsConfig = writeTsConfig;
- function checkMaybeIsTsProj(cwd, pkgInfo) {
- pkgInfo = pkgInfo || getPkgInfo(cwd);
- return (pkgInfo.egg && pkgInfo.egg.typescript) ||
- fs_1.default.existsSync(path_1.default.resolve(cwd, './tsconfig.json')) ||
- fs_1.default.existsSync(path_1.default.resolve(cwd, './config/config.default.ts')) ||
- fs_1.default.existsSync(path_1.default.resolve(cwd, './config/config.ts'));
- }
- exports.checkMaybeIsTsProj = checkMaybeIsTsProj;
- function checkMaybeIsJsProj(cwd, pkgInfo) {
- pkgInfo = pkgInfo || getPkgInfo(cwd);
- const isJs = !checkMaybeIsTsProj(cwd, pkgInfo) &&
- (fs_1.default.existsSync(path_1.default.resolve(cwd, './config/config.default.js')) ||
- fs_1.default.existsSync(path_1.default.resolve(cwd, './jsconfig.json')));
- return isJs;
- }
- exports.checkMaybeIsJsProj = checkMaybeIsJsProj;
- // load modules to object
- function loadModules(cwd, loadDefault, preHandle) {
- const modules = {};
- preHandle = preHandle || (fn => fn);
- fs_1.default
- .readdirSync(cwd)
- .filter(f => f.endsWith('.js'))
- .forEach(f => {
- const name = f.substring(0, f.lastIndexOf('.'));
- const obj = require(path_1.default.resolve(cwd, name));
- if (loadDefault && obj.default) {
- modules[name] = preHandle(obj.default);
- }
- else {
- modules[name] = preHandle(obj);
- }
- });
- return modules;
- }
- exports.loadModules = loadModules;
- // convert string to function
- function strToFn(fn) {
- if (typeof fn === 'string') {
- return (...args) => fn.replace(/{{\s*(\d+)\s*}}/g, (_, index) => args[index]);
- }
- return fn;
- }
- exports.strToFn = strToFn;
- // pick fields from object
- function pickFields(obj, fields) {
- const newObj = {};
- fields.forEach(f => (newObj[f] = obj[f]));
- return newObj;
- }
- exports.pickFields = pickFields;
- // log
- function log(msg, prefix = true) {
- console.info(`${prefix ? '[egg-ts-helper] ' : ''}${msg}`);
- }
- exports.log = log;
- // get import context
- function getImportStr(from, to, moduleName, importStar) {
- const extname = path_1.default.extname(to);
- const toPathWithoutExt = to.substring(0, to.length - extname.length);
- const importPath = path_1.default.relative(from, toPathWithoutExt).replace(/\/|\\/g, '/');
- const isTS = extname === '.ts' || fs_1.default.existsSync(`${toPathWithoutExt}.d.ts`);
- const importStartStr = isTS && importStar ? '* as ' : '';
- const fromStr = isTS ? `from '${importPath}'` : `= require('${importPath}')`;
- return `import ${importStartStr}${moduleName} ${fromStr};`;
- }
- exports.getImportStr = getImportStr;
- // write file, using fs.writeFileSync to block io that d.ts can create before egg app started.
- function writeFileSync(fileUrl, content) {
- mkdirp_1.default.sync(path_1.default.dirname(fileUrl));
- fs_1.default.writeFileSync(fileUrl, content);
- }
- exports.writeFileSync = writeFileSync;
- // clean same name js/ts
- function cleanJs(cwd) {
- const fileList = [];
- globby_1.default
- .sync(['**/*.ts', '**/*.tsx', '!**/*.d.ts', '!**/node_modules'], { cwd })
- .forEach(f => {
- const jf = removeSameNameJs(path_1.default.resolve(cwd, f));
- if (jf)
- fileList.push(path_1.default.relative(cwd, jf));
- });
- if (fileList.length) {
- console.info('[egg-ts-helper] These file was deleted because the same name ts file was exist!\n');
- console.info(' ' + fileList.join('\n ') + '\n');
- }
- }
- exports.cleanJs = cleanJs;
- // get moduleName by file path
- function getModuleObjByPath(f) {
- const props = f.substring(0, f.lastIndexOf('.')).split('/');
- // composing moduleName
- const moduleName = props.map(prop => camelProp(prop, 'upper')).join('');
- return {
- props,
- moduleName,
- };
- }
- exports.getModuleObjByPath = getModuleObjByPath;
- // format path sep to /
- function formatPath(str) {
- return str.replace(/\/|\\/g, '/');
- }
- exports.formatPath = formatPath;
- function toArray(pattern) {
- return pattern ? (Array.isArray(pattern) ? pattern : [pattern]) : [];
- }
- exports.toArray = toArray;
- // remove same name js
- function removeSameNameJs(f) {
- if (!f.match(/\.tsx?$/) || f.endsWith('.d.ts')) {
- return;
- }
- const jf = f.replace(/tsx?$/, 'js');
- if (fs_1.default.existsSync(jf)) {
- fs_1.default.unlinkSync(jf);
- return jf;
- }
- }
- exports.removeSameNameJs = removeSameNameJs;
- // resolve module
- function resolveModule(url) {
- try {
- return require.resolve(url);
- }
- catch (e) {
- return undefined;
- }
- }
- exports.resolveModule = resolveModule;
- // check whether module is exist
- function moduleExist(mod, cwd) {
- const nodeModulePath = path_1.default.resolve(cwd || process.cwd(), 'node_modules', mod);
- return fs_1.default.existsSync(nodeModulePath) || resolveModule(mod);
- }
- exports.moduleExist = moduleExist;
- // require modules
- function requireFile(url) {
- url = url && resolveModule(url);
- if (!url) {
- return undefined;
- }
- let exp = require(url);
- if (exp.__esModule && 'default' in exp) {
- exp = exp.default;
- }
- return exp;
- }
- exports.requireFile = requireFile;
- // extend
- function extend(obj, ...args) {
- args.forEach(source => {
- let descriptor, prop;
- if (source) {
- for (prop in source) {
- descriptor = Object.getOwnPropertyDescriptor(source, prop);
- Object.defineProperty(obj, prop, descriptor);
- }
- }
- });
- return obj;
- }
- exports.extend = extend;
- // parse json
- function parseJson(jsonStr) {
- if (jsonStr) {
- try {
- return JSON.parse(jsonStr);
- }
- catch (e) {
- return {};
- }
- }
- else {
- return {};
- }
- }
- exports.parseJson = parseJson;
- // load package.json
- function getPkgInfo(cwd) {
- return readJson(path_1.default.resolve(cwd, './package.json'));
- }
- exports.getPkgInfo = getPkgInfo;
- // read json file
- function readJson(jsonUrl) {
- if (!fs_1.default.existsSync(jsonUrl))
- return {};
- return parseJson(fs_1.default.readFileSync(jsonUrl, 'utf-8'));
- }
- exports.readJson = readJson;
- function readJson5(jsonUrl) {
- if (!fs_1.default.existsSync(jsonUrl))
- return {};
- return json5_1.default.parse(fs_1.default.readFileSync(jsonUrl, 'utf-8'));
- }
- exports.readJson5 = readJson5;
- // format property
- function formatProp(prop) {
- return prop.replace(/[._-][a-z]/gi, s => s.substring(1).toUpperCase());
- }
- exports.formatProp = formatProp;
- // like egg-core/file-loader
- function camelProp(property, caseStyle) {
- if (typeof caseStyle === 'function') {
- return caseStyle(property);
- }
- // camel transfer
- property = formatProp(property);
- let first = property[0];
- // istanbul ignore next
- switch (caseStyle) {
- case 'lower':
- first = first.toLowerCase();
- break;
- case 'upper':
- first = first.toUpperCase();
- break;
- case 'camel':
- break;
- default:
- break;
- }
- return first + property.substring(1);
- }
- exports.camelProp = camelProp;
- // load tsconfig.json
- function loadTsConfig(tsconfigPath) {
- tsconfigPath = path_1.default.extname(tsconfigPath) === '.json' ? tsconfigPath : `${tsconfigPath}.json`;
- const tsConfig = readJson5(tsconfigPath);
- if (tsConfig.extends) {
- const extendPattern = tsConfig.extends;
- const tsconfigDirName = path_1.default.dirname(tsconfigPath);
- const maybeRealExtendPath = [
- path_1.default.resolve(tsconfigDirName, extendPattern),
- path_1.default.resolve(tsconfigDirName, `${extendPattern}.json`),
- ];
- if (!path_1.default.extname(tsConfig.extends) && !extendPattern.startsWith('.') && !extendPattern.startsWith('/')) {
- maybeRealExtendPath.push(path_1.default.resolve(tsconfigDirName, 'node_modules', extendPattern, 'tsconfig.json'), path_1.default.resolve(process.cwd(), 'node_modules', extendPattern, 'tsconfig.json'));
- }
- const extendRealPath = maybeRealExtendPath.find(f => fs_1.default.existsSync(f));
- if (extendRealPath) {
- const extendTsConfig = loadTsConfig(extendRealPath);
- return Object.assign(Object.assign({}, tsConfig.compilerOptions), extendTsConfig);
- }
- }
- return tsConfig.compilerOptions || {};
- }
- exports.loadTsConfig = loadTsConfig;
- /**
- * ts ast utils
- */
- // find export node from sourcefile.
- function findExportNode(code) {
- const sourceFile = typescript_1.default.createSourceFile('file.ts', code, typescript_1.default.ScriptTarget.ES2017, true);
- const cache = new Map();
- const exportNodeList = [];
- let exportDefaultNode;
- sourceFile.statements.forEach(node => {
- // each node in root scope
- if (modifierHas(node, typescript_1.default.SyntaxKind.ExportKeyword)) {
- if (modifierHas(node, typescript_1.default.SyntaxKind.DefaultKeyword)) {
- // export default
- exportDefaultNode = node;
- }
- else {
- // export variable
- if (typescript_1.default.isVariableStatement(node)) {
- node.declarationList.declarations.forEach(declare => exportNodeList.push(declare));
- }
- else {
- exportNodeList.push(node);
- }
- }
- }
- else if (typescript_1.default.isVariableStatement(node)) {
- // cache variable statement
- for (const declaration of node.declarationList.declarations) {
- if (typescript_1.default.isIdentifier(declaration.name) && declaration.initializer) {
- cache.set(declaration.name.escapedText, declaration.initializer);
- }
- }
- }
- else if ((typescript_1.default.isFunctionDeclaration(node) || typescript_1.default.isClassDeclaration(node)) && node.name) {
- // cache function declaration and class declaration
- cache.set(node.name.escapedText, node);
- }
- else if (typescript_1.default.isExportAssignment(node)) {
- // export default {}
- exportDefaultNode = node.expression;
- }
- else if (typescript_1.default.isExpressionStatement(node) && typescript_1.default.isBinaryExpression(node.expression)) {
- if (typescript_1.default.isPropertyAccessExpression(node.expression.left)) {
- const obj = node.expression.left.expression;
- const prop = node.expression.left.name;
- if (typescript_1.default.isIdentifier(obj)) {
- if (obj.escapedText === 'exports') {
- // exports.xxx = {}
- exportNodeList.push(node.expression);
- }
- else if (obj.escapedText === 'module' &&
- typescript_1.default.isIdentifier(prop) &&
- prop.escapedText === 'exports') {
- // module.exports = {}
- exportDefaultNode = node.expression.right;
- }
- }
- }
- else if (typescript_1.default.isIdentifier(node.expression.left)) {
- // let exportData;
- // exportData = {};
- // export exportData
- cache.set(node.expression.left.escapedText, node.expression.right);
- }
- }
- });
- while (exportDefaultNode && typescript_1.default.isIdentifier(exportDefaultNode) && cache.size) {
- const mid = cache.get(exportDefaultNode.escapedText);
- cache.delete(exportDefaultNode.escapedText);
- exportDefaultNode = mid;
- }
- return {
- exportDefaultNode,
- exportNodeList,
- };
- }
- exports.findExportNode = findExportNode;
- function isClass(v) {
- return typeof v === 'function' && /^\s*class\s+/.test(v.toString());
- }
- exports.isClass = isClass;
- // check kind in node.modifiers.
- function modifierHas(node, kind) {
- return node.modifiers && node.modifiers.find(mod => kind === mod.kind);
- }
- exports.modifierHas = modifierHas;
- function cleanEmpty(data) {
- const clearData = {};
- Object.keys(data).forEach(k => {
- const dataValue = data[k];
- if (dataValue !== undefined && dataValue !== null) {
- clearData[k] = data[k];
- }
- });
- return clearData;
- }
- exports.cleanEmpty = cleanEmpty;
|