{"id":29701349,"url":"https://github.com/andrewwebber/cqrs-typescript","last_synced_at":"2025-10-09T04:46:09.086Z","repository":{"id":57210320,"uuid":"21223012","full_name":"andrewwebber/cqrs-typescript","owner":"andrewwebber","description":"CQRS implementation in typescript","archived":false,"fork":false,"pushed_at":"2017-01-23T22:05:33.000Z","size":41,"stargazers_count":31,"open_issues_count":0,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-07-02T09:10:35.657Z","etag":null,"topics":["cqrs","eventsourcing","javascript","typescript"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrewwebber.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-06-26T00:32:42.000Z","updated_at":"2024-04-01T19:37:40.000Z","dependencies_parsed_at":"2022-09-01T08:10:25.560Z","dependency_job_id":null,"html_url":"https://github.com/andrewwebber/cqrs-typescript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/andrewwebber/cqrs-typescript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewwebber%2Fcqrs-typescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewwebber%2Fcqrs-typescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewwebber%2Fcqrs-typescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewwebber%2Fcqrs-typescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrewwebber","download_url":"https://codeload.github.com/andrewwebber/cqrs-typescript/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewwebber%2Fcqrs-typescript/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266665813,"owners_count":23964974,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cqrs","eventsourcing","javascript","typescript"],"created_at":"2025-07-23T11:10:08.139Z","updated_at":"2025-10-09T04:46:04.047Z","avatar_url":"https://github.com/andrewwebber.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"cqrs-typescript\n===============\n\n###CQRS implementation in typescript.\n\n\n\nComponents avaliable:\n- Event Sourcing\n  - Interfaces for creating versioned events\n  - Base classes for creating an event sourced aggregates and raising versioned events  \n- Command processing\n  - Interfaces for creating commands\n  - Command bus for sending events\n  - Redis based command bus using ['rpoplpush'](http://redis.io/commands/rpoplpush)\n  - Command handling registry for signing up for command types\n- Event processing\n  - Interfaces for creating events\n  - Event bus for sending events\n  - Redis based event bus using ['rpoplpush'](http://redis.io/commands/rpoplpush)\n  - Event handling registry for signing up for command types\n\nView the tests for more examples on usage.\n\n####Event Sourcing\n\n```ts\n/// \u003creference path=\"mocha.d.ts\"/\u003e\n/// \u003creference path=\"should.d.ts\"/\u003e\n\nimport CQRS = require('cqrs-typescript');\nimport should = require('should');\nshould.equal('actual', 'actual');\n\ninterface ICreditAccountEvent extends CQRS.IVersionedEvent{\n    amount:number\n}\n\ninterface IDebitAccountEvent extends CQRS.IVersionedEvent{\n    amount:number\n}\n\nclass BankAccount extends CQRS.EventSourced{\n  constructor(id :string){\n    super(id);\n    this.balance = 0;\n  }\n\n  balance : number;\n\n  credit(amount:number) : void {\n      this.update({\n          name: 'CreditAccount',\n          amount: amount,\n          version: -1,\n          sourceId: ''\n      });\n  }\n\n  debit(amount:number) : void{\n    this.update({\n        name: 'DebitAccount',\n        amount: amount,\n        version: -1,\n        sourceId: ''\n      });\n  }\n\n  private onCreditAccount(e : ICreditAccountEvent):void{\n    this.balance += e.amount;\n  }\n\n  private onDebitAccount(e : IDebitAccountEvent):void{\n    this.balance -= e.amount;\n  }\n}\n\nvar account : BankAccount;\n\ndescribe('extending from \"EventSourced\" to create a \"bank account\"', function() {\n  it('should be ok to create one once supplying an id ', function() {\n    account = new BankAccount('1');\n  });\n\n  it('should be ok to credit the account to 100 by raising an event',function(){\n    account.credit(100);\n    account.balance.should.be.exactly(100);\n    account.getEvents().length.should.be.exactly(1);\n    account.getVersion().should.be.exactly(1);\n  });\n\n  it('should be ok to credit the account to 150 by raising an event',function(){\n    account.credit(50);\n    account.balance.should.be.exactly(150);\n    account.getEvents().length.should.be.exactly(2);\n    account.getVersion().should.be.exactly(2);\n  });\n\n  it('should be ok to debit the account by 100 by raising an event',function(){\n    account.debit(100);\n    account.balance.should.be.exactly(50);\n    account.getEvents().length.should.be.exactly(3);\n    account.getVersion().should.be.exactly(3);\n  });\n\n  it('should be ok to load a bank account from an event stream',function(){\n      var accountFromEvents = new BankAccount('1');\n      var events = account.getEvents();\n      accountFromEvents.loadFromEvents(events);\n      accountFromEvents.balance.should.be.exactly(account.balance);\n      accountFromEvents.getVersion().should.be.exactly(account.getVersion());\n  });\n});\n```\n\n####Redis based event sourcing repository\n```ts\nvar account = new BankAccount('2');\naccount.credit(100);\naccount.credit(100);\naccount.debit(50);\naccount.credit(100);\naccount.debit(200);\naccount.balance.should.be.exactly(50);\n\nvar provider = new CQRS.RedisEventSourcedRepository({ host: \"127.0.0.1\", port:6379});\nit('should connect to a specified Redis server',function(done){\n  provider.connect((error)=\u003e{\n    should.equal(error, null);\n    done();\n  });\n});\n\nit('should be able to persist an event stream for an given aggregate id',function(done){\n  var events = account.getEvents();\n  events.length.should.be.exactly(5);\n  provider.saveEventsByAggregateId(account.getId(),events, (error)=\u003e{\n      should.equal(error, null);\n      done();\n  });\n});\n\nit('should be able to retrieve an event stream by aggregate id and recreate an aggregate instance',function(done){\n  provider.getEventsByAggregateId(account.getId(),(error, events)=\u003e{\n    should.equal(error, null);\n    events.length.should.be.exactly(5);\n\n    var accountFromEvents = new BankAccount(account.getId());\n    accountFromEvents.loadFromEvents(events);\n    accountFromEvents.balance.should.be.exactly(account.balance);\n    done();\n  });\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewwebber%2Fcqrs-typescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrewwebber%2Fcqrs-typescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewwebber%2Fcqrs-typescript/lists"}