Roxie Gibson 4c85df345f Added a comment to the edit endpoint, finshing all todos | 3 years ago | |
---|---|---|
src | 3 years ago | |
.gitignore | 3 years ago | |
README.md | 3 years ago | |
package-lock.json | 3 years ago | |
package.json | 3 years ago | |
products.json | 3 years ago | |
tsconfig.json | 3 years ago | |
tslint.json | 3 years ago |
A REST API designed for a backend code test for Mission Labs. The background in this fake world is a Mission Labs merch store with a product database for the web store. API has all 4 CRUD methods for its products. Authentication protects any write methods with the X-Token header. All methods below are documents and the code base has comments and documentation throughout.
Requires node.js 14+, npm, and mongodb
npm install
Make sure you have properly setup a MongoDB instance and its running on the default port. Then run these two commands to insert our test data and set a field as an index.
mongoimport -d ml-test -c products --jsonArray products.json
mongo localhost/ml-test --eval "db.products.createIndex( { identifier: 1 }, { unique: true } )"
To run the server:
npm run prod
You should see this output
> ml-crud_api@1.0.0 prod /home/roxie/Projects/ts/mission-labs/code-test
> tsc && node ./dist/index.js
API running @ http://127.0.0.1:8081
Great! You are now running the REST API server. It is accessible at http://127.0.0.1:8081. For this demo, the secret key token for authentication is SECRET_KEY
.
The product schema will be as follows…
{
"identifier": "url-safe-identifier", // REQUIRED - CAN NOT be empty, needs to be url-safe and lowercase
"name": "Example Product", // REQUIRED - CAN NOT be empty
"price": 9000, // REQUIRED - Price is in pence, CAN NOT be negative
"category": "Examples", // REQUIRED - CAN NOT be empty
"sizes": ["Example Sized"] // OPTIONAL - Can be empty
}
Searching is done with identifiers instead of ObjectID ID’s to make API more human-readable and accessible.
Items in curly braces are parameters.
GET /api/products
This endpoint accepts two parameters to filter the output:
priceFrom
: Define a minimum price of all products in the searchpriceTo
: Define a maximum price of all products in the searchAll prices are listed as pence for ease of use.
200 OK
on success[
{
"identifier": "url-safe-identifier",
"name": "Example Product",
"price": 9000, // Price is in pence
"category": "Examples",
"sizes": ["Example Sized"]
}
]
GET /api/products/{IDENTIFIER}
200 OK
on success.404 Not Found
if product with identifier doesn’t exist.{
"identifier": "url-safe-identifier",
"name": "Example Product",
"price": 9000, // Price is in pence
"category": "Examples",
"sizes": ["Example Sized"]
}
POST /api/products/
200 OK
on success/400 Bad Request
when trying to create an object with the same identifier as an existing object.401 Unauthorized
on request without header X-Token
being set to an authorized key.Posted data should be a raw body with the header Content-Type
set to application/json
. Example of the posted JSON would look like this
{
"identifier": "ml-cool-logo-cup",
"name": "Brand New Mugs",
"price": 500, // Price is in pence
"category": "Liquid Holders"
}
PATCH /api/products/{IDENTIFIER}
Edits part of a product object (or all) with the data received.
200 OK
on success.400 Bad Request
if unable to parse some or all of the data received for updating.401 Unauthorized
on request without header X-Token
being set to an authorized key.404 Not Found
if product with identifier doesn’t exist.Posted data should be a raw body with the header Content-Type
set to application/json
. identifier
must be an identifier to an already existing product or else response will be 404 Not Found
. Partial updates are allowed when using PATCH. Example of the posted JSON would look like this
// /api/products/mug_1
{
"name": "Mugs One!",
}
This would change the name of the item.
DELETE /api/products/{IDENTIFIER}
204 No Content
on delete success.401 Unauthorized
on request without header X-Token
being set to an authorized key.404 Not Found
if product with identifier doesn’t exist.