A SOLID wallet service built with TypeScript using clean architecture and DDD best practices inspired on DDD-forum.
video2.mp4
- learn GraphQL+Apollo and how to plug the domain useCases to the queries and mutations
- learn Prisma and how to use it's schema on our toDomain and toPersistence mappers
- learn QLDB (ledger database)
- document with my own words what I believe are the main advantages of this software design approach
Subdomains of the application. Groupings of business logic that makes sense in and of itself.
Domain objects (aggregate roots and value objects) where business logic lives.
In an ideal world, non-tech/Product people should be able to read those files and see the key business rules defined for each domain object. eg. for a given wallet, you can add funds or subtract funds.
useCases that will:
- instantiate the domain objects from memory
- execute the business logic from the domain objects
- persist changes if necessary
- return some data as a DTO.
In an ideal world, non-tech/Product people should be able to read those useCase names and understand/see how they implement each user story. A user story may need one or more useCases to be satisfied.
Api contracts between frontend and backend. In a REST api, this would be the objects sent to the frontend.
Graphql adds a new layer on top of the DTO that allows the frontend to query only the fields needed.
Adapters that will strongly type anything coming in and out of our main application logic. eg. Database <-> application -> Frontend DTO.
This helps a lot with evolving the database schemas as the developer has to actively decide how to implement new fields and disencorages changing field types.
Empty interfaces that are going to describe the contract between the service (database/third party services/etc) and the application.
This is going to facilitate testing and also prevent that service specific logic leaks to the application layer.
Actual implementations of the services (database/third party services/etc) that are going to be injected at runtime.
- useCase that verifies that postgreSQL data has not been tempered by checking against QLDB ledger.
- use TypeGraphQL to define the graphQL schemas in the same place as the DTOs (inline with decorators)
- authentication middleware with apollo service
- authorization living inside the useCase to prevent consumers of the useCase from forgetting to authorize.
- move graphql queries/mutations that are relevant to a subdomain to the respective src/modules/*/infra/http/graphql/index.ts location
- useCase tests injecting mock implementations of the repos
- docker setting up whole environment
- improve error handling by strong typing all errors with the Result class and at the graphQL level
# 0. Prerequisites
# - running postgreSQL
# - working AWS Profile configured on environment
# - QLDB ledger named 'wallet-dev' configured on AWS console
# 1. install dependencies
$ yarn install
# 2. copy .env.template file and edit it (working AWS profile needed)
$ cp .env.template .env
# 3. run Prisma migrations to initialize local db
$ yarn db:migrate
# 4. run project
$ yarn start:dev
# GraphQL endpoint http://localhost:3000/graphql.
How Do I Know I Need a Ledger Database? An Introduction to Amazon QLDB