节点读取模块/读取代码文件
你如何从文件中读取类?
的.src /我-a.service.ts
export class MyAService { ... }
的.src /我-b.service.ts
export class MyBService { ... }
./read-modules.js
const fs = require('fs'); const _ = require('lodash'); let files = fs.readdirSync('./src') .filter(item => { return _.includes(item, '.service.ts') }); files.forEach(item => { // get ['MyAService', 'MyBService'] });
我知道你可以做一些stringparsing,但有一个高层次的方式来读取从文件(不导入代码,只是获得导出的类的名称)的JS / TS导出。
编辑1:有* X.service.ts文件my-a.service.ts
和my-b.service.ts
只是例子。 我不是试图导入或要求这些类在代码中使用它们只是获取代码生成的类名称。
编辑2:我看起来像tsreflect-compiler
是我所需要的:
const fs = require('fs'); const _ = require('lodash'); const compiler = require('tsreflect-compiler'); let files = fs.readdirSync('./src') .filter(item => { return _.includes(item, '.service.ts') }); let mods = new Map(); files.forEach(item => { let diag = compiler.compile( [`./src/${item}`], { noLib: false, suppressImplicitAnyIndexErrors: true, noImplicitAny: false, module: 'ES2015', moduleResolution: 'Node', target: 'ES5' }, { readFile: (filename, onError) => { let text; try { text = fs.readFileSync(filename, 'utf8'); } catch (error) { if (onError) { onError(e.message); } text = ''; } return text; }, writeFile: (fileName, data, writeByteOrderMark, onError) => { mods.set(item, JSON.parse(data).declares.map(d => d.name)); } } ); }); mods.forEach((value, key) => { console.log(key); // my-a.service.ts console.dir(value); // [ 'MyAService' ] });
然而tsreflect-compiler
只使用TypeScript 1.4编译器,我需要2.x更新。 有更现代的解决scheme吗?
不知道你的用例是什么,但最简单的方法是 –
const serviceA = require('./MyAService'); const keys = Object.keys(serviceA);
如果不是,你必须用fs
读取文件,然后做一些string匹配/正则expression式来find所有导出的函数,这可能是非常棘手的。
由于Javascript / ES6实际上没有类,所以不应该依赖类名。
你正在寻找的是名为出口:
exports.MyBService = class MyBService { ... }
那样你可以做
const allServices = require('./myservices') console.log(Object.keys(allServices))
在node.js中,您将使用commonjs格式为javascript文件导出文件。
js的基本例子
const someModule = require('./someModule'); const methods = param => { return param; }; modules.exports = { methods }
Typescript使用新的es6格式,但是您需要设置您的打字稿编译器以使其与节点一起工作。
import someClass from './someClass'; someClass.method(); export class name { .. }
这最终成为我的解决scheme:
const fs = require('fs'); const _ = require('lodash'); const ts = require('typescript'); let files = fs.readdirSync('./src') .filter(item => _.includes(item, '.service.ts')); let mods = new Map(); files.forEach(file => { let ex = []; // https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#using-the-type-checker // Build a program using the set of root file names in fileNames let program = ts.createProgram( [`./src/${file}`], { module: ts.ModuleKind.ES2015, moduleResolution: ts.ModuleResolutionKind.NodeJs, target: ts.ScriptTarget.ES5 } ); // Get the checker, we will use it to find more about classes let checker = program.getTypeChecker(); // Visit every sourceFile in the program program.getSourceFiles() .filter(sourceFile => _.includes(sourceFile.fileName, file)) .forEach(sourceFile => { // Walk the tree to search for classes ts.forEachChild(sourceFile, node => { if (node.kind === ts.SyntaxKind.ClassDeclaration) { // This is a top level class, get its symbol let symbol = checker.getSymbolAtLocation(node.name); ex.push(symbol.getName()); } }); }); mods.set(file, ex); }); mods.forEach((value, key) => { console.log(key); // my-a.service.ts console.dir(value); // [ 'MyAService' ] });