commit 46f08d42cc6eef425e977b7fd7c2b59058d093d3 Author: Robin Chappatte Date: Tue May 21 16:14:58 2024 +0200 initial commit diff --git a/dependency-manager.ts b/dependency-manager.ts new file mode 100644 index 0000000..6b4e5e1 --- /dev/null +++ b/dependency-manager.ts @@ -0,0 +1,44 @@ +type Provider = (manager: DependencyManager) => Promise | T; + +type Modules = Map; + instance?: any; +}>; + +export class DependencyManager { + private modules: Modules = new Map(); + private resolving: Set = new Set(); + + // Enregistrer un module avec son initialisateur + register(name: string, provider: Provider): void { + if (this.modules.has(name)) { + throw new Error(`Module ${name} is already registered.`); + } + this.modules.set(name, { provider }); + } + + // Résoudre un module et ses dépendances + async resolve(name: string): Promise { + const module = this.modules.get(name); + if (!module) { + throw new Error(`Module ${name} is not registered.`); + } + + if (module.instance) { + return module.instance; + } + + if (this.resolving.has(name)) { + throw new Error(`Circular dependency detected for module ${name}.`); + } + + this.resolving.add(name); + + try { + module.instance = await module.provider(this); + return module.instance; + } finally { + this.resolving.delete(name); + } + } +} diff --git a/mod.ts b/mod.ts new file mode 100644 index 0000000..662adcf --- /dev/null +++ b/mod.ts @@ -0,0 +1 @@ +export * from "./dependency-manager.ts"; diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..23a0add --- /dev/null +++ b/readme.md @@ -0,0 +1,69 @@ +# Dependency manager + +This lib provides a simplistic dependency manager. + +## Features and limitations + +- It resolves dependencies only when they are needed +- It detect circular dependency + +## Usage + +Create a manager: + +```typescript +import { DependencyManager } from 'dependency-manager/mod.ts' + +const manager = new DependencyManager() +``` + +Create providers for your dependencies. +A provider is a function that is called when attempting to retrieve the dependency for the first time. +It receive the dependency manager, and return the dependency value, or a promise that resolves to it. + +```typescript +// dependency-free provider +function loggerProvider() { + return console.log +} +type Logger = ReturnType; + +// provider that need the 'logger' dependency +async function fooProvider(manager: DependencyManager) { + const logger = await manager.resolve('logger'); + + return { + bar: () => logger('bar'), + baz: () => logger('baz'), + } +} +type Foo = Awaited>; +``` + +Register the dependency by passing the `register` method its name and provider: + +```typescript +manager.register('logger', loggerProvider); +manager.register('foo', fooProvider); +``` + +Retrieve dependencies by resolving them (always asynchrone, even if the provider was synchrone): + +```typescript +const foo = await manager.resolve('foo'); +foo.bar(); +foo.baz(); +``` + +## Typing + +Types should be explicitly defined when resolving a dependency. + +## Errors + +The `register` method throw an error if: +- the name is already used. + +The `resolve` method throw an error if: +- the name doesn't exist (if no module has been registred with the given name). +- a circular dependency is detected \ No newline at end of file