Skip to content

Commit 342a41e

Browse files
committed
implement memory db for test
1 parent c4100e8 commit 342a41e

2 files changed

Lines changed: 72 additions & 26 deletions

File tree

apps/api/src/core/prisma.ts

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,77 @@
11
import { LibnestPrismaExtension } from '@douglasneuroinformatics/libnest';
2-
import type { PrismaModelKey, PrismaModelName } from '@douglasneuroinformatics/libnest';
2+
import type {
3+
ConfigService,
4+
PrismaModelKey,
5+
PrismaModelName,
6+
PrismaModuleOptions
7+
} from '@douglasneuroinformatics/libnest';
8+
import { Injectable } from '@nestjs/common';
9+
import type { OnApplicationShutdown } from '@nestjs/common';
310
import { PrismaClient } from '@prisma/client';
11+
import type { MongoMemoryReplSet } from 'mongodb-memory-server';
412

5-
export function createPrismaClient(datasourceUrl: string) {
6-
return new PrismaClient({ datasourceUrl }).$extends(LibnestPrismaExtension);
13+
@Injectable()
14+
export class PrismaModuleOptionsFactory implements OnApplicationShutdown {
15+
private memoryReplSet: MongoMemoryReplSet | null;
16+
17+
constructor(private readonly configService: ConfigService) {
18+
this.memoryReplSet = null;
19+
}
20+
21+
async create() {
22+
let datasourceUrl: string;
23+
if (this.configService.get('NODE_ENV') === 'test') {
24+
datasourceUrl = await this.createMemoryConnection();
25+
} else {
26+
datasourceUrl = this.getExternalConnection();
27+
}
28+
const client = new PrismaClient({
29+
datasourceUrl,
30+
omit: {
31+
user: {
32+
hashedPassword: true
33+
}
34+
}
35+
}).$extends(LibnestPrismaExtension);
36+
await client.$connect();
37+
return { client } satisfies PrismaModuleOptions;
38+
}
39+
40+
async onApplicationShutdown() {
41+
if (this.memoryReplSet) {
42+
await this.memoryReplSet.stop();
43+
}
44+
}
45+
46+
private async createMemoryConnection(): Promise<string> {
47+
// prevent mongodb-memory-server from being included in the production bundle
48+
const { MongoMemoryReplSet } = await import('mongodb-memory-server');
49+
const replSet = await MongoMemoryReplSet.create({ replSet: { count: 1, name: 'rs0' } });
50+
return new URL(replSet.getUri('test')).href;
51+
}
52+
53+
private getExternalConnection(): string {
54+
const mongoUri = this.configService.get('MONGO_URI');
55+
const env = this.configService.get('NODE_ENV');
56+
const url = new URL(`${mongoUri.href}/data-capture-${env}`);
57+
const params = {
58+
directConnection: this.configService.get('MONGO_DIRECT_CONNECTION'),
59+
replicaSet: this.configService.get('MONGO_REPLICA_SET'),
60+
retryWrites: this.configService.get('MONGO_RETRY_WRITES'),
61+
w: this.configService.get('MONGO_WRITE_CONCERN')
62+
};
63+
for (const [key, value] of Object.entries(params)) {
64+
if (value) {
65+
url.searchParams.append(key, String(value));
66+
}
67+
}
68+
return url.href;
69+
}
770
}
871

9-
export type RuntimePrismaClient = ReturnType<typeof createPrismaClient>;
72+
export type RuntimePrismaClient = Awaited<
73+
ReturnType<(typeof PrismaModuleOptionsFactory)['prototype']['create']>
74+
>['client'];
1075

1176
export type PrismaModelWhereInputMap = {
1277
[K in PrismaModelName]: PrismaClient[PrismaModelKey<K>] extends {

apps/api/src/main.ts

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { AppFactory, ConfigService, PrismaModule } from '@douglasneuroinformatics/libnest';
1+
import { AppFactory, PrismaModule } from '@douglasneuroinformatics/libnest';
22

33
import { AssignmentsModule } from './assignments/assignments.module';
44
import { AuthModule } from './auth/auth.module';
5-
import { createPrismaClient } from './core/prisma';
5+
import { PrismaModuleOptionsFactory } from './core/prisma';
66
import { $Env } from './core/schemas/env.schema';
77
import { GatewayModule } from './gateway/gateway.module';
88
import { GroupsModule } from './groups/groups.module';
@@ -41,26 +41,7 @@ export default AppFactory.create({
4141
InstrumentRecordsModule,
4242
InstrumentsModule,
4343
PrismaModule.forRootAsync({
44-
inject: [ConfigService],
45-
useFactory: (configService: ConfigService) => {
46-
const mongoUri = configService.get('MONGO_URI');
47-
const env = configService.get('NODE_ENV');
48-
const url = new URL(`${mongoUri.href}/data-capture-${env}`);
49-
const params = {
50-
directConnection: configService.get('MONGO_DIRECT_CONNECTION'),
51-
replicaSet: configService.get('MONGO_REPLICA_SET'),
52-
retryWrites: configService.get('MONGO_RETRY_WRITES'),
53-
w: configService.get('MONGO_WRITE_CONCERN')
54-
};
55-
for (const [key, value] of Object.entries(params)) {
56-
if (value) {
57-
url.searchParams.append(key, String(value));
58-
}
59-
}
60-
return {
61-
client: createPrismaClient(url.href)
62-
};
63-
}
44+
useClass: PrismaModuleOptionsFactory
6445
}),
6546
SessionsModule,
6647
SetupModule,

0 commit comments

Comments
 (0)