# Build a plain REST package simulator

> **Use case id:** `library-demo-rest`
> **Goal:** Follow the library-demo path: data modules, relative/simulation endpoints, no Memorix.
> **Audiences:** developers
> **Tags:** examples, rest, tutorial

## Reading path

1. **Package Simulators** (developers) → chapters: `1-what-a-package-simulator-is`, `3-plain-rest-library-demo`
1. **Behaviors and Dispatch** (developers) → chapters: `2-relative`, `3-simulation-function`

## From: Package Simulators — 1. What a package simulator is

A **package simulator** is a small product-owned package that uses `@x12i/api-simulator` as the engine and ships its own:

- **logic** — `simulation` handlers (and optional `createStore` state)
- **data** — seeds under `api.data` and/or fixture JSON
- **metadata** — when the product speaks Memorix, declarative packs and explorer fixtures

The core library stays **zero runtime dependencies** and does not load data or metadata from disk, MongoDB, or HTTP. Your package (or an example like `examples/flowstate-simulator`) owns that.

---

## From: Package Simulators — 3. Plain REST library-demo

If the API is ordinary REST (no Memorix), follow [`examples/library-demo/TUTORIAL.md`](../../../examples/library-demo/TUTORIAL.md):

1. Data modules seed `api.data` / `createStore`.
2. Relative endpoints for list/read shapes; simulation handlers for writes and branching.
3. `createApiSimulator` + optional Node HTTP entry — **no** `@x12i/static-memorix`.

Runnable reference: [`examples/library-demo/`](../../../examples/library-demo).

---

## From: Behaviors and Dispatch — 2. Relative

Relative behavior starts with configured JSON, then resolves tokens against the matched request and the API's internal `data` object.

Supported token roots:

- `{{request.params.parentId}}`
- `{{request.query.page}}`
- `{{request.headers.x-tenant-id}}`
- `{{request.body.customer.id}}`
- `{{data.children}}`
- Array indexes, such as `{{data.users[0].id}}`

```ts
{
  id: 'children',
  method: 'GET',
  path: '/parents/:parentId/children',
  behavior: {
    type: 'relative',
    response: {
      body: {
        parentId: '{{request.params.parentId}}',
        items: '{{data.children}}'
      }
    }
  }
}
```

A token occupying the entire string preserves its original type. Therefore, `{{request.body.limit}}` can produce a number and `{{data.children}}` can produce an array. A token embedded inside text is converted to a string:

```ts
{ message: 'Children for parent {{request.params.parentId}}' }
```

Tokens inside API-local data are rendered too. This lets a reusable internal fixture inherit an identifier from the incoming request:

```ts
data: {
  children: [
    { id: 'child-1', parentId: '{{request.params.parentId}}' }
  ]
}
```

Relative behavior is strict by default. A missing token throws `TemplateResolutionError`. Set `strict: false` to leave unresolved tokens unchanged.

---

## From: Behaviors and Dispatch — 3. Simulation function

Use a simulation function when output needs conditions, calculations, validation, generated values, branching, or error responses.

```ts
{
  id: 'quote',
  method: 'POST',
  path: '/quote',
  behavior: {
    type: 'simulation',
    handler: async ({ request, data, apiId, endpointId }) => {
      const quantity = Number((request.body as { quantity: number }).quantity);
      const unitPrice = Number(data.unitPrice);

      return {
        status: 201,
        body: {
          apiId,
          endpointId,
          quantity,
          unitPrice,
          total: quantity * unitPrice
        }
      };
    }
  }
}
```

---

## Also see

- **Package Simulators** (`03-package-simulators`) — Ship logic, data, and optional Memorix fixtures in a product package — with or without static-memorix.
- **Behaviors and Dispatch** (`01-behaviors`) — The three endpoint behaviors, dispatch APIs, contracts, latency, raw bodies, and path patterns.

---

_Generated use-case pack for agents and humans. See `agent-manifest.json` for discovery._
