Last active
May 21, 2020 10:19
-
-
Save Miczeq22/79ee1b82c20f75c65c7cf216f30815ec to your computer and use it in GitHub Desktop.
CQRS Article
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
abstract class CommandHandler<T extends Command<unknown>> { | |
constructor(public readonly type: string) {} | |
public abstract async execute(command: T); | |
} |
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
abstract class Command<T> { | |
constructor(public readonly type: string, public readonly payload: T) {} | |
} |
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
class CommandBus { | |
constructor(private readonly handlers: CommandHandler<any>[]) {} | |
public async execute(command: Command<unknown>) { | |
const handler = this.handlers.find( | |
(existingHandler) => existingHandler.type === command.type | |
); | |
if (!handler) { | |
throw new Error(`Handler for command: ${command.type} does not exist.`); | |
} | |
return handler.execute(command); | |
} | |
} |
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 registerCustomerAction = ( | |
payload: RegisterCustomerPayload, | |
context: ApplicationContext | |
) => context.commandBus.execute(new RegisterCustomerCommand(payload)); |
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
function getOrCreateProduct(data: ProductData) { | |
let existingProduct = productRepository.findByAttributes(data); | |
if (!existingProduct) { | |
existingProduct = productRepository.save(data); | |
} | |
return existingProduct; | |
} |
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
export const resolvers = { | |
Mutation: { | |
addCardToDeck, | |
removeCardFromDeck, | |
}, | |
Query: { | |
getCardsForDeck, | |
}, | |
}; |
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
interface GetUserEnrolledDecksQueryHandlerDependencies { | |
enrolledDeckRepository: EnrolledDeckRepository; | |
deckElasticView: ElasticView<Deck>; | |
storageClient: StorageClient; | |
} | |
export class GetUserEnrolledDecksQueryHandler extends QueryHandler< | |
GetUserEnrolledDecks, | |
GetUserEnrolledDecksQueryResult | |
> { | |
constructor( | |
private readonly dependencies: GetUserEnrolledDecksQueryHandlerDependencies, | |
) { | |
super(GET_USER_ENROLLED_DECKS_QUERY_TYPE); | |
} | |
public async execute({ payload: { userId } }: GetUserEnrolledDecks) { | |
const { | |
enrolledDeckRepository, | |
deckElasticView, | |
storageClient, | |
} = this.dependencies; | |
const enrolledDecks = await enrolledDeckRepository.getAllByUser(userId); | |
const { items } = await deckElasticView.findMany({ | |
ids: enrolledDecks.map(enrolledDeck => enrolledDeck.getDeckId()), | |
}); | |
return new GetUserEnrolledDecksQueryResult( | |
items.map(item => ({ | |
...item, | |
imgUrl: item.imgUrl | |
? storageClient.getPublicUrlResolver(item.imgUrl) | |
: '', | |
})), | |
); | |
} | |
} |
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
interface Dependencies { | |
customerRepository: CustomerRepository; | |
} | |
class RegisterCustomerCommandHandler extends CommandHandler< | |
RegisterCustomerCommand | |
> { | |
constructor(private readonly dependencies: Dependencies) { | |
super(REGISTER_CUSTOMER_COMMAND_TYPE); | |
} | |
public async execute({ payload }: RegisterCustomerCommand) { | |
const { customerRepository } = this.dependencies; | |
const { email } = payload; | |
const existingUser = await customerRepository.findByEmail(email); | |
if (existingUser) { | |
throw new Error(`User with email: "${email}" already exist.`); | |
} | |
await customerRepository.insert(payload); | |
} | |
} |
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
interface RegisterCustomerPayload { | |
email: string; | |
password: string; | |
name: string; | |
} | |
export const REGISTER_CUSTOMER_COMMAND_TYPE = "customer/register"; | |
class RegisterCustomerCommand extends Command< | |
RegisterCustomerPayload | |
> { | |
constructor(payload: RegisterCustomerPayload) { | |
super(REGISTER_CUSTOMER_COMMAND_TYPE, payload); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment