Thanks for allowing me to complete your tech test - I really enjoyed it. I was
familiar with Fastify, Jest and TypeScript going in. TypeBox was new to me, I've
tried to use it correctly but I'm sure my usage of it could be improved. I hit a
couple of issues with it around fast-json-stringify
(for serialisation of
responses) and jest-json-schema
(for validation in tests). As far as I could
tell this seems to relate to my usage of a Union type where the variants were an
array of objects, or null
.
The original instructions requested the ability to get product entities by brand ID and store entities by product ID. I have provided the following:
- an endpoint to get brands, with optional pagination, product ID and search
parameters
- search is performed via case-insensitive substring match against the brand name field
- an endpoint to get a single brand by ID
- an endpoint to get products, with optional pagination, brand ID and search
parameters
- search is performed via case-insensitive substring match against the product label field
- an endpoint to get stores, with optional pagination, product ID, and search
parameters
- search is performed via case-insensitive substring match against the store name field
- an endpoint serving a simple health status, e.g., of the type that might be used to perform pod healthchecks in Kubernetes
- a Swagger UI endpoint serving interactive API documentation
- a metrics endpoint serving Prometheus-compatible HTTP server request duration metrics for all non-health, non-Swagger endpoints
I've used pnpm
as my package manager - apologies if this causes issues. If you
would like to run the application natively you should be able to do so with:
pnpm i
pnpm start
Alternatively, as you also mentioned Docker, I've provided a Dockerfile and a docker-compose file. You can run the application in Docker with:
docker compose up -d app
Irrespective of whether you run it natively or in Docker, the application should
be available on: http://localhost:3000
. Additionally, metrics covering HTTP
response time are available in Prometheus-compatible format on:
http://localhost:3001/metrics
.
I've added Swagger documentation, this is available on:
http://localhost:3000/documentation
. Unfortunately there is a slight issue due
to my use of TypeBox modules which means some invalid references are generated
in the schema used by Swagger. This is visible in the documentation UI via an
error alert (at the top of the page) and when looking at the response schema for
each route (where the incorrectly referenced entry is shown as "string"
). This
issue has been raised on the @fastify/swagger
repository as a
bug.
I've provided unit tests (co-located with modules being tested) and end-to-end
(E2E) tests (in the test
directory).
You can run the unit tests with: pnpm t
.
The E2E tests require the application to be running. If you're running it
natively then you can run the E2E tests with: pnpm test:e2e:run
. Alternatively
you can run: pnpm test:e2e
- this will start the application using Docker, run
the tests, and stop the application again when they exit successfully.
I've treated the provided brands.json
file as a "database". From that decision
I've structured my code as though it was a normal three-layered web application:
- route handlers (controllers) are in
src/routes
- services (business logic) are in
src/services
- database (repositories) are in
src/database
I've also provided an error handler and not found handler in
src/fastify-handlers
. I favour consistent response shapes and providing these
handlers enables that for most use-cases.