deepkit-framework icon indicating copy to clipboard operation
deepkit-framework copied to clipboard

DI: Undefined dependency "context: InjectorContext"

Open Murzbul opened this issue 1 year ago • 2 comments

Hi!

I have some tests with the InjectorContext and InjectorModule.

I've tested the docs example to inject the InjectorContext but it doesn't work.

class Database
{

}

class MyService
{
      constructor(protected context: InjectorContext)
     {
         console.log('MyService');
     }

     getDatabase(): Database
     {
          return this.context.get(Database);
     }
}

const rootModule = new InjectorModule([
      { provide: Database, useClass: Database },
      { provide: MyService, useClass: MyService }
]);

const injector = new InjectorContext(rootModule);

console.log('injector.get(MyService)');
console.log(injector.get(MyService));

This is the error.

/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:616
           throw new DependenciesUnmetError(`Undefined dependency "${options.name}: ${type}" of ${of}. Type has no provider${fromScope ? ' in scope ' + fromScope : ''}.`);
                 ^

DependenciesUnmetError: Undefined dependency "context: InjectorContext" of MyService(?). Type has no provider.
   at Injector.createFactoryProperty (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:616:19)
   at Injector.createFactory (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:461:32)
   at Injector.buildProvider (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:368:28)
   at Injector.build (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:311:37)
   at new Injector (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:210:14)
   at InjectorModule.getOrCreateInjector (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/module.js:444:25)
   at InjectorContext.getInjector (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:834:23)
   at InjectorContext.get (/home/node/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]/node_modules/@deepkit/injector/dist/cjs/src/injector.js:818:31)
   at /home/node/dist/src/index.js:47:30
   at Object.<anonymous> (/home/node/dist/src/index.js:108:3)

Node.js v21.7.0

I don't know if there is a bug or if I have a mistake understanding here with the docs.

Murzbul avatar Jul 10 '24 23:07 Murzbul

InjectorContext is not available in the low level API. It is only available in the App abstraction of @deepkit/app.

As a side note: if your MyService needs Database, you should just reference Database in the constructor instead of using the InjectorContext. InjectorContext is only necesary to either delay intantiation or load services dynamically. You should try to stay away from it to not tightly couple your code too much to the DI container or use the DI container as metasystem

marcj avatar Jul 11 '24 00:07 marcj

Thank you very much for the message.

In reality, it is a mere example.

What I would like to build is a SimpleCQRS.

So I need some way to get the context to add the handlers.

The idea is to create a simple module.

For example

export const CqrsModule = new InjectorModule([
    {provide: CommandBus, useClass: SimpleCommandBus},
    { provide: QueryBus, useClass: SimpleQueryBus }
]).forRoot();

As a first module.

Then add another module and get the SimpleCommandBus to add the corresponding handlers.

Murzbul avatar Jul 11 '24 01:07 Murzbul

InjectorContext is just a helper abstraction. if you want to work with it and low level API InjectorModule you have to do the housekeeping yourself. Our @deepkit/app abstraction does it like this:


const rootModule = new InjectorModule([
      { provide: Database, useClass: Database },
      { provide: MyService, useClass: MyService },
      { provide: InjectorContext, useFactory: () => injector },
]);

const injector = new InjectorContext(rootModule);

this way you can inject InjectorContext in your services.

I'm going to close this issue as I don't see any action item for me. feel free to reopen

marcj avatar Nov 12 '24 10:11 marcj