This is my solution to test task which I should do before I will be hired. This readme isn't complete 'cuz I found meaningless to finish it.
My main task is to make a simple web-server for ticket support system. What endpoints I told to implement:
- Create ticket
- Take ticket
- Close ticket
- Reject ticket
- Get tickets with date filter
- Endpoint to reject all tickets with status "In work"
When ticket is created there should be ability to send message and subject. When ticket is closed there should be ability to send message containing solution of the problem. When ticket is rejected there should be ability to send message containing reason of rejection. All tickets is anonymous, no work with users.
Well, I still decided to add users logic to make the task harder.
UPD. Well I got way deeper in learning of new complicated things that I barely implemented users logic on time so there is no hardness but still initial task have been done.
I don't really like Express, I hate default MVC projects made using Express, they're hell for supporting and have the ugliest code. So I have decided to make experiment, cuz Express is flexible framework and doesn't forces us to specific archicture, giving to us freedom how to make it, I decided to implement Clean Archicture (that one which is described by Robert Martin, yeah) which is really popular in ASP.NET. C# is my secondary language, through I really don't like JavaScript itself, I know ASP.NET much worse, so I don't have enough experience with it to make some really valuable project.
For database I'm gonna use PostgreSQL. PostgreSQL for storing user data and basic tickets information. Why? I just love this database for all usual cases.
Quick description of Domain Driven Design: All project is devided into layers like onion. DDD do have the following layers: API -> Application -> Domain -> Infrastucture. API contains Express-specific logic. Application is... Let's just say it's a wrapper of domain layer, which structures all possible interactions in our application (which is implemented by domain layer) into specific use cases needed. Domain layer do contain primary bussiness logic. And infrastructure layer provides access to external dependencies like database, other services and etc. In this project domain layer and infrastucture layer bound through Dependency Injection, domain layer describes interface, infrastucture layer implements it and DI passes specific needed implementation to domain layer.
It's will be easier to understand with the following scheme.

Here is folder structure which quick description so you can easier understand what the hell I did
| Folder | Description |
|---|---|
src/ |
ikr |
src/entry.ts |
Project entry point |
src/api/ |
API layer, client interactions handling |
src/api/controllers/ |
API Controllers |
src/api/middlewares/ |
API Middlewares |
src/app/ |
Application layer |
src/app/use-cases/ |
Bussiness logic |
src/app/services/ |
Data-handling helping services |
src/domain/ |
Domain application layer |
src/domain/entities/ |
Entities models |
src/domain/repositories/ |
Contains interfaces for working with data which should be implemented by infrastructure layer |
src/infrastructure/ |
Infrastructure layer, all external dependencies |
src/infrastructure/db/ |
All direct work with databases goes here, implements all abstract layers |
src/infrastructure/db/repositores/ |
Repositories implementation |
src/infrastructure/db/migrations/ |
Database migrations |
src/shared/ |
Modules, constants, utils and etc which is shared for all layers |
src/shared/errors/ |
Errors handling |
src/shared/utils/ |
Some utils and helper functions |
src/shared/config/ |
Configuration |
All entities in domain layer should be abstract, as they're abstract we'll need abstract factory for each entity which should be implemented in infrastructure layer.
Here is why. By Clean Architecture principes domain layer shouldn't access TypeORM directly, only through it's abstractions implemented in infrastructure layer and managed by TypeDI. If I would wanna keep concrete implementations in domain layer then I will be forced to implement wrapper for each entity in infrastructure layer and have a lot of a headache with type-safety of each of them. Having an factory without additional logic for each entity can sound like overengeneering but it's better than having headache with wrappers in infrastructure layer as entity creation mostly performed once in the project unlike any other entities operations.
It's more about infrastructure or, rather, about project core. For example, we have database manager which should be initialized at project startup. It should set up DI for entities and repositories, initialize database connection, manage transactions and etc. And it cannot be just a service - they're more about helpers upon entities, as database manager is separate structure. It also can become abstract and have different implementations if, for example, we decided to switch up to different database which our ORM doesn't support (not such a good example as we can just implement adapter for TypeORM but I tried to make you understand)
This project is under CC0 1.0, do with it whatever you want