Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
dist/
.tmp
src/Contexts/Mooc/Courses/infrastructure/courses.*
26 changes: 23 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@types/convict": "^4.2.1",
"@types/errorhandler": "0.0.32",
"@types/express": "^4.17.1",
"@types/glob": "^7.1.1",
"@types/helmet": "0.0.44",
"@types/node": "~11.13.0",
"@types/uuid": "^3.4.5",
Expand All @@ -32,6 +33,7 @@
"copy": "^0.3.2",
"errorhandler": "^1.5.1",
"express": "^4.17.1",
"glob": "^7.1.6",
"helmet": "^3.21.1",
"http-status": "^1.3.2",
"mandrill-api": "^1.0.45",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import CourseRepository from '../domain/CourseRepository';
import Course from '../domain/Course';

export default class CreateCourse {
export default class CourseCreator {
private repository: CourseRepository;

constructor(repository: CourseRepository) {
Expand All @@ -11,6 +11,6 @@ export default class CreateCourse {
async run(id: string, name: string, duration: string): Promise<void> {
const course = new Course(id, name, duration);

this.repository.save(course);
return this.repository.save(course);
}
}
11 changes: 11 additions & 0 deletions src/Contexts/Mooc/Courses/domain/Course.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default class Course {
readonly id: string;
readonly name: string;
readonly duration: string;

constructor(id: string, name: string, duration: string) {
this.id = id;
this.name = name;
this.duration = duration;
}
}
5 changes: 5 additions & 0 deletions src/Contexts/Mooc/Courses/domain/CourseAlreadyExists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default class CourseAlreadyExists extends Error {
constructor(courseId: string) {
super(`Course ${courseId} already exists`);
}
}
8 changes: 8 additions & 0 deletions src/Contexts/Mooc/Courses/domain/CourseRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Course from './Course';
import { Nullable } from '../../../Shared/domain/Nullable';

export default interface CourseRepository {
save(course: Course): Promise<void>;

search(id: string): Promise<Nullable<Course>>;
}
27 changes: 27 additions & 0 deletions src/Contexts/Mooc/Courses/infrastructure/FileCourseRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import CourseRepository from '../domain/CourseRepository';
import Course from '../domain/Course';
import fs from 'fs';
import BSON from 'bson';
import { Nullable } from '../../../Shared/domain/Nullable';

export default class FileCourseRepository implements CourseRepository {
private FILE_PATH = `${__dirname}/courses`;

async save(course: Course): Promise<void> {
const filePath = this.filePath(course.id);
const data = BSON.serialize(course);

return fs.writeFileSync(filePath, data);
}

async search(id: string): Promise<Nullable<Course>> {
const filePath = this.filePath(id);
const exists = fs.existsSync(filePath);

return exists ? BSON.deserialize(fs.readFileSync(this.filePath(id))) : null;
}

private filePath(id: string): string {
return `${this.FILE_PATH}.${id}.repo`;
}
}
1 change: 1 addition & 0 deletions src/Contexts/Shared/domain/Nullable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Nullable<T> = T | null;
23 changes: 0 additions & 23 deletions src/Mooc/Courses/domain/Course.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/Mooc/Courses/domain/CourseRepository.ts

This file was deleted.

20 changes: 0 additions & 20 deletions src/Mooc/Courses/infrastructure/FileCourseRepository.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
services:
Mooc.courses.CourseRepository:
class: ../../../../Mooc/Courses/infrastructure/FileCourseRepository
class: ../../../../Contexts/Mooc/Courses/infrastructure/FileCourseRepository
arguments: []

Mooc.courses.CreateCourse:
class: ../../../../Mooc/Courses/application/CreateCourse
Mooc.courses.CourseCreator:
class: ../../../../Contexts/Mooc/Courses/application/CourseCreator
arguments: ["@Mooc.courses.CourseRepository"]

Apps.mooc.controllers.CreateCourseController:
class: ../../controllers/CreateCourseController
arguments: ["@Mooc.courses.CreateCourse"]
Apps.mooc.controllers.CoursePutController:
class: ../../controllers/CoursePutController
arguments: ["@Mooc.courses.CourseCreator"]

Apps.mooc.controllers.StatusController:
class: ../../controllers/StatusController
Apps.mooc.controllers.StatusGetController:
class: ../../controllers/StatusGetController
arguments: []
5 changes: 5 additions & 0 deletions src/apps/mooc_backend/controllers/Controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {Request, Response} from 'express';

export default interface Controller {
run(req: Request, res: Response): Promise<void>;
}
29 changes: 29 additions & 0 deletions src/apps/mooc_backend/controllers/CoursePutController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Request, Response } from 'express';
import CourseCreator from '../../../Contexts/Mooc/Courses/application/CourseCreator';
import httpStatus from 'http-status';
import Controller from './Controller';
import CourseAlreadyExists from '../../../Contexts/Mooc/Courses/domain/CourseAlreadyExists';

export default class CoursePutController implements Controller {
constructor(private courseCreator: CourseCreator) {}

async run(req: Request, res: Response) {
const id: string = req.params.id;
const name: string = req.body.name;
const duration: string = req.body.duration;

try {
await this.courseCreator.run(id, name, duration);
} catch (e) {

if (e instanceof CourseAlreadyExists) {
res.status(httpStatus.BAD_REQUEST).send(e.message);
} else {
res.status(httpStatus.INTERNAL_SERVER_ERROR).json(e);
}

}

res.status(httpStatus.CREATED).send();
}
}
21 changes: 0 additions & 21 deletions src/apps/mooc_backend/controllers/CreateCourseController.ts

This file was deleted.

8 changes: 0 additions & 8 deletions src/apps/mooc_backend/controllers/StatusController.ts

This file was deleted.

9 changes: 9 additions & 0 deletions src/apps/mooc_backend/controllers/StatusGetController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Request, Response } from 'express';
import httpStatus from 'http-status';
import Controller from './Controller';

export default class StatusGetController implements Controller {
async run(req: Request, res: Response) {
res.status(httpStatus.OK).send();
}
}
8 changes: 8 additions & 0 deletions src/apps/mooc_backend/routes/courses.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Express } from 'express';
import container from '../config/dependency-injection';
import CreateCourseController from '../controllers/CoursePutController';

export const register = (app: Express) => {
const controller: CreateCourseController = container.get('Apps.mooc.controllers.CoursePutController');
app.put('/courses/:id', controller.run.bind(controller));
};
8 changes: 0 additions & 8 deletions src/apps/mooc_backend/routes/create-course.route.ts

This file was deleted.

12 changes: 8 additions & 4 deletions src/apps/mooc_backend/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { Express } from 'express';
import { statusRoute } from './status.route';
import { createUserRoute } from './create-course.route';
import glob from 'glob';

export function registerRoutes(app: Express) {
statusRoute(app);
createUserRoute(app);
const routes = glob.sync(__dirname + '/**/*.route.*');
routes.map(route => register(route, app));
}

function register(routePath: string, app: Express) {
const route = require(routePath);
route.register(app);
}
8 changes: 4 additions & 4 deletions src/apps/mooc_backend/routes/status.route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Express } from 'express';
import container from '../config/dependency-injection';
import StatusController from '../controllers/StatusController';
import StatusController from '../controllers/StatusGetController';

export const statusRoute = (app: Express) => {
const controller: StatusController = container.get('Apps.mooc.controllers.StatusController');
app.get('/status', (req, res) => controller.create(req, res));
export const register = (app: Express) => {
const controller: StatusController = container.get('Apps.mooc.controllers.StatusGetController');
app.get('/status', controller.run.bind(controller));
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import Course from '../../../../src/Mooc/Courses/domain/Course';
import CreateCourse from '../../../../src/Mooc/Courses/application/CreateCourse';
import CourseRepository from '../../../../src/Mooc/Courses/domain/CourseRepository';
import Course from '../../../../src/Contexts/Mooc/Courses/domain/Course';
import CourseCreator from '../../../../src/Contexts/Mooc/Courses/application/CourseCreator';
import CourseRepository from '../../../../src/Contexts/Mooc/Courses/domain/CourseRepository';

describe('Create Course', () => {
describe('Course Creator', () => {
it('should create a valid course', async () => {
const save = jest.fn();
const repository: CourseRepository = {
save,
search: jest.fn()
};

const createCourse = new CreateCourse(repository);
const createCourse = new CourseCreator(repository);

const id = 'some-id';
const name = 'some-name';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Course from '../../../../src/Mooc/Courses/domain/Course';
import FileCourseRepository from '../../../../src/Mooc/Courses/infrastructure/FileCourseRepository';
import Course from '../../../../src/Contexts/Mooc/Courses/domain/Course';
import FileCourseRepository from '../../../../src/Contexts/Mooc/Courses/infrastructure/FileCourseRepository';

describe('Save Course', () => {
it('should have a course', () => {
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"moduleResolution": "node",
"sourceMap": false,
"rootDir": ".",
"strict": true,
"noEmit": false,
"resolveJsonModule": true,
"outDir": "./dist"
Expand Down