Skip to content

Commit

Permalink
Backend | NestJS CQRS - Upgrade to version 7
Browse files Browse the repository at this point in the history
  • Loading branch information
MateuszNaKodach authored May 15, 2020
1 parent 4fd2d33 commit 30b277d
Show file tree
Hide file tree
Showing 10 changed files with 2,680 additions and 2,364 deletions.
3 changes: 2 additions & 1 deletion backend/.prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"printWidth": 120,
"singleQuote": true,
"trailingComma": "all"
"trailingComma": "all",
"arrowParens": "avoid"
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,14 @@ export class EventStoreEventStorage implements EventStorage {
): Promise<void> {
const eventsInGivenStream = events.filter(event => event.streamId === eventStreamName.streamId);
const eventsToStore = eventsInGivenStream.map(e => EventStoreEventStorage.toStorageEventDto(e));
return this.storeEventsInEventStore(expectedVersion, eventsToStore, eventStreamName)
.toPromise()
.then();
return this.storeEventsInEventStore(expectedVersion, eventsToStore, eventStreamName).toPromise().then();
}

readEvents(eventStreamName: EventStreamName, toDate?: Date) {
const maxEventDate = toDate ? toDate : this.time();
return this.getEventsBy(eventStreamName).then(events =>
events
.filter(it =>
moment(it.occurredAt)
.utc()
.isSameOrBefore(moment(maxEventDate).utc()),
)
.filter(it => moment(it.occurredAt).utc().isSameOrBefore(moment(maxEventDate).utc()))
.sort((e1, e2) => moment(e1.occurredAt).valueOf() - moment(e2.occurredAt).valueOf()),
);
}
Expand Down
2,659 changes: 1,425 additions & 1,234 deletions backend/package-lock.json

Large diffs are not rendered by default.

57 changes: 30 additions & 27 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"",
"format": "prettier --write \"src/**/*.ts\" \"test-module/**/*.ts\" \"test-unit/**/*.ts\" \"libs/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:dev:eventstorage-inmemory": "cross-env EVENTSOURCING_MODE=inmemory nest start --watch",
Expand All @@ -22,6 +22,9 @@
"start:debug": "nest start --debug '0.0.0.0:9229' --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test-e2e,test-module,test-unit}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:all": "jest",
"test:all:watch": "jest --watch",
"test:all:cov": "jest --coverage",
Expand All @@ -35,49 +38,49 @@
"test:module:cov": "jest --coverage --config test-module/jest-module.json",
"test:debug": "node --inspect-brk=0.0.0.0:9229 -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config test-e2e/jest-e2e.json --passWithNoTests",
"ci-format": "prettier -c \"src/**/*.ts\" \"test/**/*.ts\" \"libs/**/*.ts\"",
"ci-format": "prettier -c \"src/**/*.ts\" \"test-module/**/*.ts\" \"test-unit/**/*.ts\" \"libs/**/*.ts\"",
"ci-lint": "eslint \"{src,apps,libs,test-e2e,test-module,test-unit}/**/*.ts\" --format codeframe"
},
"dependencies": {
"@nestjs/common": "^7.0.0",
"@nestjs/core": "^7.0.0",
"@nestjs/cqrs": "^6.1.0",
"@nestjs/platform-express": "^7.0.0",
"@nestjs/swagger": "^4.5.5",
"@nestjs/common": "^7.0.11",
"@nestjs/core": "^7.0.11",
"@nestjs/cqrs": "^7.0.0",
"@nestjs/platform-express": "^7.0.11",
"@nestjs/swagger": "^4.5.6",
"@nestjs/typeorm": "^7.0.0",
"class-transformer": "^0.2.3",
"class-validator": "^0.12.2",
"moment": "^2.24.0",
"pg": "^8.0.3",
"moment": "^2.25.3",
"pg": "^8.2.0",
"postgres": "^1.0.2",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.5.4",
"rxjs": "^6.5.5",
"swagger-ui-express": "^4.1.4",
"typeorm": "^0.2.24"
},
"devDependencies": {
"@nestjs/cli": "^7.0.0",
"@nestjs/cli": "^7.1.5",
"@nestjs/schematics": "^7.0.0",
"@nestjs/testing": "^7.0.0",
"@types/express": "^4.17.3",
"@types/jest": "25.1.4",
"@types/node": "^13.9.1",
"@types/supertest": "^2.0.8",
"@typescript-eslint/eslint-plugin": "^2.23.0",
"@typescript-eslint/parser": "^2.23.0",
"@nestjs/testing": "^7.0.11",
"@types/express": "^4.17.6",
"@types/jest": "25.2.2",
"@types/node": "^14.0.1",
"@types/supertest": "^2.0.9",
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"cross-env": "^7.0.2",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
"jest": "^25.1.0",
"prettier": "^1.19.1",
"eslint": "^7.0.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.20.2",
"jest": "25.5.4",
"prettier": "^2.0.5",
"supertest": "^4.0.2",
"ts-jest": "25.2.1",
"ts-loader": "^6.2.1",
"ts-node": "^8.6.2",
"ts-jest": "25.5.1",
"ts-loader": "^7.0.4",
"ts-node": "^8.10.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.7.4"
"typescript": "^3.9.2"
},
"jest": {
"moduleFileExtensions": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import { Inject, Module, OnModuleInit } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { InvitingApplicantsApplicationModule } from './application/inviting-applicants-application.module';
import { InvitingApplicantsInfrastructureModule } from './infrastructure/inviting-applicants-infrastructure.module';
import {
CancelApplicantInvitationPublicCommand,
InviteApplicantPublicCommand,
} from '@coders-board-library/public-messages';
import { InvitingApplicantsExternalCommandHandlersModule } from './presentation/external-command-handlers/inviting-applicants-external-command-handlers.module';
import { InvitingApplicantsWriteSideRestApiModule } from './presentation/rest-api/inviting-applicants-write-side-rest-api.module';
import {
EXTERNAL_COMMAND_SENDER,
ExternalCommandSender,
} from '../../shared-kernel/write-side/application/external-command-sender/external-command-sender';

const writeRestApi = InvitingApplicantsWriteSideRestApiModule;
const externalCommandHandlers = InvitingApplicantsExternalCommandHandlersModule;
Expand All @@ -23,38 +15,4 @@ const externalCommandHandlers = InvitingApplicantsExternalCommandHandlersModule;
InvitingApplicantsInfrastructureModule,
],
})
export class InvitingApplicantsWriteSideModule implements OnModuleInit {
constructor(
@Inject(EXTERNAL_COMMAND_SENDER)
private readonly commandBus: ExternalCommandSender,
) {}

//FIXME: Delete. Just to init some data.
async onModuleInit() {
const person = {
janKowalski: {
personalEmail: '[email protected]',
firstName: 'Jan',
lastName: 'Kowalski',
},
};
const inviteCommand = new InviteApplicantPublicCommand(
person.janKowalski.personalEmail,
person.janKowalski.firstName,
person.janKowalski.lastName,
);
const invitationId = await this.commandBus.send(inviteCommand);
if (randomInt(0, 1) === 0) {
setTimeout(() => {
this.commandBus.send(new CancelApplicantInvitationPublicCommand(invitationId));
}, 2000);
setTimeout(() => {
this.commandBus.send(new CancelApplicantInvitationPublicCommand(invitationId));
}, 10000);
}
}
}

function randomInt(min, max) {
return min + Math.floor((max - min) * Math.random());
}
export class InvitingApplicantsWriteSideModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export class NestJsExternalCommandSender implements ExternalCommandSender {
constructor(private readonly commandBus: CommandBus) {}

send<T extends PublicCommand>(command: T) {
return this.commandBus.execute(command);
return this.commandBus.execute<T>(command);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
ApplicantInvitationCancelledPublicEvent,
ApplicantInvitedPublicEvent,
CancelApplicantInvitationPublicCommand,
expectLastPublishedEventAsync, InviteApplicantPublicCommand,
expectLastPublishedEventAsync,
InviteApplicantPublicCommand,
} from '@coders-board-library/public-messages';
import {
EventPublisherSpy,
Expand All @@ -16,8 +17,8 @@ import {
} from '../../../src/shared-kernel/write-side/application/external-event-publisher/external-event-publisher';
import {
EXTERNAL_COMMAND_SENDER,
ExternalCommandSender
} from "../../../src/shared-kernel/write-side/application/external-command-sender/external-command-sender";
ExternalCommandSender,
} from '../../../src/shared-kernel/write-side/application/external-command-sender/external-command-sender';

/**
* Test of InvitingApplicants. In tests of logic we bypass presentation layer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { LastName } from '../../../../src/inviting-applicants/write-side/domain/
import { ApplicantInvitation } from '../../../../src/inviting-applicants/write-side/domain/applicant-invitation.aggregate-root';
import { ApplicantInvitationId } from '../../../../src/inviting-applicants/write-side/domain/applicant-invitation-id.valueobject';
import { expectDomainEvent } from '../../../../src/shared-kernel/write-side/domain/aggregate-root.test-utils';
import {ApplicantInvited} from "../../../../src/inviting-applicants/write-side/domain/event/applicant-invited.domain-event";
import {InvitingApplicantFailed} from "../../../../src/inviting-applicants/write-side/domain/event/inviting-applicant-failed.domain-event";
import {InvitationCancelled} from "../../../../src/inviting-applicants/write-side/domain/event/invitation-cancelled.domain-events";
import {CancelingApplicantInvitationFailed} from "../../../../src/inviting-applicants/write-side/domain/event/cancelling-applicant-invitation-failed.domain-event";
import { ApplicantInvited } from '../../../../src/inviting-applicants/write-side/domain/event/applicant-invited.domain-event';
import { InvitingApplicantFailed } from '../../../../src/inviting-applicants/write-side/domain/event/inviting-applicant-failed.domain-event';
import { InvitationCancelled } from '../../../../src/inviting-applicants/write-side/domain/event/invitation-cancelled.domain-events';
import { CancelingApplicantInvitationFailed } from '../../../../src/inviting-applicants/write-side/domain/event/cancelling-applicant-invitation-failed.domain-event';

const person = {
janKowalski: {
Expand Down Expand Up @@ -51,11 +51,7 @@ describe('Feature: Applicant invitation', () => {
describe('Given: An applicant which was invited', () => {
beforeEach(() => {
applicantInvitation.loadFromHistory([
ApplicantInvited.newFrom(
applicantInvitationId,
timeProvider.currentDate(),
{ ...person.janKowalski },
),
ApplicantInvited.newFrom(applicantInvitationId, timeProvider.currentDate(), { ...person.janKowalski }),
]);
});

Expand All @@ -80,11 +76,7 @@ describe('Feature: Applicant invitation', () => {
describe('Given: An applicant which was invited', () => {
beforeEach(() => {
applicantInvitation.loadFromHistory([
ApplicantInvited.newFrom(
applicantInvitationId,
timeProvider.currentDate(),
{ ...person.janKowalski },
),
ApplicantInvited.newFrom(applicantInvitationId, timeProvider.currentDate(), { ...person.janKowalski }),
]);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,8 @@ class SampleAggregateId implements AggregateId {
}

export namespace SampleDomainEvent {
abstract class AbstractSampleAbstractDomainEvent<
P = any
> extends AbstractDomainEvent<SampleAggregateId, P> {
constructor(
eventId: DomainEventId,
occurredAt: Date,
aggregateId: SampleAggregateId,
data: P,
) {
abstract class AbstractSampleAbstractDomainEvent<P = any> extends AbstractDomainEvent<SampleAggregateId, P> {
constructor(eventId: DomainEventId, occurredAt: Date, aggregateId: SampleAggregateId, data: P) {
super(eventId, occurredAt, aggregateId, data);
}

Expand All @@ -43,31 +36,15 @@ export namespace SampleDomainEvent {
numberVariable: number;
};

export class SomethingHappened extends AbstractSampleAbstractDomainEvent<
SomethingHappenedData
> {
static newFrom(
aggregateId: SampleAggregateId,
occurredAt: Date,
data: SomethingHappenedData,
) {
return new SomethingHappened(
DomainEventId.generate(),
occurredAt,
aggregateId,
data,
);
export class SomethingHappened extends AbstractSampleAbstractDomainEvent<SomethingHappenedData> {
static newFrom(aggregateId: SampleAggregateId, occurredAt: Date, data: SomethingHappenedData) {
return new SomethingHappened(DomainEventId.generate(), occurredAt, aggregateId, data);
}
}

export class SomethingWithoutEventHandlerHappened extends AbstractSampleAbstractDomainEvent<{}> {
static newFrom(aggregateId: SampleAggregateId, occurredAt: Date, data: {}) {
return new SomethingWithoutEventHandlerHappened(
DomainEventId.generate(),
occurredAt,
aggregateId,
data,
);
return new SomethingWithoutEventHandlerHappened(DomainEventId.generate(), occurredAt, aggregateId, data);
}
}
}
Expand All @@ -79,10 +56,7 @@ class SampleAggregateRoot extends AbstractAggregateRoot<SampleAggregateId> {
super(timeProvider);
}

doSomething(
id: SampleAggregateId,
command: { stringVariable: string; numberVariable: number },
) {
doSomething(id: SampleAggregateId, command: { stringVariable: string; numberVariable: number }) {
this.apply(
SampleDomainEvent.SomethingHappened.newFrom(id, this.currentDate, {
...command,
Expand All @@ -96,13 +70,7 @@ class SampleAggregateRoot extends AbstractAggregateRoot<SampleAggregateId> {
}

doSomethingWithoutEventHandler() {
this.apply(
SampleDomainEvent.SomethingWithoutEventHandlerHappened.newFrom(
this.id,
this.currentDate,
{},
),
);
this.apply(SampleDomainEvent.SomethingWithoutEventHandlerHappened.newFrom(this.id, this.currentDate, {}));
}
}

Expand Down Expand Up @@ -138,12 +106,8 @@ describe('Feature: Event Sourced Aggregate Root', () => {

describe('When: Invoke method without handler', () => {
it('Then: Event should not be applied', () => {
expect(() =>
sampleAggregateRoot.doSomethingWithoutEventHandler(),
).toThrow(
new Error(
'Handler for domain event SomethingWithoutEventHandlerHappened not found!',
),
expect(() => sampleAggregateRoot.doSomethingWithoutEventHandler()).toThrow(
new Error('Handler for domain event SomethingWithoutEventHandlerHappened not found!'),
);
});
});
Expand Down
Loading

0 comments on commit 30b277d

Please sign in to comment.