├── .commitlintrc.mjs
├── .eslintrc.json
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── ci.yml
│ └── quality.yml
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .lintstagedrc.mjs
├── .npmrc
├── .prettierrc.json
├── LICENSE
├── README.md
├── docs
└── images
│ └── logoasl.png
├── examples
└── banking
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── docker-compose.recreate.yaml
│ ├── docker-compose.yaml
│ ├── nest-cli.json
│ ├── package.json
│ ├── src
│ ├── account
│ │ ├── application
│ │ │ ├── command
│ │ │ │ ├── create-account.command.ts
│ │ │ │ ├── create-account.handler.ts
│ │ │ │ ├── create-deposit.command.ts
│ │ │ │ ├── create-deposit.handler.ts
│ │ │ │ ├── create-widthdrawal.command.ts
│ │ │ │ ├── create-widthdrawal.handler.ts
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── query
│ │ │ │ ├── get-account.handler.ts
│ │ │ │ ├── get-account.query.ts
│ │ │ │ ├── get-accounts.handler.ts
│ │ │ │ ├── get-accounts.query.ts
│ │ │ │ └── index.ts
│ │ │ └── services
│ │ │ │ ├── account-finder.interface.ts
│ │ │ │ └── index.ts
│ │ ├── domain
│ │ │ ├── event
│ │ │ │ ├── account-was-created.event.ts
│ │ │ │ ├── deposit-was-done.event.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── withdrawal-was-done.event.ts
│ │ │ ├── exception
│ │ │ │ ├── index.ts
│ │ │ │ └── invalid-title.ts
│ │ │ ├── index.ts
│ │ │ └── model
│ │ │ │ ├── account-id.ts
│ │ │ │ ├── account.ts
│ │ │ │ ├── amount.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── title.ts
│ │ │ │ └── transaction.ts
│ │ ├── dto
│ │ │ ├── index.ts
│ │ │ ├── request
│ │ │ │ ├── create-account.dto.ts
│ │ │ │ ├── create-transaction.dto.ts
│ │ │ │ └── index.ts
│ │ │ └── response
│ │ │ │ ├── account.dto.ts
│ │ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── infraestructure
│ │ │ ├── account.module.ts
│ │ │ ├── account.providers.ts
│ │ │ ├── controller
│ │ │ ├── account.controller.ts
│ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── read-model
│ │ │ ├── accounts
│ │ │ │ ├── account-was-created.projection.ts
│ │ │ │ ├── account.schema.ts
│ │ │ │ ├── deposit-was-done.projection.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── withdrawal-was-done.projection.ts
│ │ │ └── index.ts
│ │ │ └── services
│ │ │ ├── account-finder.service.ts
│ │ │ ├── account.service.ts
│ │ │ └── index.ts
│ ├── app.module.ts
│ ├── console.ts
│ ├── main.ts
│ ├── user
│ │ ├── application
│ │ │ ├── command
│ │ │ │ ├── create-user.handler.ts
│ │ │ │ ├── create-user.query.ts
│ │ │ │ ├── delete-user.handler.ts
│ │ │ │ ├── delete-user.query.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── update-user.handler.ts
│ │ │ │ └── update-user.query.ts
│ │ │ ├── index.ts
│ │ │ ├── query
│ │ │ │ ├── get-user.handler.ts
│ │ │ │ ├── get-user.query.ts
│ │ │ │ ├── get-users.handler.ts
│ │ │ │ ├── get-users.query.ts
│ │ │ │ └── index.ts
│ │ │ └── services
│ │ │ │ ├── index.ts
│ │ │ │ └── user-finder.interface.ts
│ │ ├── domain
│ │ │ ├── event
│ │ │ │ ├── index.ts
│ │ │ │ ├── password-was-updated.event.ts
│ │ │ │ ├── user-was-created.event.ts
│ │ │ │ └── user-was-deleted.event.ts
│ │ │ ├── index.ts
│ │ │ └── model
│ │ │ │ ├── index.ts
│ │ │ │ ├── password.ts
│ │ │ │ ├── user-id.ts
│ │ │ │ ├── user.ts
│ │ │ │ └── username.ts
│ │ ├── dto
│ │ │ ├── index.ts
│ │ │ ├── request
│ │ │ │ ├── create-user.dto.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── update-user.dto.ts
│ │ │ └── response
│ │ │ │ ├── index.ts
│ │ │ │ └── user.dto.ts
│ │ ├── index.ts
│ │ └── infraestructure
│ │ │ ├── controller
│ │ │ ├── index.ts
│ │ │ └── user.controller.ts
│ │ │ ├── index.ts
│ │ │ ├── read-model
│ │ │ ├── index.ts
│ │ │ └── users
│ │ │ │ ├── index.ts
│ │ │ │ ├── password-was-updated.projection.ts
│ │ │ │ ├── user-was-created.projection.ts
│ │ │ │ ├── user-was-deleted.projection.ts
│ │ │ │ └── user.schema.ts
│ │ │ ├── services
│ │ │ ├── index.ts
│ │ │ ├── user-finder.service.ts
│ │ │ └── user.service.ts
│ │ │ ├── user.module.ts
│ │ │ └── user.providers.ts
│ └── utils
│ │ ├── catch.error.ts
│ │ └── index.ts
│ ├── tsconfig.build.json
│ └── tsconfig.json
├── package.json
├── packages
└── nestjs-eventstore
│ ├── .dockerignore
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── src
│ ├── aggregate.repository.ts
│ ├── crypto
│ │ ├── aes
│ │ │ ├── create-aes-key.ts
│ │ │ ├── decrypt-with-aes-key.ts
│ │ │ ├── encrypt-with-aes-key.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── hash
│ │ │ ├── generate-hash.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── key.dto.ts
│ │ └── key.schema.ts
│ ├── decorators
│ │ ├── index.ts
│ │ └── inject-repository.decorator.ts
│ ├── domain
│ │ ├── exceptions
│ │ │ ├── domain-error.ts
│ │ │ ├── id-already-registered.error.ts
│ │ │ ├── id-not-found.error.ts
│ │ │ ├── index.ts
│ │ │ ├── invalid-event-error.ts
│ │ │ └── invalid-id-error.ts
│ │ ├── index.ts
│ │ └── models
│ │ │ ├── aggregate-root.ts
│ │ │ ├── event.ts
│ │ │ ├── id.spec.ts
│ │ │ ├── id.ts
│ │ │ ├── index.ts
│ │ │ ├── value-object.spec.ts
│ │ │ └── value-object.ts
│ ├── errors
│ │ ├── index.ts
│ │ ├── key-not-found.error.ts
│ │ └── transformer-not-found.error.ts
│ ├── eventstore-core.module.ts
│ ├── eventstore.cli.ts
│ ├── eventstore.config.ts
│ ├── eventstore.constants.ts
│ ├── eventstore.mapper.ts
│ ├── eventstore.module.ts
│ ├── eventstore.ts
│ ├── index.ts
│ ├── interfaces
│ │ ├── eventstore-module.interface.ts
│ │ ├── index.ts
│ │ └── transformer.type.ts
│ ├── services
│ │ ├── index.ts
│ │ ├── key.service.spec.ts
│ │ ├── key.service.ts
│ │ ├── projections.service.ts
│ │ └── transformer.service.ts
│ └── utils
│ │ ├── index.ts
│ │ └── repository.ts
│ ├── tsconfig.json
│ └── tsup.config.ts
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
/.commitlintrc.mjs:
--------------------------------------------------------------------------------
1 | export default { extends: ['@commitlint/config-conventional'] }
2 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "plugin:unicorn/recommended",
4 | "plugin:@typescript-eslint/recommended",
5 | "plugin:prettier/recommended"
6 | ],
7 | "parser": "@typescript-eslint/parser",
8 | "plugins": [
9 | "@typescript-eslint",
10 | "import",
11 | "simple-import-sort",
12 | "sort",
13 | "unused-imports"
14 | ],
15 | "root": true,
16 | "ignorePatterns": "**/dist/*",
17 | "rules": {
18 | "@typescript-eslint/no-shadow": "error",
19 | "@typescript-eslint/no-unused-vars": [
20 | "error",
21 | { "ignoreRestSiblings": true }
22 | ],
23 | "default-case-last": "error",
24 | "default-param-last": "error",
25 | "dot-notation": "error",
26 | "eqeqeq": "error",
27 | "import/first": "error",
28 | "import/newline-after-import": "error",
29 | "import/no-duplicates": "error",
30 | "no-shadow": "off",
31 | "simple-import-sort/exports": "error",
32 | "simple-import-sort/imports": "error",
33 | "sort/destructuring-properties": "error",
34 | "sort/object-properties": "error",
35 | "sort/type-properties": "error",
36 | "unicorn/no-null": "off",
37 | "unicorn/no-array-reduce": "off",
38 | "unicorn/no-process-exit": "off",
39 | "unicorn/prevent-abbreviations": "off",
40 | "unused-imports/no-unused-imports": "error"
41 | },
42 | "overrides": [
43 | {
44 | "files": "examples/**/*.ts",
45 | "rules": {
46 | "unicorn/prefer-top-level-await": "off"
47 | }
48 | }
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Version [e.g. 22]
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 |
9 | jobs:
10 | test:
11 | name: 'Test'
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | node-version: [18.x, 20.x]
16 | steps:
17 | - name: Checkout
18 | uses: actions/checkout@v3
19 |
20 | - name: Setup pnpm
21 | uses: pnpm/action-setup@v4.0.0
22 | with:
23 | version: 9.6.0
24 |
25 | - name: Use Node.js ${{ matrix.node-version }}
26 | uses: actions/setup-node@v2
27 | with:
28 | node-version: ${{ matrix.node-version }}
29 | cache: 'pnpm'
30 |
31 | - name: Install dependencies
32 | run: pnpm install --frozen-lockfile --prefer-offline
33 |
34 | - name: Run tests
35 | run: pnpm test
--------------------------------------------------------------------------------
/.github/workflows/quality.yml:
--------------------------------------------------------------------------------
1 | name: Quality
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 |
9 | jobs:
10 | prettier:
11 | name: 'Prettier'
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v3
16 |
17 | - name: Setup pnpm
18 | uses: pnpm/action-setup@v4.0.0
19 | with:
20 | version: 9.6.0
21 |
22 | - name: Use Node.js 18
23 | uses: actions/setup-node@v3
24 | with:
25 | node-version: '18'
26 | cache: 'pnpm'
27 |
28 | - name: Install dependencies
29 | run: pnpm install --frozen-lockfile --prefer-offline
30 |
31 | - name: Run Prettier check
32 | run: pnpm run prettier-check
33 |
34 | eslint:
35 | name: 'ESLint'
36 | runs-on: ubuntu-latest
37 | steps:
38 | - name: Checkout
39 | uses: actions/checkout@v3
40 |
41 | - name: Setup pnpm
42 | uses: pnpm/action-setup@v4.0.0
43 | with:
44 | version: 9.6.0
45 |
46 | - name: Use Node.js 18
47 | uses: actions/setup-node@v3
48 | with:
49 | node-version: '18'
50 | cache: 'pnpm'
51 |
52 | - name: Install dependencies
53 | run: pnpm install --frozen-lockfile --prefer-offline
54 |
55 | - name: Run ESLint check
56 | run: pnpm run lint
57 |
58 | types:
59 | name: 'TypeScript'
60 | runs-on: ubuntu-latest
61 | steps:
62 | - name: Checkout
63 | uses: actions/checkout@v3
64 |
65 | - name: Setup pnpm
66 | uses: pnpm/action-setup@v4.0.0
67 | with:
68 | version: 9.6.0
69 |
70 | - name: Use Node.js 18
71 | uses: actions/setup-node@v3
72 | with:
73 | node-version: '18'
74 | cache: 'pnpm'
75 |
76 | - name: Install dependencies
77 | run: pnpm install --frozen-lockfile --prefer-offline
78 |
79 | - name: Run TypeScript type check
80 | run: pnpm run type-check
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # Snowpack dependency directory (https://snowpack.dev/)
46 | web_modules/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Optional stylelint cache
58 | .stylelintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variable files
76 | .env
77 | .env.development.local
78 | .env.test.local
79 | .env.production.local
80 | .env.local
81 |
82 | # parcel-bundler cache (https://parceljs.org/)
83 | .cache
84 | .parcel-cache
85 |
86 | # Next.js build output
87 | .next
88 | out
89 |
90 | # Nuxt.js build / generate output
91 | .nuxt
92 | dist
93 |
94 | # Gatsby files
95 | .cache/
96 | # Comment in the public line in if your project uses Gatsby and not Next.js
97 | # https://nextjs.org/blog/next-9-1#public-directory-support
98 | # public
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # vuepress v2.x temp and cache directory
104 | .temp
105 | .cache
106 |
107 | # Docusaurus cache and generated files
108 | .docusaurus
109 |
110 | # Serverless directories
111 | .serverless/
112 |
113 | # FuseBox cache
114 | .fusebox/
115 |
116 | # DynamoDB Local files
117 | .dynamodb/
118 |
119 | # TernJS port file
120 | .tern-port
121 |
122 | # Stores VSCode versions used for testing VSCode extensions
123 | .vscode-test
124 |
125 | # yarn v2
126 | .yarn/cache
127 | .yarn/unplugged
128 | .yarn/build-state.yml
129 | .yarn/install-state.gz
130 | .pnp.*
131 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | npx --no -- commitlint --edit
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx lint-staged
2 |
--------------------------------------------------------------------------------
/.lintstagedrc.mjs:
--------------------------------------------------------------------------------
1 | import { relative } from 'path'
2 |
3 | const buildEslintCommand = (filenames) =>
4 | `pnpm eslint --fix ${filenames
5 | .map((f) => relative(process.cwd(), f))
6 | .join(' ')}`
7 |
8 | export default {
9 | '*.{js,jsx,ts,tsx}': [buildEslintCommand],
10 | }
11 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers = true
2 | strict-peer-dependencies = false
3 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "trailingComma": "all"
5 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | EUROPEAN UNION PUBLIC LICENCE v. 1.2
2 | EUPL © the European Union 2007, 2016
3 |
4 | This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
5 | below) which is provided under the terms of this Licence. Any use of the Work,
6 | other than as authorised under this Licence is prohibited (to the extent such
7 | use is covered by a right of the copyright holder of the Work).
8 |
9 | The Work is provided under the terms of this Licence when the Licensor (as
10 | defined below) has placed the following notice immediately following the
11 | copyright notice for the Work:
12 |
13 | Licensed under the EUPL
14 |
15 | or has expressed by any other means his willingness to license under the EUPL.
16 |
17 | 1. Definitions
18 |
19 | In this Licence, the following terms have the following meaning:
20 |
21 | - ‘The Licence’: this Licence.
22 |
23 | - ‘The Original Work’: the work or software distributed or communicated by the
24 | Licensor under this Licence, available as Source Code and also as Executable
25 | Code as the case may be.
26 |
27 | - ‘Derivative Works’: the works or software that could be created by the
28 | Licensee, based upon the Original Work or modifications thereof. This Licence
29 | does not define the extent of modification or dependence on the Original Work
30 | required in order to classify a work as a Derivative Work; this extent is
31 | determined by copyright law applicable in the country mentioned in Article 15.
32 |
33 | - ‘The Work’: the Original Work or its Derivative Works.
34 |
35 | - ‘The Source Code’: the human-readable form of the Work which is the most
36 | convenient for people to study and modify.
37 |
38 | - ‘The Executable Code’: any code which has generally been compiled and which is
39 | meant to be interpreted by a computer as a program.
40 |
41 | - ‘The Licensor’: the natural or legal person that distributes or communicates
42 | the Work under the Licence.
43 |
44 | - ‘Contributor(s)’: any natural or legal person who modifies the Work under the
45 | Licence, or otherwise contributes to the creation of a Derivative Work.
46 |
47 | - ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
48 | the Work under the terms of the Licence.
49 |
50 | - ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
51 | renting, distributing, communicating, transmitting, or otherwise making
52 | available, online or offline, copies of the Work or providing access to its
53 | essential functionalities at the disposal of any other natural or legal
54 | person.
55 |
56 | 2. Scope of the rights granted by the Licence
57 |
58 | The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
59 | sublicensable licence to do the following, for the duration of copyright vested
60 | in the Original Work:
61 |
62 | - use the Work in any circumstance and for all usage,
63 | - reproduce the Work,
64 | - modify the Work, and make Derivative Works based upon the Work,
65 | - communicate to the public, including the right to make available or display
66 | the Work or copies thereof to the public and perform publicly, as the case may
67 | be, the Work,
68 | - distribute the Work or copies thereof,
69 | - lend and rent the Work or copies thereof,
70 | - sublicense rights in the Work or copies thereof.
71 |
72 | Those rights can be exercised on any media, supports and formats, whether now
73 | known or later invented, as far as the applicable law permits so.
74 |
75 | In the countries where moral rights apply, the Licensor waives his right to
76 | exercise his moral right to the extent allowed by law in order to make effective
77 | the licence of the economic rights here above listed.
78 |
79 | The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
80 | any patents held by the Licensor, to the extent necessary to make use of the
81 | rights granted on the Work under this Licence.
82 |
83 | 3. Communication of the Source Code
84 |
85 | The Licensor may provide the Work either in its Source Code form, or as
86 | Executable Code. If the Work is provided as Executable Code, the Licensor
87 | provides in addition a machine-readable copy of the Source Code of the Work
88 | along with each copy of the Work that the Licensor distributes or indicates, in
89 | a notice following the copyright notice attached to the Work, a repository where
90 | the Source Code is easily and freely accessible for as long as the Licensor
91 | continues to distribute or communicate the Work.
92 |
93 | 4. Limitations on copyright
94 |
95 | Nothing in this Licence is intended to deprive the Licensee of the benefits from
96 | any exception or limitation to the exclusive rights of the rights owners in the
97 | Work, of the exhaustion of those rights or of other applicable limitations
98 | thereto.
99 |
100 | 5. Obligations of the Licensee
101 |
102 | The grant of the rights mentioned above is subject to some restrictions and
103 | obligations imposed on the Licensee. Those obligations are the following:
104 |
105 | Attribution right: The Licensee shall keep intact all copyright, patent or
106 | trademarks notices and all notices that refer to the Licence and to the
107 | disclaimer of warranties. The Licensee must include a copy of such notices and a
108 | copy of the Licence with every copy of the Work he/she distributes or
109 | communicates. The Licensee must cause any Derivative Work to carry prominent
110 | notices stating that the Work has been modified and the date of modification.
111 |
112 | Copyleft clause: If the Licensee distributes or communicates copies of the
113 | Original Works or Derivative Works, this Distribution or Communication will be
114 | done under the terms of this Licence or of a later version of this Licence
115 | unless the Original Work is expressly distributed only under this version of the
116 | Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
117 | (becoming Licensor) cannot offer or impose any additional terms or conditions on
118 | the Work or Derivative Work that alter or restrict the terms of the Licence.
119 |
120 | Compatibility clause: If the Licensee Distributes or Communicates Derivative
121 | Works or copies thereof based upon both the Work and another work licensed under
122 | a Compatible Licence, this Distribution or Communication can be done under the
123 | terms of this Compatible Licence. For the sake of this clause, ‘Compatible
124 | Licence’ refers to the licences listed in the appendix attached to this Licence.
125 | Should the Licensee's obligations under the Compatible Licence conflict with
126 | his/her obligations under this Licence, the obligations of the Compatible
127 | Licence shall prevail.
128 |
129 | Provision of Source Code: When distributing or communicating copies of the Work,
130 | the Licensee will provide a machine-readable copy of the Source Code or indicate
131 | a repository where this Source will be easily and freely available for as long
132 | as the Licensee continues to distribute or communicate the Work.
133 |
134 | Legal Protection: This Licence does not grant permission to use the trade names,
135 | trademarks, service marks, or names of the Licensor, except as required for
136 | reasonable and customary use in describing the origin of the Work and
137 | reproducing the content of the copyright notice.
138 |
139 | 6. Chain of Authorship
140 |
141 | The original Licensor warrants that the copyright in the Original Work granted
142 | hereunder is owned by him/her or licensed to him/her and that he/she has the
143 | power and authority to grant the Licence.
144 |
145 | Each Contributor warrants that the copyright in the modifications he/she brings
146 | to the Work are owned by him/her or licensed to him/her and that he/she has the
147 | power and authority to grant the Licence.
148 |
149 | Each time You accept the Licence, the original Licensor and subsequent
150 | Contributors grant You a licence to their contributions to the Work, under the
151 | terms of this Licence.
152 |
153 | 7. Disclaimer of Warranty
154 |
155 | The Work is a work in progress, which is continuously improved by numerous
156 | Contributors. It is not a finished work and may therefore contain defects or
157 | ‘bugs’ inherent to this type of development.
158 |
159 | For the above reason, the Work is provided under the Licence on an ‘as is’ basis
160 | and without warranties of any kind concerning the Work, including without
161 | limitation merchantability, fitness for a particular purpose, absence of defects
162 | or errors, accuracy, non-infringement of intellectual property rights other than
163 | copyright as stated in Article 6 of this Licence.
164 |
165 | This disclaimer of warranty is an essential part of the Licence and a condition
166 | for the grant of any rights to the Work.
167 |
168 | 8. Disclaimer of Liability
169 |
170 | Except in the cases of wilful misconduct or damages directly caused to natural
171 | persons, the Licensor will in no event be liable for any direct or indirect,
172 | material or moral, damages of any kind, arising out of the Licence or of the use
173 | of the Work, including without limitation, damages for loss of goodwill, work
174 | stoppage, computer failure or malfunction, loss of data or any commercial
175 | damage, even if the Licensor has been advised of the possibility of such damage.
176 | However, the Licensor will be liable under statutory product liability laws as
177 | far such laws apply to the Work.
178 |
179 | 9. Additional agreements
180 |
181 | While distributing the Work, You may choose to conclude an additional agreement,
182 | defining obligations or services consistent with this Licence. However, if
183 | accepting obligations, You may act only on your own behalf and on your sole
184 | responsibility, not on behalf of the original Licensor or any other Contributor,
185 | and only if You agree to indemnify, defend, and hold each Contributor harmless
186 | for any liability incurred by, or claims asserted against such Contributor by
187 | the fact You have accepted any warranty or additional liability.
188 |
189 | 10. Acceptance of the Licence
190 |
191 | The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
192 | placed under the bottom of a window displaying the text of this Licence or by
193 | affirming consent in any other similar way, in accordance with the rules of
194 | applicable law. Clicking on that icon indicates your clear and irrevocable
195 | acceptance of this Licence and all of its terms and conditions.
196 |
197 | Similarly, you irrevocably accept this Licence and all of its terms and
198 | conditions by exercising any rights granted to You by Article 2 of this Licence,
199 | such as the use of the Work, the creation by You of a Derivative Work or the
200 | Distribution or Communication by You of the Work or copies thereof.
201 |
202 | 11. Information to the public
203 |
204 | In case of any Distribution or Communication of the Work by means of electronic
205 | communication by You (for example, by offering to download the Work from a
206 | remote location) the distribution channel or media (for example, a website) must
207 | at least provide to the public the information requested by the applicable law
208 | regarding the Licensor, the Licence and the way it may be accessible, concluded,
209 | stored and reproduced by the Licensee.
210 |
211 | 12. Termination of the Licence
212 |
213 | The Licence and the rights granted hereunder will terminate automatically upon
214 | any breach by the Licensee of the terms of the Licence.
215 |
216 | Such a termination will not terminate the licences of any person who has
217 | received the Work from the Licensee under the Licence, provided such persons
218 | remain in full compliance with the Licence.
219 |
220 | 13. Miscellaneous
221 |
222 | Without prejudice of Article 9 above, the Licence represents the complete
223 | agreement between the Parties as to the Work.
224 |
225 | If any provision of the Licence is invalid or unenforceable under applicable
226 | law, this will not affect the validity or enforceability of the Licence as a
227 | whole. Such provision will be construed or reformed so as necessary to make it
228 | valid and enforceable.
229 |
230 | The European Commission may publish other linguistic versions or new versions of
231 | this Licence or updated versions of the Appendix, so far this is required and
232 | reasonable, without reducing the scope of the rights granted by the Licence. New
233 | versions of the Licence will be published with a unique version number.
234 |
235 | All linguistic versions of this Licence, approved by the European Commission,
236 | have identical value. Parties can take advantage of the linguistic version of
237 | their choice.
238 |
239 | 14. Jurisdiction
240 |
241 | Without prejudice to specific agreement between parties,
242 |
243 | - any litigation resulting from the interpretation of this License, arising
244 | between the European Union institutions, bodies, offices or agencies, as a
245 | Licensor, and any Licensee, will be subject to the jurisdiction of the Court
246 | of Justice of the European Union, as laid down in article 272 of the Treaty on
247 | the Functioning of the European Union,
248 |
249 | - any litigation arising between other parties and resulting from the
250 | interpretation of this License, will be subject to the exclusive jurisdiction
251 | of the competent court where the Licensor resides or conducts its primary
252 | business.
253 |
254 | 15. Applicable Law
255 |
256 | Without prejudice to specific agreement between parties,
257 |
258 | - this Licence shall be governed by the law of the European Union Member State
259 | where the Licensor has his seat, resides or has his registered office,
260 |
261 | - this licence shall be governed by Belgian law if the Licensor has no seat,
262 | residence or registered office inside a European Union Member State.
263 |
264 | Appendix
265 |
266 | ‘Compatible Licences’ according to Article 5 EUPL are:
267 |
268 | - GNU General Public License (GPL) v. 2, v. 3
269 | - GNU Affero General Public License (AGPL) v. 3
270 | - Open Software License (OSL) v. 2.1, v. 3.0
271 | - Eclipse Public License (EPL) v. 1.0
272 | - CeCILL v. 2.0, v. 2.1
273 | - Mozilla Public Licence (MPL) v. 2
274 | - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
275 | - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
276 | works other than software
277 | - European Union Public Licence (EUPL) v. 1.1, v. 1.2
278 | - Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
279 | Reciprocity (LiLiQ-R+).
280 |
281 | The European Commission may update this Appendix to later versions of the above
282 | licences without producing a new version of the EUPL, as long as they provide
283 | the rights granted in Article 2 of this Licence and protect the covered Source
284 | Code from exclusive appropriation.
285 |
286 | All other changes or additions to this Appendix require the production of a new
287 | EUPL version.
288 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EventSource module for NestJS
2 |
3 | [![Contributors][contributors-shield]][contributors-url]
4 | [![Forks][forks-shield]][forks-url]
5 | [![Stargazers][stars-shield]][stars-url]
6 | [![Issues][issues-shield]][issues-url]
7 | [![MIT License][license-shield]][license-url]
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 | NestJS module for eventsourcing development with eventstore database 20 |
21 | 22 | 23 | 24 | 25 | ## About The Project 26 | 27 | This module allows you to connect to a [EventstoreDB](https://www.eventstore.com/) to do event sourcing with nestjs. 28 | 29 | **This is a Work In Progress**, not ready to use it in producction. 30 | 31 | ## Getting Started 32 | 33 | WIP 34 | 35 | See [example](./example) 36 | 37 | ### Prerequisites 38 | 39 | You require to have a nestjs project with this modules already installed and loaded: 40 | 41 | - [@nestjs/cqrs](https://www.npmjs.com/package/@nestjs/cqrs) 42 | - [nestjs-console](https://www.npmjs.com/package/nestjs-console) 43 | 44 | ### Installation 45 | 46 | - npm 47 | 48 | npm install @aulasoftwarelibre/nestjs-eventstore 49 | 50 | - pnpm 51 | 52 | npm add @aulasoftwarelibre/nestjs-eventstore 53 | 54 | - yarn 55 | 56 | yarn add @aulasoftwarelibre/nestjs-eventstore 57 | 58 | ## Usage 59 | 60 | ### Loading the module 61 | 62 | ## Contributing 63 | 64 | ## License 65 | 66 | Distributed under the EUPL-1.2 License. See `LICENSE` for more information. 67 | 68 | ## Running the example 69 | 70 | To run the example you will build the library first: 71 | 72 | ```shell 73 | pnpm run build 74 | ``` 75 | 76 | Then go to the example folder an run the containers: 77 | 78 | ```shell 79 | cd examples/banking 80 | docker compose up -d 81 | ``` 82 | 83 | And finally run the project: 84 | 85 | ```shell 86 | pnpm run start:dev 87 | ``` 88 | 89 | You will access to the example application in the next urls: 90 | 91 | - [Swagger API](http://localhost:3000/api/) 92 | - [EventStore Database (Write model)](http://localhost:2113) 93 | - [Mongo Database (Read model)](http://admin:pass@localhost:8081/) 94 | 95 | ## Acknowledgements 96 | 97 | This module was created following next articles: 98 | 99 | - https://medium.com/@qasimsoomro/building-microservices-using-node-js-with-ddd-cqrs-and-event-sourcing-part-1-of-2-52e0dc3d81df 100 | - https://medium.com/@qasimsoomro/building-microservices-using-node-js-with-ddd-cqrs-and-event-sourcing-part-2-of-2-9a5f6708e0f 101 | - https://nordfjord.io/blog/event-sourcing-in-nestjs 102 | 103 | 104 | 105 | 106 | [contributors-shield]: https://img.shields.io/github/contributors/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 107 | [contributors-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/graphs/contributors 108 | [forks-shield]: https://img.shields.io/github/forks/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 109 | [forks-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/network/members 110 | [stars-shield]: https://img.shields.io/github/stars/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 111 | [stars-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/stargazers 112 | [issues-shield]: https://img.shields.io/github/issues/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 113 | [issues-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/issues 114 | [license-shield]: https://img.shields.io/github/license/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 115 | [license-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/blob/master/LICENSE 116 | -------------------------------------------------------------------------------- /docs/images/logoasl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/nestjs-eventstore/d46795cc79a9c4ab1eee6adb356ac8c802808f8b/docs/images/logoasl.png -------------------------------------------------------------------------------- /examples/banking/.gitignore: -------------------------------------------------------------------------------- 1 | src/nestjs-eventstore 2 | -------------------------------------------------------------------------------- /examples/banking/LICENSE: -------------------------------------------------------------------------------- 1 | EUROPEAN UNION PUBLIC LICENCE v. 1.2 2 | EUPL © the European Union 2007, 2016 3 | 4 | This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined 5 | below) which is provided under the terms of this Licence. Any use of the Work, 6 | other than as authorised under this Licence is prohibited (to the extent such 7 | use is covered by a right of the copyright holder of the Work). 8 | 9 | The Work is provided under the terms of this Licence when the Licensor (as 10 | defined below) has placed the following notice immediately following the 11 | copyright notice for the Work: 12 | 13 | Licensed under the EUPL 14 | 15 | or has expressed by any other means his willingness to license under the EUPL. 16 | 17 | 1. Definitions 18 | 19 | In this Licence, the following terms have the following meaning: 20 | 21 | - ‘The Licence’: this Licence. 22 | 23 | - ‘The Original Work’: the work or software distributed or communicated by the 24 | Licensor under this Licence, available as Source Code and also as Executable 25 | Code as the case may be. 26 | 27 | - ‘Derivative Works’: the works or software that could be created by the 28 | Licensee, based upon the Original Work or modifications thereof. This Licence 29 | does not define the extent of modification or dependence on the Original Work 30 | required in order to classify a work as a Derivative Work; this extent is 31 | determined by copyright law applicable in the country mentioned in Article 15. 32 | 33 | - ‘The Work’: the Original Work or its Derivative Works. 34 | 35 | - ‘The Source Code’: the human-readable form of the Work which is the most 36 | convenient for people to study and modify. 37 | 38 | - ‘The Executable Code’: any code which has generally been compiled and which is 39 | meant to be interpreted by a computer as a program. 40 | 41 | - ‘The Licensor’: the natural or legal person that distributes or communicates 42 | the Work under the Licence. 43 | 44 | - ‘Contributor(s)’: any natural or legal person who modifies the Work under the 45 | Licence, or otherwise contributes to the creation of a Derivative Work. 46 | 47 | - ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of 48 | the Work under the terms of the Licence. 49 | 50 | - ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, 51 | renting, distributing, communicating, transmitting, or otherwise making 52 | available, online or offline, copies of the Work or providing access to its 53 | essential functionalities at the disposal of any other natural or legal 54 | person. 55 | 56 | 2. Scope of the rights granted by the Licence 57 | 58 | The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, 59 | sublicensable licence to do the following, for the duration of copyright vested 60 | in the Original Work: 61 | 62 | - use the Work in any circumstance and for all usage, 63 | - reproduce the Work, 64 | - modify the Work, and make Derivative Works based upon the Work, 65 | - communicate to the public, including the right to make available or display 66 | the Work or copies thereof to the public and perform publicly, as the case may 67 | be, the Work, 68 | - distribute the Work or copies thereof, 69 | - lend and rent the Work or copies thereof, 70 | - sublicense rights in the Work or copies thereof. 71 | 72 | Those rights can be exercised on any media, supports and formats, whether now 73 | known or later invented, as far as the applicable law permits so. 74 | 75 | In the countries where moral rights apply, the Licensor waives his right to 76 | exercise his moral right to the extent allowed by law in order to make effective 77 | the licence of the economic rights here above listed. 78 | 79 | The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to 80 | any patents held by the Licensor, to the extent necessary to make use of the 81 | rights granted on the Work under this Licence. 82 | 83 | 3. Communication of the Source Code 84 | 85 | The Licensor may provide the Work either in its Source Code form, or as 86 | Executable Code. If the Work is provided as Executable Code, the Licensor 87 | provides in addition a machine-readable copy of the Source Code of the Work 88 | along with each copy of the Work that the Licensor distributes or indicates, in 89 | a notice following the copyright notice attached to the Work, a repository where 90 | the Source Code is easily and freely accessible for as long as the Licensor 91 | continues to distribute or communicate the Work. 92 | 93 | 4. Limitations on copyright 94 | 95 | Nothing in this Licence is intended to deprive the Licensee of the benefits from 96 | any exception or limitation to the exclusive rights of the rights owners in the 97 | Work, of the exhaustion of those rights or of other applicable limitations 98 | thereto. 99 | 100 | 5. Obligations of the Licensee 101 | 102 | The grant of the rights mentioned above is subject to some restrictions and 103 | obligations imposed on the Licensee. Those obligations are the following: 104 | 105 | Attribution right: The Licensee shall keep intact all copyright, patent or 106 | trademarks notices and all notices that refer to the Licence and to the 107 | disclaimer of warranties. The Licensee must include a copy of such notices and a 108 | copy of the Licence with every copy of the Work he/she distributes or 109 | communicates. The Licensee must cause any Derivative Work to carry prominent 110 | notices stating that the Work has been modified and the date of modification. 111 | 112 | Copyleft clause: If the Licensee distributes or communicates copies of the 113 | Original Works or Derivative Works, this Distribution or Communication will be 114 | done under the terms of this Licence or of a later version of this Licence 115 | unless the Original Work is expressly distributed only under this version of the 116 | Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee 117 | (becoming Licensor) cannot offer or impose any additional terms or conditions on 118 | the Work or Derivative Work that alter or restrict the terms of the Licence. 119 | 120 | Compatibility clause: If the Licensee Distributes or Communicates Derivative 121 | Works or copies thereof based upon both the Work and another work licensed under 122 | a Compatible Licence, this Distribution or Communication can be done under the 123 | terms of this Compatible Licence. For the sake of this clause, ‘Compatible 124 | Licence’ refers to the licences listed in the appendix attached to this Licence. 125 | Should the Licensee's obligations under the Compatible Licence conflict with 126 | his/her obligations under this Licence, the obligations of the Compatible 127 | Licence shall prevail. 128 | 129 | Provision of Source Code: When distributing or communicating copies of the Work, 130 | the Licensee will provide a machine-readable copy of the Source Code or indicate 131 | a repository where this Source will be easily and freely available for as long 132 | as the Licensee continues to distribute or communicate the Work. 133 | 134 | Legal Protection: This Licence does not grant permission to use the trade names, 135 | trademarks, service marks, or names of the Licensor, except as required for 136 | reasonable and customary use in describing the origin of the Work and 137 | reproducing the content of the copyright notice. 138 | 139 | 6. Chain of Authorship 140 | 141 | The original Licensor warrants that the copyright in the Original Work granted 142 | hereunder is owned by him/her or licensed to him/her and that he/she has the 143 | power and authority to grant the Licence. 144 | 145 | Each Contributor warrants that the copyright in the modifications he/she brings 146 | to the Work are owned by him/her or licensed to him/her and that he/she has the 147 | power and authority to grant the Licence. 148 | 149 | Each time You accept the Licence, the original Licensor and subsequent 150 | Contributors grant You a licence to their contributions to the Work, under the 151 | terms of this Licence. 152 | 153 | 7. Disclaimer of Warranty 154 | 155 | The Work is a work in progress, which is continuously improved by numerous 156 | Contributors. It is not a finished work and may therefore contain defects or 157 | ‘bugs’ inherent to this type of development. 158 | 159 | For the above reason, the Work is provided under the Licence on an ‘as is’ basis 160 | and without warranties of any kind concerning the Work, including without 161 | limitation merchantability, fitness for a particular purpose, absence of defects 162 | or errors, accuracy, non-infringement of intellectual property rights other than 163 | copyright as stated in Article 6 of this Licence. 164 | 165 | This disclaimer of warranty is an essential part of the Licence and a condition 166 | for the grant of any rights to the Work. 167 | 168 | 8. Disclaimer of Liability 169 | 170 | Except in the cases of wilful misconduct or damages directly caused to natural 171 | persons, the Licensor will in no event be liable for any direct or indirect, 172 | material or moral, damages of any kind, arising out of the Licence or of the use 173 | of the Work, including without limitation, damages for loss of goodwill, work 174 | stoppage, computer failure or malfunction, loss of data or any commercial 175 | damage, even if the Licensor has been advised of the possibility of such damage. 176 | However, the Licensor will be liable under statutory product liability laws as 177 | far such laws apply to the Work. 178 | 179 | 9. Additional agreements 180 | 181 | While distributing the Work, You may choose to conclude an additional agreement, 182 | defining obligations or services consistent with this Licence. However, if 183 | accepting obligations, You may act only on your own behalf and on your sole 184 | responsibility, not on behalf of the original Licensor or any other Contributor, 185 | and only if You agree to indemnify, defend, and hold each Contributor harmless 186 | for any liability incurred by, or claims asserted against such Contributor by 187 | the fact You have accepted any warranty or additional liability. 188 | 189 | 10. Acceptance of the Licence 190 | 191 | The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ 192 | placed under the bottom of a window displaying the text of this Licence or by 193 | affirming consent in any other similar way, in accordance with the rules of 194 | applicable law. Clicking on that icon indicates your clear and irrevocable 195 | acceptance of this Licence and all of its terms and conditions. 196 | 197 | Similarly, you irrevocably accept this Licence and all of its terms and 198 | conditions by exercising any rights granted to You by Article 2 of this Licence, 199 | such as the use of the Work, the creation by You of a Derivative Work or the 200 | Distribution or Communication by You of the Work or copies thereof. 201 | 202 | 11. Information to the public 203 | 204 | In case of any Distribution or Communication of the Work by means of electronic 205 | communication by You (for example, by offering to download the Work from a 206 | remote location) the distribution channel or media (for example, a website) must 207 | at least provide to the public the information requested by the applicable law 208 | regarding the Licensor, the Licence and the way it may be accessible, concluded, 209 | stored and reproduced by the Licensee. 210 | 211 | 12. Termination of the Licence 212 | 213 | The Licence and the rights granted hereunder will terminate automatically upon 214 | any breach by the Licensee of the terms of the Licence. 215 | 216 | Such a termination will not terminate the licences of any person who has 217 | received the Work from the Licensee under the Licence, provided such persons 218 | remain in full compliance with the Licence. 219 | 220 | 13. Miscellaneous 221 | 222 | Without prejudice of Article 9 above, the Licence represents the complete 223 | agreement between the Parties as to the Work. 224 | 225 | If any provision of the Licence is invalid or unenforceable under applicable 226 | law, this will not affect the validity or enforceability of the Licence as a 227 | whole. Such provision will be construed or reformed so as necessary to make it 228 | valid and enforceable. 229 | 230 | The European Commission may publish other linguistic versions or new versions of 231 | this Licence or updated versions of the Appendix, so far this is required and 232 | reasonable, without reducing the scope of the rights granted by the Licence. New 233 | versions of the Licence will be published with a unique version number. 234 | 235 | All linguistic versions of this Licence, approved by the European Commission, 236 | have identical value. Parties can take advantage of the linguistic version of 237 | their choice. 238 | 239 | 14. Jurisdiction 240 | 241 | Without prejudice to specific agreement between parties, 242 | 243 | - any litigation resulting from the interpretation of this License, arising 244 | between the European Union institutions, bodies, offices or agencies, as a 245 | Licensor, and any Licensee, will be subject to the jurisdiction of the Court 246 | of Justice of the European Union, as laid down in article 272 of the Treaty on 247 | the Functioning of the European Union, 248 | 249 | - any litigation arising between other parties and resulting from the 250 | interpretation of this License, will be subject to the exclusive jurisdiction 251 | of the competent court where the Licensor resides or conducts its primary 252 | business. 253 | 254 | 15. Applicable Law 255 | 256 | Without prejudice to specific agreement between parties, 257 | 258 | - this Licence shall be governed by the law of the European Union Member State 259 | where the Licensor has his seat, resides or has his registered office, 260 | 261 | - this licence shall be governed by Belgian law if the Licensor has no seat, 262 | residence or registered office inside a European Union Member State. 263 | 264 | Appendix 265 | 266 | ‘Compatible Licences’ according to Article 5 EUPL are: 267 | 268 | - GNU General Public License (GPL) v. 2, v. 3 269 | - GNU Affero General Public License (AGPL) v. 3 270 | - Open Software License (OSL) v. 2.1, v. 3.0 271 | - Eclipse Public License (EPL) v. 1.0 272 | - CeCILL v. 2.0, v. 2.1 273 | - Mozilla Public Licence (MPL) v. 2 274 | - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 275 | - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for 276 | works other than software 277 | - European Union Public Licence (EUPL) v. 1.1, v. 1.2 278 | - Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong 279 | Reciprocity (LiLiQ-R+). 280 | 281 | The European Commission may update this Appendix to later versions of the above 282 | licences without producing a new version of the EUPL, as long as they provide 283 | the rights granted in Article 2 of this Licence and protect the covered Source 284 | Code from exclusive appropriation. 285 | 286 | All other changes or additions to this Appendix require the production of a new 287 | EUPL version. 288 | -------------------------------------------------------------------------------- /examples/banking/README.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 6 | [circleci-url]: https://circleci.com/gh/nestjs/nest 7 | 8 |A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
12 |
13 |
14 |
15 |
16 |
19 | NestJS module for eventsourcing development with eventstore database 20 |
21 | 22 | 23 | 24 | 25 | ## About The Project 26 | 27 | This module allows you to connect to a [EventstoreDB](https://www.eventstore.com/) to do event sourcing with nestjs. 28 | 29 | **This is a Work In Progress**, not ready to use it in producction. 30 | 31 | ## Getting Started 32 | 33 | WIP 34 | 35 | See [example](./example) 36 | 37 | ### Prerequisites 38 | 39 | You require to have a nestjs project with this modules already installed and loaded: 40 | 41 | - [@nestjs/cqrs](https://www.npmjs.com/package/@nestjs/cqrs) 42 | - [nestjs-console](https://www.npmjs.com/package/nestjs-console) 43 | 44 | ### Installation 45 | 46 | - npm 47 | 48 | npm install @aulasoftwarelibre/nestjs-eventstore 49 | 50 | - yarn 51 | 52 | yarn add @aulasoftwarelibre/nestjs-eventstore 53 | 54 | ## Usage 55 | 56 | ### Loading the module 57 | 58 | ## Contributing 59 | 60 | ## License 61 | 62 | Distributed under the EUPL-1.2 License. See `LICENSE` for more information. 63 | 64 | ## Running the example 65 | 66 | To run the example you will need docker. Just run: 67 | 68 | ```shell 69 | docker compose up -d 70 | ``` 71 | 72 | And a few minutes later you will access to the example application in the next urls: 73 | 74 | - [Swagger API](http://localhost:3000/api/) 75 | - [EventStore Database (Write model)](http://localhost:2113) 76 | - [Mongo Database (Read model)](http://admin:pass@localhost:8081/) 77 | 78 | ## Acknowledgements 79 | 80 | This module was created following next articles: 81 | 82 | - https://medium.com/@qasimsoomro/building-microservices-using-node-js-with-ddd-cqrs-and-event-sourcing-part-1-of-2-52e0dc3d81df 83 | - https://medium.com/@qasimsoomro/building-microservices-using-node-js-with-ddd-cqrs-and-event-sourcing-part-2-of-2-9a5f6708e0f 84 | - https://nordfjord.io/blog/event-sourcing-in-nestjs 85 | 86 | 87 | 88 | 89 | [contributors-shield]: https://img.shields.io/github/contributors/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 90 | [contributors-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/graphs/contributors 91 | [forks-shield]: https://img.shields.io/github/forks/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 92 | [forks-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/network/members 93 | [stars-shield]: https://img.shields.io/github/stars/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 94 | [stars-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/stargazers 95 | [issues-shield]: https://img.shields.io/github/issues/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 96 | [issues-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/issues 97 | [license-shield]: https://img.shields.io/github/license/aulasoftwarelibre/nestjs-eventstore.svg?style=for-the-badge 98 | [license-url]: https://github.com/aulasoftwarelibre/nestjs-eventstore/blob/master/LICENSE 99 | -------------------------------------------------------------------------------- /packages/nestjs-eventstore/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aulasoftwarelibre/nestjs-eventstore", 3 | "description": "NestJS module for eventsourcing development with eventstore database", 4 | "version": "0.8.0", 5 | "license": "EUPL-1.2", 6 | "author": "Sergio Gómez Bachillerimplements IEvent { 15 | public readonly eventId: string 16 | public readonly eventType: string 17 | private _payload: P 18 | private _metadata: Metadata 19 | 20 | public constructor(aggregateId: string, payload?: P) { 21 | this.eventId = uuid.v4() 22 | this._payload = { ...payload } 23 | this.eventType = Object.getPrototypeOf(this).constructor.name 24 | this._metadata = { 25 | _aggregate_encrypted: false, 26 | _aggregate_id: aggregateId, 27 | _aggregate_version: -2, 28 | _ocurred_on: Date.now(), 29 | } 30 | } 31 | 32 | get payload(): Readonly
{
33 | return this._payload
34 | }
35 |
36 | get metadata(): Readonly {
84 | const event = cloneDeep(this)
85 | event._metadata = {
86 | ...metadata,
87 | }
88 |
89 | return event
90 | }
91 |
92 | withPayload(payload: P): Event {
93 | const event = cloneDeep(this)
94 | event._payload = {
95 | ...payload,
96 | }
97 |
98 | return event
99 | }
100 |
101 | withStream(stream: string): Event {
102 | const event = cloneDeep(this)
103 | event._metadata = {
104 | ...this._metadata,
105 | _stream: stream,
106 | }
107 |
108 | return event
109 | }
110 |
111 | withVersion(version: number): Event {
112 | const event = cloneDeep(this)
113 | event._metadata = {
114 | ...this._metadata,
115 | _aggregate_version: version,
116 | }
117 |
118 | return event
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/packages/nestjs-eventstore/src/domain/models/id.spec.ts:
--------------------------------------------------------------------------------
1 | import * as uuid from 'uuid'
2 | import { describe, expect, it } from 'vitest'
3 |
4 | import { InvalidIdError } from '../exceptions/invalid-id-error'
5 | import { Id } from './id'
6 |
7 | describe('Id', () => {
8 | it('creates a id value object', () => {
9 | const id = uuid.v4()
10 | const myId = MyId.fromString(id)
11 |
12 | expect(myId.value).toBe(id)
13 | })
14 |
15 | it('returns exception if id is not valid', () => {
16 | expect(() => MyId.fromString('invalid')).toThrowError(
17 | InvalidIdError.withString('invalid'),
18 | )
19 | })
20 | })
21 |
22 | class MyId extends Id {
23 | private constructor(id: string) {
24 | super(id)
25 | }
26 |
27 | static fromString(id: string): MyId {
28 | return new this(id)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/nestjs-eventstore/src/domain/models/id.ts:
--------------------------------------------------------------------------------
1 | import { validate, version } from 'uuid'
2 |
3 | import { InvalidIdError } from '../exceptions'
4 | import { ValueObject } from './value-object'
5 |
6 | export abstract class Id extends ValueObject<{
7 | value: string
8 | }> {
9 | protected constructor(id: string) {
10 | if (!validate(id) || version(id) !== 4) {
11 | throw InvalidIdError.withString(id)
12 | }
13 |
14 | super({ value: id })
15 | }
16 |
17 | get value(): string {
18 | return this.props.value
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/nestjs-eventstore/src/domain/models/index.ts:
--------------------------------------------------------------------------------
1 | export * from './aggregate-root'
2 | export * from './event'
3 | export * from './id'
4 | export * from './value-object'
5 |
--------------------------------------------------------------------------------
/packages/nestjs-eventstore/src/domain/models/value-object.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest'
2 |
3 | import { ValueObject } from './value-object'
4 |
5 | describe('ValueObject', () => {
6 | it('creates a value object with one attribute', () => {
7 | const foo = FooValueObject.fromString('foo')
8 |
9 | expect(foo.value).toBe('foo')
10 | })
11 |
12 | it('creates a value object with many attributes', () => {
13 | const person = FullName.from('John', 'Doe')
14 |
15 | expect(person.first).toBe('John')
16 | expect(person.last).toBe('Doe')
17 | })
18 |
19 | it('a value objects is equal with itself', () => {
20 | const foo = FooValueObject.fromString('foo')
21 |
22 | expect(foo.equals(foo)).toBeTruthy()
23 | })
24 |
25 | it('two value objects with same values are equals', () => {
26 | const foo = FooValueObject.fromString('foo')
27 | const foo2 = FooValueObject.fromString('foo')
28 |
29 | expect(foo.equals(foo2)).toBeTruthy()
30 | })
31 |
32 | it('two value objects with different values are not equals', () => {
33 | const foo = FooValueObject.fromString('foo')
34 | const bar = FooValueObject.fromString('bar')
35 |
36 | expect(foo.equals(bar)).toBeFalsy()
37 | })
38 |
39 | it('two different value objects with same values are not equals', () => {
40 | const foo = FooValueObject.fromString('foo')
41 | const bar = BarValueObject.fromString('foo')
42 |
43 | expect(foo.equals(bar)).toBeFalsy()
44 | })
45 | })
46 |
47 | class FooValueObject extends ValueObject<{ value: string }> {
48 | public static fromString(value: string): FooValueObject {
49 | return new FooValueObject({ value })
50 | }
51 |
52 | get value(): string {
53 | return this.props.value
54 | }
55 | }
56 |
57 | class BarValueObject extends ValueObject<{ value: string }> {
58 | public static fromString(value: string): BarValueObject {
59 | return new BarValueObject({ value })
60 | }
61 |
62 | get value(): string {
63 | return this.props.value
64 | }
65 | }
66 |
67 | class FullName extends ValueObject<{ first: string; last: string }> {
68 | public static from(first: string, last: string): FullName {
69 | return new FullName({ first, last })
70 | }
71 |
72 | get first(): string {
73 | return this.props.first
74 | }
75 |
76 | get last(): string {
77 | return this.props.last
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/packages/nestjs-eventstore/src/domain/models/value-object.ts:
--------------------------------------------------------------------------------
1 | import { shallowEqual } from 'shallow-equal-object'
2 |
3 | interface ValueObjectProperties {
4 | [index: string]: unknown
5 | }
6 |
7 | export abstract class ValueObject