0.1.1 • Published 6 months ago

@riotbyte/nest-service-locator v0.1.1

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

NestJS Service Locator

The service locator package allow you to define "service tags". Service tags can be used to create a collection of services that can be retreived using a service locator. This can be helpful when implementing certain design patterns (e.g. strategy), where a service uses a collection of different implementations.

Defining a tag

To define a new tag, you need to call the defineTag function:

import { defineTag } from '@riotbyte/nest-service-locator'

export const MyTag = defineTag('my-tag-name')

NOTE: You can define a tag with the same name, mulitple times. Keep in mind that each individual instance is a different tag, and tags with the same name, will not conflict with eachother.

This tag can now be applied using the decorator method on the defined tag:

@MyTag.decorator({})
class MyTaggedClass {}

NOTE: The empty object passed to the decorator function is used to supply the tag with metadata. By default, metadata can be an empty object, but you can specify the type of metadata for each tag induvidually.

Providing metadata

Tags can provide additional information about the class that it has been applied to. You can define the type of the metadata when defining a tag:

export const MyTag = defineTag<{ name: string }>('my-tag-name')

This example now requires an object with the name property when applying the tag:

@MyTag.decorator({ name: 'my-tagged-class' })
class MyTaggedClass {}

Restricting the tag

By default, the tag can be applied to any class. If a tag is expected to only be applied to a specific interface or type, you can define a tag like this:

import { defineTag } from '@riotbyte/nest-service-locator'

export const MyTag = defineTag<object, MyInterface>('my-tag-name')

Now the compiler will show an error when the class the tag is being applied to is not an instance of MyInterface:

// This is allowed since X is a valid implementation of MyInterface
@MyTag.decorator({})
class X implements MyInterface {
  myInterfacedFunction() {}
}

// This is not allowed since Y is not a valid implementation of MyInterface
@MyTag.decorator({})
class Y {}

Retreiving tagged services

Tagged services and their metadata can be retrieved using the service locator:

import { ServiceLocator, TaggedService } from '@riotbyte/nest-service-locator'

class GroupGreeter {
  private greeters = Map<string, GreeterInterface>()

  constructor(locator: ServiceLocator) {
    const tagged: TaggedService<GreeterInterface, { name: string }>[] =
      locator.tagged(GreeterTag)
    tagger.forEach((tagged) => {
      this.greeters.set(tagged.metadata.name, tagged.service)
    })
  }

  greet(greeterName: string): void {
    this.greeters.get(greeterName).greet()
  }
}
0.1.1

6 months ago