@navios/di 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +301 -39
  2. package/docs/README.md +122 -49
  3. package/docs/api-reference.md +763 -0
  4. package/docs/container.md +274 -0
  5. package/docs/examples/basic-usage.mts +97 -0
  6. package/docs/examples/factory-pattern.mts +318 -0
  7. package/docs/examples/injection-tokens.mts +225 -0
  8. package/docs/examples/request-scope-example.mts +254 -0
  9. package/docs/examples/service-lifecycle.mts +359 -0
  10. package/docs/factory.md +584 -0
  11. package/docs/getting-started.md +308 -0
  12. package/docs/injectable.md +496 -0
  13. package/docs/injection-tokens.md +400 -0
  14. package/docs/lifecycle.md +539 -0
  15. package/docs/scopes.md +749 -0
  16. package/lib/_tsup-dts-rollup.d.mts +495 -150
  17. package/lib/_tsup-dts-rollup.d.ts +495 -150
  18. package/lib/index.d.mts +26 -12
  19. package/lib/index.d.ts +26 -12
  20. package/lib/index.js +993 -462
  21. package/lib/index.js.map +1 -1
  22. package/lib/index.mjs +983 -453
  23. package/lib/index.mjs.map +1 -1
  24. package/package.json +2 -2
  25. package/project.json +10 -2
  26. package/src/__tests__/container.spec.mts +1301 -0
  27. package/src/__tests__/factory.spec.mts +137 -0
  28. package/src/__tests__/injectable.spec.mts +32 -88
  29. package/src/__tests__/injection-token.spec.mts +333 -17
  30. package/src/__tests__/request-scope.spec.mts +263 -0
  31. package/src/__type-tests__/factory.spec-d.mts +65 -0
  32. package/src/__type-tests__/inject.spec-d.mts +27 -28
  33. package/src/__type-tests__/injectable.spec-d.mts +42 -206
  34. package/src/container.mts +167 -0
  35. package/src/decorators/factory.decorator.mts +79 -0
  36. package/src/decorators/index.mts +1 -0
  37. package/src/decorators/injectable.decorator.mts +6 -56
  38. package/src/enums/injectable-scope.enum.mts +5 -1
  39. package/src/event-emitter.mts +18 -20
  40. package/src/factory-context.mts +2 -10
  41. package/src/index.mts +3 -2
  42. package/src/injection-token.mts +24 -9
  43. package/src/injector.mts +8 -20
  44. package/src/interfaces/factory.interface.mts +3 -3
  45. package/src/interfaces/index.mts +2 -0
  46. package/src/interfaces/on-service-destroy.interface.mts +3 -0
  47. package/src/interfaces/on-service-init.interface.mts +3 -0
  48. package/src/registry.mts +7 -16
  49. package/src/request-context-holder.mts +145 -0
  50. package/src/service-instantiator.mts +158 -0
  51. package/src/service-locator-event-bus.mts +0 -28
  52. package/src/service-locator-instance-holder.mts +27 -16
  53. package/src/service-locator-manager.mts +84 -0
  54. package/src/service-locator.mts +550 -395
  55. package/src/utils/defer.mts +73 -0
  56. package/src/utils/get-injectors.mts +93 -80
  57. package/src/utils/index.mts +2 -0
  58. package/src/utils/types.mts +52 -0
  59. package/docs/concepts/injectable.md +0 -182
  60. package/docs/concepts/injection-token.md +0 -145
  61. package/src/proxy-service-locator.mts +0 -83
  62. package/src/resolve-service.mts +0 -41
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Creates a deferred promise that can be resolved or rejected externally.
3
+ * This is useful for creating stub holders that can be fulfilled later.
4
+ */
5
+ export class Deferred<T> {
6
+ public readonly promise: Promise<T>
7
+ private _resolve!: (value: T) => void
8
+ private _reject!: (reason?: any) => void
9
+ private _isResolved = false
10
+ private _isRejected = false
11
+
12
+ constructor() {
13
+ this.promise = new Promise<T>((resolve, reject) => {
14
+ this._resolve = resolve
15
+ this._reject = reject
16
+ })
17
+ }
18
+
19
+ /**
20
+ * Resolves the deferred promise with the given value.
21
+ * @param value The value to resolve with
22
+ * @throws Error if the promise has already been resolved or rejected
23
+ */
24
+ resolve(value: T): void {
25
+ if (this._isResolved || this._isRejected) {
26
+ throw new Error('Deferred promise has already been resolved or rejected')
27
+ }
28
+ this._isResolved = true
29
+ this._resolve(value)
30
+ }
31
+
32
+ /**
33
+ * Rejects the deferred promise with the given reason.
34
+ * @param reason The reason for rejection
35
+ * @throws Error if the promise has already been resolved or rejected
36
+ */
37
+ reject(reason?: any): void {
38
+ if (this._isResolved || this._isRejected) {
39
+ throw new Error('Deferred promise has already been resolved or rejected')
40
+ }
41
+ this._isRejected = true
42
+ this._reject(reason)
43
+ }
44
+
45
+ /**
46
+ * Returns true if the promise has been resolved.
47
+ */
48
+ get isResolved(): boolean {
49
+ return this._isResolved
50
+ }
51
+
52
+ /**
53
+ * Returns true if the promise has been rejected.
54
+ */
55
+ get isRejected(): boolean {
56
+ return this._isRejected
57
+ }
58
+
59
+ /**
60
+ * Returns true if the promise has been settled (resolved or rejected).
61
+ */
62
+ get isSettled(): boolean {
63
+ return this._isResolved || this._isRejected
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Creates a new deferred promise.
69
+ * @returns A new Deferred instance
70
+ */
71
+ export function createDeferred<T>(): Deferred<T> {
72
+ return new Deferred<T>()
73
+ }
@@ -1,5 +1,6 @@
1
1
  import type { z, ZodObject, ZodType } from 'zod/v4'
2
2
 
3
+ import type { FactoryContext } from '../factory-context.mjs'
3
4
  import type {
4
5
  BoundInjectionToken,
5
6
  ClassType,
@@ -7,52 +8,25 @@ import type {
7
8
  InjectionToken,
8
9
  InjectionTokenSchemaType,
9
10
  } from '../injection-token.mjs'
10
- import type { ServiceLocator } from '../service-locator.mjs'
11
+ import type { Factorable } from '../interfaces/factory.interface.mjs'
12
+ import type { InjectState, Join, UnionToArray } from './types.mjs'
11
13
 
12
14
  import { InjectableTokenMeta } from '../symbols/index.mjs'
13
15
 
14
- export interface CreateInjectorsOptions {
15
- baseLocator: ServiceLocator
16
- }
17
- type Join<TElements, TSeparator extends string> =
18
- TElements extends Readonly<[infer First, ...infer Rest]>
19
- ? Rest extends ReadonlyArray<string>
20
- ? First extends string
21
- ? `${First}${Rest extends [] ? '' : TSeparator}${Join<Rest, TSeparator>}`
22
- : never
23
- : never
24
- : ''
25
- // credits goes to https://stackoverflow.com/a/50375286
26
- type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
27
- k: infer I,
28
- ) => void
29
- ? I
30
- : never
31
-
32
- // Converts union to overloaded function
33
- type UnionToOvlds<U> = UnionToIntersection<
34
- U extends any ? (f: U) => void : never
35
- >
36
-
37
- type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never
38
-
39
- type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true
40
-
41
- type UnionToArray<T, A extends unknown[] = []> =
42
- IsUnion<T> extends true
43
- ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
44
- : [T, ...A]
45
-
46
16
  export interface Injectors {
47
17
  // #1 Simple class
48
- inject<T extends ClassType>(token: T): Promise<InstanceType<T>>
18
+ asyncInject<T extends ClassType>(
19
+ token: T,
20
+ ): InstanceType<T> extends Factorable<infer R>
21
+ ? Promise<R>
22
+ : Promise<InstanceType<T>>
49
23
  // #2 Token with required Schema
50
- inject<T, S extends InjectionTokenSchemaType>(
24
+ asyncInject<T, S extends InjectionTokenSchemaType>(
51
25
  token: InjectionToken<T, S>,
52
26
  args: z.input<S>,
53
27
  ): Promise<T>
54
28
  // #3 Token with optional Schema
55
- inject<T, S extends InjectionTokenSchemaType, R extends boolean>(
29
+ asyncInject<T, S extends InjectionTokenSchemaType, R extends boolean>(
56
30
  token: InjectionToken<T, S, R>,
57
31
  ): R extends false
58
32
  ? Promise<T>
@@ -63,17 +37,19 @@ export interface Injectors {
63
37
  >}`
64
38
  : 'Error: Your token requires args'
65
39
  // #4 Token with no Schema
66
- inject<T>(token: InjectionToken<T, undefined>): Promise<T>
67
- inject<T>(token: BoundInjectionToken<T, any>): Promise<T>
68
- inject<T>(token: FactoryInjectionToken<T, any>): Promise<T>
40
+ asyncInject<T>(token: InjectionToken<T, undefined>): Promise<T>
41
+ asyncInject<T>(token: BoundInjectionToken<T, any>): Promise<T>
42
+ asyncInject<T>(token: FactoryInjectionToken<T, any>): Promise<T>
69
43
 
70
- syncInject<T extends ClassType>(token: T): InstanceType<T>
71
- syncInject<T, S extends InjectionTokenSchemaType>(
44
+ inject<T extends ClassType>(
45
+ token: T,
46
+ ): InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>
47
+ inject<T, S extends InjectionTokenSchemaType>(
72
48
  token: InjectionToken<T, S>,
73
49
  args: z.input<S>,
74
50
  ): T
75
51
  // #3 Token with optional Schema
76
- syncInject<T, S extends InjectionTokenSchemaType, R extends boolean>(
52
+ inject<T, S extends InjectionTokenSchemaType, R extends boolean>(
77
53
  token: InjectionToken<T, S, R>,
78
54
  ): R extends false
79
55
  ? T
@@ -83,38 +59,40 @@ export interface Injectors {
83
59
  ', '
84
60
  >}`
85
61
  : 'Error: Your token requires args'
86
- syncInject<T>(token: InjectionToken<T, undefined>): T
87
- syncInject<T>(token: BoundInjectionToken<T, any>): T
88
- syncInject<T>(token: FactoryInjectionToken<T, any>): T
62
+ inject<T>(token: InjectionToken<T, undefined>): T
63
+ inject<T>(token: BoundInjectionToken<T, any>): T
64
+ inject<T>(token: FactoryInjectionToken<T, any>): T
89
65
 
90
- wrapSyncInit(cb: () => any): () => [any, Promise<any>[]]
66
+ wrapSyncInit(
67
+ cb: () => any,
68
+ ): (injectState?: InjectState) => [any, Promise<any>[], InjectState]
91
69
 
92
- provideServiceLocator(locator: ServiceLocator): ServiceLocator
70
+ provideFactoryContext(context: FactoryContext | null): FactoryContext | null
93
71
  }
94
72
 
95
- export const InjectorsBase = new Map<ServiceLocator, Injectors>()
73
+ export function getInjectors() {
74
+ let currentFactoryContext: FactoryContext | null = null
96
75
 
97
- export function getInjectors({ baseLocator }: CreateInjectorsOptions) {
98
- if (InjectorsBase.has(baseLocator)) {
99
- return InjectorsBase.get(baseLocator)!
76
+ function provideFactoryContext(
77
+ context: FactoryContext,
78
+ ): FactoryContext | null {
79
+ const original = currentFactoryContext
80
+ currentFactoryContext = context
81
+ return original
100
82
  }
101
- let currentLocator: ServiceLocator = baseLocator
102
-
103
- function getServiceLocator() {
104
- if (!currentLocator) {
83
+ function getFactoryContext(): FactoryContext {
84
+ if (!currentFactoryContext) {
105
85
  throw new Error(
106
- '[Injector] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator.',
86
+ '[Injector] Trying to access injection context outside of a injectable context',
107
87
  )
108
88
  }
109
- return currentLocator
110
- }
111
- function provideServiceLocator(locator: ServiceLocator): ServiceLocator {
112
- const original = currentLocator
113
- currentLocator = locator
114
- return original
89
+ return currentFactoryContext
115
90
  }
116
91
 
117
- function inject(
92
+ let promiseCollector: null | ((promise: Promise<any>) => void) = null
93
+ let injectState: InjectState | null = null
94
+
95
+ function asyncInject(
118
96
  token:
119
97
  | ClassType
120
98
  | InjectionToken<any>
@@ -122,43 +100,79 @@ export function getInjectors({ baseLocator }: CreateInjectorsOptions) {
122
100
  | FactoryInjectionToken<any, any>,
123
101
  args?: unknown,
124
102
  ) {
125
- // @ts-expect-error In case we have a class
126
- const realToken = token[InjectableTokenMeta] ?? token
103
+ if (!injectState) {
104
+ throw new Error(
105
+ '[Injector] Trying to access inject outside of a injectable context',
106
+ )
107
+ }
108
+ if (injectState.isFrozen) {
109
+ const idx = injectState.currentIndex++
110
+ const request = injectState.requests[idx]
111
+ if (request.token !== token) {
112
+ throw new Error(
113
+ `[Injector] Wrong token order. Expected ${request.token.toString()} but got ${token.toString()}`,
114
+ )
115
+ }
116
+ return request.promise
117
+ }
127
118
 
128
- // @ts-expect-error We check the type in overload
129
- return getServiceLocator().getOrThrowInstance(realToken, args)
130
- }
119
+ const promise = getFactoryContext().inject(token as any, args as any)
120
+ injectState.requests.push({
121
+ token,
122
+ promise,
123
+ })
124
+ injectState.currentIndex++
131
125
 
132
- let promiseCollector: null | ((promise: Promise<any>) => void) = null
126
+ return promise
127
+ }
133
128
 
134
129
  function wrapSyncInit(cb: () => any) {
135
- return () => {
130
+ return (previousState?: InjectState) => {
136
131
  const promises: Promise<any>[] = []
137
132
  const originalPromiseCollector = promiseCollector
133
+ const originalInjectState = injectState
134
+ injectState = previousState
135
+ ? {
136
+ ...previousState,
137
+ currentIndex: 0,
138
+ }
139
+ : {
140
+ currentIndex: 0,
141
+ isFrozen: false,
142
+ requests: [],
143
+ }
138
144
  promiseCollector = (promise) => {
139
145
  promises.push(promise)
140
146
  }
141
147
  const result = cb()
142
148
  promiseCollector = originalPromiseCollector
143
- return [result, promises]
149
+ const newInjectState = {
150
+ ...injectState,
151
+ isFrozen: true,
152
+ }
153
+ injectState = originalInjectState
154
+ return [result, promises, newInjectState]
144
155
  }
145
156
  }
146
157
 
147
- function syncInject<
158
+ function inject<
148
159
  T,
149
160
  Token extends
150
161
  | InjectionToken<T>
151
162
  | BoundInjectionToken<T, any>
152
163
  | FactoryInjectionToken<T, any>,
153
- S extends ZodObject<any> | unknown = Token['schema'],
154
- >(token: Token, args?: S extends ZodObject<any> ? z.input<S> : never): T {
164
+ S extends ZodObject | unknown = Token['schema'],
165
+ >(token: Token, args?: S extends ZodObject ? z.input<S> : never): T {
155
166
  // @ts-expect-error In case we have a class
156
167
  const realToken = token[InjectableTokenMeta] ?? token
157
168
 
158
- const instance = getServiceLocator().getSyncInstance(realToken, args)
169
+ const instance = getFactoryContext().locator.getSyncInstance(
170
+ realToken,
171
+ args,
172
+ )
159
173
  if (!instance) {
160
174
  if (promiseCollector) {
161
- const promise = getServiceLocator().getInstance(realToken, args)
175
+ const promise = getFactoryContext().inject(realToken, args)
162
176
  promiseCollector(promise)
163
177
  } else {
164
178
  throw new Error(`[Injector] Cannot initiate ${realToken.toString()}`)
@@ -168,7 +182,7 @@ export function getInjectors({ baseLocator }: CreateInjectorsOptions) {
168
182
  {
169
183
  get() {
170
184
  throw new Error(
171
- `[Injector] Trying to access ${realToken.toString()} before it's initialized, please use inject() instead of syncInject() or do not use the value outside of class methods`,
185
+ `[Injector] Trying to access ${realToken.toString()} before it's initialized, please use asyncInject() instead of inject() or do not use the value outside of class methods`,
172
186
  )
173
187
  },
174
188
  },
@@ -178,12 +192,11 @@ export function getInjectors({ baseLocator }: CreateInjectorsOptions) {
178
192
  }
179
193
 
180
194
  const injectors: Injectors = {
195
+ asyncInject,
181
196
  inject,
182
- syncInject,
183
197
  wrapSyncInit,
184
- provideServiceLocator,
198
+ provideFactoryContext,
185
199
  } as Injectors
186
- InjectorsBase.set(baseLocator, injectors)
187
200
 
188
201
  return injectors
189
202
  }
@@ -1,2 +1,4 @@
1
1
  export * from './get-injectors.mjs'
2
2
  export * from './get-injectable-token.mjs'
3
+ export * from './defer.mjs'
4
+ export * from './types.mjs'
@@ -0,0 +1,52 @@
1
+ import type {
2
+ BoundInjectionToken,
3
+ ClassType,
4
+ FactoryInjectionToken,
5
+ InjectionToken,
6
+ } from '../injection-token.mjs'
7
+
8
+ // Utility types for string manipulation and union handling
9
+ export type Join<TElements, TSeparator extends string> =
10
+ TElements extends Readonly<[infer First, ...infer Rest]>
11
+ ? Rest extends ReadonlyArray<string>
12
+ ? First extends string
13
+ ? `${First}${Rest extends [] ? '' : TSeparator}${Join<Rest, TSeparator>}`
14
+ : never
15
+ : never
16
+ : ''
17
+
18
+ // credits goes to https://stackoverflow.com/a/50375286
19
+ export type UnionToIntersection<U> = (
20
+ U extends any ? (k: U) => void : never
21
+ ) extends (k: infer I) => void
22
+ ? I
23
+ : never
24
+
25
+ // Converts union to overloaded function
26
+ export type UnionToOvlds<U> = UnionToIntersection<
27
+ U extends any ? (f: U) => void : never
28
+ >
29
+
30
+ export type PopUnion<U> =
31
+ UnionToOvlds<U> extends (a: infer A) => void ? A : never
32
+
33
+ export type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true
34
+
35
+ export type UnionToArray<T, A extends unknown[] = []> =
36
+ IsUnion<T> extends true
37
+ ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
38
+ : [T, ...A]
39
+
40
+ // InjectState interface for managing injection state
41
+ export interface InjectState {
42
+ currentIndex: number
43
+ isFrozen: boolean
44
+ requests: {
45
+ token:
46
+ | InjectionToken<any>
47
+ | BoundInjectionToken<any, any>
48
+ | FactoryInjectionToken<any, any>
49
+ | ClassType
50
+ promise: Promise<any>
51
+ }[]
52
+ }
@@ -1,182 +0,0 @@
1
- # @Injectable decorator
2
-
3
- The `@Injectable` decorator is used to define a class or a factory class as an injectable service.
4
-
5
- ## Parameters
6
-
7
- The `@Injectable` decorator accepts the following fields in its options:
8
-
9
- - `token`: The injection token to use for the service. If not provided, will create a new token using the class itself.
10
- - `scope`: The lifetime of the service. Accepts `InjectableScope.Singleton` or `InjectableScope.Instance`. By default, it will be `InjectableScope.Singleton`.
11
- - `type`: The type of the service. Accepts `InjectableType.Class` or `InjectableType.Factory`. By default, it will be `InjectableType.Class`.
12
- - `registry`: The registry to use for the service. Uses the default registry if not provided.
13
-
14
- ## Usage
15
-
16
- Injectable can be used as a class decorator or a factory decorator.
17
-
18
- Inside a class that you're decorating with `@Injectable` you can use `inject` and `syncInject` functions to inject the services.
19
-
20
- ```ts
21
- @Injectable()
22
- class GreeterService {
23
- sayHello(name: string) {
24
- return `Hello ${name}`
25
- }
26
- }
27
-
28
- @Injectable()
29
- class UserService {
30
- private readonly greeterService = syncInject(GreeterService)
31
-
32
- makeGreeting(name: string) {
33
- return this.greeterService.sayHello(name)
34
- }
35
- }
36
- ```
37
-
38
- Please note that `syncInject` can be used only with services that are created with `InjectableScope.Singleton`.
39
-
40
- If you need to inject a service that is created with `InjectableScope.Instance`, you can use `inject` function. and it will return a Promise.
41
-
42
- For example:
43
-
44
- ```ts
45
- @Injectable({ scope: InjectableScope.Instance })
46
- class GreeterService {
47
- private readonly createdAt = new Date()
48
-
49
- sayHello(name: string) {
50
- return `Hello ${name} ${this.createdAt.toISOString()}`
51
- }
52
- }
53
-
54
- @Injectable()
55
- class UserService {
56
- private readonly greeterService = inject(GreeterService)
57
-
58
- async makeGreeting(name: string) {
59
- const service = await this.greeterService
60
- return service.sayHello(name)
61
- }
62
- }
63
- ```
64
-
65
- ## Examples
66
-
67
- ### Simple class
68
-
69
- ```ts
70
- @Injectable()
71
- class GreeterService {
72
- sayHello(name: string) {
73
- return `Hello ${name}`
74
- }
75
- }
76
-
77
- const greeterService = await inject(GreeterService)
78
- console.log(greeterService.sayHello('John'))
79
- ```
80
-
81
- ### Simple Factory
82
-
83
- ```ts
84
- @Injectable({ type: InjectableType.Factory })
85
- class GreeterServiceFactory {
86
- create() {
87
- return new GreeterService()
88
- }
89
- }
90
-
91
- const greeterService = await inject(GreeterServiceFactory)
92
- console.log(greeterService.sayHello('John'))
93
- ```
94
-
95
- ### Class with token
96
-
97
- ```ts
98
- export interface GreeterServiceInterface {
99
- sayHello(name: string): string
100
- }
101
-
102
- const GreeterServiceParams = z.object({
103
- context: z.string(),
104
- })
105
-
106
- export const GREETER_SERVICE = InjectionToken.create<
107
- GreeterServiceInterface,
108
- typeof GreeterServiceParams
109
- >('GreeterService', GreeterServiceParams)
110
-
111
- @Injectable({ token: GREETER_SERVICE })
112
- class GreeterService {
113
- constructor(private readonly config: z.infer<typeof GreeterServiceParams>) {}
114
-
115
- sayHello(name: string) {
116
- return `Hello ${name} ${this.config.context}`
117
- }
118
- }
119
-
120
- const greeterService = await inject(GREETER_SERVICE, { context: 'World' })
121
- console.log(greeterService.sayHello('John'))
122
- ```
123
-
124
- ### Factory with token
125
-
126
- ```ts
127
- export interface GreeterServiceInterface {
128
- sayHello(name: string): string
129
- }
130
-
131
- const GreeterServiceParams = z.object({
132
- context: z.string(),
133
- })
134
-
135
- export const GREETER_SERVICE = InjectionToken.create<
136
- GreeterServiceInterface,
137
- typeof GreeterServiceParams
138
- >('GreeterService', GreeterServiceParams)
139
-
140
- @Injectable({ type: InjectableType.Factory, token: GREETER_SERVICE })
141
- class GreeterServiceFactory {
142
- create(ctx: FactoryContext, args: z.infer<typeof GreeterServiceParams>) {
143
- return new GreeterService(args)
144
- }
145
- }
146
-
147
- const greeterService = await inject(GREETER_SERVICE, { context: 'World' })
148
- console.log(greeterService.sayHello('John'))
149
- ```
150
-
151
- ## InjectableScope
152
-
153
- The `InjectableScope` enum defines the scope of the service.
154
-
155
- - `InjectableScope.Singleton`: The service will be created once and reused.
156
- - `InjectableScope.Instance`: The service will be created every time it is injected.
157
-
158
- ## InjectableType
159
-
160
- The `InjectableType` enum defines the type of the service.
161
-
162
- - `InjectableType.Class`: The service will be a class.
163
- - `InjectableType.Factory`: The service will be a factory.
164
-
165
- ## Registry
166
-
167
- The `Registry` is the registry of the service. It is used to store the service and its dependencies.
168
-
169
- ## FactoryContext
170
-
171
- The `FactoryContext` is the context of the factory. It is used to add additional information to the factory.
172
-
173
- Context API:
174
-
175
- - `inject`: Injects the service, same as global inject, but additionally it will track the dependencies of the service.
176
- - `on`: Adds a listener to the service locator event bus.
177
- - `getDependencies`: Returns the dependencies of the service.
178
- - `invalidate`: Invalidates self and all the services that depend on it.
179
- - `addEffect`: Adds an effect to the service. Effect is a function that will be called when the service is invalidated.
180
- - `setTtl`: Sets the ttl of the service.
181
- - `getTtl`: Returns the ttl of the service.
182
- - `locator`: Returns the service locator you are currently in.