Skip to content

Commit 40d8ef4

Browse files
committed
Add course repository for Mongo
1 parent 08ffb74 commit 40d8ef4

File tree

14 files changed

+172
-36
lines changed

14 files changed

+172
-36
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Collection } from 'mongodb';
2+
import { Nullable } from '../../../../Shared/domain/Nullable';
3+
import { MongoRepository } from '../../../../Shared/infrastructure/persistence/mongo/MongoRepository';
4+
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
5+
import { Course } from '../../domain/Course';
6+
import { CourseDuration } from '../../domain/CourseDuration';
7+
import { CourseName } from '../../domain/CourseName';
8+
import { CourseRepository } from '../../domain/CourseRepository';
9+
import { CourseDocument } from './mongo/CourseDocument';
10+
11+
export class MongoCourseRepository extends MongoRepository<CourseDocument> implements CourseRepository {
12+
public async save(course: Course): Promise<void> {
13+
const document = toPersistence(course);
14+
15+
const collection = await this.coursesCollection();
16+
17+
await this.persist(document, collection);
18+
}
19+
20+
private async coursesCollection(): Promise<Collection<CourseDocument>> {
21+
return this.collection('courses');
22+
}
23+
24+
public async search(id: CourseId): Promise<Nullable<Course>> {
25+
const collection = await this.coursesCollection();
26+
27+
const document = await collection.findOne({ _id: id.value });
28+
29+
return document ? toDomain(document) : null;
30+
}
31+
}
32+
33+
const toPersistence = (source: Course): CourseDocument => ({
34+
_id: source.id.value,
35+
name: source.name.value,
36+
duration: source.duration.value
37+
});
38+
39+
const toDomain = (source: CourseDocument): Course =>
40+
new Course(new CourseId(source._id), new CourseName(source.name), new CourseDuration(source.duration));
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { MongoDocument } from '../../../../../Shared/infrastructure/persistence/mongo/MongoDocument';
2+
3+
export type CourseDocument = MongoDocument & {
4+
name: string;
5+
duration: string;
6+
};

src/Contexts/Shared/infrastructure/persistence/mongo/MongoClientFactory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class MongoClientFactory {
2222
}
2323

2424
private static async createAndConnectClient(): Promise<MongoClient> {
25-
const client = new MongoClient(config.get('mongo.url'));
25+
const client = new MongoClient(config.get('mongo.url'), { useUnifiedTopology: true });
2626

2727
await client.connect();
2828

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type MongoDocument = {
2+
_id: string;
3+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Collection, MongoClient } from 'mongodb';
2+
import { MongoDocument } from './MongoDocument';
3+
4+
export class MongoRepository<T extends MongoDocument> {
5+
constructor(private _client: Promise<MongoClient>) {}
6+
7+
protected client(): Promise<MongoClient> {
8+
return this._client;
9+
}
10+
11+
protected async collection(name: string): Promise<Collection<T>> {
12+
return (await this._client).db().collection(name);
13+
}
14+
15+
protected async persist(document: T, collection: Collection<T>): Promise<void> {
16+
await collection.updateOne({ _id: document._id } as any, { $set: document }, { upsert: true });
17+
}
18+
}

src/apps/mooc_backend/config/config.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ const convictConfig = convict({
1212
doc: 'The Mongo connection URL',
1313
format: String,
1414
env: 'MONGO_URL'
15-
},
16-
name: {
17-
doc: 'The Mongo database name',
18-
format: String,
19-
env: 'MONGO_DB_NAME'
2015
}
2116
}
2217
});

src/apps/mooc_backend/config/dependency-injection/application.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
services:
2+
Mooc.ConnectionManager:
3+
factory:
4+
class: ../../../../Contexts/Shared/infrastructure/persistence/mongo/MongoClientFactory
5+
method: "createClient"
6+
arguments: ["mooc"]
7+
28
Mooc.courses.CourseRepository:
3-
class: ../../../../Contexts/Mooc/Courses/infrastructure/FileCourseRepository
4-
arguments: []
9+
class: ../../../../Contexts/Mooc/Courses/infrastructure/persistence/MongoCourseRepository
10+
arguments: ["@Mooc.ConnectionManager"]
511

612
Mooc.courses.CourseCreator:
713
class: ../../../../Contexts/Mooc/Courses/application/CourseCreator
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
imports:
22
- { resource: ./application.yaml }
3+
4+
services:
5+
Mooc.EnvironmentArranger:
6+
factory:
7+
class: ../../../../../tests/Contexts/Shared/infrastructure/arranger/EnvironmentArrangerFactory
8+
method: createEnvironmentArranger
9+
arguments: ["@Mooc.ConnectionManager"]
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import container from '../../../../../../src/apps/mooc_backend/config/dependency-injection';
2+
import { CourseRepository } from '../../../../../../src/Contexts/Mooc/Courses/domain/CourseRepository';
3+
import { EnvironmentArranger } from '../../../../Shared/infrastructure/arranger/EnvironmentArranger';
4+
import { CourseMother } from '../../domain/CourseMother';
5+
6+
const repository: CourseRepository = container.get('Mooc.courses.CourseRepository');
7+
const environmentArranger: Promise<EnvironmentArranger> = container.get('Mooc.EnvironmentArranger');
8+
9+
beforeAll(async () => {
10+
await (await environmentArranger).arrange('courses');
11+
});
12+
13+
afterAll(async () => {
14+
await (await environmentArranger).close();
15+
});
16+
17+
describe('Save Course', () => {
18+
it('should save a course', async () => {
19+
const course = CourseMother.random();
20+
21+
await repository.save(course);
22+
});
23+
});
24+
25+
describe('Search Course', () => {
26+
it('should return an existing course', async () => {
27+
const course = CourseMother.random();
28+
29+
await repository.save(course);
30+
31+
expect(course).toEqual(await repository.search(course.id));
32+
});
33+
34+
it('should not return a non existing course', async () => {
35+
expect(await repository.search(CourseMother.random().id)).toBeFalsy();
36+
});
37+
});

tests/Contexts/Mooc/Courses/infrastructure/persistence/FileCourseRepository.test.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)