Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send twit after a new course created #90

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b033d9b
move courseName to shared folder and update references
mgzamora Nov 28, 2020
20aab3b
update CourseName tests references
mgzamora Nov 28, 2020
62c56b0
remove unused reference
mgzamora Nov 28, 2020
144fa10
added new twit object with its properties
mgzamora Nov 28, 2020
6766596
added tests about twit object
mgzamora Nov 28, 2020
a83a424
added new course twit model and error
mgzamora Nov 29, 2020
f3b4434
added course created event
mgzamora Nov 29, 2020
21e77cf
added twit sender interface and fake implementation
mgzamora Nov 29, 2020
641f4cc
added send new course twit handler and use case
mgzamora Nov 29, 2020
8916b19
twit sender mock
mgzamora Nov 29, 2020
db95f79
test use case
mgzamora Nov 29, 2020
e235b5a
inject created classes
mgzamora Nov 29, 2020
d93c973
relocate application create course to a proper folder
mgzamora Nov 30, 2020
c41d634
added finder use case
mgzamora Nov 30, 2020
8fc6dc8
added get controller
mgzamora Dec 1, 2020
707e9b4
added get course route
mgzamora Dec 1, 2020
816952d
change get course response object in order to return primitive values
mgzamora Dec 1, 2020
c10e21b
added dependency injection configuration
mgzamora Dec 1, 2020
51434cf
added get course query handler tests
mgzamora Dec 1, 2020
fc1f07c
added course finder tests
mgzamora Dec 2, 2020
a1ddf94
added api test
mgzamora Dec 2, 2020
61ef769
added api test completed
mgzamora Dec 3, 2020
1890909
Feature/rename course (#1)
mgzamora Dec 5, 2020
03b0e01
Cqrs/first command (#2)
mgzamora Dec 11, 2020
83ab0f3
Cqrs/get all courses query (#3)
mgzamora Dec 13, 2020
f499a30
Feature/course like (#4)
mgzamora Dec 16, 2020
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
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ services:

mooc-backend:
<<: *default-app
command: bash -c "npm run build && npm run start"
command: bash -c "npm run build && npm run dev"
ports:
- 3000:3000

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Command } from '../../../../Shared/domain/Command';

export class ChangeDescriptionCourseCommand extends Command {
readonly id: string;
readonly description: string;

constructor(id: string, description: string) {
super();
this.id = id;
this.description = description;
}
}
34 changes: 0 additions & 34 deletions src/Contexts/Mooc/Courses/application/CourseCreator.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { CourseRepository } from '../../domain/CourseRepository';
import { Course } from '../../domain/Course';
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
import { CourseDuration } from '../../domain/CourseDuration';
import { EventBus } from '../../../../Shared/domain/EventBus';
import { CourseName } from '../../../Shared/domain/Courses/CourseName';
import { CourseDescription } from '../../domain/CourseDescription';

type Params = {
courseId: CourseId;
courseName: CourseName;
courseDuration: CourseDuration;
courseDescription: CourseDescription
};

export class CourseCreator {
private repository: CourseRepository;
private eventBus: EventBus;

constructor(repository: CourseRepository, eventBus: EventBus) {
this.repository = repository;
this.eventBus = eventBus;
}

async run({ courseId, courseName, courseDuration, courseDescription }: Params): Promise<void> {
const course = Course.create(
courseId,
courseName,
courseDuration,
courseDescription
);

await this.repository.save(course);
await this.eventBus.publish(course.pullDomainEvents());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Command } from '../../../../Shared/domain/Command';

type Params = {
id: string;
name: string;
duration: string;
description: string;
};

export class CreateCourseCommand extends Command {
readonly id: string;
readonly name: string;
readonly duration: string;
readonly description: string;

constructor({ id, name, duration, description }: Params) {
super();
this.id = id;
this.name = name;
this.duration = duration;
this.description = description;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { CreateCourseCommand } from './CreateCourseCommand';
import { CommandHandler } from '../../../Shared/domain/CommandHandler';
import { CommandHandler } from '../../../../Shared/domain/CommandHandler';
import { CourseCreator } from './CourseCreator';
import { Command } from '../../../Shared/domain/Command';
import { CourseId } from '../../Shared/domain/Courses/CourseId';
import { CourseName } from '../domain/CourseName';
import { CourseDuration } from '../domain/CourseDuration';
import { Command } from '../../../../Shared/domain/Command';
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
import { CourseDuration } from '../../domain/CourseDuration';
import { CourseName } from '../../../Shared/domain/Courses/CourseName';
import { CourseDescription } from '../../domain/CourseDescription';

export class CreateCourseCommandHandler implements CommandHandler<CreateCourseCommand> {
constructor(private courseCreator: CourseCreator) {}
Expand All @@ -17,6 +18,7 @@ export class CreateCourseCommandHandler implements CommandHandler<CreateCourseCo
const courseId = new CourseId(command.id);
const courseName = new CourseName(command.name);
const courseDuration = new CourseDuration(command.duration);
await this.courseCreator.run({ courseId, courseName, courseDuration });
const courseDescription = new CourseDescription(command.description);
await this.courseCreator.run({ courseId, courseName, courseDuration, courseDescription });
}
}
20 changes: 0 additions & 20 deletions src/Contexts/Mooc/Courses/application/CreateCourseCommand.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/Contexts/Mooc/Courses/application/CreateCourseRequest.ts

This file was deleted.

20 changes: 20 additions & 0 deletions src/Contexts/Mooc/Courses/application/GetCourse/CourseFinder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { CourseFinder as DomainCourseFinder } from '../../domain/CourseFinder';
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
import { CourseResponse } from '../../../Shared/domain/Courses/application/CourseResponse';

export type Params = {
courseId: CourseId;
};

export class CourseFinder {
private courseFinder: DomainCourseFinder;

constructor(courseFinder: DomainCourseFinder) {
this.courseFinder = courseFinder;
}

async run({ courseId }: Params): Promise<CourseResponse> {
const course = await this.courseFinder.run(courseId);
return new CourseResponse(course);
}
}
11 changes: 11 additions & 0 deletions src/Contexts/Mooc/Courses/application/GetCourse/GetCourseQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { GetCourseRequest } from './GetCourseRequest';
import { Query } from '../../../../Shared/domain/Query';

export class GetCourseQuery extends Query {
id: string;

constructor({ id }: GetCourseRequest) {
super();
this.id = id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { GetCourseQuery } from './GetCourseQuery';
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
import { CourseFinder } from './CourseFinder';
import { CourseResponse } from '../../../Shared/domain/Courses/application/CourseResponse';
import { QueryHandler } from '../../../../Shared/domain/QueryHandler';
import { Query } from '../../../../Shared/domain/Query';

export class GetCourseQueryHandler implements QueryHandler<GetCourseQuery, CourseResponse> {
constructor(private courseFinder: CourseFinder) {}

subscribedTo(): Query {
return GetCourseQuery;
}

async handle(query: GetCourseQuery): Promise<CourseResponse> {
const courseId = new CourseId(query.id);
return this.courseFinder.run({ courseId });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type GetCourseRequest = {
id: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Course } from '../../domain/Course';
import { CourseResponse } from '../../../Shared/domain/Courses/application/CourseResponse';
import { Nullable } from '../../../../Shared/domain/Nullable';
export class CoursesResponse {
readonly data: CourseResponse[];

constructor(courses: Nullable<Course[]>) {
this.data = [];
if (courses !== null) {
courses.forEach(course => {
this.data.push(new CourseResponse(course))
});
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { CourseFinder as DomainCourseFinder } from '../../domain/CourseFinder';
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
import { CourseResponse } from '../../../Shared/domain/Courses/application/CourseResponse';
import { CourseRepository } from '../../domain/CourseRepository';
import { Course } from '../../domain/Course';
import { CoursesResponse } from './CoursesResponse';
import { Nullable } from '../../../../Shared/domain/Nullable';

export class CoursesSearcher {
private repository: CourseRepository;

constructor(repository: CourseRepository) {
this.repository = repository;
}

async run(): Promise<CoursesResponse> {
const courses : Nullable<Course[]> = await this.repository.getAll();
return new CoursesResponse(courses);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Query } from '../../../../Shared/domain/Query';

export class GetCoursesQuery extends Query {

constructor() {
super();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { QueryHandler } from '../../../../Shared/domain/QueryHandler';
import { Query } from '../../../../Shared/domain/Query';
import { CoursesResponse } from './CoursesResponse';
import { GetCoursesQuery } from './GetCoursesQuery';
import { CoursesSearcher } from './CoursesSearcher';

export class GetCoursesQueryHandler implements QueryHandler<GetCoursesQuery, CoursesResponse> {
constructor(private coursesSearcher: CoursesSearcher) {}

subscribedTo(): Query {
return GetCoursesQuery;
}

async handle(query: GetCoursesQuery): Promise<CoursesResponse> {
return this.coursesSearcher.run();
}
}
21 changes: 21 additions & 0 deletions src/Contexts/Mooc/Courses/application/LikeCourse/CourseLiker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CourseId } from './../../../Shared/domain/Courses/CourseId';
import { CourseFinder } from '../../domain/CourseFinder';
import { UserId } from '../../domain/UserId';
import { CourseRepository } from '../../domain/CourseRepository';

type Params = {
courseId: CourseId;
userId: UserId;
};

export class CourseLiker {
constructor(private courseFinder: CourseFinder, private repository: CourseRepository) {}

async run({ courseId, userId }: Params): Promise<void> {
const course = await this.courseFinder.run(courseId);

course.like(userId);

await this.repository.save(course);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Command } from '../../../../Shared/domain/Command';

type Params = {
id: string;
userId: string;
};

export class LikeCourseCommand implements Command {
readonly id: string;
readonly userId: string;

constructor({ id, userId }: Params) {
this.id = id;
this.userId = userId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Command } from '../../../../Shared/domain/Command';
import { CommandHandler } from '../../../../Shared/domain/CommandHandler';
import { LikeCourseCommand } from './LikeCourseCommand';
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
import { CourseLiker } from './CourseLiker';
import { UserId } from '../../domain/UserId';
export class LikeCourseCommandHandler implements CommandHandler<LikeCourseCommand> {
constructor(private courseLiker: CourseLiker) {}

subscribedTo(): Command {
return LikeCourseCommand;
}

handle(command: LikeCourseCommand): Promise<void> {
const courseId = new CourseId(command.id);
const userId = new UserId(command.userId);
return this.courseLiker.run({ courseId, userId });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { CourseRepository } from '../../domain/CourseRepository';
import { CourseId } from '../../../Shared/domain/Courses/CourseId';
import { EventBus } from '../../../../Shared/domain/EventBus';
import { CourseName } from '../../../Shared/domain/Courses/CourseName';
import { CourseFinder } from '../../domain/CourseFinder';

type Params = {
courseId: CourseId;
courseName: CourseName;
};

export class CourseRenamer {
private courseFinder: CourseFinder;
private eventBus: EventBus;
private repository: CourseRepository;

constructor(courseFinder: CourseFinder, repository: CourseRepository, eventBus: EventBus) {
this.courseFinder = courseFinder;
this.eventBus = eventBus;
this.repository = repository;
}

async run({ courseId, courseName }: Params): Promise<void> {
const course = await this.courseFinder.run(courseId);
course.rename(courseName);

await this.repository.save(course);
await this.eventBus.publish(course.pullDomainEvents());
}
}
Loading