Naalya Handbook
Using Chowbea

Keeping the Hub client in sync

How extract, the bus endpoint, and api:watch fit together so a backend change shows up in the Education Hub.

You added an endpoint, or you exported a bus type. The Hub still has yesterday's types. This page is the loop that closes that gap — both pipes, in the order a developer actually runs them.

Local day-to-day

API repo (Naalya-API):

package.json scripts
pnpm bus:extract    # chowbea-axios extract          → chowbea.bus.json
pnpm bus:watch      # extract --watch                → re-extract on save
pnpm bus:check      # extract --check                → CI gate, no write
pnpm prebuild       # extract runs automatically before nest build

extract walks *.chowbea.ts (and @chowbea-export tags), validates the closed world, and writes chowbea.bus.json at the repo root. That file is a build artifact. Do not hand-edit it. The repo currently commits it as the served manifest; treat extract as the source of truth anyway.

The server mounts the bus in file mode:

apps/server/src/config/swagger.config.ts
app.use(DEFAULT_API_ROUTE, busHandler());

DEFAULT_API_ROUTE is /.well-known/chowbea.json. busHandler() with no argument stats the file per request and re-reads when it changes — so bus:watch plus a running server is live types without a restart. If the manifest is missing, the handler 503s with a hint to run extract. A mid-write file serves last-good.

Swagger stays at /docs/swagger/json. Two URLs, two pipes.

Education Hub:

package.json scripts
bun api:watch     # poll spec + bus, regenerate _generated
bun api:generate  # one-shot from the cached/local spec
bun dev:all       # api:watch alongside Vite

api.config.toml points api_endpoint at Swagger and [bus].endpoint at the well-known URL. watch fetches both. If the API is down, REST generate fails with a fetch error; if the bus endpoint 503s, bus output goes stale while REST may still update — run bus:extract on the API.

You almost never run generate by hand. dev:all is the default.


What you may edit

Education Hub src/services/api/
_internal/          caches — never edit, never hand-resolve merge conflicts
_generated/         ALWAYS overwritten
  api.types.ts
  api.operations.ts
  api.contracts.ts
  bus/              one file per API barrel + index.ts
api.client.ts       generated once, then yours
api.instance.ts     generated once — Bearer + refresh live here
api.error.ts
api.helpers.ts

Rule: _generated/ and _internal/ are projections. Change the OpenAPI spec or the .chowbea.ts barrel. If git reports a conflict under _generated/, run chowbea-axios resolve — do not merge the file like application code.


Checklist after an API change

New/changed REST endpoint

  1. DTO + controller as usual (Add an Endpoint).
  2. API running so /docs/swagger/json is current.
  3. Hub api:watch (or api:generate) — api.op.yourOperation appears.
  4. Wrap it in a query module; do not call api.op from a component.

New/changed bus type

  1. Export from a *.chowbea.ts barrel — Exporting a type on the bus.
  2. pnpm bus:extract in the API repo (or rely on bus:watch).
  3. Confirm curl -s localhost:8000/.well-known/chowbea.json | head has your symbol.
  4. Hub api:watch_generated/bus updates.
  5. Import from @/services/api/_generated/bus.

CI

API:

pnpm bus:check
# optional breaking-change tripwire against staging:
pnpm bus:diff   # extract --check --diff <staging bus URL> --fail-on-removed

Hub: the generated-client workflow re-fetches the spec on PRs and fails when _generated is stale. After a bus change, the PR must include the regenerated bus/ files (or the Hub CI equivalent). A Hub PR that uses a new bus symbol without regenerating will not type-check.


Gotchas

readBusManifest() is cwd-relative. Extract from the API repo root. Running the server with a different cwd 503s the bus route.

Global vs project CLI. The API pins chowbea-axios in package.json (^2.7.0 for file-mode busHandler()). A global install delegates to the project's copy when one exists. chowbea-axios status shows which binary is running. The Hub historically used a global CLI for REST — follow that repo's README; the [bus] block still needs a CLI new enough to fetch the manifest.

Unknown chowbeaBus version. If extract writes a newer manifest schema than the Hub CLI understands, fetch fails loud. Upgrade the Hub's CLI; do not hand-edit the version field.

Enums are runtime values on both pipes. Prefer the bus enum (Action from _generated/bus) when you need Action.READ as a value. Do not hand-write a mirror in lib/.

Where to go next

On this page