# SliceDrop HW1: A Beginner's Guide to the Finished API

This guide explains the completed SliceDrop menu and orders API from the
ground up. It assumes that HTTP, Express, TypeScript, and automated tests are
all new. The examples and descriptions match the code and checked-in tests in
this repository.

The assignment is small on purpose. It gives one application enough pieces to
show the Week 1 and Week 2 ideas working together:

- a client sends HTTP requests;
- an Express server receives them and runs middleware in order;
- routers choose the behavior for a path;
- plain functions validate data and look up menu items;
- a small in-memory data module stores orders;
- the server returns a status code, headers, and a JSON body;
- Vitest and Supertest check the observable behavior.

## 1. The mental model: a client talks to a server through an API

An API is a set of agreed request and response shapes. A client can be a web
page, a mobile app, Postman, `curl`, or a test. The client does not call
TypeScript functions such as `addOrder` directly. It sends an HTTP request.

```text
client
  │  HTTP request: method, URL, headers, optional JSON body
  ▼
Express application (`app`)
  │  body parser → router → auth middleware → handler → data/validation
  ▼
HTTP response: status, headers, JSON body
  │
  ▼
client reads the result
```

For example, a customer placing an order sends:

```http
POST /orders HTTP/1.1
Authorization: Bearer slicedrop-customer-secret
Content-Type: application/json

{"customerName":"Ada","items":[{"menuItemId":"soda","quantity":1}]}
```

The server parses the JSON body, checks the token, validates the order, stores
it in memory, and answers with `201 Created` and a JSON representation of the
new order. The client only needs the API contract: it does not need to know
which array or function stored the order.

This project has no database, browser UI, or deployed service. The API is the
Express application. The `index.ts` file is the part that opens a network port
when the application is run as a server.

## 2. HTTP pieces used by this API

### Methods and routes

An HTTP method says what kind of operation the client is requesting. A route is
the method plus the path pattern. The same path can have different behavior for
different methods; `GET /orders` and `POST /orders` are separate routes.

| Method and path | Who may call it | Behavior |
| --- | --- | --- |
| `GET /menu` | anyone | Return all six menu items, or filter by `category`. |
| `GET /menu/:id` | anyone | Return one menu item by its exact ID, or `404`. |
| `POST /orders` | customer token | Validate and create an order, or return validation errors. |
| `GET /orders` | staff token | Return all stored orders, or filter by `status`. |

The `:id` in `GET /menu/:id` is a route parameter. A request for
`/menu/hawaiian` makes `req.params.id` equal to the string `"hawaiian"`.

### Status codes

The status code is a compact description of what happened.

- `200 OK` means the request succeeded. It is used for menu responses and
  successful order listings.
- `201 Created` means a new resource was created. A valid `POST /orders`
  returns this status.
- `400 Bad Request` means the client sent something the server cannot process,
  such as invalid JSON or an invalid order body.
- `401 Unauthorized` means the request did not present the required valid
  token. This assignment uses `401` for a missing, malformed, unknown, or
  wrong-role token.
- `404 Not Found` means no route handled the path, or a requested menu ID does
  not exist.
- `500 Internal Server Error` means application code failed unexpectedly. It
  is a server problem, even when it happens while handling a valid request.

The status is part of the API contract. A client can make a useful decision
from `201`, `400`, or `401` even before reading the body.

### Headers

Headers are named metadata attached to an HTTP request or response. This API
uses two request headers especially:

- `Authorization: Bearer <token>` carries the customer or staff credential.
- `Content-Type: application/json` tells the server that the body is JSON.

`express.json()` uses the content type and JSON parser to turn a valid JSON
request body into `req.body`. If JSON cannot be parsed, the parser raises an
error before an order handler runs.

### Body, query string, and route parameters

These are three different places request data can live:

```text
GET /menu/hawaiian?category=pizza
    └──────┬─────┘ └──────┬──────┘
 route parameter `id`      query parameter `category`
```

- The body is normally used for data being submitted. The order body contains
  `customerName` and `items`.
- A query string begins after `?`. `GET /menu?category=pizza` puts the value
  in `req.query.category`; `GET /orders?status=pending` puts the value in
  `req.query.status`. Query filters do not create a missing-resource error: an
  unknown category or status produces `200` with `[]`.
- A route parameter is part of the path pattern. In `/menu/:id`, the value is
  available at `req.params.id`.

Week 1 introduced these ideas with small `app.get` and `app.post` handlers.
HW1 applies the same ideas after the handlers have been organized into routers.

## 3. The project map and the app/server split

The important files fit together like this:

```text
src/index.ts                 starts listening on port 3000
src/app.ts                   builds and exports the Express app
src/routers/menu.ts          GET /menu and GET /menu/:id
src/routers/orders.ts        POST /orders and GET /orders
src/middleware/auth.ts       Bearer parsing and role checks
src/validation/validate-order.ts
                              order-body validation
src/data/menu.ts             supplied menu array and lookup function
src/data/orders.ts           in-memory order array and ID generation
src/types.ts                 shared TypeScript types
src/constants.ts             tokens and port
src/__tests__/*.test.ts      Vitest/Supertest behavior checks
```

`src/app.ts` exports `app` but does not call `listen`. `src/index.ts` imports
that app and starts the real server:

```ts
import { app } from "./app";
import { PORT } from "./constants";

app.listen(PORT, () => {
  console.log(`SliceDrop listening on http://localhost:${PORT}`);
});
```

This split is important for testing. Supertest can import the app and manage a
temporary listener for each test run, so the developer does not have to start
the server on its normal fixed port first. Calling `listen` in `app.ts` would
start that fixed listener whenever the module was imported and could cause port
conflicts.

The supplied `constants.ts` gives the exact development values:

```text
customer token: slicedrop-customer-secret
staff token:    slicedrop-staff-secret
port:           3000
```

These hard-coded tokens are suitable only for this exercise. The comments in
that file point toward a later course topic: real secrets should come from
configuration such as environment variables, rather than source code.

## 4. The middleware chain: order is behavior

Express processes a request by walking through the middleware and route
handlers in the order they were registered. Each ordinary middleware has the
shape `(req, res, next)`:

- inspect or change the request;
- send a response and stop, or call `next()` to continue;
- never do neither, or the request can hang.

The finished `app.ts` registers the shared chain in this order:

```text
1. express.json()
2. /menu router
3. /orders router
4. JSON 404 handler
5. four-argument error handler
```

The order matters in several ways.

### JSON parsing must be before routes

The order handlers expect `req.body` to contain parsed JSON. Therefore
`express.json()` must be registered before both routers. A valid JSON body is
available to the order handler; malformed JSON causes the parser to pass an
error to the final error handler.

### Authorization must be before order validation

`POST /orders` has this route-specific chain:

```text
express.json()
  → orders router matches `/`
  → requireCustomerToken
  → POST handler
  → validateOrder
  → addOrder
```

The customer middleware is placed before the handler, so a request with no
token gets `401` without being validated. The test named “auth runs before
validation” deliberately sends `{}` with no token and expects `401`, not `400`.
That result is a consequence of registration order, not a special case inside
the validator.

`GET /orders` follows the same pattern with `requireStaffToken` before the
listing handler. A valid customer token is still rejected there because the
route requires the staff token.

### 404 must be after the routers

The 404 handler is a normal fall-through middleware. If it came before the
routers, it would answer every request and the routers would never run. After
the routers, it means “no earlier route matched.” It returns:

```json
{"error":"Not found"}
```

### The error handler must be last and have four parameters

Express identifies error-handling middleware by the exact four-parameter form:

```ts
(err, req, res, next)
```

The finished handler is registered after the 404 handler. The `next` parameter
is not used in this assignment, but it must remain in the function signature so
Express recognizes the function as an error handler.

## 5. Authentication and exact Bearer parsing

The authentication module separates token parsing from Express middleware. That
is a useful Week 2 design choice: the parser is a plain function that can be
tested without constructing a request, while the middleware handles the HTTP
response and `next()`.

### What counts as a valid header

`parseBearerToken(header)` accepts only the exact shape:

```text
Bearer <one-or-more-non-whitespace-characters>
```

The implementation uses the case-sensitive regular expression
`/^Bearer ([^\s]+)$/`.

| Header value | Result |
| --- | --- |
| missing/`undefined` | `null` |
| `Bearer slicedrop-customer-secret` | token string |
| `bearer slicedrop-customer-secret` | `null` because `Bearer` is case-sensitive |
| `Basic slicedrop-customer-secret` | `null` |
| `Bearer ` | `null` because the token is empty |
| `Bearer one two` | `null` because the token contains whitespace |
| `Bearer nope` | `"nope"`; parsing succeeds, but authorization rejects it |

The parser does not decide whether the token is customer or staff. It only
extracts a candidate string or returns `null`.

### What the two middleware functions do

`requireCustomerToken` reads `req.headers.authorization`, passes it to the
parser, and compares the result to `CUSTOMER_TOKEN`. If it does not match, it
sends:

```http
401 Unauthorized
```

```json
{"error":"Unauthorized"}
```

On a match it calls `next()`, allowing validation and order creation to run.
`requireStaffToken` has the same structure but compares with `STAFF_TOKEN`.

The distinction is intentional: possession of a valid customer token does not
grant access to the staff-only order list.

## 6. The menu API

### `GET /menu`

With no query parameter, the menu router returns the supplied `menu` array
directly as JSON. It contains six items:

```text
hawaiian, meat-lovers, build-your-own,
bread-nugz, dipping-sauce, soda
```

With `?category=pizza`, the handler uses `menu.filter(...)` and keeps items
whose `category` exactly equals `"pizza"`. The result contains three pizzas.

```http
GET /menu?category=pizza
```

```json
[
  {"id":"hawaiian","name":"Hawaiian","category":"pizza", "...":"..."},
  {"id":"meat-lovers","name":"Meat Lovers","category":"pizza", "...":"..."},
  {"id":"build-your-own","name":"Build Your Own","category":"pizza", "...":"..."}
]
```

The `"..."` markers above mean additional real fields are present; they are
not literal response fields. A category with no matches, such as
`category=seafood`, returns `200` and `[]`. If a query value is not a string
(for example, a repeated or unusually shaped query parameter), the handler
also returns `[]` rather than treating it as an exact category.

### `GET /menu/:id`

The handler reads `req.params.id` and calls `findMenuItem(id)`. That supplied
function uses `menu.find(...)` and returns either a `MenuItem` or `undefined`.

For a known ID:

```http
GET /menu/hawaiian
```

the response is `200` and includes the full item, including its three sizes,
crust choices, and toppings. For an unknown ID:

```http
GET /menu/sushi
```

the response is:

```http
404 Not Found
```

```json
{"error":"Menu item not found"}
```

Returning `[]` would be appropriate for an empty collection filter, but a
single requested resource that does not exist is represented by `404`.

## 7. Orders: creating and listing data

### `POST /orders`

The request first needs the customer token. Once authorized, the handler calls
`validateOrder(req.body)`. An empty error list means the body is valid. A
non-empty list is returned as:

```http
400 Bad Request
```

```json
{
  "errors": [
    "customerName must be a non-blank string",
    "items must be a non-empty array"
  ]
}
```

For valid input, `addOrder(req.body)` creates and stores the order, and the
handler returns `201`:

```http
POST /orders
Authorization: Bearer slicedrop-customer-secret
Content-Type: application/json
```

```json
{
  "customerName": "Ada",
  "items": [
    {"menuItemId": "hawaiian", "quantity": 2, "size": "large"}
  ]
}
```

```http
201 Created
```

```json
{
  "id": "1",
  "status": "pending",
  "createdAt": "2026-09-16T12:00:00.000Z",
  "customerName": "Ada",
  "items": [
    {"menuItemId": "hawaiian", "quantity": 2, "size": "large"}
  ]
}
```

The timestamp in a real response is the current time, so tests check that it
is a parseable string instead of comparing one fixed value. IDs are strings and
increase from `"1"`; each call receives a distinct ID while the process is
running. Every new order starts with status `"pending"`.

### `GET /orders`

This endpoint requires the staff token:

```http
GET /orders
Authorization: Bearer slicedrop-staff-secret
```

With no filter it returns the current array in insertion order. With
`?status=pending`, it calls `listOrders("pending")` and returns only matching
orders. An unknown or currently empty status returns `200` and `[]`; it is not
an invalid request.

The order data is deliberately in memory. `src/data/orders.ts` starts with:

```ts
let orders: Order[] = [];
let nextId = 1;
```

`addOrder` creates an `Order`, increments `nextId`, pushes the order, and
returns it. `listOrders` either returns all orders or uses `filter` for a
status. `_resetOrders()` clears the array and resets IDs for tests. The orders
are lost and IDs start over when the Node process restarts; this is not a
persistent database.

## 8. Order validation, including every error

`validateOrder(body)` is a plain function returning `string[]`. It does not
send an HTTP response. The route handler decides that a non-empty array means
`400`. Keeping validation separate makes the rules easier to read and test.

The function is defensive because `req.body` comes from an outside client. A
client can send `null`, a number, an array, or an object with unexpected field
types. The implementation checks before reading nested properties.

### Request-level checks

1. It checks whether `body` is a non-null object and not an array. If not, the
   values used for validation are treated as `undefined`.
2. `customerName` must be a string whose `trim()` is not empty. This rejects a
   missing value, a number, `""`, and whitespace-only text.
3. `items` must be a non-empty array. If it is not an array, the function
   returns the errors found so far rather than calling `.forEach` on an unsafe
   value.

### Item-level checks

For every item, the validator checks:

- the item is object-like before reading its fields;
- `menuItemId` is a string identifying an existing menu item;
- `quantity` is an integer at least `1`;
- an optional `size` is offered by that menu item;
- an optional `crust` is offered by that menu item;
- an optional `sauce` is offered by that menu item;
- an optional `toppings` value is an array, and every topping name is offered.

The validator uses the item index in messages, such as
`items[0].quantity must be a whole number of at least 1`. It does not stop at
the first problem. For example, an order with a blank name, an unknown menu
ID, and quantity `0` receives all applicable messages in the same `errors`
array. This is more useful to a client than forcing three separate requests.

Option checks happen only when the menu item was found. That avoids trying to
read option lists from `undefined`. It also means an unknown menu item gets
the menu-ID error without a misleading size, crust, sauce, or topping error.

The four supplied helper functions at the bottom of the file implement the
membership checks:

- `offersSize` returns `false` when `sizes` is absent, then uses `.some` to
  compare an option's `name`.
- `offersCrust` returns `false` when `crusts` is absent, then uses `.includes`.
- `offersSauce` does the same for `sauces`.
- `offersTopping` returns `false` when `toppings` is absent, then uses `.some`
  to compare topping names.

Matching is exact and case-sensitive. `"Large"` is not the same as `"large"`.
The `soda` item has sizes but no crusts or toppings; a supplied unsupported
option therefore fails validation.

## 9. TypeScript ideas in this code

### Interfaces and type aliases

`src/types.ts` describes the shapes shared across modules.

- `Category` is a union of four allowed strings: `"pizza"`, `"appetizer"`,
  `"side"`, and `"beverage"`.
- `SizeOption` and `ToppingOption` require a `name` and numeric `price`.
- `MenuItem` requires `id`, `name`, and `category`; `description`, `price`,
  `sizes`, `crusts`, `sauces`, and `toppings` are optional with `?`.
- `OrderStatus` is the union `"pending" | "in-progress" | "completed"`.
- `OrderItem` requires `menuItemId` and `quantity`, while customization fields
  are optional.
- `NewOrder` is the customer-submitted shape.
- `Order extends NewOrder`, so an `Order` has all of the new-order fields plus
  `id`, `status`, and `createdAt`.

An interface describes an object shape; a type alias such as `Category` or
`OrderStatus` can describe a set of allowed literal values. TypeScript checks
these shapes while compiling, but a client can still send bad runtime data.
That is why `validateOrder` still performs real runtime checks.

### `undefined` and narrowing

Optional properties may be absent, so TypeScript represents their values as
possibly `undefined`. `findMenuItem` returns `MenuItem | undefined` because a
lookup may fail. The code narrows before using the value:

```ts
const menuItem = findMenuItem(id);
if (menuItem === undefined) {
  res.status(404).json({ error: "Menu item not found" });
  return;
}

res.json(menuItem); // here TypeScript knows it is a MenuItem
```

The validator uses checks such as `Array.isArray(items)`, `typeof category ===
"string"`, and `menuItem === undefined` to narrow broad runtime values into
safe, more specific ones. The early `return` statements make those narrowed
facts easy to follow.

`validateOrder(body: any)` intentionally accepts any incoming body so it can
inspect malformed values. `any` turns off compile-time protection for that
value, so the function compensates with explicit runtime guards. The topping
callback uses `unknown`, which is safer: a value of type `unknown` must be
checked before treating it as a string.

### Arrays and callback methods

Several small array methods express the business rules directly:

```ts
menu.find((item) => item.id === id);       // one matching item or undefined
menu.filter((item) => item.category === category); // all matches
items.forEach((item, index) => { ... });   // validate every item
options.some((option) => option.name === size); // any option matches
crusts.includes(crust);                    // exact string membership
```

The tests also use `.map` to project order names and `.every` to verify that a
filtered result satisfies a condition. These methods take callback functions:
the arrow function receives an element, and the method returns the appropriate
result without requiring a manual index loop.

## 10. File-by-file walkthrough of the completed work

This section follows the changed files from the outside of the application
toward the inside.

### `src/app.ts`

1. The imports bring in Express request/response types, the two routers, and
   the types needed by the error handler.
2. `export const app = express()` creates the application object and exports it
   for both `index.ts` and tests.
3. `app.use(express.json())` installs the body parser before any route.
4. `app.use("/menu", menuRouter)` mounts the menu router at the `/menu` base
   path. `app.use("/orders", ordersRouter)` does the same for orders.
5. The next middleware returns JSON `404` for any request that got through
   both routers without a match.
6. The final four-argument middleware distinguishes malformed JSON from other
   errors. A `SyntaxError` with a `body` property is answered with `400` and
   `{ error: "Request body must be valid JSON" }`. Any other error is logged
   with `console.error` and answered with `500` and
   `{ error: "Internal server error" }`.

The `return` statements after responses are control-flow guards. They stop the
handler from trying to send a second response.

### `src/middleware/auth.ts`

1. It imports Express types and the two token constants.
2. `parseBearerToken` handles only extraction. It returns `null` for a missing
   header or a regex mismatch and returns capture group `1` for a valid header.
3. `requireCustomerToken` calls the parser, sends `401` on any non-matching
   token, and calls `next()` only for the customer token.
4. `requireStaffToken` repeats that pattern for the staff token.

The parser is deliberately not middleware. A plain function has no response to
send and no `next()` to call, so its job stays focused and direct.

### `src/routers/menu.ts`

1. It imports Express request/response/router types and the supplied menu data
   functions.
2. `menuRouter = Router()` creates a router whose paths are relative to the
   mount point in `app.ts`.
3. `menuRouter.get("/", ...)` handles the mounted `GET /menu`. It returns the
   whole array when `category` is absent, returns `[]` when the query value is
   not a string, and otherwise filters for an exact category.
4. `menuRouter.get("/:id", ...)` handles mounted `GET /menu/:id`. It looks up
   the ID, returns a `404` error object when there is no item, and returns the
   item when there is one.

Because the router is mounted at `/menu`, its internal `/` is not just `/` to
the client. The combination is `/menu/` (and Express also handles the usual
slash variation), while its internal `/:id` becomes `/menu/:id`.

### `src/routers/orders.ts`

1. It imports the supplied `addOrder` and `listOrders` functions, both auth
   middleware functions, and `validateOrder`.
2. `ordersRouter = Router()` creates a relative router.
3. `ordersRouter.post("/", requireCustomerToken, handler)` puts customer auth
   before the handler. The handler collects validation errors, returns `400`
   with `{ errors }` when needed, and otherwise calls `addOrder` and returns
   `201` with the new order.
4. `ordersRouter.get("/", requireStaffToken, handler)` puts staff auth before
   the listing logic. The handler returns all orders without a `status` query,
   returns `[]` for a non-string query value, and passes a string status to
   `listOrders`.

The leading slash in each router path is relative to the `/orders` mount, so
the public paths are `POST /orders` and `GET /orders`.

### `src/validation/validate-order.ts`

1. It imports the `MenuItem` type and `findMenuItem`.
2. It creates an error accumulator, checks whether the body is a non-array
   object, and validates `customerName`.
3. It validates that `items` is a non-empty array. If not, it returns the
   accumulated errors safely.
4. It loops through every item, looks up the menu ID, checks quantity, and
   returns the menu-ID and quantity errors as appropriate.
5. When an item and menu item are both safe to inspect, it checks each optional
   customization by calling the supplied helper functions.
6. It returns the complete `errors` array. An empty array is the success signal.
7. The four helpers at the bottom handle option membership and safely treat an
   absent option list as “not offered.”

The function deliberately accumulates with `errors.push(...)` instead of
returning immediately from the first bad field. It only returns early when
continuing would be unsafe, such as when `items` is not an array.

### `src/types.ts`

This supplied module is the shared vocabulary. It prevents a menu item from
silently becoming an arbitrary object inside the typed parts of the program,
documents which fields are optional, and distinguishes a customer-submitted
`NewOrder` from a stored `Order` with server-generated fields.

### `src/data/menu.ts`

This supplied module defines the six menu items and reusable constants for
standard toppings, crusts, and dipping sauces. `findMenuItem` uses `.find` and
can return `undefined`. The data is process-local and is not changed by the
API routes.

### `src/data/orders.ts`

This supplied module is the exercise's temporary database. `addOrder` creates
the server fields, increments the ID counter, pushes into the array, and
returns the object. `listOrders` preserves insertion order when unfiltered and
uses `.filter` for a status. `_resetOrders` is test-only and is never called by
application routes.

### `src/constants.ts` and `src/index.ts`

`constants.ts` holds the two tokens and port. `index.ts` is the executable
entrypoint that starts listening. Keeping this start-up action out of `app.ts`
is what lets Supertest import the app safely.

## 11. How the tests map to requirements

Vitest supplies `describe`, `it`, `beforeEach`, `expect`, and test doubles such
as `vi`. Supertest supplies a client-like API:

```ts
const res = await request(app)
  .post("/orders")
  .set("Authorization", `Bearer ${CUSTOMER_TOKEN}`)
  .send(ORDER);

expect(res.status).toBe(201);
expect(res.body.status).toBe("pending");
```

`request(app)` gives the exported Express app to Supertest. It does not require
the developer to run `npm run dev` or start port `3000`; Supertest manages the
temporary listener used for the request. `.set` adds a header, `.send` supplies
a JSON body, and Supertest parses JSON responses into `res.body`.

### `src/__tests__/auth.test.ts`

- verifies that missing and unknown customer tokens produce `401`;
- verifies that the customer token allows `POST /orders`;
- verifies that missing, unknown, and customer tokens are rejected by
  `GET /orders`;
- verifies that the staff token allows the order list;
- verifies that authentication runs before validation by expecting `401` for a
  missing token and bad body.

### `src/__tests__/errors.test.ts`

- verifies a path no router handles returns `404` with an `error` field;
- verifies invalid orders return `400` with an `errors` array;
- verifies the validator catches unknown menu IDs, quantities below one,
  unsupported crusts, and unsupported sizes;
- mocks `addOrder` to throw and verifies an application failure becomes `500`,
  not a client-facing `400`;
- sends malformed JSON and verifies the parser error becomes a JSON `400`.

The mock test is especially useful because it distinguishes two error sources:
the client sent valid JSON and a valid order, but application code still failed.

### `src/__tests__/menu.test.ts`

- checks that the unfiltered menu has six items;
- checks exact category filtering for pizzas;
- checks an unknown category returns an empty successful array;
- checks a known item includes customization options;
- checks an unknown ID returns `404` with an `error` field.

### `src/__tests__/orders.test.ts`

- checks successful creation returns `201`, preserves customer and items,
  starts as `pending`, gives an ID, and creates an ISO-parseable timestamp;
- checks two orders receive different IDs;
- checks an empty order list before creation;
- checks status filtering and the empty result for a status with no matches;
- checks that unfiltered results preserve insertion order.

Each order test file calls `_resetOrders()` in `beforeEach`. That keeps tests
independent even though the application data module is stateful. Tests should
not rely on another test having run first.

The timestamp assertion demonstrates a general testing rule: assert a stable
property, such as “is a parseable date string,” rather than an unstable exact
value, such as the clock time from one particular run.

## 12. Install, run, test, type-check, and build

Run these commands from the repository directory:

```bash
npm install
npm test
npm run typecheck
npm run build
```

What each command does:

- `npm install` installs the dependencies in `package.json` and records them
  through the lockfile.
- `npm test` runs `vitest run`, which executes the test suite once.
- `npm run test:watch` runs Vitest interactively and reruns tests as files
  change.
- `npm run typecheck` runs `tsc --noEmit`. It checks types without creating
  output files.
- `npm run build` runs `tsc -p tsconfig.build.json` and emits compiled server
  code into `dist` while excluding tests.
- `npm run dev` runs `tsx src/index.ts`, starts the server on port `3000`, and
  prints its local URL. `tsx` runs TypeScript directly; it does not replace the
  separate type-check command.

With the development server running, equivalent manual requests include:

```bash
curl http://localhost:3000/menu
curl 'http://localhost:3000/menu?category=pizza'
curl http://localhost:3000/menu/hawaiian

curl -X POST http://localhost:3000/orders \
  -H 'Authorization: Bearer slicedrop-customer-secret' \
  -H 'Content-Type: application/json' \
  -d '{"customerName":"Ada","items":[{"menuItemId":"soda","quantity":1}]}'

curl http://localhost:3000/orders \
  -H 'Authorization: Bearer slicedrop-staff-secret'
```

The last two requests must occur in the same running process if the listing is
expected to show the newly created order. Restarting the process clears the
in-memory order array.

The repository README says the short workflow is to install dependencies and
make the tests pass, and that the live assignment specification is the primary
source when available. The checked-in tests are the concrete, executable
examples of the behavior described here.

## 13. Common mistakes and a debugging routine

### Common implementation mistakes

1. **Registering `express.json()` too late.** Put it before both routers so
   `req.body` is ready.
2. **Putting auth inside validation or after the handler.** Auth belongs as the
   route-specific middleware argument before the handler. Otherwise a missing
   token can incorrectly produce `400` or create an order.
3. **Using the wrong token for a role.** The customer token is valid only for
   `POST /orders`; the staff token is required for `GET /orders`.
4. **Accepting loose Bearer formats.** The required parser is exact: capital
   `Bearer`, one literal separating space, and a non-whitespace token with no
   extra text.
5. **Mounting paths twice.** Once the app mounts `menuRouter` at `/menu`, the
   router should define `/` and `/:id`, not `/menu` and `/menu/:id`.
6. **Returning `200` for a missing single item.** Unknown `/menu/:id` values
   are `404`; unknown collection filters are `200` with `[]`.
7. **Stopping validation at the first error.** Keep pushing all discovered
   problems into the array.
8. **Calling `.forEach` before checking `items`.** Check `Array.isArray(items)`
   first. Likewise, check that a menu lookup succeeded before reading option
   lists.
9. **Confusing malformed JSON with an invalid order.** Malformed JSON is a
   parser error and gets `400` from the global handler. Valid JSON with bad
   fields gets `400` with `{ errors: [...] }`. A thrown application exception
   gets `500`.
10. **Forgetting to return after sending.** A handler that sends an error and
    keeps running can attempt a second response and trigger another error.
11. **Removing the fourth error-handler parameter.** Express uses the four
    parameters to recognize error middleware, even when `next` is unused.
12. **Expecting orders to survive a restart.** The array is in memory. Restart
    means an empty list and IDs beginning again at `"1"`.
13. **Testing an exact timestamp.** Check its type and parseability, as the
    supplied test does.
14. **Relying on test order.** Reset state in `beforeEach`; a test should be
    able to run by itself.

### A practical debugging routine

When a request fails, inspect the problem in this order:

1. Confirm the method and full path. `POST /orders` and `GET /orders` are
   different, and a router path is relative to its mount point.
2. Check the status code before reading the body. `401` points to auth, `404`
   to routing or an unknown menu ID, and `400` to parsing or validation.
3. Check the headers. For orders, use the exact token and
   `Content-Type: application/json`.
4. Check the body shape. `customerName` must be non-blank and `items` must be
   a non-empty array; each item needs a known menu ID and integer quantity.
5. Add a focused test or run one existing test by its description. A failing
   test tells you the observable contract rather than an internal guess.
6. If the status is `500`, read the server log. The global handler logs the
   unexpected error while returning a deliberately generic client message.
7. Run `npm run typecheck` after fixing behavior. Passing tests alone does not
   prove that TypeScript's compile-time checks pass.

When the result seems surprising, trace the chain from the top: JSON parser,
mount point, router path, route-specific middleware, handler, data function,
then response. That follows the order Express actually uses.

## 14. Self-check quiz

Try to answer these without looking at the answer key.

1. What is the difference between the exported `app` and the server started by
   `index.ts`?
2. Which middleware makes a valid JSON body available as `req.body`?
3. Why must that middleware be registered before the routers?
4. What public path is produced when `app.ts` mounts `menuRouter` at `/menu`
   and the router defines `get("/:id", ...)`?
5. Which token and method are required to create an order?
6. What does `parseBearerToken("Bearer nope")` return, and where is the token
   accepted or rejected afterward?
7. What response should a request with no token and body `{}` receive for
   `POST /orders`?
8. What is the difference between an unknown category and an unknown menu ID?
9. Why does `validateOrder` return an array instead of immediately responding?
10. Name three conditions that make `quantity` invalid.
11. Why does the validator check `menuItem === undefined` before checking a
    size or topping?
12. What does `Order extends NewOrder` communicate?
13. Why does the error handler need four parameters if it does not call
    `next()`?
14. How does the application distinguish malformed JSON from an application
    exception?
15. What happens to orders when the Node process restarts?
16. Why do order tests call `_resetOrders()` before each test?
17. Which command runs tests once, and which command checks types without
    emitting JavaScript?
18. What status should a successful order creation return, and why is that more
    specific than `200`?

### Answer key

1. `app.ts` constructs and exports the Express app for reuse; `index.ts`
   imports it and calls `listen` on port `3000`.
2. `express.json()`.
3. It must parse the body before handlers that read `req.body`; its position in
   the chain controls whether the routes see parsed data.
4. `GET /menu/:id`, such as `GET /menu/hawaiian`.
5. `POST /orders` requires the exact customer token
   `slicedrop-customer-secret` in `Authorization: Bearer ...` form.
6. It returns the string `"nope"`; the customer or staff middleware compares
   that candidate with its required constant and rejects it with `401`.
7. `401 Unauthorized`, because auth runs before validation.
8. An unknown category is an empty successful collection (`200`, `[]`); an
   unknown single menu ID is `404` with an error object.
9. A plain function can be tested and reused independently of Express; the
   route handler translates its returned errors into an HTTP response.
10. It is missing, not a number, not an integer, zero, or negative. Fractions
    are also invalid.
11. A failed lookup returns `undefined`, so reading option properties would be
    unsafe and could cause a server exception.
12. A stored `Order` has all `NewOrder` fields plus server-generated `id`,
    `status`, and `createdAt`.
13. Express recognizes error middleware by `(err, req, res, next)`; the fourth
    parameter is part of that recognition rule.
14. The handler checks for `SyntaxError` with a `body` property and returns
    `400`; all other errors are logged and return generic `500`.
15. The in-memory array disappears, so orders are lost and the next ID starts
    at `"1"` in the new process.
16. To clear shared in-memory state and keep tests independent of execution
    order.
17. `npm test` runs the suite once; `npm run typecheck` runs `tsc --noEmit`.
18. `201 Created`, because the request created a new order resource and the
    status communicates that fact to the client.

If the answer to any question was uncertain, trace the matching request through
the middleware chain and then read the corresponding test. That is the same
method used to understand the rest of this API: identify the request, follow
the ordered handlers, and inspect the status and JSON response.
