Skip to content

Commit 958da96

Browse files
committed
bugfix(core): Allow circular structures for dynamic module nestjs#678
1 parent 65bb7e7 commit 958da96

5 files changed

Lines changed: 43 additions & 2 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { expect } from 'chai';
2+
import { Test } from '@nestjs/testing';
3+
import { CircularModule } from '../src/circular-structure-dynamic-module/circular.module';
4+
import { InputService } from '../src/circular-structure-dynamic-module/input.service';
5+
6+
describe('Circular structure for dynamic modules', () => {
7+
it('should resolve circular structure with dynamic modules', async () => {
8+
const builder = Test.createTestingModule({
9+
imports: [CircularModule.forRoot()],
10+
});
11+
const testingModule = await builder.compile();
12+
const inputService = testingModule.get<InputService>(InputService);
13+
14+
expect(inputService).to.be.instanceof(InputService);
15+
});
16+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { DynamicModule } from '@nestjs/common';
2+
import { InputService } from './input.service';
3+
4+
export class CircularModule {
5+
static forRoot(): DynamicModule {
6+
const a = {
7+
module: CircularModule,
8+
providers: [
9+
InputService,
10+
],
11+
b: null,
12+
};
13+
a.b = a;
14+
return a;
15+
}
16+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Injectable } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class InputService {
5+
}

packages/core/injector/module-token-factory.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { DynamicModule } from '@nestjs/common';
22
import { SHARED_MODULE_METADATA } from '@nestjs/common/constants';
33
import { Type } from '@nestjs/common/interfaces/type.interface';
44
import * as hash from 'object-hash';
5+
import safeStringify from 'fast-safe-stringify';
56

67
export class ModuleTokenFactory {
78
public create(
@@ -22,7 +23,9 @@ export class ModuleTokenFactory {
2223
public getDynamicMetadataToken(
2324
dynamicModuleMetadata: Partial<DynamicModule> | undefined,
2425
): string {
25-
return dynamicModuleMetadata ? JSON.stringify(dynamicModuleMetadata) : '';
26+
// Uses safeStringify instead of JSON.stringify
27+
// to support circular dynamic modules
28+
return dynamicModuleMetadata ? safeStringify(dynamicModuleMetadata) : '';
2629
}
2730

2831
public getModuleName(metatype: Type<any>): string {

packages/core/test/injector/module-token-factory.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { expect } from 'chai';
22
import * as hash from 'object-hash';
33
import { SingleScope } from '../../../common';
44
import { ModuleTokenFactory } from '../../injector/module-token-factory';
5+
import safeStringify from 'fast-safe-stringify';
56

67
describe('ModuleTokenFactory', () => {
78
let factory: ModuleTokenFactory;
@@ -46,7 +47,7 @@ describe('ModuleTokenFactory', () => {
4647
expect(token).to.be.deep.eq(
4748
hash({
4849
module: Module.name,
49-
dynamic: JSON.stringify({
50+
dynamic: safeStringify({
5051
components: [{}],
5152
}),
5253
scope: [Module.name],

0 commit comments

Comments
 (0)