• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nestjs / nest / e79cdc3c-762e-40cd-acb3-21e17deb1cd9

18 Aug 2024 03:11PM UTC coverage: 92.124% (-0.09%) from 92.213%
e79cdc3c-762e-40cd-acb3-21e17deb1cd9

Pull #13485

circleci

DylanVeldra
fix(core): merge req context with tenant payload in the request instance
Pull Request #13485: fix(core): merge request context with tenant context payload in the request singleton

2559 of 3078 branches covered (83.14%)

1 of 2 new or added lines in 2 files covered. (50.0%)

74 existing lines in 13 files now uncovered.

6737 of 7313 relevant lines covered (92.12%)

17.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.46
/packages/core/scanner.ts
1
import { DynamicModule, ForwardReference, Provider } from '@nestjs/common';
2
import {
1✔
3
  CATCH_WATERMARK,
4
  CONTROLLER_WATERMARK,
5
  ENHANCER_KEY_TO_SUBTYPE_MAP,
6
  EXCEPTION_FILTERS_METADATA,
7
  EnhancerSubtype,
8
  GUARDS_METADATA,
9
  INJECTABLE_WATERMARK,
10
  INTERCEPTORS_METADATA,
11
  MODULE_METADATA,
12
  PIPES_METADATA,
13
  ROUTE_ARGS_METADATA,
14
} from '@nestjs/common/constants';
15
import {
1✔
16
  CanActivate,
17
  ClassProvider,
18
  Controller,
19
  ExceptionFilter,
20
  ExistingProvider,
21
  FactoryProvider,
22
  Injectable,
23
  InjectionToken,
24
  NestInterceptor,
25
  PipeTransform,
26
  Scope,
27
  Type,
28
  ValueProvider,
29
} from '@nestjs/common/interfaces';
30
import {
1✔
31
  isFunction,
32
  isNil,
33
  isUndefined,
34
} from '@nestjs/common/utils/shared.utils';
35
import { iterate } from 'iterare';
1✔
36
import { ApplicationConfig } from './application-config';
1✔
37
import {
1✔
38
  APP_FILTER,
39
  APP_GUARD,
40
  APP_INTERCEPTOR,
41
  APP_PIPE,
42
  ENHANCER_TOKEN_TO_SUBTYPE_MAP,
43
} from './constants';
44
import { CircularDependencyException } from './errors/exceptions/circular-dependency.exception';
1✔
45
import { InvalidClassModuleException } from './errors/exceptions/invalid-class-module.exception';
1✔
46
import { InvalidModuleException } from './errors/exceptions/invalid-module.exception';
1✔
47
import { UndefinedModuleException } from './errors/exceptions/undefined-module.exception';
1✔
48
import { getClassScope } from './helpers/get-class-scope';
1✔
49
import { NestContainer } from './injector/container';
50
import { InstanceWrapper } from './injector/instance-wrapper';
51
import { InternalCoreModuleFactory } from './injector/internal-core-module/internal-core-module-factory';
1✔
52
import { Module } from './injector/module';
53
import { GraphInspector } from './inspector/graph-inspector';
54
import { UuidFactory } from './inspector/uuid-factory';
1✔
55
import { ModuleDefinition } from './interfaces/module-definition.interface';
56
import { ModuleOverride } from './interfaces/module-override.interface';
57
import { MetadataScanner } from './metadata-scanner';
58

59
interface ApplicationProviderWrapper {
60
  moduleKey: string;
61
  providerKey: string;
62
  type: InjectionToken;
63
  scope?: Scope;
64
}
65

66
interface ModulesScanParameters {
67
  moduleDefinition: ModuleDefinition;
68
  scope?: Type<unknown>[];
69
  ctxRegistry?: (ForwardReference | DynamicModule | Type<unknown>)[];
70
  overrides?: ModuleOverride[];
71
  lazy?: boolean;
72
}
73

74
export class DependenciesScanner {
1✔
75
  private readonly applicationProvidersApplyMap: ApplicationProviderWrapper[] =
44✔
76
    [];
77

78
  constructor(
79
    private readonly container: NestContainer,
44✔
80
    private readonly metadataScanner: MetadataScanner,
44✔
81
    private readonly graphInspector: GraphInspector,
44✔
82
    private readonly applicationConfig = new ApplicationConfig(),
44✔
83
  ) {}
84

85
  public async scan(
86
    module: Type<any>,
87
    options?: { overrides?: ModuleOverride[] },
88
  ) {
89
    await this.registerCoreModule(options?.overrides);
8✔
90
    await this.scanForModules({
8✔
91
      moduleDefinition: module,
92
      overrides: options?.overrides,
93
    });
94
    await this.scanModulesForDependencies();
8✔
95
    this.calculateModulesDistance();
8✔
96

97
    this.addScopedEnhancersMetadata();
8✔
98
    this.container.bindGlobalScope();
8✔
99
  }
100

101
  public async scanForModules({
102
    moduleDefinition,
103
    lazy,
104
    scope = [],
11✔
105
    ctxRegistry = [],
13✔
106
    overrides = [],
11✔
107
  }: ModulesScanParameters): Promise<Module[]> {
108
    const { moduleRef: moduleInstance, inserted: moduleInserted } =
109
      (await this.insertOrOverrideModule(moduleDefinition, overrides, scope)) ??
25✔
110
      {};
111

112
    moduleDefinition =
25✔
113
      this.getOverrideModuleByModule(moduleDefinition, overrides)?.newModule ??
47✔
114
      moduleDefinition;
115

116
    moduleDefinition =
25✔
117
      moduleDefinition instanceof Promise
118
        ? await moduleDefinition
25!
119
        : moduleDefinition;
120

121
    ctxRegistry.push(moduleDefinition);
25✔
122

123
    if (this.isForwardReference(moduleDefinition)) {
25✔
124
      moduleDefinition = (moduleDefinition as ForwardReference).forwardRef();
1✔
125
    }
126
    const modules = !this.isDynamicModule(
25✔
127
      moduleDefinition as Type<any> | DynamicModule,
128
    )
129
      ? this.reflectMetadata(
25!
130
          MODULE_METADATA.IMPORTS,
131
          moduleDefinition as Type<any>,
132
        )
133
      : [
134
          ...this.reflectMetadata(
135
            MODULE_METADATA.IMPORTS,
136
            (moduleDefinition as DynamicModule).module,
137
          ),
138
          ...((moduleDefinition as DynamicModule).imports || []),
×
139
        ];
140

141
    let registeredModuleRefs = [];
25✔
142
    for (const [index, innerModule] of modules.entries()) {
25✔
143
      // In case of a circular dependency (ES module system), JavaScript will resolve the type to `undefined`.
144
      if (innerModule === undefined) {
14✔
145
        throw new UndefinedModuleException(moduleDefinition, index, scope);
1✔
146
      }
147
      if (!innerModule) {
13✔
148
        throw new InvalidModuleException(moduleDefinition, index, scope);
1✔
149
      }
150
      if (ctxRegistry.includes(innerModule)) {
12!
151
        continue;
×
152
      }
153
      const moduleRefs = await this.scanForModules({
12✔
154
        moduleDefinition: innerModule,
155
        scope: [].concat(scope, moduleDefinition),
156
        ctxRegistry,
157
        overrides,
158
        lazy,
159
      });
160
      registeredModuleRefs = registeredModuleRefs.concat(moduleRefs);
12✔
161
    }
162
    if (!moduleInstance) {
23✔
163
      return registeredModuleRefs;
5✔
164
    }
165

166
    if (lazy && moduleInserted) {
18✔
167
      this.container.bindGlobalsToImports(moduleInstance);
4✔
168
    }
169
    return [moduleInstance].concat(registeredModuleRefs);
18✔
170
  }
171

172
  public async insertModule(
173
    moduleDefinition: any,
174
    scope: Type<unknown>[],
175
  ): Promise<
176
    | {
177
        moduleRef: Module;
178
        inserted: boolean;
179
      }
180
    | undefined
181
  > {
182
    const moduleToAdd = this.isForwardReference(moduleDefinition)
26✔
183
      ? moduleDefinition.forwardRef()
26✔
184
      : moduleDefinition;
185

186
    if (
26✔
187
      this.isInjectable(moduleToAdd) ||
73✔
188
      this.isController(moduleToAdd) ||
189
      this.isExceptionFilter(moduleToAdd)
190
    ) {
191
      throw new InvalidClassModuleException(moduleDefinition, scope);
3✔
192
    }
193

194
    return this.container.addModule(moduleToAdd, scope);
22✔
195
  }
196

197
  public async scanModulesForDependencies(
198
    modules: Map<string, Module> = this.container.getModules(),
8✔
199
  ) {
200
    for (const [token, { metatype }] of modules) {
11✔
201
      await this.reflectImports(metatype, token, metatype.name);
18✔
202
      this.reflectProviders(metatype, token);
18✔
203
      this.reflectControllers(metatype, token);
18✔
204
      this.reflectExports(metatype, token);
18✔
205
    }
206
  }
207

208
  public async reflectImports(
209
    module: Type<unknown>,
210
    token: string,
211
    context: string,
212
  ) {
213
    const modules = [
18✔
214
      ...this.reflectMetadata(MODULE_METADATA.IMPORTS, module),
215
      ...this.container.getDynamicMetadataByToken(
216
        token,
217
        MODULE_METADATA.IMPORTS as 'imports',
218
      ),
219
    ];
220
    for (const related of modules) {
18✔
221
      await this.insertImport(related, token, context);
9✔
222
    }
223
  }
224

225
  public reflectProviders(module: Type<any>, token: string) {
226
    const providers = [
18✔
227
      ...this.reflectMetadata(MODULE_METADATA.PROVIDERS, module),
228
      ...this.container.getDynamicMetadataByToken(
229
        token,
230
        MODULE_METADATA.PROVIDERS as 'providers',
231
      ),
232
    ];
233
    providers.forEach(provider => {
18✔
234
      this.insertProvider(provider, token);
9✔
235
      this.reflectDynamicMetadata(provider, token);
9✔
236
    });
237
  }
238

239
  public reflectControllers(module: Type<any>, token: string) {
240
    const controllers = [
18✔
241
      ...this.reflectMetadata(MODULE_METADATA.CONTROLLERS, module),
242
      ...this.container.getDynamicMetadataByToken(
243
        token,
244
        MODULE_METADATA.CONTROLLERS as 'controllers',
245
      ),
246
    ];
247
    controllers.forEach(item => {
18✔
248
      this.insertController(item, token);
10✔
249
      this.reflectDynamicMetadata(item, token);
10✔
250
    });
251
  }
252

253
  public reflectDynamicMetadata(cls: Type<Injectable>, token: string) {
254
    if (!cls || !cls.prototype) {
21✔
255
      return;
2✔
256
    }
257
    this.reflectInjectables(cls, token, GUARDS_METADATA);
19✔
258
    this.reflectInjectables(cls, token, INTERCEPTORS_METADATA);
19✔
259
    this.reflectInjectables(cls, token, EXCEPTION_FILTERS_METADATA);
19✔
260
    this.reflectInjectables(cls, token, PIPES_METADATA);
19✔
261
    this.reflectParamInjectables(cls, token, ROUTE_ARGS_METADATA);
19✔
262
  }
263

264
  public reflectExports(module: Type<unknown>, token: string) {
265
    const exports = [
18✔
266
      ...this.reflectMetadata(MODULE_METADATA.EXPORTS, module),
267
      ...this.container.getDynamicMetadataByToken(
268
        token,
269
        MODULE_METADATA.EXPORTS as 'exports',
270
      ),
271
    ];
272
    exports.forEach(exportedProvider =>
18✔
273
      this.insertExportedProvider(exportedProvider, token),
4✔
274
    );
275
  }
276

277
  public reflectInjectables(
278
    component: Type<Injectable>,
279
    token: string,
280
    metadataKey: string,
281
  ) {
282
    const controllerInjectables = this.reflectMetadata<Type<Injectable>>(
72✔
283
      metadataKey,
284
      component,
285
    );
286
    const methodInjectables = this.metadataScanner
72✔
287
      .getAllMethodNames(component.prototype)
288
      .reduce((acc, method) => {
289
        const methodInjectable = this.reflectKeyMetadata(
×
290
          component,
291
          metadataKey,
292
          method,
293
        );
294

295
        if (methodInjectable) {
×
296
          acc.push(methodInjectable);
×
297
        }
298

299
        return acc;
×
300
      }, []);
301

302
    controllerInjectables.forEach(injectable =>
72✔
303
      this.insertInjectable(
×
304
        injectable,
305
        token,
306
        component,
307
        ENHANCER_KEY_TO_SUBTYPE_MAP[metadataKey],
308
      ),
309
    );
310
    methodInjectables.forEach(methodInjectable => {
72✔
311
      methodInjectable.metadata.forEach(injectable =>
×
312
        this.insertInjectable(
×
313
          injectable,
314
          token,
315
          component,
316
          ENHANCER_KEY_TO_SUBTYPE_MAP[metadataKey],
317
          methodInjectable.methodKey,
318
        ),
319
      );
320
    });
321
  }
322

323
  public reflectParamInjectables(
324
    component: Type<Injectable>,
325
    token: string,
326
    metadataKey: string,
327
  ) {
328
    const paramsMethods = this.metadataScanner.getAllMethodNames(
18✔
329
      component.prototype,
330
    );
331

332
    paramsMethods.forEach(methodKey => {
18✔
333
      const metadata: Record<
334
        string,
335
        {
336
          index: number;
337
          data: unknown;
338
          pipes: Array<Type<PipeTransform> | PipeTransform>;
339
        }
340
      > = Reflect.getMetadata(metadataKey, component, methodKey);
×
341

342
      if (!metadata) {
×
343
        return;
×
344
      }
345

346
      const params = Object.values(metadata);
×
347
      params
×
348
        .map(item => item.pipes)
×
349
        .flat(1)
350
        .forEach(injectable =>
351
          this.insertInjectable(
×
352
            injectable,
353
            token,
354
            component,
355
            'pipe',
356
            methodKey,
357
          ),
358
        );
359
    });
360
  }
361

362
  public reflectKeyMetadata(
363
    component: Type<Injectable>,
364
    key: string,
365
    methodKey: string,
366
  ): { methodKey: string; metadata: any } | undefined {
367
    let prototype = component.prototype;
3✔
368
    do {
3✔
369
      const descriptor = Reflect.getOwnPropertyDescriptor(prototype, methodKey);
3✔
370
      if (!descriptor) {
3✔
371
        continue;
1✔
372
      }
373
      const metadata = Reflect.getMetadata(key, descriptor.value);
2✔
374
      if (!metadata) {
2!
375
        return;
×
376
      }
377
      return { methodKey, metadata };
2✔
378
    } while (
379
      (prototype = Reflect.getPrototypeOf(prototype)) &&
2!
380
      prototype !== Object.prototype &&
381
      prototype
382
    );
383
    return undefined;
1✔
384
  }
385

386
  public calculateModulesDistance() {
387
    const modulesGenerator = this.container.getModules().values();
8✔
388

389
    // Skip "InternalCoreModule" from calculating distance
390
    modulesGenerator.next();
8✔
391

392
    const modulesStack = [];
8✔
393
    const calculateDistance = (moduleRef: Module, distance = 1) => {
8✔
394
      if (!moduleRef || modulesStack.includes(moduleRef)) {
8✔
395
        return;
2✔
396
      }
397
      modulesStack.push(moduleRef);
6✔
398

399
      const moduleImports = moduleRef.imports;
6✔
400
      moduleImports.forEach(importedModuleRef => {
6✔
401
        if (importedModuleRef) {
×
402
          if (distance > importedModuleRef.distance) {
×
403
            importedModuleRef.distance = distance;
×
404
          }
405
          calculateDistance(importedModuleRef, distance + 1);
×
406
        }
407
      });
408
    };
409

410
    const rootModule = modulesGenerator.next().value as Module;
8✔
411
    calculateDistance(rootModule);
8✔
412
  }
413

414
  public async insertImport(related: any, token: string, context: string) {
415
    if (isUndefined(related)) {
11✔
416
      throw new CircularDependencyException(context);
1✔
417
    }
418
    if (this.isForwardReference(related)) {
10✔
419
      return this.container.addImport(related.forwardRef(), token);
2✔
420
    }
421
    await this.container.addImport(related, token);
8✔
422
  }
423

424
  public isCustomProvider(
425
    provider: Provider,
426
  ): provider is
427
    | ClassProvider
428
    | ValueProvider
429
    | FactoryProvider
430
    | ExistingProvider {
431
    return provider && !isNil((provider as any).provide);
15✔
432
  }
433

434
  public insertProvider(provider: Provider, token: string) {
435
    const isCustomProvider = this.isCustomProvider(provider);
15✔
436
    if (!isCustomProvider) {
15✔
437
      return this.container.addProvider(provider as Type<any>, token);
9✔
438
    }
439
    const applyProvidersMap = this.getApplyProvidersMap();
6✔
440
    const providersKeys = Object.keys(applyProvidersMap);
6✔
441
    const type = (
442
      provider as
6✔
443
        | ClassProvider
444
        | ValueProvider
445
        | FactoryProvider
446
        | ExistingProvider
447
    ).provide;
448

449
    if (!providersKeys.includes(type as string)) {
6✔
450
      return this.container.addProvider(provider as any, token);
3✔
451
    }
452
    const uuid = UuidFactory.get(type.toString());
3✔
453
    const providerToken = `${type as string} (UUID: ${uuid})`;
3✔
454

455
    let scope = (provider as ClassProvider | FactoryProvider).scope;
3✔
456
    if (isNil(scope) && (provider as ClassProvider).useClass) {
3!
457
      scope = getClassScope((provider as ClassProvider).useClass);
×
458
    }
459
    this.applicationProvidersApplyMap.push({
3✔
460
      type,
461
      moduleKey: token,
462
      providerKey: providerToken,
463
      scope,
464
    });
465

466
    const newProvider = {
3✔
467
      ...provider,
468
      provide: providerToken,
469
      scope,
470
    } as Provider;
471

472
    const enhancerSubtype =
473
      ENHANCER_TOKEN_TO_SUBTYPE_MAP[
3✔
474
        type as
475
          | typeof APP_GUARD
476
          | typeof APP_PIPE
477
          | typeof APP_FILTER
478
          | typeof APP_INTERCEPTOR
479
      ];
480
    const factoryOrClassProvider = newProvider as
3✔
481
      | FactoryProvider
482
      | ClassProvider;
483
    if (this.isRequestOrTransient(factoryOrClassProvider.scope)) {
3✔
484
      return this.container.addInjectable(newProvider, token, enhancerSubtype);
1✔
485
    }
486
    this.container.addProvider(newProvider, token, enhancerSubtype);
2✔
487
  }
488

489
  public insertInjectable(
490
    injectable: Type<Injectable> | object,
491
    token: string,
492
    host: Type<Injectable>,
493
    subtype: EnhancerSubtype,
494
    methodKey?: string,
495
  ) {
496
    if (isFunction(injectable)) {
4✔
497
      const instanceWrapper = this.container.addInjectable(
2✔
498
        injectable as Type,
499
        token,
500
        subtype,
501
        host,
502
      ) as InstanceWrapper;
503

504
      this.graphInspector.insertEnhancerMetadataCache({
2✔
505
        moduleToken: token,
506
        classRef: host,
507
        enhancerInstanceWrapper: instanceWrapper,
508
        targetNodeId: instanceWrapper.id,
509
        subtype,
510
        methodKey,
511
      });
512
      return instanceWrapper;
2✔
513
    } else {
514
      this.graphInspector.insertEnhancerMetadataCache({
2✔
515
        moduleToken: token,
516
        classRef: host,
517
        enhancerRef: injectable,
518
        methodKey,
519
        subtype,
520
      });
521
    }
522
  }
523

524
  public insertExportedProvider(
525
    exportedProvider: Type<Injectable>,
526
    token: string,
527
  ) {
528
    this.container.addExportedProvider(exportedProvider, token);
3✔
529
  }
530

531
  public insertController(controller: Type<Controller>, token: string) {
532
    this.container.addController(controller, token);
10✔
533
  }
534

535
  private insertOrOverrideModule(
536
    moduleDefinition: ModuleDefinition,
537
    overrides: ModuleOverride[],
538
    scope: Type<unknown>[],
539
  ): Promise<
540
    | {
541
        moduleRef: Module;
542
        inserted: boolean;
543
      }
544
    | undefined
545
  > {
546
    const overrideModule = this.getOverrideModuleByModule(
25✔
547
      moduleDefinition,
548
      overrides,
549
    );
550
    if (overrideModule !== undefined) {
25✔
551
      return this.overrideModule(
3✔
552
        moduleDefinition,
553
        overrideModule.newModule,
554
        scope,
555
      );
556
    }
557

558
    return this.insertModule(moduleDefinition, scope);
22✔
559
  }
560

561
  private getOverrideModuleByModule(
562
    module: ModuleDefinition,
563
    overrides: ModuleOverride[],
564
  ): ModuleOverride | undefined {
565
    if (this.isForwardReference(module)) {
50✔
566
      return overrides.find(moduleToOverride => {
2✔
567
        return (
2✔
568
          moduleToOverride.moduleToReplace === module.forwardRef() ||
4✔
569
          (
570
            moduleToOverride.moduleToReplace as ForwardReference
571
          ).forwardRef?.() === module.forwardRef()
572
        );
573
      });
574
    }
575

576
    return overrides.find(
48✔
577
      moduleToOverride => moduleToOverride.moduleToReplace === module,
12✔
578
    );
579
  }
580

581
  private async overrideModule(
582
    moduleToOverride: ModuleDefinition,
583
    newModule: ModuleDefinition,
584
    scope: Type<unknown>[],
585
  ): Promise<
586
    | {
587
        moduleRef: Module;
588
        inserted: boolean;
589
      }
590
    | undefined
591
  > {
592
    return this.container.replaceModule(
3✔
593
      this.isForwardReference(moduleToOverride)
594
        ? moduleToOverride.forwardRef()
3✔
595
        : moduleToOverride,
596
      this.isForwardReference(newModule) ? newModule.forwardRef() : newModule,
3✔
597
      scope,
598
    );
599
  }
600

601
  public reflectMetadata<T = any>(
602
    metadataKey: string,
603
    metatype: Type<any>,
604
  ): T[] {
605
    return Reflect.getMetadata(metadataKey, metatype) || [];
169✔
606
  }
607

608
  public async registerCoreModule(overrides?: ModuleOverride[]) {
UNCOV
609
    const moduleDefinition = InternalCoreModuleFactory.create(
×
610
      this.container,
611
      this,
612
      this.container.getModuleCompiler(),
613
      this.container.getHttpAdapterHostRef(),
614
      this.graphInspector,
615
      overrides,
616
    );
UNCOV
617
    const [instance] = await this.scanForModules({
×
618
      moduleDefinition,
619
      overrides,
620
    });
621
    this.container.registerCoreModuleRef(instance);
×
622
  }
623

624
  /**
625
   * Add either request or transient globally scoped enhancers
626
   * to all controllers metadata storage
627
   */
628
  public addScopedEnhancersMetadata() {
629
    iterate(this.applicationProvidersApplyMap)
9✔
630
      .filter(wrapper => this.isRequestOrTransient(wrapper.scope))
1✔
631
      .forEach(({ moduleKey, providerKey }) => {
632
        const modulesContainer = this.container.getModules();
1✔
633
        const { injectables } = modulesContainer.get(moduleKey);
1✔
634
        const instanceWrapper = injectables.get(providerKey);
1✔
635

636
        const iterableIterator = modulesContainer.values();
1✔
637
        iterate(iterableIterator)
1✔
638
          .map(moduleRef =>
639
            Array.from<InstanceWrapper>(moduleRef.controllers.values()).concat(
1✔
640
              moduleRef.entryProviders,
641
            ),
642
          )
643
          .flatten()
644
          .forEach(controllerOrEntryProvider =>
645
            controllerOrEntryProvider.addEnhancerMetadata(instanceWrapper),
2✔
646
          );
647
      });
648
  }
649

650
  public applyApplicationProviders() {
651
    const applyProvidersMap = this.getApplyProvidersMap();
2✔
652
    const applyRequestProvidersMap = this.getApplyRequestProvidersMap();
2✔
653

654
    const getInstanceWrapper = (
2✔
655
      moduleKey: string,
656
      providerKey: string,
657
      collectionKey: 'providers' | 'injectables',
658
    ) => {
659
      const modules = this.container.getModules();
2✔
660
      const collection = modules.get(moduleKey)[collectionKey];
2✔
661
      return collection.get(providerKey);
2✔
662
    };
663

664
    // Add global enhancers to the application config
665
    this.applicationProvidersApplyMap.forEach(
2✔
666
      ({ moduleKey, providerKey, type, scope }) => {
667
        let instanceWrapper: InstanceWrapper;
668
        if (this.isRequestOrTransient(scope)) {
2✔
669
          instanceWrapper = getInstanceWrapper(
1✔
670
            moduleKey,
671
            providerKey,
672
            'injectables',
673
          );
674

675
          this.graphInspector.insertAttachedEnhancer(instanceWrapper);
1✔
676
          return applyRequestProvidersMap[type as string](instanceWrapper);
1✔
677
        }
678
        instanceWrapper = getInstanceWrapper(
1✔
679
          moduleKey,
680
          providerKey,
681
          'providers',
682
        );
683
        this.graphInspector.insertAttachedEnhancer(instanceWrapper);
1✔
684
        applyProvidersMap[type as string](instanceWrapper.instance);
1✔
685
      },
686
    );
687
  }
688

689
  public getApplyProvidersMap(): { [type: string]: Function } {
690
    return {
11✔
691
      [APP_INTERCEPTOR]: (interceptor: NestInterceptor) =>
692
        this.applicationConfig.addGlobalInterceptor(interceptor),
1✔
693
      [APP_PIPE]: (pipe: PipeTransform) =>
694
        this.applicationConfig.addGlobalPipe(pipe),
1✔
695
      [APP_GUARD]: (guard: CanActivate) =>
696
        this.applicationConfig.addGlobalGuard(guard),
1✔
697
      [APP_FILTER]: (filter: ExceptionFilter) =>
698
        this.applicationConfig.addGlobalFilter(filter),
1✔
699
    };
700
  }
701

702
  public getApplyRequestProvidersMap(): { [type: string]: Function } {
703
    return {
5✔
704
      [APP_INTERCEPTOR]: (interceptor: InstanceWrapper<NestInterceptor>) =>
705
        this.applicationConfig.addGlobalRequestInterceptor(interceptor),
1✔
706
      [APP_PIPE]: (pipe: InstanceWrapper<PipeTransform>) =>
707
        this.applicationConfig.addGlobalRequestPipe(pipe),
1✔
708
      [APP_GUARD]: (guard: InstanceWrapper<CanActivate>) =>
709
        this.applicationConfig.addGlobalRequestGuard(guard),
1✔
710
      [APP_FILTER]: (filter: InstanceWrapper<ExceptionFilter>) =>
711
        this.applicationConfig.addGlobalRequestFilter(filter),
1✔
712
    };
713
  }
714

715
  public isDynamicModule(
716
    module: Type<any> | DynamicModule,
717
  ): module is DynamicModule {
718
    return module && !!(module as DynamicModule).module;
25✔
719
  }
720

721
  /**
722
   * @param metatype
723
   * @returns `true` if `metatype` is annotated with the `@Injectable()` decorator.
724
   */
725
  private isInjectable(metatype: Type<any>): boolean {
726
    return !!Reflect.getMetadata(INJECTABLE_WATERMARK, metatype);
26✔
727
  }
728

729
  /**
730
   * @param metatype
731
   * @returns `true` if `metatype` is annotated with the `@Controller()` decorator.
732
   */
733
  private isController(metatype: Type<any>): boolean {
734
    return !!Reflect.getMetadata(CONTROLLER_WATERMARK, metatype);
24✔
735
  }
736

737
  /**
738
   * @param metatype
739
   * @returns `true` if `metatype` is annotated with the `@Catch()` decorator.
740
   */
741
  private isExceptionFilter(metatype: Type<any>): boolean {
742
    return !!Reflect.getMetadata(CATCH_WATERMARK, metatype);
23✔
743
  }
744

745
  private isForwardReference(
746
    module: ModuleDefinition,
747
  ): module is ForwardReference {
748
    return module && !!(module as ForwardReference).forwardRef;
117✔
749
  }
750

751
  private isRequestOrTransient(scope: Scope): boolean {
752
    return scope === Scope.REQUEST || scope === Scope.TRANSIENT;
6✔
753
  }
754
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc