Last active
January 22, 2019 15:51
-
-
Save mauricioklein/68d91ea4b839dfe27993d7999ec61421 to your computer and use it in GitHub Desktop.
CQRS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const uuidv1 = require('uuid/v1'); | |
class OrderId { | |
id: string | |
constructor(id: string) { | |
this.id = id | |
} | |
static fromString(id: string): OrderId { | |
return new this(id) | |
} | |
static generateNew(): OrderId { | |
return new this(uuidv1()) | |
} | |
equals(other: OrderId): boolean { | |
return this.id === other.id | |
} | |
toString(): string { | |
return this.id | |
} | |
} | |
const orderA = new OrderId("123") | |
const orderB = OrderId.generateNew() | |
const orderC = OrderId.fromString("123") | |
console.log("Order A:", orderA.toString()) | |
console.log("Order B:", orderB.toString()) | |
console.log("Order C:", orderC.toString()) | |
console.log("Order A equals to Order B?", orderA.equals(orderB)) | |
console.log("Order A equals to itself?", orderA.equals(orderA)) | |
console.log("Order A equals to Order C?", orderA.equals(orderC)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import uuidv1 from 'uuid/v1'; | |
import * as moment from 'moment' | |
const FORMAT: string = "YYYY-MM-DD HH:mm:ss" | |
class Timestamp { | |
unixTs: number | |
constructor(timestamp: string) { | |
const parsedDateTime = moment(timestamp, FORMAT) | |
if(!parsedDateTime.isValid()) throw `"${timestamp}" is not a valid datetime` | |
this.unixTs = parsedDateTime.unix() | |
} | |
equals(other: Timestamp): boolean { | |
return this.unixTs === other.unixTs | |
} | |
isBefore(other: Timestamp): boolean { | |
return (this.unixTs < other.unixTs) | |
} | |
isAfter(other: Timestamp): boolean { | |
return (this.unixTs > other.unixTs) | |
} | |
toString(): string { | |
return moment.unix(this.unixTs).format(FORMAT) | |
} | |
} | |
const ts1 = new Timestamp("2019-01-20 08:00:00") | |
const ts2 = new Timestamp("2019-01-22 11:12:00") | |
console.log("TS1", ts1.toString()); | |
console.log("TS2", ts2.toString()); | |
console.log("TS1 equals TS2?", ts1 === ts2); | |
console.log("TS1 before TS2?", ts1.isBefore(ts2)); | |
console.log("TS1 after TS2?", ts1.isAfter(ts2)); | |
const ts3 = new Timestamp("wicbniwdbvwibvb") | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as moment from 'moment' | |
const FORMAT: string = "YYYY-MM-DD HH:mm:ss" | |
class InvalidTimestampError extends Error { | |
constructor(timestamp) { | |
super(`${timestamp}" is not a valid datetime`) | |
} | |
} | |
class Timestamp { | |
private unixTs: number | |
constructor(timestamp: string) { | |
const parsedDateTime = moment(timestamp, FORMAT) | |
if(!parsedDateTime.isValid()) throw new InvalidTimestampError(timestamp) | |
this.unixTs = parsedDateTime.unix() | |
} | |
equals(other: Timestamp): boolean { | |
return this.unixTs === other.unixTs | |
} | |
isBefore(other: Timestamp): boolean { | |
return this.unixTs < other.unixTs | |
} | |
isAfter(other: Timestamp): boolean { | |
return this.unixTs > other.unixTs | |
} | |
toString(): string { | |
return moment.unix(this.unixTs).format(FORMAT) | |
} | |
} | |
class MemberRegistered { | |
private _id: string | |
private _name: string | |
private _email: string | |
private _registeredAt: Timestamp | |
constructor(id: string, name: string, email: string, registeredAt: Timestamp) { | |
this._id = id | |
this._name = name | |
this._email = email | |
this._registeredAt = registeredAt | |
} | |
get id(): string { | |
return this._id | |
} | |
get name(): string { | |
return this._name | |
} | |
get email(): string { | |
return this._email | |
} | |
get registeredAt(): Timestamp { | |
return this._registeredAt | |
} | |
} | |
const id = "123" | |
const name = "Max Mustermann" | |
const email = "[email protected]" | |
const registeredAt = new Timestamp("2019-01-20 08:00:00") | |
const event = new MemberRegistered(id, name, email, registeredAt) | |
console.log("ID:", event.id); | |
console.log("Name:", event.name); | |
console.log("Email:", event.email); | |
console.log("Registered at:", event.registeredAt.toString()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as moment from 'moment' | |
const FORMAT: string = "YYYY-MM-DD HH:mm:ss" | |
class InvalidTimestampError extends Error { | |
constructor(timestamp) { | |
super(`${timestamp}" is not a valid datetime`) | |
} | |
} | |
class Timestamp { | |
private unixTs: number | |
constructor(timestamp: string) { | |
const parsedDateTime = moment(timestamp, FORMAT) | |
if(!parsedDateTime.isValid()) throw new InvalidTimestampError(timestamp) | |
this.unixTs = parsedDateTime.unix() | |
} | |
equals(other: Timestamp): boolean { | |
return this.unixTs === other.unixTs | |
} | |
isBefore(other: Timestamp): boolean { | |
return this.unixTs < other.unixTs | |
} | |
isAfter(other: Timestamp): boolean { | |
return this.unixTs > other.unixTs | |
} | |
toString(): string { | |
return moment.unix(this.unixTs).format(FORMAT) | |
} | |
} | |
class MemberChangedTheirEmail { | |
private _memberId: string | |
private _oldEmail: string | |
private _newEmail: string | |
private _timestamp: Timestamp | |
constructor(memberId: string, oldEmail: string, newEmail: string, timestamp: Timestamp) { | |
this._memberId = memberId | |
this._oldEmail = oldEmail | |
this._newEmail = newEmail | |
this._timestamp = timestamp | |
} | |
get memberId(): string { | |
return this._memberId | |
} | |
get oldEmail(): string { | |
return this._oldEmail | |
} | |
get newEmail(): string { | |
return this._newEmail | |
} | |
get timestamp(): Timestamp { | |
return this._timestamp | |
} | |
} | |
const memberId = "123" | |
const oldEmail = "[email protected]" | |
const newEmail = "[email protected]" | |
const registeredAt = new Timestamp("2019-01-20 08:00:00") | |
const event = new MemberChangedTheirEmail(memberId, oldEmail, newEmail, registeredAt) | |
console.log("Member ID:", event.memberId); | |
console.log("Old email:", event.oldEmail); | |
console.log("New email:", event.newEmail); | |
console.log("Timestamp:", event.timestamp.toString()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as moment from 'moment' | |
import { appendFile } from 'fs' | |
const FORMAT: string = "YYYY-MM-DD HH:mm:ss" | |
class InvalidTimestampError extends Error { | |
constructor(timestamp) { | |
super(`${timestamp}" is not a valid datetime`) | |
} | |
} | |
class Timestamp { | |
private unixTs: number | |
constructor(timestamp: string) { | |
const parsedDateTime = moment(timestamp, FORMAT) | |
if(!parsedDateTime.isValid()) throw new InvalidTimestampError(timestamp) | |
this.unixTs = parsedDateTime.unix() | |
} | |
equals(other: Timestamp): boolean { | |
return this.unixTs === other.unixTs | |
} | |
isBefore(other: Timestamp): boolean { | |
return this.unixTs < other.unixTs | |
} | |
isAfter(other: Timestamp): boolean { | |
return this.unixTs > other.unixTs | |
} | |
toString(): string { | |
return moment.unix(this.unixTs).format(FORMAT) | |
} | |
} | |
class MemberRegistered { | |
private _id: string | |
private _name: string | |
private _email: string | |
private _registeredAt: Timestamp | |
constructor(id: string, name: string, email: string, registeredAt: Timestamp) { | |
this._id = id | |
this._name = name | |
this._email = email | |
this._registeredAt = registeredAt | |
} | |
get id(): string { | |
return this._id | |
} | |
get name(): string { | |
return this._name | |
} | |
get email(): string { | |
return this._email | |
} | |
get registeredAt(): Timestamp { | |
return this._registeredAt | |
} | |
} | |
class MemberChangedTheirEmail { | |
private _memberId: string | |
private _oldEmail: string | |
private _newEmail: string | |
private _timestamp: Timestamp | |
constructor(memberId: string, oldEmail: string, newEmail: string, timestamp: Timestamp) { | |
this._memberId = memberId | |
this._oldEmail = oldEmail | |
this._newEmail = newEmail | |
this._timestamp = timestamp | |
} | |
get memberId(): string { | |
return this._memberId | |
} | |
get oldEmail(): string { | |
return this._oldEmail | |
} | |
get newEmail(): string { | |
return this._newEmail | |
} | |
get timestamp(): Timestamp { | |
return this._timestamp | |
} | |
} | |
const LOG_FILE_PATH = "./events.log" | |
interface Handleble { | |
handle(event: any) | |
} | |
class LogEvents { | |
handle(event: any) { | |
appendFile(LOG_FILE_PATH, this.toMsg(event), err => { | |
if (err) console.error(`Failed to log event: ${err}`) | |
}); | |
} | |
private toMsg(event: any) { | |
return `Received an event of type ${event.constructor.name}\n` | |
} | |
} | |
const logEvents = new LogEvents | |
const memberId = "123" | |
const memberName = "Max Mustermann" | |
const oldEmail = "[email protected]" | |
const newEmail = "[email protected]" | |
const registeredAt = new Timestamp("2019-01-20 08:00:00") | |
const memberRegisteredEvent = new MemberRegistered(memberId, memberName, oldEmail, registeredAt) | |
const memberChangedEmailEvent = new MemberChangedTheirEmail(memberId, oldEmail, newEmail, registeredAt) | |
logEvents.handle(memberRegisteredEvent) | |
logEvents.handle(memberChangedEmailEvent) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as moment from 'moment' | |
import { appendFile } from 'fs' | |
import { listeners } from 'cluster'; | |
const FORMAT: string = "YYYY-MM-DD HH:mm:ss" | |
class InvalidTimestampError extends Error { | |
constructor(timestamp) { | |
super(`${timestamp}" is not a valid datetime`) | |
} | |
} | |
class Timestamp { | |
private unixTs: number | |
constructor(timestamp: string) { | |
const parsedDateTime = moment(timestamp, FORMAT) | |
if(!parsedDateTime.isValid()) throw new InvalidTimestampError(timestamp) | |
this.unixTs = parsedDateTime.unix() | |
} | |
equals(other: Timestamp): boolean { | |
return this.unixTs === other.unixTs | |
} | |
isBefore(other: Timestamp): boolean { | |
return this.unixTs < other.unixTs | |
} | |
isAfter(other: Timestamp): boolean { | |
return this.unixTs > other.unixTs | |
} | |
toString(): string { | |
return moment.unix(this.unixTs).format(FORMAT) | |
} | |
} | |
class MemberRegistered { | |
private _id: string | |
private _name: string | |
private _email: string | |
private _registeredAt: Timestamp | |
constructor(id: string, name: string, email: string, registeredAt: Timestamp) { | |
this._id = id | |
this._name = name | |
this._email = email | |
this._registeredAt = registeredAt | |
} | |
get id(): string { | |
return this._id | |
} | |
get name(): string { | |
return this._name | |
} | |
get email(): string { | |
return this._email | |
} | |
get registeredAt(): Timestamp { | |
return this._registeredAt | |
} | |
} | |
class MemberChangedTheirEmail { | |
private _memberId: string | |
private _oldEmail: string | |
private _newEmail: string | |
private _timestamp: Timestamp | |
constructor(memberId: string, oldEmail: string, newEmail: string, timestamp: Timestamp) { | |
this._memberId = memberId | |
this._oldEmail = oldEmail | |
this._newEmail = newEmail | |
this._timestamp = timestamp | |
} | |
get memberId(): string { | |
return this._memberId | |
} | |
get oldEmail(): string { | |
return this._oldEmail | |
} | |
get newEmail(): string { | |
return this._newEmail | |
} | |
get timestamp(): Timestamp { | |
return this._timestamp | |
} | |
} | |
const LOG_FILE_PATH = "./events.log" | |
interface Handleble { | |
handle(event: any) | |
} | |
class LogEvents { | |
handle(event: any) { | |
appendFile(LOG_FILE_PATH, this.toMsg(event), err => { | |
if (err) console.error(`Failed to log event: ${err}`) | |
}); | |
} | |
private toMsg(event: any) { | |
return `Received an event of type ${event.constructor.name}\n` | |
} | |
} | |
class EventDispatcher { | |
private listeners | |
constructor() { | |
this.listeners = [] | |
} | |
addListener(listener: Handleble) { | |
this.listeners.push(listener) | |
} | |
dispatch(event: any) { | |
this.listeners.forEach(listener => listener.handle(event)) | |
} | |
} | |
const memberId = "123" | |
const memberName = "Max Mustermann" | |
const oldEmail = "[email protected]" | |
const newEmail = "[email protected]" | |
const registeredAt = new Timestamp("2019-01-20 08:00:00") | |
const memberRegisteredEvent = new MemberRegistered(memberId, memberName, oldEmail, registeredAt) | |
const memberChangedEmailEvent = new MemberChangedTheirEmail(memberId, oldEmail, newEmail, registeredAt) | |
const logEvents = new LogEvents | |
const dispatcher = new EventDispatcher | |
dispatcher.addListener(logEvents) | |
dispatcher.dispatch(memberRegisteredEvent) | |
dispatcher.dispatch(memberChangedEmailEvent) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment