service.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import { Observable, Subject } from 'rxjs'
  2. import { Container, currentContainer } from './container'
  3. /**
  4. * A Dioc service that can bound to a container and can bind dependency services.
  5. *
  6. * NOTE: Services cannot have a constructor that takes arguments.
  7. *
  8. * @template EventDef The type of events that can be emitted by the service. These will be accessible by event streams
  9. */
  10. export abstract class Service<EventDef = {}> {
  11. /**
  12. * The internal event stream of the service
  13. */
  14. private event$ = new Subject<EventDef>()
  15. /** The container the service is bound to */
  16. #container: Container
  17. constructor() {
  18. if (!currentContainer) {
  19. throw new Error(
  20. `Tried to initialize service with no container (ID: ${ (this.constructor as any).ID })`
  21. )
  22. }
  23. this.#container = currentContainer
  24. }
  25. /**
  26. * Binds a dependency service into this service.
  27. * @param service The class reference of the service to bind
  28. */
  29. protected bind<T extends typeof Service<any> & { ID: string }>(service: T): InstanceType<T> {
  30. if (!currentContainer) {
  31. throw new Error('No currentContainer defined.')
  32. }
  33. return currentContainer.bind(service, this.constructor as typeof Service<any> & { ID: string })
  34. }
  35. /**
  36. * Returns the container the service is bound to
  37. */
  38. protected getContainer(): Container {
  39. return this.#container
  40. }
  41. /**
  42. * Emits an event on the service's event stream
  43. * @param event The event to emit
  44. */
  45. protected emit(event: EventDef) {
  46. this.event$.next(event)
  47. }
  48. /**
  49. * Returns the event stream of the service
  50. */
  51. public getEventStream(): Observable<EventDef> {
  52. return this.event$.asObservable()
  53. }
  54. }