{"_id":"@berniemac/event-sourcing-nestjs","_rev":"3-f488e583a5630cb002916e59b473597e","name":"@berniemac/event-sourcing-nestjs","dist-tags":{"latest":"1.1.7"},"versions":{"1.1.4":{"name":"@berniemac/event-sourcing-nestjs","version":"1.1.4","description":"NestJS module for implementing Event Sourcing.","main":"index.js","scripts":{"prebuild":"rm -rf dist","build":"tsc -p tsconfig.json","prepublish:npm":"npm run build","publish:npm":"npm publish --access public","prepublish:next":"npm run build","publish:next":"npm publish --access public --tag next","lint":"eslint \"{src,test}/**/*.ts\" --fix && npm run prettier","prettier":"prettier --write 'src/*.{ts, js}'"},"dependencies":{"eventstore":"^1.15.5","mongodb":"^3.5.2"},"devDependencies":{"@commitlint/cli":"^12.1.4","@commitlint/config-conventional":"^12.1.4","@nestjs/common":"^7.6.18","@nestjs/core":"^7.6.18","@nestjs/cqrs":"^7.0.1","@nestjs/platform-express":"^7.6.18","@types/node":"^15.12.4","@typescript-eslint/eslint-plugin":"^4.27.0","@typescript-eslint/parser":"^4.27.0","eslint":"^7.29.0","eslint-config-prettier":"^8.3.0","eslint-plugin-import":"^2.20.1","husky":"^6.0.0","prettier":"^2.0.1","reflect-metadata":"^0.1.13","rxjs":"^6.6.7","ts-node":"^10.0.0","tsconfig-paths":"^3.9.0","typescript":"^4.3.4"},"repository":{"type":"git","url":"git+https://github.com/bernarma/event-sourcing-nestjs.git"},"keywords":["nestjs","es","eventsourcing","cqrs","ddd"],"author":{"name":"ArkerLabs"},"license":"ISC","bugs":{"url":"https://github.com/bernarma/event-sourcing-nestjs/issues"},"homepage":"https://github.com/bernarma/event-sourcing-nestjs#readme","husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS"}},"directories":{"doc":"docs"},"gitHead":"aec775ce57b0ca5703306c80bb200147a1ee0396","_id":"@berniemac/event-sourcing-nestjs@1.1.4","_nodeVersion":"12.22.1","_npmVersion":"7.19.0","dist":{"integrity":"sha512-mdzmDLL+8T8GToV55uusAp2fOK2Qt1dtMkUDaVZSLBTE0SUaLtW47ctImBYv9U7vdeOPwQw8U/S1uRSMy/YCBQ==","shasum":"dc3d5e3dd5addca323cef5dcda1cb6e1a408daef","tarball":"https://registry.npmjs.org/@berniemac/event-sourcing-nestjs/-/event-sourcing-nestjs-1.1.4.tgz","fileCount":55,"unpackedSize":58060,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg1sbTCRA9TVsSAnZWagAAuCgP/RP84peq0xM/6cGr3TRu\nwJz+iOv3jpusDAzhCOrzAFxern7qSVvBfOgIWsBcVSRKoMAhWv1Ti+PiDHrH\nPQJJehfGe7/yP3b4OOGqlAztm/Kar/OF3RRmSIGmHjwJauAwrypSVvMYc6lv\nNE30IL+dc3+8izJpQwp2mp93SzfGT9sc6sTaK8+az8kpM4JeclGwvYqhwOE7\n5tNGpwjUG+2NO0UPKepQqdnku9/uHpiDvCLiQAuZP4C06T25f3SALwqXkXTu\nODpuJksVjwP0tmDfGVxdDDYDEYkoVDml56WUmhh7cMjiG09UViRce31j/B0x\npWjGYo9wy9DfO1Od/WMSdAPsiUE+NvF9tAWEGdRzqNaU4jhZHFPjTFI53soX\nLkxlW5miE/vee3JMCVT4Q/rnD8qufhLB8AJZMD+9AvDrVsLbhMrVV5gpxM6W\nIpzXXzy7RnYK4nOqdLpS6yylCuSY51MsjrVWw9Dn7HUpoVcardmp5bZDJ0Vf\n/HJaqf0kObKFnuoWJVnaVpoafkwj+6JGQMb5FyAqVo2Kh9fGe1SUEtzQWDl7\nTnRgH6Rbe6tTSSv7G1iYKHN8HyjAdOGKmBYuDcbMMq2vM9G623N9xmBhwRKx\n87F9GIBGUg6SVpg7iATSP3FRdSflIdJlJlrr9hW52TSuk38gTH+7Ckiotlhn\npw3U\r\n=B8Gb\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC1R2/+Qg9txrCjsLpS/tKrPsXHjzcw0A8gJ3sDTPCAmAIgF6edIqBE89UEXxh1TgSIXjNDaz3A5LyexAn+31/QyfU="}]},"_npmUser":{"name":"berniemac","email":"berniemac@outlook.com"},"maintainers":[{"name":"berniemac","email":"berniemac@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/event-sourcing-nestjs_1.1.4_1624688339022_0.7031213447913127"},"_hasShrinkwrap":false},"1.1.6":{"name":"@berniemac/event-sourcing-nestjs","version":"1.1.6","description":"NestJS module for implementing Event Sourcing with Snapshots.","main":"index.js","scripts":{"prebuild":"rm -rf dist","build":"tsc -p tsconfig.json","prepublish:npm":"npm run build","publish:npm":"npm publish --access public","prepublish:next":"npm run build","publish:next":"npm publish --access public --tag next","lint":"eslint \"{src,test}/**/*.ts\" --fix && npm run prettier","prettier":"prettier --write 'src/*.{ts, js}'"},"dependencies":{"eventstore":"^1.15.5","mongodb":"^3.5.2"},"devDependencies":{"@commitlint/cli":"^12.1.4","@commitlint/config-conventional":"^12.1.4","@nestjs/common":"^8.0.1","@nestjs/core":"^8.0.1","@nestjs/cqrs":"^8.0.0","@nestjs/platform-express":"^8.0.1","@types/node":"^16.3.1","@typescript-eslint/eslint-plugin":"^4.28.2","@typescript-eslint/parser":"^4.28.2","eslint":"^7.29.0","eslint-config-prettier":"^8.3.0","eslint-plugin-import":"^2.20.1","husky":"^7.0.1","prettier":"^2.0.1","reflect-metadata":"^0.1.13","rxjs":"^7.2.0","ts-node":"^10.0.0","tsconfig-paths":"^3.10.1","typescript":"^4.3.4"},"repository":{"type":"git","url":"git+https://github.com/bernarma/event-sourcing-nestjs.git"},"keywords":["nestjs","es","eventsourcing","cqrs","ddd"],"author":{"name":"ArkerLabs"},"license":"ISC","bugs":{"url":"https://github.com/bernarma/event-sourcing-nestjs/issues"},"homepage":"https://github.com/bernarma/event-sourcing-nestjs#readme","husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS"}},"directories":{"doc":"docs"},"gitHead":"473ba25892639f319951ce5580f9aca65c92d0c4","_id":"@berniemac/event-sourcing-nestjs@1.1.6","_nodeVersion":"12.22.1","_npmVersion":"7.19.1","dist":{"integrity":"sha512-buTdnYNIjvbQnbX3FT6rSugj05IQndV7uaPrSUlRjlDFbnNL0ZgPtMBs/YCvrdJnwBuVtGKhhfgkKvEtTIirOQ==","shasum":"a585cfd78990aaa4d35d7fa8df334b98bdb878e6","tarball":"https://registry.npmjs.org/@berniemac/event-sourcing-nestjs/-/event-sourcing-nestjs-1.1.6.tgz","fileCount":55,"unpackedSize":58314,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg62+cCRA9TVsSAnZWagAAAtwQAIL79bVLGSXuzyLcM4rN\nP13Mm61n1rdLZScqFUYT2Qw89FYYSFVvYEgOMhxNbslMoANI3Ir12sR7DS3G\nCwu5ZTjWCIwSqPSyq00Ny8gZs11NVOIqr2QiRBnapJlRonpLbUWaA7z9hm86\ni4ccf4HowMaHXOn47nCvPSR6uSmcb6IRMby3lONOyWYw3jJr5Nw4dBHNbtri\nvwj1chlwO45J5h1oF2M1GY6U9rtvqLERU8YpXmHo8cxJL9MihFco8fYgQi5R\naUDlk1P/nnZ0PXi37hoygDUY6C8M5YvV89cvwDSb+n6tCYHKJgqJTAM1vyn2\n+JBZZC8FjQOwht4ud6ZJuKp14NToq36O1mnkneTl+IdkUqlk63gIrkpmWUk5\nFHAMIOcG3m+v+dlY/T7wADpP0XiBUG9Zz7kQ3fHCX+vEqUAQ6YSJdUrZtBnG\nx9PBqNN/+IU3myIAlVwdDgOPFh5N57nQmMi/ICzRjiiYNrPQBFXpEZkshL1a\nQsEFuHGch96AdSkne+t2+VAsGdalf4ZoDDDDzYovQu4oS8nvKExHMJvWhAFR\nNo8jIDrjM5kEOei0vk/SiRvXY2oO2oF4wp5DXPPQkonctK7R34WcDZuRMfcB\nZIy94oUT2WH/f9CQBe8iDpnXtAVfbdiqIjJD8VisItg8zOu/ljwXN29xxFtv\nUI7/\r\n=a9QS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFypctz3hkV0CVQSresjSjkbO/PhCLS3+0iz4ASdZFpsAiEA7LdPI+yB+xDjv6JQABAT43Ju2KpsFmEUQroDcWzh7R0="}]},"_npmUser":{"name":"berniemac","email":"berniemac@outlook.com"},"maintainers":[{"name":"berniemac","email":"berniemac@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/event-sourcing-nestjs_1.1.6_1626042268289_0.39713425060987584"},"_hasShrinkwrap":false},"1.1.7":{"name":"@berniemac/event-sourcing-nestjs","version":"1.1.7","description":"NestJS module for implementing Event Sourcing with Snapshots.","main":"index.js","scripts":{"prebuild":"rm -rf dist","build":"tsc -p tsconfig.json","prepublish:npm":"npm run build","publish:npm":"npm publish --access public","prepublish:next":"npm run build","publish:next":"npm publish --access public --tag next","lint":"eslint \"{src,test}/**/*.ts\" --fix && npm run prettier","prettier":"prettier --write 'src/*.{ts, js}'"},"dependencies":{"eventstore":"^1.15.5","mongodb":"^3.5.2"},"devDependencies":{"@commitlint/cli":"^12.1.4","@commitlint/config-conventional":"^12.1.4","@nestjs/common":"^7.6.18","@nestjs/core":"^7.6.18","@nestjs/cqrs":"^7.0.1","@nestjs/platform-express":"^7.6.18","@types/node":"^15.12.4","@typescript-eslint/eslint-plugin":"^4.27.0","@typescript-eslint/parser":"^4.27.0","eslint":"^7.29.0","eslint-config-prettier":"^8.3.0","eslint-plugin-import":"^2.20.1","husky":"^6.0.0","prettier":"^2.0.1","reflect-metadata":"^0.1.13","rxjs":"^6.6.7","ts-node":"^10.0.0","tsconfig-paths":"^3.9.0","typescript":"^4.3.4"},"repository":{"type":"git","url":"git+https://github.com/bernarma/event-sourcing-nestjs.git"},"keywords":["nestjs","es","eventsourcing","cqrs","ddd"],"author":{"name":"ArkerLabs"},"license":"ISC","bugs":{"url":"https://github.com/bernarma/event-sourcing-nestjs/issues"},"homepage":"https://github.com/bernarma/event-sourcing-nestjs#readme","husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS"}},"directories":{"doc":"docs"},"gitHead":"473ba25892639f319951ce5580f9aca65c92d0c4","_id":"@berniemac/event-sourcing-nestjs@1.1.7","_nodeVersion":"12.22.1","_npmVersion":"7.19.1","dist":{"integrity":"sha512-T7BXogDDFgew9u/CDQ6N2+aAhQiTPe5mR8F02v23SkUGhn8kMAwEUICpq80gOF3GqjqAUd6tDPUmzOKUnhj74Q==","shasum":"f676b425706416119ef3990e70b6749207588dda","tarball":"https://registry.npmjs.org/@berniemac/event-sourcing-nestjs/-/event-sourcing-nestjs-1.1.7.tgz","fileCount":53,"unpackedSize":58112,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg7LfICRA9TVsSAnZWagAAAgkP/A0/a49gV2y5vfN11avt\n8ASEtafbKxTd+tA/yxgdK+bT0MjvYfjUasRV9m2aaFCB4SEYVCEupdDzz/XV\nFPYSnVivXmo1+w8Qu1oNxnhByQYsqwQMhegp5cIraD7gSoA/ILiFKbD9ekom\nC3yCMK7z6inFFzxXCWseJlqc+dBt1mbPUXv/m7clL4IqZw399kWBi+QPrwaR\n3OaBGMbA0wH3AwbsbSqT8q0ZEZ5qJXDDk2tBbSuAOyY5cQnyH+MoO0lvWwH2\npd/5yrIostSFOiEh+zXjimE+80/qt1YOsp7VONQQQYJmawK+ABCII5KKKXRX\n/9vvLXw5XBNoOiIrQdIFhtnOyux2lBczTBLP4/E9QXFU8XdQ9cknSeT5qs5v\nUYXCM+P7TH8VRH+kFzE4dkW1E3Jhi2kW38k8gI9jcyEBNWWKGw71U7uB/xeZ\nmFboC2I12o1vKxkiTlrlRpCFdKeHv88FuhE/HhgtGlXdz8vbWxE0QpwUT+f9\naQQTM1iG8m0p+PlSI4vCUcFqndVQAq90l4MHLeEmpR4DmcruwU9nX76KZdB5\ntgTfjygheAAP/dxl5N8tuusV+JDEQGt/NXe2m9NLUaI6tMYQdiV7BBBr+zVU\nYTZniWq2EJE6mdxkk39EDCdiXCZSVlYBSeKMoTMRLtQszWv2BG7HXFfvVuM3\nxfll\r\n=TwyS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCmsJvRYwttRQC7PIZFV0e68jBrgWVoCf3bo7OoNHhG5wIhAM27Yz/fgkEN5iQu0r/Ya736wnDnLFwycxj4bvrGgjci"}]},"_npmUser":{"name":"berniemac","email":"berniemac@outlook.com"},"maintainers":[{"name":"berniemac","email":"berniemac@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/event-sourcing-nestjs_1.1.7_1626126279705_0.9016509019645205"},"_hasShrinkwrap":false}},"time":{"created":"2021-06-26T06:18:58.957Z","1.1.4":"2021-06-26T06:18:59.369Z","modified":"2022-04-04T18:31:57.287Z","1.1.6":"2021-07-11T22:24:28.439Z","1.1.7":"2021-07-12T21:44:39.813Z"},"maintainers":[{"name":"berniemac","email":"berniemac@outlook.com"}],"description":"NestJS module for implementing Event Sourcing with Snapshots.","homepage":"https://github.com/bernarma/event-sourcing-nestjs#readme","keywords":["nestjs","es","eventsourcing","cqrs","ddd"],"repository":{"type":"git","url":"git+https://github.com/bernarma/event-sourcing-nestjs.git"},"author":{"name":"ArkerLabs"},"bugs":{"url":"https://github.com/bernarma/event-sourcing-nestjs/issues"},"license":"ISC","readme":"# ✨ Event Sourcing for Nestjs\n\n[![](https://badgen.net/npm/v/event-sourcing-nestjs)](https://www.npmjs.com/package/event-sourcing-nestjs) ![](https://badgen.net/npm/dt/event-sourcing-nestjs)\n\nLibrary that implements event sourcing using NestJS and his CQRS library.\n\n## ⭐️ Features\n\n- **StoreEventBus**: A class that replaces Nest's EventBus to also persists events in mongodb.\n- **StoreEventPublisher**: A class that replaces Nest's EventPublisher.\n- **ViewUpdaterHandler**: The EventBus will also delegate the Events to his View Updaters, so you can update your read database.\n- **Replay**: You can re-run stored events. This will only trigger the view updater handlers to reconstruct your read db.\n- **EventStore**: Get history of events for an aggregate.\n\n## 📖 Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Importing](#importing)\n  - [Events](#events)\n  - [Event emitter](#event-emitter)\n  - [Event Publisher](#event-publisher)\n  - [Get event history](#get-event-history)\n    - [Full example](#full-example)\n  - [View updaters](#view-updaters)\n    - [State of the art](#state-of-the-art)\n- [Reconstructing the view db](#reconstructing-the-view-db)\n- [Examples](#examples)\n\n## 🛠 Installation\n\n```bash\nnpm install event-sourcing-nestjs @nestjs/cqrs --save\n```\n\n## Usage\n\n### Importing\n\napp.module.ts\n\n```ts\nimport { Module } from '@nestjs/common';\nimport { EventSourcingModule } from 'event-sourcing-nestjs';\n\n@Module({\n  imports: [\n    EventSourcingModule.forRoot({\n      mongoURL: 'mongodb://localhost:27017/eventstore',\n    }),\n  ],\n})\nexport class ApplicationModule {}\n```\n\nImporting it in your modules\n\n```ts\nimport { Module } from '@nestjs/common';\nimport { EventSourcingModule } from 'event-sourcing-nestjs';\n\n@Module({\n  imports: [EventSourcingModule.forFeature()],\n})\nexport class UserModule {}\n```\n\n### Events\n\nYour events must extend the abstract class StorableEvent.\n\n```ts\nexport class UserCreatedEvent extends StorableEvent {\n  eventAggregate = 'user';\n  eventVersion = 1;\n  id = '_id_';\n}\n```\n\n### Event emitter\n\nInstead of using Nest's EventBus use StoreEventBus, so events will persist before their handlers are executed.\n\n```ts\nimport { CommandHandler, ICommandHandler } from '@nestjs/cqrs';\nimport { StoreEventBus } from 'event-sourcing-nestjs';\n\n@CommandHandler(CreateUserCommand)\nexport class CreateUserHandler implements ICommandHandler<CreateUserCommand> {\n  constructor(private readonly eventBus: StoreEventBus) {}\n\n  async execute(command: CreateUserCommand) {\n    this.eventBus.publish(new UserCreatedEvent(command.name));\n  }\n}\n```\n\n### Event Publisher\n\nUse **StoreEventPublisher** if you want to dispatch events from your AggregateRoot and store it before calling their handlers.\n\n```ts\nimport { CommandHandler, ICommandHandler } from '@nestjs/cqrs';\nimport { HeroRepository } from '../../repository/hero.repository';\nimport { KillDragonCommand } from '../impl/kill-dragon.command';\nimport { StoreEventPublisher } from 'event-sourcing-nestjs';\n\n@CommandHandler(KillDragonCommand)\nexport class KillDragonHandler implements ICommandHandler<KillDragonCommand> {\n  constructor(\n    private readonly repository: HeroRepository,\n    private readonly publisher: StoreEventPublisher,\n  ) {}\n\n  async execute(command: KillDragonCommand) {\n    const { heroId, dragonId } = command;\n    const hero = this.publisher.mergeObjectContext(\n      await this.repository.findOneById(heroId),\n    );\n    hero.killEnemy(dragonId);\n    hero.commit();\n  }\n}\n```\n\n### Get event history\n\nReconstruct an aggregate getting his event history.\n\n```ts\nconst aggregate = 'user';\nconst id = '_id_';\nconsole.log(await this.eventStore.getEvents(aggregate, id));\n```\n\n#### Full example\n\nhero-killed-dragon.event.ts\n\n```ts\nimport { StorableEvent } from 'event-sourcing-nestjs';\n\nexport class HeroKilledDragonEvent extends StorableEvent {\n  eventAggregate = 'hero';\n  eventVersion = 1;\n\n  constructor(public readonly id: string, public readonly dragonId: string) {\n    super();\n  }\n}\n```\n\nhero.model.ts\n\n```ts\nimport { AggregateRoot } from '@nestjs/cqrs';\n\nexport class Hero extends AggregateRoot {\n  public readonly id: string;\n\n  public dragonsKilled: string[] = [];\n\n  public state: any;\n\n  constructor(id: string, version?: number, state?: any) {\n    super();\n    this.id = id;\n    this.version = version;\n    this._state = state || {}; // alternatively merge state with this\n  }\n\n  killEnemy(enemyId: string) {\n    this.apply(new HeroKilledDragonEvent(this.id, enemyId));\n  }\n\n  onHeroKilledDragonEvent(event: HeroKilledDragonEvent) {\n    this.dragonsKilled.push(event.dragonId);\n  }\n}\n```\n\nhero.repository.ts\n\n```ts\nimport { Injectable } from '@nestjs/common';\nimport { Hero } from '../models/hero.model';\nimport { EventStore } from 'event-sourcing-nestjs';\n\n@Injectable()\nexport class HeroRepository {\n  constructor(private readonly eventStore: EventStore) {}\n\n  async findOneById(id: string): Promise<Hero> {\n    const hero = new Hero(id);\n    hero.loadFromHistory(await this.eventStore.getEvents('hero', id));\n    return hero;\n  }\n}\n```\n\n### View updaters\n\n#### State of the art\n\n![State of the art](https://raw.githubusercontent.com/ArkerLabs/event-sourcing-nestjs/master/docs/state.jpg)\n\nAfter emitting an event, use a view updater to update the read database state.\nThis view updaters will be used to recontruct the db if needed.\n\nRead more info about the Materialized View pattern [here](https://docs.microsoft.com/en-gb/azure/architecture/patterns/materialized-view)\n\n```ts\nimport { IViewUpdater, ViewUpdaterHandler } from 'event-sourcing-nestjs';\n\n@ViewUpdaterHandler(UserCreatedEvent)\nexport class UserCreatedUpdater implements IViewUpdater<UserCreatedEvent> {\n  async handle(event: UserCreatedEvent) {\n    // Save user into our view db\n  }\n}\n```\n\n## Reconstructing the view db\n\n```ts\nawait ReconstructViewDb.run(await NestFactory.create(AppModule.forRoot()));\n```\n\n## Examples\n\nYou can find a working example using the Materialized View pattern [here](https://github.com/ArkerLabs/event-sourcing-nestjs-example).\n\nAlso a working example with Nest aggregates working [here](https://github.com/Nytyr/nest-cqrs-eventsourcing-example).\n\n## 📝 Stay in touch\n\n- Author - [Nytyr](https://keybase.io/nytyr)\n- Website - [https://arkerlabs.com/](https://arkerlabs.com/)\n","readmeFilename":"README.md"}