Meal API: Elysia backend serving the menu API and a single-file frontend
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# Meal API
|
||||
|
||||
A small food menu API with a single-page frontend.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
| --- | --- |
|
||||
| `index.html` | The frontend (page, styles and script are all inline) |
|
||||
| `server.js` | The whole backend: the menu data + the routes |
|
||||
| `package.json` | Only needed so `elysia` can be installed |
|
||||
|
||||
`index.html` and `server.js` are the whole application — no `public/` folder,
|
||||
no separate `menu.js`, `app.js` or `style.css`.
|
||||
|
||||
## Run it
|
||||
|
||||
```sh
|
||||
npm install
|
||||
npm start # node server.js
|
||||
```
|
||||
|
||||
Then open <http://localhost:3000>.
|
||||
|
||||
Other ways to run the exact same file:
|
||||
|
||||
```sh
|
||||
npm run dev # node --watch server.js (auto-restart on save)
|
||||
npm run bun # bun server.js
|
||||
```
|
||||
|
||||
`server.js` runs on **both** Node and Bun. Elysia serves through `Bun.serve` on
|
||||
Bun, and `server.js` loads the `@elysiajs/node` adapter automatically whenever
|
||||
Bun isn't present, so neither runtime needs its own version of the file.
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Method | Path | Result |
|
||||
| --- | --- | --- |
|
||||
| GET | `/` or `/index.html` | the frontend |
|
||||
| GET | `/api/menu` | the whole menu |
|
||||
| GET | `/api/menu/:id` | one menu item |
|
||||
|
||||
```sh
|
||||
curl http://localhost:3000/api/menu
|
||||
curl http://localhost:3000/api/menu/2
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
`GET /api/menu` -> `200`
|
||||
|
||||
```json
|
||||
[
|
||||
{ "id": 1, "food": "Adobo", "price": 75 },
|
||||
{ "id": 2, "food": "Fried Chicken", "price": 50 },
|
||||
{ "id": 3, "food": "Yum Burger", "price": 70 }
|
||||
]
|
||||
```
|
||||
|
||||
`GET /api/menu/2` -> `200`
|
||||
|
||||
```json
|
||||
{ "id": 2, "food": "Fried Chicken", "price": 50 }
|
||||
```
|
||||
|
||||
| Case | Status | Body |
|
||||
| --- | --- | --- |
|
||||
| id doesn't exist (`/api/menu/99`) | `404` | `{ "error": "No menu item with ID 99." }` |
|
||||
| id isn't a whole number (`/api/menu/abc`, `/api/menu/0`, `/api/menu/1.5`) | `400` | `{ "error": "ID must be a whole number, like 1." }` |
|
||||
| any non-GET method | `405` | `{ "error": "Method not allowed" }` |
|
||||
| unknown path (`/nope`) | `404` | `Not found` |
|
||||
|
||||
## Menu data
|
||||
|
||||
Defined in `server.js`:
|
||||
|
||||
```js
|
||||
const menu = [
|
||||
{ id: 1, food: 'Adobo', price: 75 },
|
||||
{ id: 2, food: 'Fried Chicken', price: 50 },
|
||||
{ id: 3, food: 'Yum Burger', price: 70 },
|
||||
]
|
||||
```
|
||||
|
||||
## Frontend
|
||||
|
||||
`index.html` lets you either load the whole menu or look up a single item by ID.
|
||||
It fetches the API with `fetch()`, renders the results into a table, and shows a
|
||||
message instead of the table whenever the API returns an error.
|
||||
Reference in New Issue
Block a user