Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper implementation of providers in Loopback 4

I've been trying to wrap my head around providers and decorators in loopback 4 and I have a tough time getting to understand it.

  1. What is the main purpose of the provider?
  2. Is it only for the sequence or can it be used elsewhere?
  3. Is there template to follow?
  4. Whats the best way to use it with a decorator?

My current implementations look like the following:

export interface MyProviderFn {
  (args: any[]): Promise<void>;
}

export class MyActionProvider implements Provider<MyProviderFn> {
  public constructor(
    @inject(CoreBindings.APPLICATION_INSTANCE)
    public app: RestApplication,
    @inject.getter(CoreBindings.CONTROLLER_CLASS, { optional: true })
    private readonly getController: Getter<Constructor<{}>>,
    @inject.getter(CoreBindings.CONTROLLER_METHOD_NAME, { optional: true })
    private readonly getMethod: Getter<string>,
  ) {}

  public value(): MyProviderFn {
    return args => this.action(args);
  }

  public async action(args: any[]): Promise<void> {
    const controllerClass = await this.getController();
    const methodName = await this.getMethod();
    if (!controllerClass || !methodName) return;

    const metadata = getDecoratorMetadata(controllerClass, methodName);
    if (!metadata) {
      return;
    }

    // Provider specific code here
  }
}

Is this an accurate way of doing it? Can it be cleaner?

like image 260
Navos Avatar asked Nov 16 '25 22:11

Navos


1 Answers

  1. In LoopBack 4, Provider solves the following problem for dependency injection:

    • The bound value is dynamically created/calculated (not a constant, cannot use binding.to())
    • The bound value has dependencies on other bindings (cannot use binding.toDynamicValue())
    • The bound value is not an instance from a class (cannot use binding.toClass())

For example:

class GreetingProvider implements Provider<string> {

  // Inject the current language
  private constructor(@inject('language') private lang: string) {
  }
  
  // Produce resolved value for the binding
  value() {
    if (this.lang === 'zh') return '你好';
    else return 'Hello';
  }
}
  1. It can be used in LB4 applications to back any kind of bindings, not limited to actions.

  2. You can find examples in loopback-next repo

  3. Provider has to be a class so that decorators can be applied for dependency injection. Constructor parameters and properties can be decorated.

like image 135
Raymond Feng Avatar answered Nov 18 '25 13:11

Raymond Feng