Skip to main content

Core

The core package provides a generic Store with typed Collection<T> instances supporting CRUD, indexing, filtering, and pagination. Each service plugin registers its routes with the shared internal app and uses the store for state. The internal HTTP layer builds on Hono’s API and design. Thank you to Yusuke Wada and the Hono contributors. Hono’s copyright and MIT license notice are included in THIRD_PARTY_NOTICES.md and distributed with the npm packages.

Plugin system

Each service is a plugin that:
  1. Defines its entity types and store collections
  2. Registers HTTP routes with the shared internal app
  3. Provides a seed function to populate initial state from config
  4. Uses shared middleware for auth, error handling, and pagination
Multiple services can run simultaneously, each on its own port (auto-incremented from the base port).

One process per provider

The CLI and createEmulator run each built-in service in its own Node process. The CLI is the host: it reads the config, keeps the saved state and the control API, and starts a provider process per service. Each provider listens on its own port and answers its traffic directly, WebSockets included; the host never sits in the request path. The two talk over Node’s IPC channel with a small versioned protocol: the host starts a provider with its seed and tokens, asks it for its state when it is saved, restores it, resets it, and sets its faults. A provider forwards /_baseline/* requests to the host, so every service port still answers the control API for the whole run. When a provider crashes, the host restarts it on the same port from the last state it holds, up to three times a minute. Custom emulators stay in the host process.

In-memory state

All state is held in memory with no database. This makes the emulator fast, easy to reset, and ideal for CI pipelines. State is populated from the seed config on startup and can be modified via API calls during a test run. When state is saved (--state, or createEmulator({ state })), it is written as one JSON document, format: 2, with an entry per service. Each entry holds a snapshot of the service’s store, its token map, and its webhook subscriptions, plus the provider’s stateVersion and the provider package and version that wrote it. Files written as format: 1 still load. Loading checks stateVersion first, so data saved for an older entity shape is refused with a message naming the service rather than loaded half broken. Snapshots written before the format existed load and are upgraded in memory.

Middleware

The core provides shared middleware:
  • Auth: validates Bearer/token authorization headers against configured tokens
  • Error handling: consistent error responses matching each service’s format
  • Pagination: GitHub-style page/per_page with Link headers, cursor-based pagination (Slack, Notion, Stripe)

Custom emulators

Custom definitions created with defineEmulator from @deploybaseline/cli work in the CLI and in in-process tests. The same definition provides typed state, HTTP handlers, reset, versioned snapshots, and optional inspection/persistence. See Custom emulators for the quickstart, API reference, and complete lifecycle semantics.