UNPKG

dipend

Version:

This library implements a dependency injection (DI) system in JavaScript/TypeScript, making it easier to manage dependencies in modular applications.

107 lines (105 loc) 5.64 kB
/* * Copyright 2025 Saulo V. Alvarenga. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DependencyContainerTransform = void 0; const base_transform_1 = require("./base-transform"); class DependencyContainerTransform extends base_transform_1.BaseTransform { findMethodName(nodeExpression) { const symbol = this.typeChecker.getSymbolAtLocation(nodeExpression.expression); if (!symbol?.valueDeclaration) return undefined; const type = this.typeChecker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration); if (this.typeChecker.typeToString(type) !== "DependencyContainer") return undefined; const validMethods = new Set([ "addSingletonBuilder", "addMappedSingletonBuilder", "addSingletonInstance", "addMappedSingletonInstance", "addSingleton", "addMappedSingleton", "addTransientBuilder", "addMappedTransientBuilder", "addTransient", "addMappedTransient", "getDependency", "getMappedDependency", ]); if (!validMethods.has(nodeExpression.name.getText())) return undefined; return nodeExpression.name.getText(); } getDependencyTokenValue(dependencyToken) { const dependencyTokenType = this.typeChecker.getTypeFromTypeNode(dependencyToken); const dependencyTokenSymbol = dependencyTokenType.getSymbol(); const declaration = dependencyTokenSymbol?.declarations?.[0]; if (declaration && this.tsInstance.isInterfaceDeclaration(declaration) && this.interfaces.has(declaration)) { const interfaceIdentifier = this.interfaces.get(declaration); if (!interfaceIdentifier) throw new Error("Invalid interface identifier"); return interfaceIdentifier; } return this.tsFactory.createIdentifier(dependencyToken.getText()); } createUpdatedDependencyRegisterConfigObjectLiteral(methodArgument, dependencyTokenPropertyValue, classConstructorPropertyAssignmentArray) { const dependencyTokenPropertyAssignment = this.tsFactory.createPropertyAssignment("dependencyToken", dependencyTokenPropertyValue); if (methodArgument && this.tsInstance.isObjectLiteralExpression(methodArgument)) { const existingProperties = methodArgument.properties; const propertyNames = new Set(existingProperties.map((prop) => prop.name?.text)); return this.tsFactory.updateObjectLiteralExpression(methodArgument, [ ...existingProperties, ...(!propertyNames.has("dependencyToken") ? [dependencyTokenPropertyAssignment] : []), ...(!propertyNames.has("classConstructor") ? classConstructorPropertyAssignmentArray : []), ]); } return this.tsFactory.createObjectLiteralExpression([ dependencyTokenPropertyAssignment, ...classConstructorPropertyAssignmentArray, ]); } createUpdatedDependencyRegisterCallExpression(node, nodeExpression, methodName, dependencyTokenPropertyValue, classConstructorExpr) { const methodArgument = node.arguments?.[0]; const requiresClassConstructor = new Set([ "addSingleton", "addMappedSingleton", "addTransient", "addMappedTransient", ]).has(methodName); const classConstructorPropertyAssignmentArray = requiresClassConstructor ? [this.tsFactory.createPropertyAssignment("classConstructor", classConstructorExpr)] : []; const newObjectLiteral = this.createUpdatedDependencyRegisterConfigObjectLiteral(methodArgument, dependencyTokenPropertyValue, classConstructorPropertyAssignmentArray); return this.tsFactory.updateCallExpression(node, this.tsFactory.updatePropertyAccessExpression(nodeExpression, nodeExpression.expression, nodeExpression.name), undefined, [newObjectLiteral]); } execute(node) { if (!this.tsInstance.isCallExpression(node) || !this.tsInstance.isPropertyAccessExpression(node.expression)) return; const methodName = this.findMethodName(node.expression); if (methodName === undefined) return; const [dependencyToken, classConstructor] = node.typeArguments || []; if (!dependencyToken) return; const dependencyTokenExpr = this.tsFactory.createIdentifier(dependencyToken.getText()); const classConstructorExpr = classConstructor ? this.tsFactory.createIdentifier(classConstructor.getText()) : undefined; const dependencyTokenPropertyValue = this.getDependencyTokenValue(dependencyToken); return this.createUpdatedDependencyRegisterCallExpression(node, node.expression, methodName, dependencyTokenPropertyValue, classConstructorExpr || dependencyTokenExpr); } } exports.DependencyContainerTransform = DependencyContainerTransform;