Your task is to implement simple CRUD API using in-memory database underneath.
- Task can be implemented on Javascript or Typescript
- Only
nodemon,dotenv,cross-env,typescript,ts-node,ts-node-dev,eslintand its plugins,webpack-cli,webpackand its plugins,prettier,uuid,@types/*as well as libraries used for testing are allowed - Use 18 LTS version of Node.js
- Prefer asynchronous API whenever possible
- Implemented endpoint
api/users:- GET
api/usersis used to get all persons- Server should answer with
status code200 and all users records
- Server should answer with
- GET
api/users/{userId}- Server should answer with
status code200 and record withid === userIdif it exists - Server should answer with
status code400 and corresponding message ifuserIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === userIddoesn't exist
- Server should answer with
- POST
api/usersis used to create record about new user and store it in database- Server should answer with
status code201 and newly created record - Server should answer with
status code400 and corresponding message if requestbodydoes not contain required fields
- Server should answer with
- PUT
api/users/{userId}is used to update existing user- Server should answer with
status code200 and updated record - Server should answer with
status code400 and corresponding message ifuserIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === userIddoesn't exist
- Server should answer with
- DELETE
api/users/{userId}is used to delete existing user from database- Server should answer with
status code204 if the record is found and deleted - Server should answer with
status code400 and corresponding message ifuserIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === userIddoesn't exist
- Server should answer with
- GET
- Users are stored as
objectsthat have following properties:id— unique identifier (string,uuid) generated on server sideusername— user's name (string, required)age— user's age (number, required)hobbies— user's hobbies (arrayofstringsor emptyarray, required)
- Requests to non-existing endpoints (e.g.
some-non/existing/resource) should be handled (server should answer withstatus code404 and corresponding human-friendly message) - Errors on the server side that occur during the processing of a request should be handled and processed correctly (server should answer with
status code500 and corresponding human-friendly message) - Value of
porton which application is running should be stored in.envfile - There should be 2 modes of running application (development and production):
- The application is run in development mode using
nodemonorts-node-dev(there is anpmscriptstart:dev) - The application is run in production mode (there is a
npmscriptstart:prodthat starts the build process and then runs the bundled file)
- The application is run in development mode using
- There could be some tests for API (not less than 3 scenarios). Example of test scenario:
- Get all records with a
GETapi/usersrequest (an empty array is expected) - A new object is created by a
POSTapi/usersrequest (a response containing newly created record is expected) - With a
GETapi/user/{userId}request, we try to get the created record by itsid(the created record is expected) - We try to update the created record with a
PUTapi/users/{userId}request (a response is expected containing an updated object with the sameid) - With a
DELETEapi/users/{userId}request, we delete the created object byid(confirmation of successful deletion is expected) - With a
GETapi/users/{userId}request, we are trying to get a deleted object byid(expected answer is that there is no such object)
- Get all records with a
- There could be implemented horizontal scaling for application, there should be
npmscriptstart:multithat starts multiple instances of your application using the Node.jsClusterAPI (equal to the number of available parallelism - 1 on the host machine, each listening on port PORT + n) with a load balancer that distributes requests across them (using Round-robin algorithm). For example: available parallelism is 4,PORTis 4000. On runnpm run start:multiit works following way
- On
localhost:4000/apiload balancer is listening for requests - On
localhost:4001/api,localhost:4002/api,localhost:4003/apiworkers are listening for requests from load balancer - When user sends request to
localhost:4000/api, load balancer sends this request tolocalhost:4001/api, next user request is sent tolocalhost:4002/apiand so on. - After sending request to
localhost:4003/apiload balancer starts from the first worker again (sends request tolocalhost:4001/api) - State of db should be consistent between different workers, for example:
- First
POSTrequest addressed tolocalhost:4001/apicreates user - Second
GETrequest addressed tolocalhost:4002/apishould return created user - Third
DELETErequest addressed tolocalhost:4003/apideletes created user - Fourth
GETrequest addressed tolocalhost:4001/apishould return 404 status code for created user
- First