Build a full stack JavaScript app that is functionally similar to this: <https://personal-library.freecodecamp.rocks/>. Working on this project will involve you writing your code using one of the following methods:
- Clone [this GitHub repo](https://github.com/freeCodeCamp/boilerplate-project-library) and complete your project locally.
- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo.
When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field.
You can send a <b>POST</b> request to `/api/books` with `title` as part of the form data to add a book. The returned response will be an object with the `title` and a unique `_id` as keys. If `title` is not included in the request, the returned response should be the string `missing required field title`.
```js
async (getUserInput) => {
try {
let data1 = await $.post(getUserInput('url') + '/api/books', {
title: 'Faux Book 1'
});
assert.isObject(data1);
assert.property(data1, 'title');
assert.equal(data1.title, 'Faux Book 1');
assert.property(data1, '_id');
let data2 = await $.post(getUserInput('url') + '/api/books');
assert.isString(data2);
assert.equal(data2, 'missing required field title');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
```
You can send a <b>GET</b> request to `/api/books` and receive a JSON response representing all the books. The JSON response will be an array of objects with each object (book) containing `title`, `_id`, and `commentcount` properties.
You can send a <b>GET</b> request to `/api/books/{_id}` to retrieve a single object of a book containing the properties `title`, `_id`, and a `comments` array (empty array if no comments present). If no book is found, return the string `no book exists`.
```js
async (getUserInput) => {
try {
let url = getUserInput('url') + '/api/books';
let noBook = await $.get(url + '/5f665eb46e296f6b9b6a504d');
assert.isString(noBook);
assert.equal(noBook, 'no book exists');
let sampleBook = await $.post(url, { title: 'Faux Book Alpha' });
assert.isObject(sampleBook);
let bookId = sampleBook._id;
let bookQuery = await $.get(url + '/' + bookId);
assert.isObject(bookQuery);
assert.property(bookQuery, 'title');
assert.equal(bookQuery.title, 'Faux Book Alpha');
assert.property(bookQuery, 'comments');
assert.isArray(bookQuery.comments);
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
```
You can send a <b>POST</b> request containing `comment` as the form body data to `/api/books/{_id}` to add a comment to a book. The returned response will be the books object similar to <b>GET</b>`/api/books/{_id}` request in an earlier test. If `comment` is not included in the request, return the string `missing required field comment`. If no book is found, return the string `no book exists`.
```js
async (getUserInput) => {
try {
let url = getUserInput('url') + '/api/books';
let commentTarget = await $.post(url, { title: 'Notable Book' });
assert.isObject(commentTarget);
let bookId = commentTarget._id;
let bookCom1 = await $.post(url + '/' + bookId, {
comment: 'This book is fab!'
});
let bookCom2 = await $.post(url + '/' + bookId, {
comment: 'I did not care for it'
});
assert.isObject(bookCom2);
assert.property(bookCom2, '_id');
assert.property(bookCom2, 'title');
assert.property(bookCom2, 'comments');
assert.lengthOf(bookCom2.comments, 2);
bookCom2.comments.forEach((comment) => {
assert.isString(comment);
assert.oneOf(comment, ['This book is fab!', 'I did not care for it']);
});
let commentErr = await $.post(url + '/' + bookId);
assert.isString(commentErr);
assert.equal(commentErr, 'missing required field comment');
let failingComment = await $.post(url + '/5f665eb46e296f6b9b6a504d', {
comment: 'Never Seen Comment'
});
assert.isString(failingComment);
assert.equal(failingComment, 'no book exists');
} catch (err) {
throw new Error(err.responseText || err.message);
}
};
```
You can send a <b>DELETE</b> request to `/api/books/{_id}` to delete a book from the collection. The returned response will be the string `delete successful` if successful. If no book is found, return the string `no book exists`.
```js
async (getUserInput) => {
try {
let url = getUserInput('url') + '/api/books';
let deleteTarget = await $.post(url, { title: 'Deletable Book' });
You can send a <b>DELETE</b> request to `/api/books` to delete all books in the database. The returned response will be the string `'complete delete successful` if successful.