How do you read the classes from a file?
.src/my-a.service.ts
export class MyAService {
...
}
.src/my-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']
});
I know you could do some string parsing but is there a high level way to read js/ts exports from a file(not import the code but just get the names of the exported classes).
Edit 1: There is X number of *.service.ts files my-a.service.ts
and my-b.service.ts
are just examples. I'm not trying to import or require these classes to use them in code just get the class names for code generation.
Edit 2: I looks like tsreflect-compiler
is what I need:
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' ]
});
However tsreflect-compiler
only uses TypeScript 1.4 compiler and I need 2.x newer. Is there a more modern solution?
This ended up being my solution:
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' ]
});
Not sure what you're use case is but the easiest way would be -
const serviceA = require('./MyAService');
const keys = Object.keys(serviceA);
If not, you'd have to read in the file with fs
and then do some string matching/regex to find all of the exported function which could be very tricky.
Since Javascript/ES6 doesn't actually have classes, you shouldn't be relying on class names.
What you are looking for is named exports:
exports.MyBService = class MyBService {
...
}
That way you can do
const allServices = require('./myservices')
console.log(Object.keys(allServices))
In node.js, you would export files using the commonjs format for javascript files.
Basic Example for js
const someModule = require('./someModule');
const methods = param => { return param; };
modules.exports = { methods }
Typescript gets to use the new es6 format, but you need to setup your typescript compiler for it to work with node.
import someClass from './someClass';
someClass.method();
export class name { .. }
use typescript-require To get ts file object in js
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.