tsedio / tsed

:triangular_ruler: Ts.ED is a Node.js and TypeScript framework on top of Express to write your application with TypeScript (or ES6). It provides a lot of decorators and guideline to make your code more readable and less error-prone. ⭐️ Star to support our work!
https://tsed.io/
MIT License
2.86k stars 284 forks source link

Feat injectable function #2857

Closed Romakita closed 1 month ago

Romakita commented 1 month ago

Information

Type Breaking change
Feature Yes

Usage example

This feature allow provider registration using injectable, controller functions. Decorators can also be used.

Register class

Functional API:

import {injectable, inject, logger} from "@tsed/di";

class MyInjectable {
   logger = logger()
   anotherService = inject(AnotherService)
}

injectable(MyInjectable)

Decorator API:

import {Injectable, Inject} from "@tsed/di";
import {Logger} from "@tsed/logger";

@Injectable()
class MyInjectable {
   @Inject(Logger)
   logger: Logger;

   @Inject(AnotherService)
   anotherService: AnotherService
}

injectable(MyInjectable)

Register factory

Functional API:

import {injectable, inject, logger, ProviderType} from "@tsed/di";

export const MY_TOKEN = injectable(Symbol.for("MY_TOKEN"))
   .deps([AnotherService])
   .factory((anotherService: AnotherService) => {
       return {
         id: anotherService.id() + "HELLO"
       }
   })
   .token();

// alternative
export const MY_TOKEN = injectable(Symbol.for("MY_TOKEN"))
   .factory(() => {
       const anotherService = inject(AnotherService);

       return {
         id: anotherService.id() + "HELLO"
       }
   })
   .token();

// MODULE

class MyModule {
   myFactory = inject(MY_TOKEN)

   $onInit() {
      console.log(this.myFactory)
   } 
}

injectable(MyModule).type(ProviderType.MODULE)

Equivalent in v7 (still available in v8):

export const MY_TOKEN = Symbol.for("MY_TOKEN");

registerProvider({
   provide: MY_TOKEN
   deps: [AnotherService],
   useFactory: (anotherService: AnotherService) => {
       return {
         id: anotherService.id() + "HELLO"
       }
   }
})

Register async factory

Functional API:

import {injectable, inject, logger} from "@tsed/di";

export const MY_TOKEN = injectable(Symbol.for("MY_TOKEN"))
   .deps([AnotherService])
   .asyncFactory(async (anotherService: AnotherService) => {
       return {
         id: await anotherService.id() + "HELLO"
       }
   })
   .token();

// alternative
export const MY_TOKEN = injectable(Symbol.for("MY_TOKEN"))
   .asyncFactory(async () => {
       const anotherService = inject(AnotherService);
       return {
         id: await anotherService.id() + "HELLO"
       }
   })
   .token();

Equivalent in v7 (still available in v8):

export const MY_TOKEN = Symbol.for("MY_TOKEN");

registerProvider({
   provide: MY_TOKEN
   deps: [AnotherService],
   useAsyncFactory: async (anotherService: AnotherService) => {
       return {
         id: await anotherService.id() + "HELLO"
       }
   }
});

register Value

Functional API:

import {injectable, inject, logger} from "@tsed/di";

export const MY_TOKEN = injectable(Symbol.for("MY_TOKEN")).value("VALUE").token();

Equivalent in v7 (still available in v8):

export const MY_TOKEN = Symbol.for("MY_TOKEN");

registerProvider({
   provide: MY_TOKEN
   useValue: "VALUE"
});

removed from v8, available in v7

registerValue(MY_TOKEN, "VALUE");

Todos

Romakita commented 1 month ago

:tada: This PR is included in version 8.0.0-beta.3 :tada:

The release is available on:

Your semantic-release bot :package::rocket: