@travetto/di 2.1.5 → 2.2.2

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.
package/README.md CHANGED
@@ -8,10 +8,10 @@
8
8
  npm install @travetto/di
9
9
  ```
10
10
 
11
- [Dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) is a framework primitive. When used in conjunction with automatic file scanning, it provides for handling of application dependency wiring. Due to the nature of [Typescript](https://typescriptlang.org) and type erasure of interfaces, dependency injection only supports `class`es as type signafiers. The primary goal of dependency injection is to allow for separation of concerns of object creation and it's usage.
11
+ [Dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) is a framework primitive. When used in conjunction with automatic file scanning, it provides for handling of application dependency wiring. Due to the nature of [Typescript](https://typescriptlang.org) and type erasure of interfaces, dependency injection only supports `class`es as a type signifier. The primary goal of dependency injection is to allow for separation of concerns of object creation and it's usage.
12
12
 
13
13
  ## Declaration
14
- The [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L30) and [@InjectableFactory](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L72) decorators provide the registration of dependencies. Dependency declaration revolves around exposing `class`es and subtypes thereof to provide necessary functionality. Additionally, the framework will utilize dependencies to satisfy contracts with various implementations (e.g. [MongoModelService](https://github.com/travetto/travetto/tree/main/module/model-mongo/src/service.ts#L44) provides itself as an injectable candidate for [ModelCrudSupport](https://github.com/travetto/travetto/tree/main/module/model/src/service/crud.ts).
14
+ The [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L32) and [@InjectableFactory](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L75) decorators provide the registration of dependencies. Dependency declaration revolves around exposing `class`es and subtypes thereof to provide necessary functionality. Additionally, the framework will utilize dependencies to satisfy contracts with various implementations (e.g. [MongoModelService](https://github.com/travetto/travetto/tree/main/module/model-mongo/src/service.ts#L49) provides itself as an injectable candidate for [ModelCrudSupport](https://github.com/travetto/travetto/tree/main/module/model/src/service/crud.ts).
15
15
 
16
16
  **Code: Example Injectable**
17
17
  ```typescript
@@ -72,7 +72,7 @@ class SpecificService extends BaseService {
72
72
  }
73
73
  ```
74
74
 
75
- In this scenario, `SpecificService` is a valid candidate for `BaseService` due to the abstract inheritance. Sometimes, you may want to provide a slight variation to a dependency without extending a class. To this end, the [@InjectableFactory](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L72) decorator denotes a `static` class method that produces an [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L30).
75
+ In this scenario, `SpecificService` is a valid candidate for `BaseService` due to the abstract inheritance. Sometimes, you may want to provide a slight variation to a dependency without extending a class. To this end, the [@InjectableFactory](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L75) decorator denotes a `static` class method that produces an [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L32).
76
76
 
77
77
  **Code: Example InjectableFactory**
78
78
  ```typescript
@@ -93,15 +93,15 @@ class Config {
93
93
 
94
94
  Given the `static` method `initService`, the function will be provided as a valid candidate for `CoolService`. Instead of calling the constructor of the type directly, this function will work as a factory for producing the injectable.
95
95
 
96
- **Note**: Other modules are able to provide aliases to [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L30) that also provide additional functionality. For example, the [@Config](https://github.com/travetto/travetto/tree/main/module/config/src/decorator.ts#L9) or the [@Controller](https://github.com/travetto/travetto/tree/main/module/rest/src/decorator/controller.ts#L9) decorator registers the associated class as an injectable element.
96
+ **Note**: Other modules are able to provide aliases to [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L32) that also provide additional functionality. For example, the [@Config](https://github.com/travetto/travetto/tree/main/module/config/src/decorator.ts#L9) or the [@Controller](https://github.com/travetto/travetto/tree/main/module/rest/src/decorator/controller.ts#L9) decorator registers the associated class as an injectable element.
97
97
 
98
98
  ## Injection
99
99
 
100
- Once all of your necessary dependencies are defined, now is the time to provide those [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L30) instances to your code. There are three primary methods for injection:
100
+ Once all of your necessary dependencies are defined, now is the time to provide those [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L32) instances to your code. There are three primary methods for injection:
101
101
 
102
- The [@Inject](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L30) decorator, which denotes a desire to inject a value directly. These will be set post construction.
102
+ The [@Inject](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L32) decorator, which denotes a desire to inject a value directly. These will be set post construction.
103
103
 
104
- **Code: Example Injectable with dependencies as [@Inject](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L30) fields**
104
+ **Code: Example Injectable with dependencies as [@Inject](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L32) fields**
105
105
  ```typescript
106
106
  import { Injectable, Inject } from '@travetto/di';
107
107
  import { DependentService } from './dep';
@@ -117,7 +117,7 @@ class CustomService {
117
117
  }
118
118
  ```
119
119
 
120
- The [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L30) constructor params, which will be provided as the instance is being constructed.
120
+ The [@Injectable](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L32) constructor params, which will be provided as the instance is being constructed.
121
121
 
122
122
  **Code: Example Injectable with dependencies in constructor**
123
123
  ```typescript
@@ -134,7 +134,7 @@ class CustomService {
134
134
  }
135
135
  ```
136
136
 
137
- Via [@InjectableFactory](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L72) params, which are comparable to constructor params
137
+ Via [@InjectableFactory](https://github.com/travetto/travetto/tree/main/module/di/src/decorator.ts#L75) params, which are comparable to constructor params
138
138
 
139
139
  **Code: Example InjectableFactory with parameters as dependencies**
140
140
  ```typescript
@@ -154,7 +154,7 @@ class Config {
154
154
 
155
155
  If you are building modules for others to consume, often times it is possible to end up with multiple implementations for the same class.
156
156
 
157
- **Code: Example Multiple Candiate Types**
157
+ **Code: Example Multiple Candidate Types**
158
158
  ```typescript
159
159
  import { Injectable, Inject } from '@travetto/di';
160
160
 
@@ -178,7 +178,7 @@ class ContractConsumer {
178
178
 
179
179
  By default, if there is only one candidate without qualification, then that candidate will be used. If multiple candidates are found, then the injection system will bail. To overcome this the end user will need to specify which candidate type should be considered `primary`:
180
180
 
181
- **Code: Example Multiple Candiate Types**
181
+ **Code: Example Multiple Candidate Types**
182
182
  ```typescript
183
183
  import { InjectableFactory } from '@travetto/di';
184
184
  import { Contract, ComplexContract } from './injectable-multiple-default';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@travetto/di",
3
3
  "displayName": "Dependency Injection",
4
- "version": "2.1.5",
4
+ "version": "2.2.2",
5
5
  "description": "Dependency registration/management and injection support.",
6
6
  "keywords": [
7
7
  "ast-transformations",
@@ -29,12 +29,12 @@
29
29
  "directory": "module/di"
30
30
  },
31
31
  "dependencies": {
32
- "@travetto/transformer": "^2.1.4",
33
- "@travetto/registry": "^2.1.5"
32
+ "@travetto/transformer": "^2.2.2",
33
+ "@travetto/registry": "^2.2.2"
34
34
  },
35
35
  "devDependencies": {
36
- "@travetto/config": "^2.1.5",
37
- "@travetto/schema": "^2.1.5"
36
+ "@travetto/config": "^2.2.2",
37
+ "@travetto/schema": "^2.2.2"
38
38
  },
39
39
  "docDependencies": {
40
40
  "@travetto/model-mongo": true,
package/src/decorator.ts CHANGED
@@ -4,7 +4,8 @@ import { MethodDescriptor } from '@travetto/base/src/internal/types';
4
4
  import { InjectableFactoryConfig, InjectableConfig, Dependency } from './types';
5
5
  import { DependencyRegistry, ResolutionType } from './registry';
6
6
 
7
- function collapseConfig<T extends { qualifier?: symbol }>(...args: (symbol | Partial<InjectConfig> | undefined)[]) {
7
+ function collapseConfig<T extends { qualifier?: symbol }>(...args: (symbol | Partial<InjectConfig> | undefined)[]): T {
8
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8
9
  let out = {} as T;
9
10
  if (args) {
10
11
  if (Array.isArray(args)) {
@@ -16,6 +17,7 @@ function collapseConfig<T extends { qualifier?: symbol }>(...args: (symbol | Par
16
17
  }
17
18
  }
18
19
  } else {
20
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
19
21
  out = args as T;
20
22
  }
21
23
  }
@@ -28,10 +30,11 @@ function collapseConfig<T extends { qualifier?: symbol }>(...args: (symbol | Par
28
30
  * @augments `@trv:di/Injectable`
29
31
  */
30
32
  export function Injectable(first?: Partial<InjectableConfig> | symbol, ...args: (Partial<InjectableConfig> | undefined)[]) {
31
- return <T extends Class>(target: T) => {
32
- const config = collapseConfig(first, ...args) as Partial<InjectableConfig>;
33
+ return <T extends Class>(target: T): T => {
34
+ const config = collapseConfig<Partial<InjectableConfig>>(first, ...args);
33
35
 
34
36
  config.class = target;
37
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
35
38
  DependencyRegistry.registerClass(target, config as InjectableConfig);
36
39
  return target;
37
40
  };
@@ -40,7 +43,7 @@ export function Injectable(first?: Partial<InjectableConfig> | symbol, ...args:
40
43
  export type InjectConfig = { qualifier?: symbol, optional?: boolean, resolution?: ResolutionType };
41
44
 
42
45
  export function InjectArgs(configs?: InjectConfig[][]) {
43
- return <T extends Class>(target: T) => {
46
+ return <T extends Class>(target: T): void => {
44
47
  DependencyRegistry.registerConstructor(target,
45
48
  configs?.map(x => collapseConfig(...x)));
46
49
  };
@@ -52,14 +55,14 @@ export function InjectArgs(configs?: InjectConfig[][]) {
52
55
  * @augments `@trv:di/Inject`
53
56
  */
54
57
  export function Inject(first?: InjectConfig | symbol, ...args: (InjectConfig | undefined)[]) {
55
- return (target: unknown, propertyKey: string | symbol, idx?: number | PropertyDescriptor) => {
58
+ return (target: unknown, propertyKey: string | symbol, idx?: number | PropertyDescriptor): void => {
56
59
  if (typeof idx !== 'number') { // Only register if on property
57
60
  const config: InjectConfig = collapseConfig(first, ...args);
58
61
 
59
62
  DependencyRegistry.registerProperty(
60
- (target as ClassInstance).constructor,
61
- propertyKey as string,
62
- config as Dependency);
63
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
64
+ (target as ClassInstance).constructor, propertyKey as string, config as Dependency
65
+ );
63
66
  }
64
67
  };
65
68
  }
@@ -70,7 +73,7 @@ export function Inject(first?: InjectConfig | symbol, ...args: (InjectConfig | u
70
73
  * @augments `@trv:di/InjectableFactory`
71
74
  */
72
75
  export function InjectableFactory(first?: Partial<InjectableFactoryConfig> | symbol, ...args: (Partial<InjectableFactoryConfig> | undefined)[]) {
73
- return <T extends Class>(target: T, property: string | symbol, descriptor: MethodDescriptor) => {
76
+ return <T extends Class>(target: T, property: string | symbol, descriptor: MethodDescriptor): void => {
74
77
  const config: InjectableFactoryConfig = collapseConfig(first, ...args);
75
78
  DependencyRegistry.registerFactory({
76
79
  ...config,
package/src/error.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AppError } from '@travetto/base';
2
2
  import { ClassTarget } from './types';
3
3
 
4
- function getName(symbol: symbol) {
4
+ function getName(symbol: symbol): string {
5
5
  return symbol.toString().split(/[()]/g)[1];
6
6
  }
7
7
 
package/src/registry.ts CHANGED
@@ -14,10 +14,12 @@ export type ResolutionType = 'strict' | 'loose' | 'any';
14
14
  const PrimaryCandidateⲐ = Symbol.for('@trv:di/primary');
15
15
 
16
16
  function hasPostConstruct(o: unknown): o is { postConstruct: () => Promise<unknown> } {
17
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
17
18
  return !!o && !!(o as Record<string, unknown>)['postConstruct'];
18
19
  }
19
20
 
20
21
  function hasPreDestroy(o: unknown): o is { preDestroy: () => unknown } {
22
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
21
23
  return !!o && !!(o as Record<string, unknown>)['preDestroy'];
22
24
  }
23
25
 
@@ -67,7 +69,10 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
67
69
  qualifier = filtered[0];
68
70
  } else if (filtered.length > 1) {
69
71
  // If dealing with sub types, prioritize exact matches
70
- const exact = this.getCandidateTypes(target as Class).filter(x => x.class === target);
72
+ const exact = this
73
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
74
+ .getCandidateTypes(target as Class)
75
+ .filter(x => x.class === target);
71
76
  if (exact.length === 1) {
72
77
  qualifier = exact[0].qualifier;
73
78
  } else {
@@ -94,6 +99,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
94
99
  }
95
100
  }
96
101
 
102
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
97
103
  const config = this.get(cls!) as InjectableConfig<T>;
98
104
  return {
99
105
  qualifier,
@@ -105,7 +111,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
105
111
  /**
106
112
  * Retrieve all dependencies
107
113
  */
108
- protected async fetchDependencies(managed: InjectableConfig, deps?: Dependency[]) {
114
+ protected async fetchDependencies(managed: InjectableConfig, deps?: Dependency[]): Promise<unknown[]> {
109
115
  if (!deps || !deps.length) {
110
116
  return [];
111
117
  }
@@ -113,12 +119,15 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
113
119
  const promises = deps.map(async x => {
114
120
  try {
115
121
  return await this.getInstance(x.target, x.qualifier, x.resolution);
116
- } catch (e) {
117
- if (x.optional && e instanceof InjectionError && e.category === 'notfound') {
122
+ } catch (err) {
123
+ if (!err || !(err instanceof Error)) {
124
+ throw err;
125
+ }
126
+ if (x.optional && err instanceof InjectionError && err.category === 'notfound') {
118
127
  return undefined;
119
128
  } else {
120
- e.message = `${e.message} via=${managed.class.ᚕid}`;
121
- throw e;
129
+ err.message = `${err.message} via=${managed.class.ᚕid}`;
130
+ throw err;
122
131
  }
123
132
  }
124
133
  });
@@ -129,14 +138,16 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
129
138
  /**
130
139
  * Resolve all field dependencies
131
140
  */
132
- protected async resolveFieldDependencies<T>(config: InjectableConfig<T>, instance: T) {
141
+ protected async resolveFieldDependencies<T>(config: InjectableConfig<T>, instance: T): Promise<void> {
133
142
  const keys = Object.keys(config.dependencies.fields ?? {})
143
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
134
144
  .filter(k => instance[k as keyof T] === undefined); // Filter out already set ones
135
145
 
136
146
  // And auto-wire
137
147
  if (keys.length) {
138
148
  const deps = await this.fetchDependencies(config, keys.map(x => config.dependencies.fields[x]));
139
149
  for (let i = 0; i < keys.length; i++) {
150
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
140
151
  instance[keys[i] as keyof T] = deps[i] as T[keyof T];
141
152
  }
142
153
  }
@@ -154,6 +165,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
154
165
  // Create instance
155
166
  const inst = managed.factory ?
156
167
  managed.factory(...consValues) :
168
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
157
169
  new (managed.class as ConcreteClass<T>)(...consValues);
158
170
 
159
171
  // And auto-wire fields
@@ -161,6 +173,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
161
173
 
162
174
  // If factory with field properties on the sub class
163
175
  if (managed.factory) {
176
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
164
177
  const resolved = this.get((inst as ClassInstance<T>).constructor);
165
178
 
166
179
  if (resolved) {
@@ -179,7 +192,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
179
192
  /**
180
193
  * Create the instance
181
194
  */
182
- protected async createInstance<T>(target: ClassTarget<T>, qualifier: symbol) {
195
+ protected async createInstance<T>(target: ClassTarget<T>, qualifier: symbol): Promise<T> {
183
196
  const classId = this.resolveTarget(target, qualifier).id;
184
197
 
185
198
  if (!this.instances.has(classId)) {
@@ -188,7 +201,8 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
188
201
  }
189
202
 
190
203
  if (this.instancePromises.get(classId)!.has(qualifier)) {
191
- return this.instancePromises.get(classId)!.get(qualifier);
204
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
205
+ return this.instancePromises.get(classId)!.get(qualifier) as unknown as T;
192
206
  }
193
207
 
194
208
  const instancePromise = this.construct(target, qualifier);
@@ -197,17 +211,17 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
197
211
  const instance = await instancePromise;
198
212
  this.instances.get(classId)!.set(qualifier, instance);
199
213
  return instance;
200
- } catch (e) {
214
+ } catch (err) {
201
215
  // Clear it out, don't save failed constructions
202
216
  this.instancePromises.get(classId)!.delete(qualifier);
203
- throw e;
217
+ throw err;
204
218
  }
205
219
  }
206
220
 
207
221
  /**
208
222
  * Destroy an instance
209
223
  */
210
- protected destroyInstance(cls: Class, qualifier: symbol) {
224
+ protected destroyInstance(cls: Class, qualifier: symbol): void {
211
225
  const classId = cls.ᚕid;
212
226
 
213
227
  const activeInstance = this.instances.get(classId)!.get(qualifier);
@@ -225,7 +239,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
225
239
  /**
226
240
  * Handle initial installation for the entire registry
227
241
  */
228
- override initialInstall() {
242
+ override initialInstall(): Class[] {
229
243
  const finalizing = this.pendingFinalize;
230
244
  this.pendingFinalize = [];
231
245
 
@@ -233,13 +247,13 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
233
247
  this.install(cls, { type: 'added', curr: cls });
234
248
  }
235
249
 
236
- return [] as Class[];
250
+ return [];
237
251
  }
238
252
 
239
253
  /**
240
254
  * Register a cls as pending
241
255
  */
242
- createPending(cls: Class) {
256
+ createPending(cls: Class): Partial<InjectableConfig> {
243
257
  if (!this.resolved) {
244
258
  this.pendingFinalize.push(cls);
245
259
  }
@@ -265,23 +279,25 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
265
279
  if (!this.instances.has(classId) || !this.instances.get(classId)!.has(qualifier)) {
266
280
  await this.createInstance(target, qualifier); // Wait for proxy
267
281
  }
282
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
268
283
  return this.instances.get(classId)!.get(qualifier)! as T;
269
284
  }
270
285
 
271
286
  /**
272
287
  * Get all available candidate types for the target
273
288
  */
274
- getCandidateTypes<T>(target: Class<T>) {
289
+ getCandidateTypes<T>(target: Class<T>): InjectableConfig[] {
275
290
  const targetId = target.ᚕid;
276
291
  const qualifiers = this.targetToClass.get(targetId)!;
277
292
  const uniqueQualifiers = qualifiers ? Array.from(new Set(qualifiers.values())) : [];
293
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
278
294
  return uniqueQualifiers.map(id => this.get(id)! as InjectableConfig<T>);
279
295
  }
280
296
 
281
297
  /**
282
298
  * Register a constructor with dependencies
283
299
  */
284
- registerConstructor<T>(cls: Class<T>, dependencies?: Dependency[]) {
300
+ registerConstructor<T>(cls: Class<T>, dependencies?: Dependency[]): void {
285
301
  const conf = this.getOrCreatePending(cls);
286
302
  conf.dependencies!.cons = dependencies;
287
303
  }
@@ -289,7 +305,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
289
305
  /**
290
306
  * Register a property as a dependency
291
307
  */
292
- registerProperty<T>(cls: Class<T>, field: string, dependency: Dependency) {
308
+ registerProperty<T>(cls: Class<T>, field: string, dependency: Dependency): void {
293
309
  const conf = this.getOrCreatePending(cls);
294
310
  conf.dependencies!.fields[field] = dependency;
295
311
  }
@@ -297,27 +313,28 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
297
313
  /**
298
314
  * Register a class
299
315
  */
300
- registerClass<T>(cls: Class<T>, pconfig: Partial<InjectableConfig<T>> = {}) {
301
- const config = this.getOrCreatePending(pconfig.class ?? cls);
316
+ registerClass<T>(cls: Class<T>, pConfig: Partial<InjectableConfig<T>> = {}): void {
317
+ const config = this.getOrCreatePending(pConfig.class ?? cls);
302
318
 
303
319
  config.class = cls;
304
- config.qualifier = pconfig.qualifier ?? config.qualifier ?? Symbol.for(cls.ᚕid);
305
- if (pconfig.interfaces) {
306
- config.interfaces?.push(...pconfig.interfaces);
320
+ config.qualifier = pConfig.qualifier ?? config.qualifier ?? Symbol.for(cls.ᚕid);
321
+ if (pConfig.interfaces) {
322
+ config.interfaces?.push(...pConfig.interfaces);
307
323
  }
308
- if (pconfig.primary !== undefined) {
309
- config.primary = pconfig.primary;
324
+ if (pConfig.primary !== undefined) {
325
+ config.primary = pConfig.primary;
310
326
  }
311
- if (pconfig.factory) {
312
- config.factory = pconfig.factory ?? config.factory;
327
+ if (pConfig.factory) {
328
+ config.factory = pConfig.factory ?? config.factory;
313
329
  }
314
- if (pconfig.target) {
315
- config.target = pconfig.target;
330
+ if (pConfig.target) {
331
+ config.target = pConfig.target;
316
332
  }
317
- if (pconfig.dependencies) {
333
+ if (pConfig.dependencies) {
318
334
  config.dependencies = {
319
335
  fields: {},
320
- ...pconfig.dependencies as Omit<InjectableConfig['dependencies'], 'fields'>
336
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
337
+ ...pConfig.dependencies as Omit<InjectableConfig['dependencies'], 'fields'>
321
338
  };
322
339
  }
323
340
  }
@@ -329,7 +346,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
329
346
  id: string;
330
347
  qualifier?: undefined | symbol;
331
348
  fn: (...args: unknown[]) => unknown;
332
- }) {
349
+ }): void {
333
350
  const finalConfig: Partial<InjectableConfig> = {};
334
351
 
335
352
  finalConfig.factory = config.fn;
@@ -349,6 +366,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
349
366
  }
350
367
 
351
368
  // Create mock cls for DI purposes
369
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
352
370
  const cls = { ᚕid: config.id } as Class;
353
371
 
354
372
  finalConfig.class = cls;
@@ -359,13 +377,14 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
359
377
  this.factories.set(config.src.ᚕid, new Map());
360
378
  }
361
379
 
380
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
362
381
  this.factories.get(config.src.ᚕid)!.set(cls, finalConfig as InjectableConfig);
363
382
  }
364
383
 
365
384
  /**
366
385
  * On Install event
367
386
  */
368
- override onInstall<T>(cls: Class<T>, e: ChangeEvent<Class<T>>) {
387
+ override onInstall<T>(cls: Class<T>, e: ChangeEvent<Class<T>>): void {
369
388
  super.onInstall(cls, e);
370
389
 
371
390
  // Install factories separate from classes
@@ -379,9 +398,10 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
379
398
  /**
380
399
  * Handle installing a class
381
400
  */
382
- onInstallFinalize<T>(cls: Class<T>) {
401
+ onInstallFinalize<T>(cls: Class<T>): InjectableConfig<T> {
383
402
  const classId = cls.ᚕid;
384
403
 
404
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
385
405
  const config = this.getOrCreatePending(cls) as InjectableConfig<T>;
386
406
 
387
407
  // Allow for the factory to fulfill the target
@@ -475,11 +495,11 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
475
495
 
476
496
  // Register primary if only one interface provided and no parent config
477
497
  if (config.interfaces.length === 1 && !parentConfig) {
478
- const [intf] = config.interfaces;
479
- if (!this.targetToClass.has(intf.ᚕid)) {
480
- this.targetToClass.set(intf.ᚕid, new Map());
498
+ const [primaryInterface] = config.interfaces;
499
+ if (!this.targetToClass.has(primaryInterface.ᚕid)) {
500
+ this.targetToClass.set(primaryInterface.ᚕid, new Map());
481
501
  }
482
- this.targetToClass.get(intf.ᚕid)!.set(PrimaryCandidateⲐ, classId);
502
+ this.targetToClass.get(primaryInterface.ᚕid)!.set(PrimaryCandidateⲐ, classId);
483
503
  }
484
504
  }
485
505
 
@@ -489,7 +509,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
489
509
  /**
490
510
  * Handle uninstalling a class
491
511
  */
492
- override onUninstallFinalize(cls: Class) {
512
+ override onUninstallFinalize(cls: Class): void {
493
513
  const classId = cls.ᚕid;
494
514
 
495
515
  if (!this.classToTarget.has(cls.ᚕid)) {
@@ -506,7 +526,7 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
506
526
  /**
507
527
  * Reset registry
508
528
  */
509
- override onReset() {
529
+ override onReset(): void {
510
530
  super.onReset();
511
531
  this.pendingFinalize = [];
512
532
  this.instances.clear();
@@ -519,7 +539,8 @@ class $DependencyRegistry extends MetadataRegistry<InjectableConfig> {
519
539
  /**
520
540
  * Inject fields into instance
521
541
  */
522
- async injectFields<T extends { constructor: Class<T> }>(o: T, cls = o.constructor as Class<T>) {
542
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
543
+ async injectFields<T extends { constructor: Class<T> }>(o: T, cls = o.constructor as Class<T>): Promise<void> {
523
544
  this.verifyInitialized();
524
545
  // Compute fields to be auto-wired
525
546
  return await this.resolveFieldDependencies(this.get(cls), o);
@@ -2,12 +2,12 @@ import { RetargettingProxy } from '@travetto/base/src/internal/proxy';
2
2
  import { Class, ClassInstance } from '@travetto/base';
3
3
 
4
4
  import type { DependencyRegistry } from '../src/registry';
5
- import type { ClassTarget } from '../src/types';
5
+ import type { ClassTarget, InjectableConfig } from '../src/types';
6
6
 
7
7
  /**
8
8
  * Wraps the Dependency Registry to support proxying instances
9
9
  */
10
- export function init($DependencyRegistry: Class<typeof DependencyRegistry>) {
10
+ export function init($DependencyRegistry: Class<typeof DependencyRegistry>): typeof $DependencyRegistry {
11
11
 
12
12
  /**
13
13
  * Extending the $DependencyRegistry class to add some functionality for watching
@@ -20,35 +20,37 @@ export function init($DependencyRegistry: Class<typeof DependencyRegistry>) {
20
20
  */
21
21
  protected proxyInstance<T>(target: ClassTarget<T>, qual: symbol | undefined, instance: T): T {
22
22
  const { qualifier, id: classId } = this.resolveTarget(target, qual);
23
- let proxy: RetargettingProxy<unknown>;
23
+ let proxy: RetargettingProxy<T>;
24
24
 
25
25
  if (!this.#proxies.has(classId)) {
26
26
  this.#proxies.set(classId, new Map());
27
27
  }
28
28
 
29
29
  if (!this.#proxies.get(classId)!.has(qualifier)) {
30
- proxy = new RetargettingProxy<unknown>(instance);
30
+ proxy = new RetargettingProxy<T>(instance);
31
31
  this.#proxies.get(classId)!.set(qualifier, proxy);
32
32
  console.debug('Registering proxy', { id: target.ᚕid, qualifier: qualifier.toString() });
33
33
  } else {
34
- proxy = this.#proxies.get(classId)!.get(qualifier)! as RetargettingProxy<unknown>;
34
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
35
+ proxy = this.#proxies.get(classId)!.get(qualifier) as RetargettingProxy<T>;
35
36
  proxy.setTarget(instance);
36
37
  console.debug('Updating target', {
38
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
37
39
  id: target.ᚕid, qualifier: qualifier.toString(), instanceType: (instance as unknown as ClassInstance<T>).constructor.name as string
38
40
  });
39
41
  }
40
42
 
41
- return proxy.get() as T;
43
+ return proxy.get();
42
44
  }
43
45
 
44
46
  /**
45
47
  * Create instance and wrap in a proxy
46
48
  */
47
- protected async createInstance<T>(target: ClassTarget<T>, qualifier: symbol) {
49
+ protected async createInstance<T>(target: ClassTarget<T>, qualifier: symbol): Promise<T> {
48
50
  const instance = await super.createInstance(target, qualifier);
49
51
  const classId = this.resolveTarget(target, qualifier).id;
50
52
  // Reset as proxy instance
51
- const proxied = this.proxyInstance(target, qualifier, instance);
53
+ const proxied = this.proxyInstance<T>(target, qualifier, instance);
52
54
  this.instances.get(classId)!.set(qualifier, proxied);
53
55
  return proxied;
54
56
  }
@@ -56,7 +58,7 @@ export function init($DependencyRegistry: Class<typeof DependencyRegistry>) {
56
58
  /**
57
59
  * Reload proxy if in watch mode
58
60
  */
59
- onInstallFinalize<T>(cls: Class<T>) {
61
+ onInstallFinalize<T>(cls: Class<T>): InjectableConfig<T> {
60
62
  const config = super.onInstallFinalize(cls);
61
63
  // If already loaded, reload
62
64
  const classId = cls.ᚕid;
@@ -74,7 +76,7 @@ export function init($DependencyRegistry: Class<typeof DependencyRegistry>) {
74
76
  return config;
75
77
  }
76
78
 
77
- destroyInstance(cls: Class, qualifier: symbol) {
79
+ destroyInstance(cls: Class, qualifier: symbol): void {
78
80
  const classId = cls.ᚕid;
79
81
  const proxy = this.#proxies.get(classId)!.get(qualifier);
80
82
  super.destroyInstance(cls, qualifier);
@@ -83,7 +85,7 @@ export function init($DependencyRegistry: Class<typeof DependencyRegistry>) {
83
85
  }
84
86
  }
85
87
 
86
- onReset() {
88
+ onReset(): void {
87
89
  super.onReset();
88
90
  this.#proxies.clear();
89
91
  }
package/support/invoke.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  import { EnvInit } from '@travetto/base/bin/init';
2
2
 
3
- export async function invoke(...[mod, cls, method, qualifier]: (string | undefined)[]) {
3
+ export async function invoke(...[mod, cls, method, qualifier]: (string | undefined)[]): Promise<unknown> {
4
4
  EnvInit.init();
5
5
  await (await import('@travetto/base')).PhaseManager.run('init');
6
6
  const inst = await (await import('../src/registry')).DependencyRegistry
7
- .getInstance((await import(mod!))[cls!], qualifier ? Symbol.for(qualifier) : qualifier as undefined);
7
+ .getInstance(
8
+ (await import(mod!))[cls!],
9
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
10
+ qualifier ? Symbol.for(qualifier) : qualifier as undefined
11
+ );
12
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
8
13
  return await (inst as Record<string, () => Promise<unknown>>)[method!]();
9
14
  }
10
15
 
@@ -16,13 +16,14 @@ export class InjectableTransformer {
16
16
  /**
17
17
  * Handle a specific declaration param/property
18
18
  */
19
- static processDeclaration(state: TransformerState, param: ts.ParameterDeclaration | ts.SetAccessorDeclaration | ts.PropertyDeclaration) {
19
+ static processDeclaration(state: TransformerState, param: ts.ParameterDeclaration | ts.SetAccessorDeclaration | ts.PropertyDeclaration): ts.Expression[] {
20
20
  const existing = state.findDecorator(this, param, 'Inject', INJECTABLE_MOD);
21
21
 
22
22
  if (!(existing || ts.isParameter(param))) {
23
23
  return [];
24
24
  }
25
25
 
26
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
26
27
  const callExpr = existing?.expression as ts.CallExpression;
27
28
  const args: ts.Expression[] = [...(callExpr?.arguments ?? [])];
28
29
 
@@ -43,17 +44,17 @@ export class InjectableTransformer {
43
44
  * Mark class as Injectable
44
45
  */
45
46
  @OnClass('Injectable')
46
- static registerInjectable(state: TransformerState, node: ts.ClassDeclaration) {
47
- const cons = node.members.find(x => ts.isConstructorDeclaration(x)) as ts.ConstructorDeclaration;
47
+ static registerInjectable(state: TransformerState, node: ts.ClassDeclaration): typeof node {
48
+ const cons = node.members.find((x): x is ts.ConstructorDeclaration => ts.isConstructorDeclaration(x));
48
49
  const injectArgs = cons &&
49
50
  state.fromLiteral(cons.parameters.map(x => this.processDeclaration(state, x)));
50
51
 
51
52
  // Extract all interfaces
52
53
  const interfaces: ts.Node[] = [];
53
- for (const impls of node.heritageClauses ?? []) {
54
- if (impls.token === ts.SyntaxKind.ImplementsKeyword) {
55
- for (const intType of impls.types) {
56
- const resolvedType = state.resolveType(intType);
54
+ for (const clause of node.heritageClauses ?? []) {
55
+ if (clause.token === ts.SyntaxKind.ImplementsKeyword) {
56
+ for (const typeExpression of clause.types) {
57
+ const resolvedType = state.resolveType(typeExpression);
57
58
  if (resolvedType.key === 'external') {
58
59
  const resolved = state.getOrImport(resolvedType);
59
60
  interfaces.push(resolved);
@@ -85,7 +86,7 @@ export class InjectableTransformer {
85
86
  * Handle Inject annotations for fields/args
86
87
  */
87
88
  @OnProperty('Inject')
88
- static registerInjectProperty(state: TransformerState, node: ts.PropertyDeclaration, dm?: DecoratorMeta) {
89
+ static registerInjectProperty(state: TransformerState, node: ts.PropertyDeclaration, dm?: DecoratorMeta): typeof node {
89
90
  const decl = state.findDecorator(this, node, 'Inject', INJECTABLE_MOD);
90
91
 
91
92
  // Doing decls
@@ -106,7 +107,7 @@ export class InjectableTransformer {
106
107
  * Handle Inject annotations for fields/args
107
108
  */
108
109
  @OnSetter('Inject')
109
- static registerInjectSetter(state: TransformerState, node: ts.SetAccessorDeclaration, dm?: DecoratorMeta) {
110
+ static registerInjectSetter(state: TransformerState, node: ts.SetAccessorDeclaration, dm?: DecoratorMeta): typeof node {
110
111
  const decl = state.findDecorator(this, node, 'Inject', INJECTABLE_MOD);
111
112
 
112
113
  // Doing decls
@@ -126,7 +127,7 @@ export class InjectableTransformer {
126
127
  * Handle InjectableFactory creation
127
128
  */
128
129
  @OnStaticMethod('InjectableFactory')
129
- static registerFactory(state: TransformerState, node: ts.MethodDeclaration, dm?: DecoratorMeta) {
130
+ static registerFactory(state: TransformerState, node: ts.MethodDeclaration, dm?: DecoratorMeta): typeof node {
130
131
  if (!dm?.dec) {
131
132
  return node;
132
133
  }
@@ -148,6 +149,7 @@ export class InjectableTransformer {
148
149
 
149
150
  args.unshift(state.extendObjectLiteral({
150
151
  dependencies,
152
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
151
153
  src: (node.parent as ts.ClassDeclaration).name,
152
154
  target
153
155
  }));