Skip to content

Commit 4d8934f

Browse files
Merge branch 'master' of https://github.com/Pong420/mongoose
2 parents 306be9d + 766edd4 commit 4d8934f

File tree

5 files changed

+120
-67
lines changed

5 files changed

+120
-67
lines changed

lib/mongoose.providers.ts

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { flatten } from '@nestjs/common';
1+
import { Provider } from '@nestjs/common';
22
import { Connection, Document, Model } from 'mongoose';
33
import { getConnectionToken, getModelToken } from './common/mongoose.utils';
44
import {
@@ -9,50 +9,68 @@ import {
99

1010
function addDiscriminators(
1111
model: Model<Document>,
12-
discriminators?: DiscriminatorOptions[],
13-
) {
14-
if (discriminators) {
15-
for (const { name, schema } of discriminators) {
16-
model.discriminator(name, schema);
17-
}
18-
}
19-
return model;
12+
discriminators: DiscriminatorOptions[] = [],
13+
): Model<Document>[] {
14+
return discriminators.map(({ name, schema }) =>
15+
model.discriminator(name, schema),
16+
);
2017
}
2118

2219
export function createMongooseProviders(
2320
connectionName?: string,
2421
options: ModelDefinition[] = [],
25-
) {
26-
const providers = (options || []).map((option) => ({
27-
provide: getModelToken(option.name),
28-
useFactory: (connection: Connection) => {
29-
const model = connection.model(
30-
option.name,
31-
option.schema,
32-
option.collection,
33-
);
34-
return addDiscriminators(model, option.discriminators);
35-
},
36-
inject: [getConnectionToken(connectionName)],
37-
}));
38-
return providers;
22+
): Provider[] {
23+
return options.reduce(
24+
(providers, option) => [
25+
...providers,
26+
...createMongooseProviders(connectionName, option.discriminators),
27+
{
28+
provide: getModelToken(option.name),
29+
useFactory: (connection: Connection) => {
30+
const model = connection.model(
31+
option.name,
32+
option.schema,
33+
option.collection,
34+
);
35+
addDiscriminators(model, option.discriminators);
36+
return model;
37+
},
38+
inject: [getConnectionToken(connectionName)],
39+
},
40+
],
41+
[] as Provider[],
42+
);
3943
}
4044

4145
export function createMongooseAsyncProviders(
4246
connectionName?: string,
4347
modelFactories: AsyncModelFactory[] = [],
44-
) {
45-
const providers = (modelFactories || []).map((option) => [
46-
{
47-
provide: getModelToken(option.name),
48-
useFactory: async (connection: Connection, ...args: unknown[]) => {
49-
const schema = await option.useFactory(...args);
50-
const model = connection.model(option.name, schema, option.collection);
51-
addDiscriminators(model, option.discriminators);
52-
return model;
48+
): Provider[] {
49+
return modelFactories.reduce((providers, option) => {
50+
return [
51+
...providers,
52+
{
53+
provide: getModelToken(option.name),
54+
useFactory: async (connection: Connection, ...args: unknown[]) => {
55+
const schema = await option.useFactory(...args);
56+
const model = connection.model(
57+
option.name,
58+
schema,
59+
option.collection,
60+
);
61+
addDiscriminators(model, option.discriminators);
62+
return model;
63+
},
64+
inject: [getConnectionToken(connectionName), ...(option.inject || [])],
5365
},
54-
inject: [getConnectionToken(connectionName), ...(option.inject || [])],
55-
},
56-
]);
57-
return flatten(providers);
66+
// discriminators must convert to `AsyncModelFactory`.
67+
// Otherwise, the discriminators will register as `Model` before `model.discriminator` and throw OverwriteModelError
68+
...createMongooseAsyncProviders(
69+
connectionName,
70+
(option.discriminators || []).map<AsyncModelFactory>(
71+
({ name, schema }) => ({ name, useFactory: async () => schema }),
72+
),
73+
),
74+
];
75+
}, [] as Provider[]);
5876
}

tests/e2e/discriminator.spec.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,58 @@
1-
import { HttpStatus, INestApplication } from '@nestjs/common';
1+
import { HttpStatus, INestApplication, DynamicModule } from '@nestjs/common';
22
import { Test } from '@nestjs/testing';
33
import { Server } from 'http';
44
import * as request from 'supertest';
5-
import { AppModule } from '../src/app.module';
5+
import { MongooseModule } from '../../lib';
6+
import { EventModule } from '../src/event/event.module';
7+
import { Event, EventSchema } from '../src/event/schemas/event.schema';
8+
import {
9+
ClieckLinkEvent,
10+
ClieckLinkEventSchema,
11+
} from '../src/event/schemas/click-link-event.schema';
12+
import {
13+
SignUpEvent,
14+
SignUpEventSchema,
15+
} from '../src/event/schemas/sign-up-event.schema';
616

7-
describe('Discriminator', () => {
17+
const testCase: [string, DynamicModule][] = [
18+
[
19+
'forFeature',
20+
MongooseModule.forFeature([
21+
{
22+
name: Event.name,
23+
schema: EventSchema,
24+
discriminators: [
25+
{ name: ClieckLinkEvent.name, schema: ClieckLinkEventSchema },
26+
{ name: SignUpEvent.name, schema: SignUpEventSchema },
27+
],
28+
},
29+
]),
30+
],
31+
[
32+
'forFeatureAsync',
33+
MongooseModule.forFeatureAsync([
34+
{
35+
name: Event.name,
36+
useFactory: async () => EventSchema,
37+
discriminators: [
38+
{ name: ClieckLinkEvent.name, schema: ClieckLinkEventSchema },
39+
{ name: SignUpEvent.name, schema: SignUpEventSchema },
40+
],
41+
},
42+
]),
43+
],
44+
];
45+
46+
describe.each(testCase)('Discriminator - %s', (_, features) => {
847
let server: Server;
948
let app: INestApplication;
1049

1150
beforeEach(async () => {
1251
const module = await Test.createTestingModule({
13-
imports: [AppModule],
52+
imports: [
53+
MongooseModule.forRoot('mongodb://localhost:27017/test'),
54+
EventModule.forFeature(features),
55+
],
1456
}).compile();
1557

1658
app = module.createNestApplication();

tests/src/app.module.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import { Module } from '@nestjs/common';
22
import { MongooseModule } from '../../lib';
33
import { CatsModule } from './cats/cats.module';
4-
import { EventModule } from './event/event.module';
54

65
@Module({
76
imports: [
87
MongooseModule.forRoot('mongodb://localhost:27017/test'),
98
CatsModule,
10-
EventModule,
119
],
1210
})
1311
export class AppModule {}

tests/src/event/event.module.ts

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,15 @@
1-
import { Module } from '@nestjs/common';
2-
import { MongooseModule } from '../../../lib';
1+
import { DynamicModule, Module } from '@nestjs/common';
32
import { EventService } from './event.service';
43
import { EventController } from './event.controller';
5-
import { Event, EventSchema } from './schemas/event.schema';
6-
import {
7-
ClieckLinkEvent,
8-
ClieckLinkEventSchema,
9-
} from './schemas/click-link-event.schema';
10-
import { SignUpEvent, SignUpEventSchema } from './schemas/sign-up-event.schema';
114

12-
@Module({
13-
imports: [
14-
MongooseModule.forFeature([
15-
{
16-
name: Event.name,
17-
schema: EventSchema,
18-
discriminators: [
19-
{ name: ClieckLinkEvent.name, schema: ClieckLinkEventSchema },
20-
{ name: SignUpEvent.name, schema: SignUpEventSchema },
21-
],
22-
},
23-
]),
24-
],
25-
controllers: [EventController],
26-
providers: [EventService],
27-
})
28-
export class EventModule {}
5+
@Module({})
6+
export class EventModule {
7+
static forFeature(module: DynamicModule): DynamicModule {
8+
return {
9+
imports: [module],
10+
module: EventModule,
11+
controllers: [EventController],
12+
providers: [EventService],
13+
};
14+
}
15+
}

tests/src/event/event.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,20 @@ import { InjectModel } from '../../../lib';
44
import { CreateClickLinkEventDto } from './dto/create-click-link-event.dto';
55
import { CreateSignUpEventDto } from './dto/create-sign-up-event.dto';
66
import { Event } from './schemas/event.schema';
7+
import { ClieckLinkEvent } from './schemas/click-link-event.schema';
8+
import { SignUpEvent } from './schemas/sign-up-event.schema';
79

810
@Injectable()
911
export class EventService {
1012
constructor(
1113
@InjectModel(Event.name)
1214
private readonly eventModel: Model<Event & Document>,
15+
16+
@InjectModel(ClieckLinkEvent.name)
17+
private readonly clientEventModel: Model<Event & Document>,
18+
19+
@InjectModel(SignUpEvent.name)
20+
private readonly signUpEventModel: Model<Event & Document>,
1321
) {}
1422

1523
async create(

0 commit comments

Comments
 (0)