artmapper
Version:
Spring Boot clone for Node.js with TypeScript/JavaScript - JPA-like ORM, Lombok decorators, dependency injection, and MySQL support
171 lines • 5.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Container = void 0;
require("reflect-metadata");
const component_1 = require("../decorators/component");
class Container {
constructor() {
this.beans = new Map();
this.beanTypes = new Map();
this.config = new Map();
this.pool = null;
}
static getInstance() {
if (!Container.instance) {
Container.instance = new Container();
}
return Container.instance;
}
/**
* Set database pool for repositories
*/
setPool(pool) {
this.pool = pool;
}
/**
* Register a configuration value
*/
setConfig(key, value) {
this.config.set(key, value);
}
/**
* Get a configuration value
*/
getConfig(key) {
return this.config.get(key);
}
/**
* Register a bean (component, service, controller, repository)
*/
registerBean(target, instance) {
const componentMetadata = Reflect.getMetadata(component_1.COMPONENT_METADATA_KEY, target);
const serviceMetadata = Reflect.getMetadata(component_1.SERVICE_METADATA_KEY, target);
const controllerMetadata = Reflect.getMetadata(component_1.CONTROLLER_METADATA_KEY, target);
const repositoryMetadata = Reflect.getMetadata(component_1.REPOSITORY_METADATA_KEY, target);
let beanName;
if (componentMetadata) {
beanName = componentMetadata.name || target.name;
}
else if (serviceMetadata) {
beanName = serviceMetadata.name || target.name;
}
else if (controllerMetadata) {
beanName = target.name;
}
else if (repositoryMetadata) {
beanName = repositoryMetadata.name || target.name;
}
else {
beanName = target.name;
}
this.beanTypes.set(beanName, target);
if (instance) {
this.beans.set(beanName, instance);
}
}
/**
* Get a bean by name or type
*/
getBean(nameOrType) {
let beanName;
if (typeof nameOrType === 'function') {
// Find by type
for (const [name, type] of this.beanTypes.entries()) {
if (type === nameOrType || type.prototype instanceof nameOrType) {
beanName = name;
break;
}
}
if (!beanName) {
throw new Error(`Bean of type ${nameOrType.name} not found`);
}
}
else {
beanName = nameOrType;
}
// Return existing instance if available
if (this.beans.has(beanName)) {
return this.beans.get(beanName);
}
// Create new instance
const beanType = this.beanTypes.get(beanName);
if (!beanType) {
throw new Error(`Bean ${beanName} not found`);
}
const instance = this.createInstance(beanType);
this.beans.set(beanName, instance);
return instance;
}
/**
* Create an instance of a class with dependency injection
*/
createInstance(target) {
// Get constructor parameters
const paramTypes = Reflect.getMetadata('design:paramtypes', target) || [];
const autowiredMetadata = Reflect.getMetadata(component_1.AUTOWIRED_METADATA_KEY, target) || {};
const valueMetadata = Reflect.getMetadata(component_1.VALUE_METADATA_KEY, target) || {};
const qualifierMetadata = Reflect.getMetadata(component_1.QUALIFIER_METADATA_KEY, target) || {};
// Resolve constructor dependencies
const constructorArgs = paramTypes.map((paramType, index) => {
if (paramType && paramType.name === 'Pool' && this.pool) {
return this.pool;
}
// Try to find bean by type
try {
return this.getBean(paramType);
}
catch {
return undefined;
}
});
// Create instance
const instance = new target(...constructorArgs);
// Inject field dependencies
Object.keys(autowiredMetadata).forEach(propertyKey => {
const autowiredInfo = autowiredMetadata[propertyKey];
const qualifier = qualifierMetadata[propertyKey];
let dependency;
if (qualifier) {
dependency = this.getBean(qualifier);
}
else if (autowiredInfo.type) {
dependency = this.getBean(autowiredInfo.type);
}
if (dependency) {
instance[propertyKey] = dependency;
}
});
// Inject configuration values
Object.keys(valueMetadata).forEach(propertyKey => {
const configKey = valueMetadata[propertyKey];
const configValue = this.getConfig(configKey);
if (configValue !== undefined) {
instance[propertyKey] = configValue;
}
});
return instance;
}
/**
* Scan and register all beans from a directory
*/
async scanAndRegister(modulePath) {
// In a real implementation, this would scan the file system
// For now, we'll rely on manual registration or explicit imports
}
/**
* Get all registered beans
*/
getAllBeans() {
return new Map(this.beans);
}
/**
* Clear all beans
*/
clear() {
this.beans.clear();
this.beanTypes.clear();
this.config.clear();
}
}
exports.Container = Container;
//# sourceMappingURL=Container.js.map