Event | Day | Date | Time |
---|---|---|---|
Release | Fri | Nov 01 | 09:00 AM ET |
Due | Fri | Nov 08 | 05:00 PM ET |
In this assignment, you will implement the Flashcards API server using Hono.js. The API should provide endpoints for managing decks and cards. It should follow RESTful principles and use appropriate HTTP methods for different operations.
To add persistence to the API, you will connect it to a local SQLite database using Drizzle ORM. Implement the database schema for decks and cards, ensuring a one-to-many relationship between decks and cards.
The API endpoints should allow users to perform CRUD operations on decks and cards. Each operation should have its own endpoint with appropriate HTTP methods:
Ensure that your API handles edge cases gracefully. For example, trying to create a card in a non-existent deck should return an appropriate error message. Use Zod for input validation and Hono’s built-in error handling capabilities to catch and format errors consistently.
You should implement pagination for list operations (GET /decks
and GET /decks/:deckId/cards
). The API should accept page
and limit
query parameters and return appropriate metadata (total count, total pages) along with the results.
Moreover, implement search functionality for both decks and cards. The API should accept a search
query parameter and perform case-insensitive searches on relevant fields (deck title for decks, front and back for cards).
Finally, organize your code effectively. Use separate files for routes, database schema, validation schemas, and any utility functions. Follow a consistent naming convention for files and functions. When done, you should have the following files and folders inside the api
folder:
Begin by logging into your GitHub account at https://github.com/. Then, accept the invitation by clicking on this link. This action will create a private GitHub repository with the starter code.
Please keep the repository private. Do not change its visibility or add collaborators. Clone this repository to your local machine to start your work.
Clone the repository to your local machine and follow the instructions in the README file to set up the project. Develop the app according to the provided description and specifications.
You don’t need to deploy this api server. However, don’t forget to update the info.json
file with links to your GitHub repository:
Make sure to commit and push the updated info.json
file to your GitHub repository. After doing so, submit your work on Gradescope.
If you need to resubmit, push the changes to your repository first, then re-submit on Gradescope.
Teaching assistants will evaluate your submission using the following criteria:
Spec 1: The Flashcards API should be built using Hono.js and should provide endpoints for managing decks and cards. After starting the local API server using the pnpm dev
command, it should not crash under any circumstances, including erroneous requests.
Spec 2: To retrieve a list of decks, send a GET request to http://localhost:3000/decks
. The request can include optional query parameters: page
(default: 1), limit
(default: 20, max: 100), and search
(optional string for searching deck titles). A successful request will receive a response with a 200 status code and a JSON body containing an array of deck objects and pagination metadata.
Spec 3: To retrieve a specific deck, send a GET request to http://localhost:3000/decks/:id
, where :id
is the ID of the desired deck. A successful request will receive a response with a 200 status code and a JSON body containing the deck object. If the deck is not found, the response will have a 404 status code.
Spec 4: To create a new deck, send a POST request to http://localhost:3000/decks
. The request body should be a JSON object containing a title
field (string, 1-100 characters). A successful request will receive a response with a 201 status code and a JSON body containing the newly created deck object.
Spec 5: To update a deck, send a PATCH request to http://localhost:3000/decks/:id
, where :id
is the ID of the deck to update. The request body should be a JSON object containing a title
field (string, 1-100 characters). A successful request will receive a response with a 200 status code and a JSON body containing the updated deck object. If the deck is not found, the response will have a 404 status code.
Spec 6: To delete a deck, send a DELETE request to http://localhost:3000/decks/:id
, where :id
is the ID of the deck to delete. A successful request will receive a response with a 200 status code and a JSON body containing a success message. If the deck is not found, the response will have a 404 status code.
Spec 7: To retrieve a list of cards in a deck, send a GET request to http://localhost:3000/decks/:deckId/cards
, where :deckId
is the ID of the deck. The request can include optional query parameters: page
(default: 1), limit
(default: 20, max: 100), and search
(optional string for searching card front or back content). A successful request will receive a response with a 200 status code and a JSON body containing an array of card objects and pagination metadata.
Spec 8: To retrieve a specific card, send a GET request to http://localhost:3000/decks/:deckId/cards/:cardId
, where :deckId
is the ID of the deck and :cardId
is the ID of the desired card. A successful request will receive a response with a 200 status code and a JSON body containing the card object. If the card or deck is not found, the response will have a 404 status code.
Spec 9: To create a new card in a deck, send a POST request to http://localhost:3000/decks/:deckId/cards
, where :deckId
is the ID of the deck. The request body should be a JSON object containing front
and back
fields (both strings, 1-500 characters). A successful request will receive a response with a 201 status code and a JSON body containing the newly created card object. If the deck is not found, the response will have a 404 status code.
Spec 10: To update a card, send a PATCH request to http://localhost:3000/decks/:deckId/cards/:cardId
, where :deckId
is the ID of the deck and :cardId
is the ID of the card to update. The request body should be a JSON object containing front
and/or back
fields (strings, 1-500 characters). A successful request will receive a response with a 200 status code and a JSON body containing the updated card object. If the card or deck is not found, the response will have a 404 status code.
Spec 11: To delete a card, send a DELETE request to http://localhost:3000/decks/:deckId/cards/:cardId
, where :deckId
is the ID of the deck and :cardId
is the ID of the card to delete. A successful request will receive a response with a 200 status code and a JSON body containing a success message. If the card or deck is not found, the response will have a 404 status code.
Spec 12: For all endpoints, if the request body fails validation (e.g., missing required fields, invalid data types, or out-of-range values), the response should have a 400 status code and include a JSON body with detailed error messages. Use Zod for input validation. Implement validation schemas for all input data (request bodies, query parameters, and path parameters) and use them with the zValidator
middleware from @hono/zod-validator
.
Spec 13: For all endpoints, if an unexpected server error occurs, the response should have a 500 status code and include a JSON body with a generic error message. Use Hono’s built-in error handling capabilities to catch and format errors consistently. Handle common scenarios such as “not found” errors, validation errors, and unexpected server errors.
Spec 14: Use SQLite as the database, with Drizzle ORM for database operations. Implement the database schema for decks and cards, ensuring a one-to-many relationship between decks and cards. Implement database migrations using Drizzle ORM. Include scripts in the package.json
file for generating and running migrations.
Spec 15: Create a seed script to populate the database with initial data for testing purposes. This script should insert sample decks and cards. Include scripts in the package.json
file for running the seed script.
Spec 16: Organize your code effectively. Use separate files for routes, database schema, validation schemas, and any utility functions. Follow a consistent naming convention for files and functions.