Skip to content
This repository has been archived by the owner on Oct 18, 2022. It is now read-only.

Implement a dependency injection system #14

Open
ben-ryder opened this issue May 31, 2022 · 0 comments
Open

Implement a dependency injection system #14

ben-ryder opened this issue May 31, 2022 · 0 comments
Assignees
Labels
discovery more information is needed feature New feature or request package/core issues related to @kangojs/core
Milestone

Comments

@ben-ryder
Copy link
Owner

ben-ryder commented May 31, 2022

Package Information: kangojs

Describe your feature
Implement a dependency injection (DI) / Inversion of Control (IoC) system into KangoJS.
This would mean you could mark dependencies to inject into controlllers, services etc and KangoJS would handle the depedency creation and injection.
This DI must be recursive, so the application must work down the dependency tree (controller -> service -> other services/helpers etc) and handle injecting everything.

Is your suggestion related to any problems?
For testing (unit tests and e2e) you need to be able to access the dependency instances that are part of the application and also potentially overwrite / mock dependencies.

This will be useful for a number of things during testing:

  • For database setup/teardown during e2e testing you could re-use the same database service that the application uses to create content rather than having to write custom things for testing or creating duplicate instances.
  • Testing certain states may rely on knowing/editing internal application state so having access to the same dependency instance that is being used by the services/controllers could let you view/edit application state for tests.

Additional context
I think this would be done the same / a similar way to how it's done in NesJS or InversifyJS:

import { Inject } from "@kangojs/core";
import { UserService } from "./users.service";

export class UserController {
    constructor(
        @Inject(UserService) userService: UserService
    )
}
import { Inject } from "@kangojs/core";
import { UserDatabase } from "./users.database";

export class UserService {
    constructor(
        @Inject(UserDatabase) userDatabase: UserDatabase,
        @Inject(RandomService) randomService: RandomService
    )
}
import { Inject } from "@kangojs/core";

export class UserDatabase {
    constructor(
        @Inject(Config) config: Config
    )
}

Some notes:

  • @Inject decorator can be used to mark a dependency as injectable and tells KangoJS what class should be instantiated, passed to the class and stored in a centeral IoC container for later use.
  • I will need to consider if/how to implement singleton injection vs multiple instance injection / factories etc.
  • DI will work using an IoC container, meaning dependencies will be stored/managed in one centeral container and injected from this container. This means that there could be an interface to let you fetch dependencies from the KangoJS class. For example:
const kangoJS = new KangoJS();
await kangoJS.bootstrap();

const userDatabase = await kangoJS.getDependency<UserDatabase>(UserDatabase);

Maybe there could also then be a way to manually add/overwrite dependencies too? I don't think this would be a paticualr focus for an MVP of this feature though:

const kangoJS = new KangoJS();
await kangoJS.bootstrap();

class MockUserDatabase implements UserDatabaseInterface {
      isUserValid(user: User) {
             if (user.id === "test-user-id") {
                    return true;
             }

             return this.super.isUserValid(user);
      }
}

// Set dependency to use, but still let KangoJS handle instantiation via the DI system
// as maybe MockUserDatabase still relies on other injected services
await kangoJS.setDependency(UserDatabase, MockUserDatabase);

// Maybe you'd also need a way to full overwrite/bypass KangoJS's DI system
await kangoJS.setDependencyInstance(UserDatabase, new MockUserDatabase(new TestConfig()));
@ben-ryder ben-ryder added discovery more information is needed feature New feature or request package/core issues related to @kangojs/core labels May 31, 2022
@ben-ryder ben-ryder self-assigned this May 31, 2022
@ben-ryder ben-ryder added this to the New Features milestone May 31, 2022
@ben-ryder ben-ryder linked a pull request Jun 2, 2022 that will close this issue
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
discovery more information is needed feature New feature or request package/core issues related to @kangojs/core
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant