@tdi2/di-core
Version:
TypeScript Dependency Injection 2 - Core DI framework
204 lines (201 loc) • 7.08 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/context.tsx
import * as React from "react";
import { createContext, useContext } from "react";
// src/container.ts
var _CompileTimeDIContainer = class _CompileTimeDIContainer {
constructor(parent) {
__publicField(this, "services", /* @__PURE__ */ new Map());
__publicField(this, "instances", /* @__PURE__ */ new Map());
__publicField(this, "factories", /* @__PURE__ */ new Map());
__publicField(this, "scopes", /* @__PURE__ */ new Map());
__publicField(this, "parent");
this.parent = parent;
}
register(token, implementation, scope = "singleton") {
const tokenKey = this.getTokenKey(token);
if (typeof implementation === "function") {
try {
const result = implementation(this);
if (typeof result === "function") {
this.factories.set(tokenKey, result);
} else {
this.services.set(tokenKey, implementation);
}
} catch (e) {
this.services.set(tokenKey, implementation);
}
} else {
this.instances.set(tokenKey, implementation);
}
this.scopes.set(tokenKey, scope);
}
resolve(token) {
const tokenKey = this.getTokenKey(token);
if (this.scopes.get(tokenKey) === "singleton" && this.instances.has(tokenKey)) {
return this.instances.get(tokenKey);
}
if (!this.has(token) && this.parent) {
return this.parent.resolve(token);
}
let instance;
if (this.factories.has(tokenKey)) {
const factory = this.factories.get(tokenKey);
instance = factory();
} else if (this.services.has(tokenKey)) {
const constructor = this.services.get(tokenKey);
if (typeof constructor === "function") {
instance = new constructor();
} else {
instance = constructor;
}
} else {
throw new Error(`Service not registered: ${String(token)}`);
}
if (this.scopes.get(tokenKey) === "singleton") {
this.instances.set(tokenKey, instance);
}
return instance;
}
has(token) {
const tokenKey = this.getTokenKey(token);
return this.factories.has(tokenKey) || this.services.has(tokenKey) || this.instances.has(tokenKey) || (this.parent?.has(token) ?? false);
}
createScope() {
return new _CompileTimeDIContainer(this);
}
// FIXED: Enhanced loadConfiguration method with better logging
loadConfiguration(diMap) {
console.log("\u{1F527} Loading DI configuration...");
console.log("\u{1F4CB} DI_CONFIG keys:", Object.keys(diMap));
for (const [token, config] of Object.entries(diMap)) {
try {
if (!config.factory) {
console.warn(`\u26A0\uFE0F No factory found for token: ${token}`);
continue;
}
console.log(`\u{1F517} Registering: ${token} -> ${config.implementationClass || "unknown"}`);
const factory = config.factory(this);
this.factories.set(token, factory);
this.scopes.set(token, config.scope);
} catch (error) {
console.error(`\u274C Failed to register ${token}:`, error);
}
}
console.log("\u2705 DI configuration loaded");
}
getTokenKey(token) {
return typeof token === "symbol" ? token.toString() : token;
}
// Enhanced debug method to see what's registered
getRegisteredTokens() {
const tokens = /* @__PURE__ */ new Set();
this.factories.forEach((_, key) => tokens.add(this.getTokenKey(key)));
this.services.forEach((_, key) => tokens.add(this.getTokenKey(key)));
this.instances.forEach((_, key) => tokens.add(this.getTokenKey(key)));
return Array.from(tokens);
}
// NEW: Debug method to inspect the current state
debugContainer() {
console.log("\u{1F50D} Container Debug Info:");
console.log("\u{1F4CB} Factories:", Array.from(this.factories.keys()));
console.log("\u{1F3D7}\uFE0F Services:", Array.from(this.services.keys()));
console.log("\u{1F4E6} Instances:", Array.from(this.instances.keys()));
console.log("\u{1F3AF} Scopes:", Array.from(this.scopes.entries()));
}
// NEW: Method to register by interface (for enhanced interface-based DI)
registerByInterface(interfaceName, implementation, scope = "singleton") {
this.register(interfaceName, implementation, scope);
}
// NEW: Method to resolve by interface
resolveByInterface(interfaceName) {
return this.resolve(interfaceName);
}
// NEW: Method to check if interface is registered
hasInterface(interfaceName) {
return this.has(interfaceName);
}
};
__name(_CompileTimeDIContainer, "CompileTimeDIContainer");
var CompileTimeDIContainer = _CompileTimeDIContainer;
// src/context.tsx
import { proxy, useSnapshot } from "valtio";
var DIContext = /* @__PURE__ */ createContext(null);
function DIProvider({ container, children }) {
const diContainer = container || new CompileTimeDIContainer();
return /* @__PURE__ */ React.createElement(DIContext.Provider, {
value: diContainer
}, children);
}
__name(DIProvider, "DIProvider");
function useDI() {
const container = useContext(DIContext);
if (!container) {
throw new Error("useDI must be used within a DIProvider");
}
return container;
}
__name(useDI, "useDI");
function useService(token) {
const container = useDI();
const [_] = React.useState(proxy(container.resolve(token)));
if (_ === void 0) {
throw new Error(`Service not found: ${String(token)}`);
}
useSnapshot(_);
return _;
}
__name(useService, "useService");
function useOptionalService(token) {
const container = useDI();
try {
if (container.has(token)) {
return container.resolve(token);
}
return void 0;
} catch (error) {
console.warn(`Optional service not found: ${String(token)}`);
return void 0;
}
}
__name(useOptionalService, "useOptionalService");
function useServices(serviceMap) {
const container = useDI();
const services = {};
for (const [key, token] of Object.entries(serviceMap)) {
services[key] = container.resolve(token);
}
return services;
}
__name(useServices, "useServices");
function useFunctionalDI(dependencies) {
const container = useDI();
const services = {};
for (const dep of dependencies) {
if (dep.optional) {
try {
if (container.has(dep.token)) {
services[dep.key] = container.resolve(dep.token);
}
} catch (error) {
console.warn(`Optional dependency not available: ${String(dep.token)}`);
}
} else {
services[dep.key] = container.resolve(dep.token);
}
}
return services;
}
__name(useFunctionalDI, "useFunctionalDI");
export {
DIProvider,
useDI,
useFunctionalDI,
useOptionalService,
useService,
useServices
};
//# sourceMappingURL=context.js.map