wechaty-cqrs
TypeScript icon, indicating that this package has built-in type declarations

0.12.5 • Public • Published

CQRS Wechaty

NPM Version NPM Ducksify Extension ES Modules

An event-driven architecture wrapper for Wechaty that applies the CQS principle by using separate Query and Command messages to retrieve and modify the bot state, respectively.

Command Query Responsibility Segregation (CQRS) Wechaty

Image source: Introducing Derivative Event Sourcing

Command Query Responsibility Separation (CQRS)

Command query responsibility separation (CQRS) generalises CQS to message-driven and event-driven architectures: it applies the CQS principle by using separate Query and Command messages to retrieve and modify data, respectively.

Wikipedia: Command–query separation

Command Query Responsibility Segregation (CQRS) Pattern

Image source: CQRS (command query responsibility segregation)

Motivation

Can we use Wechaty by only sending / receiving the Plain Old JavaScript Object (POJO)?

That's an Event-driven way, which will give us the following benifites:

  1. Better integration with Domain-driven Design (DDD)
  2. Decouple the sub-systems with the Wechaty instance completely
  3. Enable using Wechaty with Microservices
  4. Make it possible for providing an API endpoint with JSON request/responses
  5. etc.

So we decided to support the Event-driven Architecture by enabling the Event-driven Programming with Wechaty by publishing the wechaty-cqrs NPM module.

Features

  1. Convert Wechaty instance to a messaging bus$ with the from() function.
  2. Well-defined commands, queries, responses, and events payload creators.
  3. A great execute$() helper function for sending the events to the bus and get back the response.
  4. Well-defined events$ for the Wechaty events
  5. Well-defined sayables for build all the message contents
  6. Static typing with TypeScript with all events & streams
  7. Working perfect with the powerful RxJS

Usage

Install

npm install wechaty-cqrs wechaty

Quick start

Here's the CQRS version of the Wechaty ding/dong bot:

import * as CQRS    from 'wechaty-cqrs'
import * as WECHATY from 'wechaty'
import { filter, map, mergeMap }  from 'rxjs/operators'

const wechaty = WECHATY.WechatyBuilder.build()
await wechaty.init()

const bus$ = CQRS.from(wechaty)

bus$.pipe(
  filter(CQRS.isActionOf(CQRS.actions.messageReceivedEvent)),
  // MessageReceivedEvent -> Sayable
  map(messageId => CQRS.duck.actions.getSayablePayloadQuery(
    messageReceivedEvent.meta.puppetId,
    messageId,
  )),
  mergeMap(CQRS.execute$(bus$)(CQRS.duck.actions.getSayablePayloadQueryResponse)),
  // Log `sayable` to console
).subscribe(sayable =>
  console.info('Sayable:', sayable),
)

bus$.next(CQRS.duck.actions.startCommand(wechaty.puppet.id))

Getting Started

Here's a video introduction for CQRS Wechaty with live demo, presented by Huan:

CQRS Wechaty Getting Started

YouTube: https://youtu.be/kauxyPVa0jo

The getting started ding-dong-bot.ts in the video: https://github.com/wechaty/getting-started/blob/main/examples/cqrs/ding-dong-bot.ts

Diagrams

CQRS Events Structure

graph LR
  classDef event fill:DarkGoldenRod
  classDef command fill:blue
  classDef query fill:green

  subgraph Command
    C(VerbNounCommand):::command
  end

  subgraph Response
    RC(VerbNounCommandResponse)
    RQ(GetNounQueryResponse)
  end
    
  subgraph Query
    Q(GetNounQuery):::query
  end

  subgraph Event
    ER(ReceivedEvent):::event
  end

  C-->RC

  ER-->ER

  Q-->RQ

Command

sequenceDiagram
    participant Bus
    participant Redux
    participant Wechaty

    Bus->>Redux: ExecuteCommand
    Redux->>Wechaty: Call
    Wechaty->>Redux: Call Return (void)
    Redux->>Bus: ExecuteCommandResponse

Query

sequenceDiagram
    participant Bus
    participant Redux
    participant Wechaty

    Bus->>Redux: GetNounQuery
    Redux->>Wechaty: Call
    Wechaty->>Redux: Call Return (value)
    Redux->>Bus: GetNounQueryResponse

Event

sequenceDiagram
    participant Bus
    participant Redux
    participant Wechaty

    Wechaty->>Redux: ReceivedEvent
    Redux->>Bus: ReceivedEvent

API Reference

Read CQRS Wechaty API Reference at: https://paka.dev/npm/wechaty-cqrs

Blogs

Resources

History

main v1.12 (Mar 27, 2022)

  1. Classify action builders so that they will be compatible with Class events with NestJS #1
  2. execute$() helper function for sending the events to the bus and get back the response, with automatically type inferring.
  3. lots of typing enhancements.

Learn more from PR #3

v0.10 (Mar 17) Beta release

  • v0.9 (Mar 17,2022): Refactoring(clean) module exports
  • v0.7 (Mar 16, 2022): Refactoring execute$ with duck.actions builders.
  • v0.6 (Mar 13, 2022): Alpha release.
  • v0.4 (Mar 13, 2022): CQRS Ding/Dong BOT works as expected.
  • v0.2 (Mar 11, 2022): Unit tests all passed, DevOps enabled.
  • v0.0.1 (Mar 6, 2022): Init README & Draft design.

Author

Huan LI (李卓桓), Microsoft Regional Director, zixia@zixia.net

Profile of Huan LI (李卓桓) on StackOverflow

Copyright & License

  • Code & Docs © 2022 Huan (李卓桓) <zixia@zixia.net>
  • Code released under the Apache-2.0 License
  • Docs released under Creative Commons

Package Sidebar

Install

npm i wechaty-cqrs

Weekly Downloads

254

Version

0.12.5

License

Apache-2.0

Unpacked Size

1.19 MB

Total Files

1036

Last publish

Collaborators

  • zixia