ts-bakery
Version:
Baked dependency injection for Typescript.
140 lines • 5.97 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const path = require("path");
const TsImportType_1 = require("../Types/TsImportType");
const TsTypeReference_1 = require("../Types/TsTypeReference");
class ScriptIndex {
constructor(bakeryConverter) {
this.bakeryConverter = bakeryConverter;
this.allFiles = [];
this.pathMap = new Map();
}
initialize(directory) {
const filePaths = this.indexFiles(directory);
for (const filePath of filePaths) {
const parsedFile = this.bakeryConverter.convertPath(filePath);
this.allFiles.push(parsedFile);
this.pathMap.set(filePath, parsedFile);
}
}
getFile(path) {
if (!this.pathMap.has(path)) {
throw new Error('Unable to resolve path ' + path);
}
return this.pathMap.get(path);
}
resolveParameterDefinition(parameter) {
const filePath = parameter.getFilePath();
const file = this.getFile(filePath);
if (file == null) {
console.log(filePath);
throw new Error('NOT FOUND');
}
if (parameter.type instanceof TsTypeReference_1.TsClassTypeReference) {
return this.resolveClassTypeReference(parameter.type, file);
}
else if (parameter.type instanceof TsTypeReference_1.TsQualifiedTypeReference) {
return this.resolveQualifiedTypeReference(parameter.type, file);
}
throw new Error('Unable to build dependency graph. Parameter not injectable in file ' + filePath);
}
getInheritingClasses(classDefinition) {
const inheritingClassDefinitions = [];
for (const tsFile of this.allFiles) {
for (const tsClass of tsFile.classes) {
if (this.inheritsFrom(tsClass, classDefinition)) {
inheritingClassDefinitions.push(tsClass);
}
}
}
return inheritingClassDefinitions;
}
inheritsFrom(child, parent) {
//TODO: MAKE MORE ROBUST! check file imports of each classes
for (const clause of child.heritageClauses) {
if (clause == parent.name) {
return true;
}
}
return false;
}
resolveTypeReference(typeReference, typeOrigin) {
if (typeReference instanceof TsTypeReference_1.TsClassTypeReference) {
return this.resolveClassTypeReference(typeReference, typeOrigin);
}
else if (typeReference instanceof TsTypeReference_1.TsQualifiedTypeReference) {
return this.resolveQualifiedTypeReference(typeReference, typeOrigin);
}
}
resolveClassTypeReference(typeReference, typeOrigin) {
return this.resolveTypeReferenceByString(typeReference.name, typeOrigin);
}
resolveQualifiedTypeReference(typeReference, typeOrigin) {
const imports = typeOrigin.imports;
for (const importDef of imports) {
if (importDef.importType == TsImportType_1.default.Namespace && importDef.names.includes(typeReference.left)) {
const modulePath = path.resolve(path.dirname(typeOrigin.path), importDef.modulePath + '.ts');
const moduleFile = this.getFile(modulePath);
return this.resolveTypeReferenceByString(typeReference.right, moduleFile);
}
}
return null;
}
resolveTypeReferenceByString(typeReferenceName, file) {
const allClassDefintions = [];
allClassDefintions.push(...file.classes);
allClassDefintions.push(...file.interfaces);
// Check classes / interfaces in file
for (const classDefinition of allClassDefintions) {
if (classDefinition.name == typeReferenceName ||
(typeReferenceName == 'default' && classDefinition.isDefault)) {
return classDefinition;
}
}
// Check imports
for (const importDefinition of file.imports) {
for (const importName of importDefinition.names) {
if (importName == typeReferenceName) {
const filePath = importDefinition.getFilePath();
const fileDirectory = path.dirname(filePath);
const importedFilePath = path.resolve(fileDirectory, importDefinition.modulePath + '.ts');
const importedFile = this.getFile(importedFilePath);
return this.resolveTypeReferenceByString(typeReferenceName, importedFile);
}
}
}
// Check classes / interfaces again but simply check default
for (const classDefinition of allClassDefintions) {
if (classDefinition.isDefault) {
return classDefinition;
}
}
//TODO: Check classes that are simply exported but also imported (like index.ts)
throw new Error('Unable to resolve type reference ' + typeReferenceName + ' from file ' + file.getFilePath());
}
indexFiles(directory) {
const files = [];
const directoryContents = fs.readdirSync(directory);
for (let contentEntry of directoryContents) {
if (contentEntry.startsWith('.')) {
continue;
}
const fullPath = path.join(directory, contentEntry);
const entryInfo = fs.statSync(fullPath);
if (entryInfo.isFile() && contentEntry.endsWith('.ts')) {
files.push(fullPath);
}
else if (entryInfo.isDirectory()) {
if (contentEntry == 'node_modules') {
continue;
}
const directoryFiles = this.indexFiles(fullPath);
directoryFiles.forEach(file => files.push(file));
}
}
return files;
}
}
exports.default = ScriptIndex;
//# sourceMappingURL=ScriptIndex.js.map