2017-08-01 35 views
1

如何讀取文件中的類?節點讀取模塊/讀取代碼文件

的.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'] 
}); 

我知道你可以做一些字符串解析,但有一種高層次的方式來讀取從文件中導出的js/ts(不導入代碼,只是獲取導出類的名稱)。

編輯1: 有* X.service.ts文件my-a.service.tsmy-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只使用打字稿1.4編譯器,我需要2.X更新。有更現代的解決方案嗎?

回答

0

這結束了我的解決方案:

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' ] 
}); 
+0

也有這個項目https://dsherret.github.io/ts-simple-ast/ –

0

不知道你是用例,但最簡單的方法是 -

const serviceA = require('./MyAService'); 
const keys = Object.keys(serviceA); 

如果沒有,你有fs在文件中讀取,然後做一些字符串匹配/正則表達式找到所有可能非常棘手的導出函數。

+0

使用情況的代碼生成。我有x個* .service.ts文件'my-a.service.ts'和'my-b.service.ts'就是例子。 「用fs讀取文件,然後執行一些字符串匹配/正則表達式來查找所有可能非常棘手的導出函數。」 - 這就是爲什麼我希望有一個高層次的方式。 –

0

由於Javascript/ES6實際上沒有類,所以不應該依賴類名。

您正在尋找被命名爲出口什麼:

exports.MyBService = class MyBService { 
    ... 
} 

這樣,你可以做

const allServices = require('./myservices') 
console.log(Object.keys(allServices)) 
0

在node.js中,你會使用CommonJS的格式爲JavaScript文件導出文件。

基本示例JS

const someModule = require('./someModule'); 

const methods = param => { return param; }; 

modules.exports = { methods } 

打字稿得到使用新的ES6格式,但你需要設置你的打字稿編譯器爲它與節點工作。

import someClass from './someClass'; 
someClass.method(); 
export class name { .. } 
+0

我不是想要'new'類或者在代碼中使用它們,並且有*個X.service.ts文件my.a.service.ts和my-b.service.ts就是一個例子。 –

+0

這只是一個例子。你可以執行'someClass.method()' – jemiloii

+0

不要試圖這樣做,或者只需要一個字符串數組,其中包含文件導出的所有內容,而不需要知道它導出的內容。 –