arky-js
Version:
**Arky.js** is a powerful, annotation-based framework for building serverless applications on **AWS Lambda and API Gateway**. Inspired by Angular and NestJS, Arky.js simplifies serverless development by providing decorators for defining modules, controlle
115 lines (114 loc) • 5.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModuleTreeWalker = void 0;
const ts_morph_1 = require("ts-morph");
const file_util_1 = require("../../utils/file-util");
const class_config_util_1 = require("../../utils/class-config-util");
class ModuleTreeWalker {
constructor(projectConfig) {
this.projectConfig = projectConfig;
this.defaultRootModuleFile = "app.module.ts";
this.appRootModule = this.initiateRootModule();
this.project = new ts_morph_1.Project();
}
initiateRootModule() {
var _a;
return ((_a = this.projectConfig) === null || _a === void 0 ? void 0 : _a.rootModule) || this.defaultRootModuleFile;
}
getRootModuleFilePath() {
const root = "./src";
return (0, file_util_1.findFile)(root, this.appRootModule);
}
loadControllerDeclarations(moduleDeclarations) {
return moduleDeclarations.flatMap((moduleDeclaration) => {
return moduleDeclaration.controllers.map((controller) => ({
controller,
module: moduleDeclaration.module,
providers: moduleDeclaration.providers,
}));
});
}
loadModuleDeclarations() {
var _a;
const moduleDeclarations = [];
const rootModulePath = this.getRootModuleFilePath();
if (!rootModulePath) {
console.error("❌ Root module cannot be found.");
return;
}
const sourceFiles = this.project.addSourceFilesAtPaths(rootModulePath);
if ((sourceFiles === null || sourceFiles === void 0 ? void 0 : sourceFiles.length) > 1) {
console.error("❌ Multiple root modules found for same name.");
return;
}
const rootModuleFile = sourceFiles[0];
const rootModuleClass = (_a = rootModuleFile.getClasses()) === null || _a === void 0 ? void 0 : _a[0];
this.traverseTheModuleTree(rootModuleClass, this.project, moduleDeclarations);
return moduleDeclarations;
}
traverseTheModuleTree(moduleClass, project, moduleDeclarations, parentModuleDeclaration) {
var _a;
const moduleDecorator = moduleClass.getDecorator("Module");
if (!moduleDecorator) {
return;
}
const moduleArguments = this.getModuleDecoratorConfig(moduleDecorator);
if (!moduleArguments) {
return;
}
const moduleDeclarationObject = this.createModuleDeclarationObj(moduleClass, moduleArguments, project);
moduleDeclarations.push(moduleDeclarationObject);
if ((_a = moduleDeclarationObject.imports) === null || _a === void 0 ? void 0 : _a.length) {
moduleDeclarationObject.imports.forEach((importModule) => this.traverseTheModuleTree(importModule, project, moduleDeclarations, parentModuleDeclaration));
}
}
getModuleDecoratorConfig(decorator) {
const arg = decorator.getArguments()[0];
if (!arg || !arg.isKind(ts_morph_1.SyntaxKind.ObjectLiteralExpression)) {
return null;
}
const objectLiteral = arg;
const config = {};
objectLiteral.getProperties().forEach((prop) => {
if (prop.isKind(ts_morph_1.SyntaxKind.PropertyAssignment)) {
const propertyAssignment = prop.asKindOrThrow(ts_morph_1.SyntaxKind.PropertyAssignment);
const key = propertyAssignment.getName();
const value = propertyAssignment.getInitializer();
if (value === null || value === void 0 ? void 0 : value.isKind(ts_morph_1.SyntaxKind.ArrayLiteralExpression)) {
config[key] = value.getElements().map((el) => el.getText());
}
}
});
return config;
}
createModuleDeclarationObj(moduleClass, moduleArguments, project) {
var _a, _b, _c;
let imports = [];
let controllers = [];
let providers = [];
// const functions: ClassDeclaration[] = []; // not implemented yet
if ((_a = moduleArguments === null || moduleArguments === void 0 ? void 0 : moduleArguments.imports) === null || _a === void 0 ? void 0 : _a.length) {
imports = moduleArguments.imports
.map((moduleName) => (0, class_config_util_1.findClassByImport)(moduleClass, moduleName, project))
.filter((value) => !!value);
}
if ((_b = moduleArguments === null || moduleArguments === void 0 ? void 0 : moduleArguments.controllers) === null || _b === void 0 ? void 0 : _b.length) {
controllers = moduleArguments.controllers
.map((controllerName) => (0, class_config_util_1.findClassByImport)(moduleClass, controllerName, project))
.filter((value) => !!value);
}
if ((_c = moduleArguments === null || moduleArguments === void 0 ? void 0 : moduleArguments.providers) === null || _c === void 0 ? void 0 : _c.length) {
providers = moduleArguments.providers
.map((providerName) => (0, class_config_util_1.findClassByImport)(moduleClass, providerName, project))
.filter((value) => !!value);
}
const moduleDeclaration = {
controllers,
providers,
imports,
module: moduleClass,
};
return moduleDeclaration;
}
}
exports.ModuleTreeWalker = ModuleTreeWalker;