An API to connect Vendors and Jobs.
ℹ️ This project has been developed as part of VendorSmart's application test
The challenge is to find suitable and qualified vendors that offer the requested service to a community considering its location.
I decided to use some Clean Architecture in order to keep things organized, with separation of concerns and testable.
- Domain: the domain (Job, Location, ServiceCategory and Vendor) can be found in the
src/domain
folder and it's a model representation of the system. Since the domain is separated, it's easily tested; - Use Cases: the use cases (CreateJob, CreateVendor, FindVendorsForJob and GetReachableVendors) can be found in the
src/usecases
folder. It's designed like that so they are independent from one another; - Resources:
- Repositories: the repositories can be found in the
src/resources
folder. They mediate between the domain and the data layer. The repository implementations are memory (used for testing) and json (used for storing values on the file system); - DAO: the
src/resources/FileDAO.ts
acts like a DAO (data-access object) and interacts with the data layer, which are files on the file system;
- Repositories: the repositories can be found in the
- API: the API acts as a driver to the application. It's completely separated and it only implements the endpoints and calls the usecases.
I decided to store the data on the file system in order to quickly testing everything without having to readd everything all the time. This behavior could've been easily changed by just using the "Memory" repository implementation instead of the "JSON" ones. So, keep in mind that all suggested vendors and jobs are already added to the system.
- Node.js and Typescript - I decided on both technologies because of my expertise on them. That was a decision based on how fast could I deliver this challenge correctly.
- Express - I could've gone with other web frameworks such as NestJS or Fastify, but Express is well accepted and easy to plug in;
- jest - I used jest to test the application (unit and integration tests);
- axios - I used axios to test the API;
- Docker - I used docker to serve the application easily. You just need Docker installed in order to run it.
After cloning the project, you have two options to run it, using Docker or manually running it.
To run the application using Docker:
docker-compose up --build
That will build an image and run a container using it.
Install the application using:
npm install
If everything is right with the installation, you'll be able to run the application:
npm run dev
You can open http://localhost:3000/
to see the text "API is running"
You can test the application by running:
npm test
Beware that in order for the API tests to run, you need to run the application first (npm run dev).
To use the API, you can make requests on the following routes:
Endpoint: http://localhost:3000/create-job
// body
{
"name": <string>,
"locationId": <number>,
"serviceCategoryId": <number>
}
An authenticated endpoint to create a job.
Endpoint: http://localhost:3000/create-vendor
// body
{
"name": <string>,
"locationId": <number>,
"serviceCategories": [{
"id": <number>,
"compliant": <boolean>
}]
}
An authenticated endpoint to create a vendor.
Endpoint: http://localhost:3000/find-vendors-for-job?jobId={jobId}
An authenticated endpoint that returns the potential vendors for a given job. Compliant vendors should appear first.
Endpoint: http://localhost:3000/get-reachable-vendors?locationId={locationId}&serviceCategoryId={serviceCategoryId}
A public endpoint that returns total vendors, number of compliant vendors, and number of not compliant vendors. All for a given job details (service category, location);
API - I would document the API using Swagger. That way, all developers and API users would know exactly what to expect from the endpoints;
Environment variables - I would move the authentication values to environment variables. That way, the authentication secrets would stay a secret.
Database - I would use a database to store the data, instead of a file. It could be a SQL database, since there are some relationships between the data;
Tests - I don't think there is a need of testing the API even further, because the application itself (domain and usecases) are tested. The scenario would be different if there were expected status values and specific responses.