Find the task description in the end of the README.md file
This is my submission to the DPS Backend Coding Challenge. Enjoy and feel free to reach out to me if you have any questions.
- Install dependencies using
npm install
- Copy the
.env.example
file to.env
and leave theDATABASE_URL
as it is - Generate the models for the api using
npm run api:gen
- Generate the Prisma client (ORM) using
npm run prisma:gen
- Run the application using
npm run dev
The application is now running on http://localhost:8080
. You can access the API documentation on http://localhost:8080/api-specs
. If you want to send requests to the backend, use the following token in the Authorization
header:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6IlBhc3N3b3JkMTIzIn0.RDGxHLrPkPThUU9QepQqnm-qInz5GyhRC92Z_g1TOYc
I added some tools/technologies to the project to make it more robust and maintainable. Here is a list of the technologies used in the project:
- Logging: Winston
- ORM: Prisma
- API Documentation: Swagger (incl. autogenerated API client & models)
- Authentication: JWT
- Validation: zod
The API documentation is available at http://localhost:8080/api-specs
. You can also find the API documentation in the api
folder (here).
The endpoints expect UUID strings for the projectId
and reportId
parameters. Not complying with this will result in a 400 Bad Request response. When creating a project or a report, the id
field is not required. The id
field is generated by the database and returned in the response.
- Get Hello World!
GET /
- Get all projects
GET /projects
- Create a project
POST /projects
- Get a project
GET /projects/{projectId}
- Update a project
PUT /projects/{projectId}
- Delete a project
DELETE /projects/{projectId}
- Get all reports of a project
GET /projects/{projectId}/reports
- Create a report for a project
POST /projects/{projectId}/reports
- Get a report of a project
GET /projects/{projectId}/reports/{reportId}
- Update a report of a project
PUT /projects/{projectId}/reports/{reportId}
- Delete a report of a project
DELETE /projects/{projectId}/reports/{reportId}
- Get all reports where the given query word occurs at least 3 times
GET /reports?query={query}
Please copy the environment variables provided in the .env.example
file to a new .env
file. The DATABASE_URL
variable is already set up for you.
I decided not to use the initally provided database schema, as it did not enforce any constraints. Instead, I created a new schema using Prisma. The schema can be found in the prisma
folder (here). The database is stored in the db
folder (here).
The schema itself follows the specification from the task description.
erDiagram
ProjectDao {
String id PK
String name
String description
}
ReportDao {
String id PK
String text
String projectId FK
}
ProjectDao ||--o{ ReportDao : "reports"
PK
indicates a primary key.FK
indicates a foreign key.- there is a one-to-many relationship between
ProjectDao
andReportDao
.
.
├── README.md | this file
├── api | folder containing the API documentation
│ ├── generated
│ │ ├── core
│ │ ├── index.ts
│ │ ├── models | generated models
│ │ └── services
│ └── src
│ └── api-spec.yaml | API documentation using swagger
├── db | database folder
│ ├── db-tobi.sqlite3 | database file (used in this project)
│ ├── db-tobi.sqlite3-journal
│ └── db.sqlite3
├── images | images used in the README.md
│ └── database_schema.png
├── package-lock.json
├── package.json | npm package file with dependencies & scripts
├── prisma | prisma folder for the ORM
│ ├── migrations
│ │ ├── 20240714183344_init
│ │ └── migration_lock.toml
│ └── schema.prisma | prisma schema file
├── src
│ ├── controllers | controllers for the API
│ │ ├── projectController.ts
│ │ └── reportController.ts
│ ├── index.ts | main application file
│ ├── middleware | middleware for the API
│ │ ├── auth | authentication middleware
│ │ ├── errorhandler | error handling middleware
│ │ └── logger | logging middleware
│ ├── routes | routes for the API
│ │ ├── projectReportRouter.ts
│ │ ├── projectRouter.ts
│ │ └── reportRouter.ts
│ └── services | services for the API
│ ├── converters | converters for the API converting between DAOs and DTOs
│ ├── db.service.ts | NOT USED
│ ├── projectService.ts
│ ├── reportService.ts
│ └── validators | validators for data received from the API
└── tsconfig.json
The structure and the codebase of this project is based on other projects I did in private repositories or university projects. I decided to use an ORM to handle database operations. As software engineers we should not try to reinvent the wheel - instead, we should use off-the-shelf components where possible to guarantee the best quality and maintainability of the codebase while also delivering at a high pace.
For the database, I redefined the schema to enforce FK and unique constraints. This puts some of the responsibility on the database to ensure data integrity - the OS community that implemented the database was probably much more successful in covering all the edge-cases, that I would have forgotten.
This repository contains a very basic web application based on Typescript and Express.js. Main application file is index.ts
. Node and npm are required.
Ensure you have Node.js (v14.x or later) and npm (v6.x or later) installed.
To set up and run the application, execute the following commands:
npm install
npm run dev
The application will then be accessible at http://localhost:3000.
You will develop a backend system for managing data about a company's projects and their associated reports. Each project may have multiple reports linked to it, though having reports is not mandatory. Start your implementation using the provided SQLite database(db/db.sqlite3).
Refer to the database schema provided for understanding the data structure 👇
NOTE: You can use (db.service.ts) to handle SQL queries to the database.
- Fork this project: Start by forking this repository
- REST API Development: Design and implement a RESTful API to create, read, update, and delete projects and their reports.
- Special API Endpoint: Create an API endpoint that retrieves all reports where the same word appears at least three times.
- Optional: Secure all API routes with a hardcoded authentication token ("Password123").
- Submission: After completing the challenge, email us the URL of your GitHub repository.
- Further information:
- If there is anything unclear regarding requirements, contact us by replying to our email.
- Use small commits, we want to see your progress towards the solution.
- Code clean and follow the best practices.
Happy coding!