Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Pong420/mongoose
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec committed Nov 24, 2020
2 parents 306be9d + 766edd4 commit 4d8934f
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 67 deletions.
90 changes: 54 additions & 36 deletions lib/mongoose.providers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { flatten } from '@nestjs/common';
import { Provider } from '@nestjs/common';
import { Connection, Document, Model } from 'mongoose';
import { getConnectionToken, getModelToken } from './common/mongoose.utils';
import {
Expand All @@ -9,50 +9,68 @@ import {

function addDiscriminators(
model: Model<Document>,
discriminators?: DiscriminatorOptions[],
) {
if (discriminators) {
for (const { name, schema } of discriminators) {
model.discriminator(name, schema);
}
}
return model;
discriminators: DiscriminatorOptions[] = [],
): Model<Document>[] {
return discriminators.map(({ name, schema }) =>
model.discriminator(name, schema),
);
}

export function createMongooseProviders(
connectionName?: string,
options: ModelDefinition[] = [],
) {
const providers = (options || []).map((option) => ({
provide: getModelToken(option.name),
useFactory: (connection: Connection) => {
const model = connection.model(
option.name,
option.schema,
option.collection,
);
return addDiscriminators(model, option.discriminators);
},
inject: [getConnectionToken(connectionName)],
}));
return providers;
): Provider[] {
return options.reduce(
(providers, option) => [
...providers,
...createMongooseProviders(connectionName, option.discriminators),
{
provide: getModelToken(option.name),
useFactory: (connection: Connection) => {
const model = connection.model(
option.name,
option.schema,
option.collection,
);
addDiscriminators(model, option.discriminators);
return model;
},
inject: [getConnectionToken(connectionName)],
},
],
[] as Provider[],
);
}

export function createMongooseAsyncProviders(
connectionName?: string,
modelFactories: AsyncModelFactory[] = [],
) {
const providers = (modelFactories || []).map((option) => [
{
provide: getModelToken(option.name),
useFactory: async (connection: Connection, ...args: unknown[]) => {
const schema = await option.useFactory(...args);
const model = connection.model(option.name, schema, option.collection);
addDiscriminators(model, option.discriminators);
return model;
): Provider[] {
return modelFactories.reduce((providers, option) => {
return [
...providers,
{
provide: getModelToken(option.name),
useFactory: async (connection: Connection, ...args: unknown[]) => {
const schema = await option.useFactory(...args);
const model = connection.model(
option.name,
schema,
option.collection,
);
addDiscriminators(model, option.discriminators);
return model;
},
inject: [getConnectionToken(connectionName), ...(option.inject || [])],
},
inject: [getConnectionToken(connectionName), ...(option.inject || [])],
},
]);
return flatten(providers);
// discriminators must convert to `AsyncModelFactory`.
// Otherwise, the discriminators will register as `Model` before `model.discriminator` and throw OverwriteModelError
...createMongooseAsyncProviders(
connectionName,
(option.discriminators || []).map<AsyncModelFactory>(
({ name, schema }) => ({ name, useFactory: async () => schema }),
),
),
];
}, [] as Provider[]);
}
50 changes: 46 additions & 4 deletions tests/e2e/discriminator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,58 @@
import { HttpStatus, INestApplication } from '@nestjs/common';
import { HttpStatus, INestApplication, DynamicModule } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { Server } from 'http';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import { MongooseModule } from '../../lib';
import { EventModule } from '../src/event/event.module';
import { Event, EventSchema } from '../src/event/schemas/event.schema';
import {
ClieckLinkEvent,
ClieckLinkEventSchema,
} from '../src/event/schemas/click-link-event.schema';
import {
SignUpEvent,
SignUpEventSchema,
} from '../src/event/schemas/sign-up-event.schema';

describe('Discriminator', () => {
const testCase: [string, DynamicModule][] = [
[
'forFeature',
MongooseModule.forFeature([
{
name: Event.name,
schema: EventSchema,
discriminators: [
{ name: ClieckLinkEvent.name, schema: ClieckLinkEventSchema },
{ name: SignUpEvent.name, schema: SignUpEventSchema },
],
},
]),
],
[
'forFeatureAsync',
MongooseModule.forFeatureAsync([
{
name: Event.name,
useFactory: async () => EventSchema,
discriminators: [
{ name: ClieckLinkEvent.name, schema: ClieckLinkEventSchema },
{ name: SignUpEvent.name, schema: SignUpEventSchema },
],
},
]),
],
];

describe.each(testCase)('Discriminator - %s', (_, features) => {
let server: Server;
let app: INestApplication;

beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
imports: [
MongooseModule.forRoot('mongodb://localhost:27017/test'),
EventModule.forFeature(features),
],
}).compile();

app = module.createNestApplication();
Expand Down
2 changes: 0 additions & 2 deletions tests/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '../../lib';
import { CatsModule } from './cats/cats.module';
import { EventModule } from './event/event.module';

@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017/test'),
CatsModule,
EventModule,
],
})
export class AppModule {}
37 changes: 12 additions & 25 deletions tests/src/event/event.module.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '../../../lib';
import { DynamicModule, Module } from '@nestjs/common';
import { EventService } from './event.service';
import { EventController } from './event.controller';
import { Event, EventSchema } from './schemas/event.schema';
import {
ClieckLinkEvent,
ClieckLinkEventSchema,
} from './schemas/click-link-event.schema';
import { SignUpEvent, SignUpEventSchema } from './schemas/sign-up-event.schema';

@Module({
imports: [
MongooseModule.forFeature([
{
name: Event.name,
schema: EventSchema,
discriminators: [
{ name: ClieckLinkEvent.name, schema: ClieckLinkEventSchema },
{ name: SignUpEvent.name, schema: SignUpEventSchema },
],
},
]),
],
controllers: [EventController],
providers: [EventService],
})
export class EventModule {}
@Module({})
export class EventModule {
static forFeature(module: DynamicModule): DynamicModule {
return {
imports: [module],
module: EventModule,
controllers: [EventController],
providers: [EventService],
};
}
}
8 changes: 8 additions & 0 deletions tests/src/event/event.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ import { InjectModel } from '../../../lib';
import { CreateClickLinkEventDto } from './dto/create-click-link-event.dto';
import { CreateSignUpEventDto } from './dto/create-sign-up-event.dto';
import { Event } from './schemas/event.schema';
import { ClieckLinkEvent } from './schemas/click-link-event.schema';
import { SignUpEvent } from './schemas/sign-up-event.schema';

@Injectable()
export class EventService {
constructor(
@InjectModel(Event.name)
private readonly eventModel: Model<Event & Document>,

@InjectModel(ClieckLinkEvent.name)
private readonly clientEventModel: Model<Event & Document>,

@InjectModel(SignUpEvent.name)
private readonly signUpEventModel: Model<Event & Document>,
) {}

async create(
Expand Down

0 comments on commit 4d8934f

Please sign in to comment.