Skip to content

Commit eb71a1e

Browse files
committed
added two other varieties of module registration
1 parent 31441c5 commit eb71a1e

File tree

11 files changed

+192
-16
lines changed

11 files changed

+192
-16
lines changed

packages/server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"fastify": "^4.23.2",
2929
"fastify-type-provider-zod": "^1.1.9",
3030
"mongodb": "^6.1.0",
31-
"nanoid": "^4.0.2",
31+
"nanoid": "^3.3.7",
3232
"reflect-metadata": "^0.2.2",
3333
"rxjs": "^7.8.1",
3434
"ts-byob": "^1.0.3",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {DynamicModule} from "@nestjs/common";
2+
import {CART_REPO, ORDER_REPO, PRODUCT_REPO} from "./index";
3+
import {MemoryCartRepository} from "./cart.repo";
4+
import {InMemoryOrderRepository, InMemoryProductRepository} from "./fake";
5+
import {ProductTemplate} from "../types";
6+
7+
8+
export class MemoryModule {
9+
static forTests(products: ProductTemplate[]): DynamicModule {
10+
return {
11+
module: MemoryModule,
12+
providers: [
13+
14+
{
15+
provide: PRODUCT_REPO,
16+
useValue: new InMemoryProductRepository(products)
17+
},
18+
{
19+
provide: ORDER_REPO,
20+
useClass: InMemoryOrderRepository,
21+
},
22+
{
23+
provide: CART_REPO,
24+
useClass: MemoryCartRepository,
25+
}
26+
],
27+
exports: [PRODUCT_REPO, ORDER_REPO, CART_REPO]
28+
}
29+
}
30+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {MongoClient} from "mongodb";
2+
import {DynamicModule} from "@nestjs/common";
3+
import {CART_REPO, ORDER_REPO, PRODUCT_REPO} from "./index";
4+
import {MongoDBProductRepository} from "./product.repo";
5+
import {MongoDBOrderRepository} from "./order.repo";
6+
import {MemoryCartRepository} from "./cart.repo";
7+
8+
export class MongoDBModule {
9+
static forRoot(uri: string): DynamicModule {
10+
11+
return {
12+
module: MongoDBModule,
13+
providers: [
14+
{
15+
provide: "storeDB",
16+
useFactory: async () => {
17+
const mongo = await new MongoClient(uri, {
18+
connectTimeoutMS: 100,
19+
serverSelectionTimeoutMS: 100,
20+
socketTimeoutMS: 100
21+
}).connect();
22+
23+
return mongo.db("store");
24+
},
25+
},
26+
{
27+
provide: PRODUCT_REPO,
28+
useClass: MongoDBProductRepository
29+
},
30+
{
31+
provide: ORDER_REPO,
32+
useClass: MongoDBOrderRepository,
33+
},
34+
{
35+
provide: CART_REPO,
36+
useClass: MemoryCartRepository,
37+
}
38+
],
39+
exports: [PRODUCT_REPO, ORDER_REPO, CART_REPO]
40+
}
41+
}
42+
}

packages/server/src/adapters/order.repo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Collection, Db, ObjectId, WithId } from "mongodb";
22
import { Order } from "../types";
3-
import {Injectable} from "@nestjs/common";
3+
import {Inject, Injectable} from "@nestjs/common";
44

55
type MongoOrder = Omit<Order, "id">;
66
const docToOrder = ({_id, ...rest}: WithId<MongoOrder>) => Order.parse({id: _id.toString(), ...rest});
@@ -9,7 +9,7 @@ const docToOrder = ({_id, ...rest}: WithId<MongoOrder>) => Order.parse({id: _id.
99
export class MongoDBOrderRepository {
1010
private orders: Collection<MongoOrder>;
1111

12-
constructor(db: Db) {
12+
constructor(@Inject("storeDB") db: Db) {
1313
this.orders = db.collection("orders");
1414
}
1515

packages/server/src/adapters/product.repo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { Collection, Db, ObjectId, WithId } from "mongodb";
22
import { Product, ProductTemplate } from "../types";
3-
import {Injectable} from "@nestjs/common";
3+
import {Inject, Injectable} from "@nestjs/common";
44

55
const docToProduct = ({_id, ...rest}: WithId<ProductTemplate>) => Product.parse({id: _id.toString(), ...rest});
66

77
@Injectable()
88
export class MongoDBProductRepository {
99
private products: Collection<ProductTemplate>;
1010

11-
constructor(db: Db) {
11+
constructor(@Inject("storeDB") db: Db) {
1212
this.products = db.collection("products");
1313
}
1414

packages/server/src/app.module.ts renamed to packages/server/src/app.module.ioc.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import {CART_REPO, ORDER_REPO, PRODUCT_REPO} from "./adapters";
66
import {MemoryCartRepository} from "./adapters/cart.repo";
77

88
@Module({})
9-
export class AppModule {
9+
export class AppModuleInversionOfControl {
1010
static register(productRepo: ProductRepository, orderRepo: OrderRepository): DynamicModule {
1111
return {
12-
module: AppModule,
12+
module: AppModuleInversionOfControl,
1313
providers: [
1414
{
1515
provide: PRODUCT_REPO,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Module} from "@nestjs/common";
2+
import {CartController, CheckoutController, OrderController, ProductController} from "./controllers";
3+
import {MongoDBModule} from "./adapters/mongodb.module";
4+
5+
@Module({
6+
imports: [MongoDBModule.forRoot(`mongodb://root:[email protected]`)],
7+
controllers: [CartController, ProductController, OrderController, CheckoutController]
8+
})
9+
export class AppModuleOverrides {
10+
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {DynamicModule, Module} from "@nestjs/common";
2+
import {CartController, CheckoutController, OrderController, ProductController} from "./controllers";
3+
4+
5+
@Module({})
6+
export class AppModuleWithRegister {
7+
static register(adapters: DynamicModule) {
8+
return {
9+
imports: [adapters],
10+
controllers: [CartController, ProductController, OrderController, CheckoutController],
11+
module: AppModuleWithRegister
12+
}
13+
}
14+
}

packages/server/src/index.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import { MongoClient } from "mongodb";
22
import { MongoDBOrderRepository } from "./adapters/order.repo";
33
import { MongoDBProductRepository } from "./adapters/product.repo";
44
import {NestFactory} from "@nestjs/core";
5-
import {AppModule} from "./app.module";
5+
import {AppModuleInversionOfControl} from "./app.module.ioc";
6+
import {AppModuleOverrides} from "./app.module.overrides";
7+
import {AppModuleWithRegister} from "./app.module.register";
8+
import {MongoDBModule} from "./adapters/mongodb.module";
69

7-
async function startServer() {
10+
// @ts-ignore
11+
async function startServerIoC() {
812
const mongo = await new MongoClient(
913
`mongodb://root:[email protected]?retryWrites=true&writeConcern=majority`
1014
).connect();
@@ -13,11 +17,26 @@ async function startServer() {
1317
const productRepo = new MongoDBProductRepository(db);
1418
const orderRepo = new MongoDBOrderRepository(db);
1519

16-
const app = await NestFactory.create(AppModule.register(productRepo, orderRepo))
20+
const app = await NestFactory.create(AppModuleInversionOfControl.register(productRepo, orderRepo))
1721
app.enableCors({origin: "*"});
1822
await app.listen(8080);
1923
}
2024

21-
void startServer();
25+
// @ts-ignore
26+
async function startServerOverrides() {
27+
const app = await NestFactory.create(AppModuleOverrides)
28+
app.enableCors({origin: "*"});
29+
await app.listen(8080);
30+
}
31+
32+
async function startServerRegister() {
33+
const app = await NestFactory.create(AppModuleWithRegister.register(
34+
MongoDBModule.forRoot(`mongodb://root:[email protected]`)
35+
));
36+
app.enableCors({origin: "*"});
37+
await app.listen(8080);
38+
}
39+
40+
void startServerRegister();
2241

2342

packages/server/src/server.testkit.ts

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,68 @@
11
import {ProductTemplate} from "./types";
22
import {Test} from "@nestjs/testing";
33
import {InMemoryOrderRepository, InMemoryProductRepository} from "./adapters/fake";
4-
import {AppModule} from "./app.module";
5-
export async function createTestingModule(products: ProductTemplate[] = []) {
4+
import {AppModuleInversionOfControl} from "./app.module.ioc";
5+
import {AppModuleOverrides} from "./app.module.overrides";
6+
import {ORDER_REPO, PRODUCT_REPO} from "./adapters";
7+
import {MongoDBModule} from "./adapters/mongodb.module";
8+
import {Module} from "@nestjs/common";
9+
import {AppModuleWithRegister} from "./app.module.register";
10+
import {MemoryModule} from "./adapters/memory.module";
11+
export async function createTestingModuleWithIoC(products: ProductTemplate[] = []) {
612
const productRepo = new InMemoryProductRepository(products);
713
const orderRepo = new InMemoryOrderRepository();
814
const testingModule = await Test.createTestingModule({
9-
imports: [AppModule.register(productRepo, orderRepo)],
15+
imports: [AppModuleInversionOfControl.register(productRepo, orderRepo)],
1016
})
1117
.compile();
1218

1319
const nest = testingModule.createNestApplication();
1420
nest.enableCors({origin: "*"});
1521
await nest.init();
1622
return {nest, orderRepo, productRepo};
17-
}
23+
}
24+
25+
export async function createTestingModuleWithOverrides(products: ProductTemplate[] = []) {
26+
const productRepo = new InMemoryProductRepository(products);
27+
const orderRepo = new InMemoryOrderRepository();
28+
const testingModule = await Test.createTestingModule({
29+
imports: [AppModuleOverrides],
30+
})
31+
.overrideModule(MongoDBModule).useModule(NopModule) // this doesn't actually do anything, MongoDB needs to be available for connection even though we don't use it
32+
.overrideProvider(PRODUCT_REPO).useValue(productRepo)
33+
.overrideProvider(ORDER_REPO).useValue(orderRepo)
34+
.compile();
35+
36+
const nest = testingModule.createNestApplication();
37+
nest.enableCors({origin: "*"});
38+
await nest.init();
39+
return {nest, orderRepo, productRepo};
40+
}
41+
42+
export async function createTestingModuleWithRegister(products: ProductTemplate[] = []) {
43+
44+
const testingModule = await Test.createTestingModule({
45+
imports: [AppModuleWithRegister.register(MemoryModule.forTests(products))],
46+
})
47+
.compile();
48+
49+
const productRepo: InMemoryProductRepository = testingModule.get(PRODUCT_REPO);
50+
const orderRepo: InMemoryOrderRepository = testingModule.get(ORDER_REPO);
51+
52+
const nest = testingModule.createNestApplication();
53+
nest.enableCors({origin: "*"});
54+
await nest.init();
55+
return {nest, orderRepo, productRepo};
56+
}
57+
58+
// export const createTestingModule = createTestingModuleWithOverrides;
59+
// export const createTestingModule = createTestingModuleWithIoC;
60+
export const createTestingModule = createTestingModuleWithRegister;
61+
62+
@Module({
63+
providers: [{
64+
provide: "storeDB",
65+
useValue: null
66+
}],
67+
})
68+
class NopModule{}

0 commit comments

Comments
 (0)