{"id":20381231,"url":"https://github.com/zhuravlevma/typescript-ddd-architecture","last_synced_at":"2025-04-05T12:03:00.856Z","repository":{"id":156329751,"uuid":"632580523","full_name":"zhuravlevma/typescript-ddd-architecture","owner":"zhuravlevma","description":"Typescript DDD architecture for nest.js with saga, subdomains, clean architecture, domain model, aggregates, event-driven ⚡","archived":false,"fork":false,"pushed_at":"2025-01-07T21:12:11.000Z","size":1011,"stargazers_count":142,"open_issues_count":7,"forks_count":8,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-29T11:04:33.626Z","etag":null,"topics":["aggregates","architecture","clean-architecture","ddd","ddd-architecture","domain-driven-design","domain-model","event-driven","event-driven-architecture","eventbus","example","javascript","nestjs","node-js","nodejs","rabbitmq","saga","saga-pattern","typeorm","typescript"],"latest_commit_sha":null,"homepage":"https://learning.oreilly.com/library/view/learning-domain-driven-design/9781098100124/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zhuravlevma.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-25T17:49:38.000Z","updated_at":"2025-03-17T03:57:04.000Z","dependencies_parsed_at":"2024-01-26T22:22:51.388Z","dependency_job_id":"8a850c67-0a9f-4e6a-b854-28590fea0b64","html_url":"https://github.com/zhuravlevma/typescript-ddd-architecture","commit_stats":{"total_commits":240,"total_committers":2,"mean_commits":120.0,"dds":0.008333333333333304,"last_synced_commit":"ecafa827304342f8ea4a799cd0ba5fb164b6cf6f"},"previous_names":["zhuravlevma/nestjs-ddd-clean-architecture","zhuravlevma/typescript-ddd-architecture"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhuravlevma%2Ftypescript-ddd-architecture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhuravlevma%2Ftypescript-ddd-architecture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhuravlevma%2Ftypescript-ddd-architecture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhuravlevma%2Ftypescript-ddd-architecture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zhuravlevma","download_url":"https://codeload.github.com/zhuravlevma/typescript-ddd-architecture/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247332560,"owners_count":20921853,"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","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":["aggregates","architecture","clean-architecture","ddd","ddd-architecture","domain-driven-design","domain-model","event-driven","event-driven-architecture","eventbus","example","javascript","nestjs","node-js","nodejs","rabbitmq","saga","saga-pattern","typeorm","typescript"],"created_at":"2024-11-15T02:12:17.870Z","updated_at":"2025-04-05T12:03:00.830Z","avatar_url":"https://github.com/zhuravlevma.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DDD patterns with examples\n\n## Marketplace Domain\n\n### Event Storming schema\n\n![image](https://github.com/user-attachments/assets/cb8b6344-5cdb-4963-8686-cce267ea08ea)\n\n### Describe\n\n**Bounded Contexts:**\n\n- **`Cart`** - Context for cart operations\n  - **Subdomains:** -\n    - **`Core Cart`** - adding items to the shopping cart\n    - **`Generic Payment`** - payment for goods\n- **`Warehouse`** - Context for warehouse operations\n  - **Subdomains:** -\n    - **`Core OrderManagement`** - order management at the warehouse\n    - **`Supporting Location`** - management of product locations at the warehouse, product categorization\n- **`Accounting`** - accounting context\n  - **Subdomains:** -\n    - **`Core Reports`** - financial reports generation\n    - **`Supporting Verification`** - order verification\n- **`Delivery`** - delivery context\n  - **Subdomains:** -\n    - **`Core Board`** - board of order proposals\n    - **`Core Couriers`** - management of couriers\n    - **`Supporting Tracking`** - delivery status tracking\n\n### Module boundaries\n\nThis project is a large monolith structured at a high level into [bounded contexts](https://martinfowler.com/bliki/BoundedContext.html). Each context contains subdomains that, depending on the type, implement their architectural pattern. For the **`Core subdomain`**, a [Domain model](https://martinfowler.com/eaaCatalog/domainModel.html) is chosen, while for the **`Supporting subdomain`**, either [Transaction script](https://martinfowler.com/eaaCatalog/transactionScript.html) or [Active Record](https://www.martinfowler.com/eaaCatalog/activeRecord.html) is implemented as its architectural pattern.\n\n- **`Domain model: Core`**\n\n  [Domain model](https://martinfowler.com/eaaCatalog/domainModel.html) with a clean architecture with ports and adapters. It takes into account some tactical patterns from DDD.\n\n  \u003cimg src='https://github.com/zhuravlevma/nestjs-ddd-clean-architecture/assets/44276887/2be14dbf-818b-452d-a39e-0a9de80c9a6b' alt=\"domain model schema\" width='50%'\u003e\n\n- **`Active Record: Generic/Supporting`**\n\n  [Active Record](https://www.martinfowler.com/eaaCatalog/activeRecord.html) uses the most obvious approach, putting data access logic in the domain object.\n\n  \u003cimg src='https://github.com/zhuravlevma/nestjs-ddd-architecture/assets/44276887/5debb30e-91df-44c6-abf0-e82d4442d0b9' alt=\"active record schema\" width='50%'\u003e\n\n- **`Transaction Script: Generic/Supporting`**\n\n  [Transaction Script](https://martinfowler.com/eaaCatalog/transactionScript.html) organizes business logic by procedures where each procedure handles a single request from the presentation.\n\n  \u003cimg src='https://github.com/zhuravlevma/nestjs-ddd-architecture/assets/44276887/29971154-b39a-4650-b9fb-b867c5321483' alt=\"transaction script schema\" width='50%'\u003e\n\nIf you have a large monolith that contains many [bounded contexts](https://martinfowler.com/bliki/BoundedContext.html), then the service can be divided into modules by context.\n\nIf you have a micro service architecture and you prefer to allocate contexts to different services (which is preferable). If it's not enough for you, then you can also divide subdomains into services.\nEach Core subdomain can be divided into modules by [aggregates](https://martinfowler.com/bliki/DDD_Aggregate.html).\n\n### Why do I need an event bus?\n\nFirstly, we have a limitation - this is the change of one aggregate in one transaction (strong consistency). To change multiple aggregates at the same time, you need to use eventual consistency.\n\n### Why do I need Relay?\n\nWe cannot write a message directly to the broker, because it may not be available. Pattern [Transactional outbox](https://microservices.io/patterns/data/transactional-outbox.html).\n\nTransactional outbox can be done using synchronous calls, the broker is not biased. But this option is more suitable for point-to-point communication.\n\nIn a good way, each bounded context in a micro-service architecture should have its own Relay. In the demonstration monolith, I decided to limit myself to one.\n\n### Saga\n\nThe project uses a saga with choreography and a registrar. The registrar is capable of rolling back transactions in case of failure.\n\n#### Calling for compensation\n\n![image](https://github.com/user-attachments/assets/334c00b2-9bda-4552-be61-76b2771ee938)\n\n#### Timeout compensation\n\n![image](https://github.com/user-attachments/assets/6e25acc7-46b5-4ae6-972b-fd9fd164d687)\n\n### Important\n\nThis is not a production ready solution!\n\n### ArchUnit\n\nUtilities for convenient architectural testing (similar to [ArchUnit in Java](https://www.archunit.org/)) have been developed for the project. They can be executed using the command:\n\n```bash\nnpm run test:arch\n```\n\n## Installation\n\n```bash\nnpm install\n```\n\n## Running the app (local)\n\n```sql\nCREATE SCHEMA IF NOT EXISTS accounting\nCREATE SCHEMA IF NOT EXISTS warehouse\nCREATE SCHEMA IF NOT EXISTS delivery\nCREATE SCHEMA IF NOT EXISTS public\n```\n\n```bash\ncp .env.example .env\n```\n\n```bash\nnpm install\n```\n\n```bash\nnpm install dotenv-cli\n```\n\n```bash\ndotenv npm run start:dev\n```\n\n## Running the app (docker)\n\n```bash\ncp .env.example .env\n```\n\n```bash\ndocker-compose up\n```\n\n## Test\n\n```bash\n# unit tests\n$ npm run test\n\n# arch tests\n$ npm run test:arch\n\n# test coverage\n$ npm run test:cov\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhuravlevma%2Ftypescript-ddd-architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzhuravlevma%2Ftypescript-ddd-architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhuravlevma%2Ftypescript-ddd-architecture/lists"}