Skip to content

Latest commit

 

History

History
88 lines (66 loc) · 5.84 KB

File metadata and controls

88 lines (66 loc) · 5.84 KB

Architecture

packages/
  emulate/          # CLI entry point (commander)
  @emulators/
    core/           # HTTP server, in-memory store, plugin interface, manifest, control plane
    adapter-next/   # Next.js App Router integration
    cloudflare/     # Cloudflare worker host: apex catalog, service + instance hosts, Durable Object
    vercel/         # Vercel API service
    github/         # GitHub API service
    google/         # Google OAuth 2.0 / OIDC + Gmail, Calendar, Drive
    slack/          # Slack Web API, OAuth v2, incoming webhooks
    apple/          # Apple Sign In / OIDC
    microsoft/      # Microsoft Entra ID OAuth 2.0 / OIDC + Graph users, mail, calendar, and files
    aws/            # AWS S3, SQS, IAM, STS
    okta/           # Okta identity provider / OIDC
    mongoatlas/     # MongoDB Atlas Admin API + Data API
    resend/         # Resend email API
    stripe/         # Stripe billing and payments API
    clerk/          # Clerk authentication and user management API
    spotify/        # Spotify OAuth and Web API
apps/
  web/              # Documentation site (Next.js), deployed at docs.emulators.dev
  console/          # Manifest-driven inspector and catalog console

GitHub also exposes a deliberate MCP surface alongside its REST, GraphQL, OAuth, GitHub App, and webhook surfaces. A surface is only advertised when it matches the real provider, so emulate does not add MCP or GraphQL to a service just because the platform supports them.

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.

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).

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.

Service Manifest and Control Plane

The core server registers /_emulate routes for every service. These routes are public by design so a human, test harness, or agent can land on an unknown emulator URL and discover how to use it.

  • /_emulate/manifest returns service identity, supported surfaces, auth capabilities, spec coverage, and instance URLs. The Service Manifest is the single source of truth.
  • /_emulate/quickstart returns compact text instructions.
  • /_emulate/specs, /_emulate/openapi, /_emulate/graphql, and /_emulate/mcp expose advertised spec and protocol entry points.
  • /_emulate/coverage reports per-operation spec coverage with a summary by status.
  • /_emulate/connections returns copyable SDK, CLI, env, and curl snippets resolved against the instance.
  • /_emulate/credentials creates service-shaped credentials such as bearer tokens, API keys, OAuth clients, or client-credentials apps.
  • /_emulate/seed adds runtime seed data using the service seed schema.
  • /_emulate/instances returns URLs for hosted instances, which deployments create lazily when first used.
  • /_emulate/ledger returns recent request and response records with auth headers, tokens, client secrets, API keys, and similar fields redacted. See the Request Ledger.
  • /_emulate/faults arms, lists, and clears one-shot or counted fault responses for matching provider requests.
  • /_emulate/logs returns webhook deliveries plus the most recent provider requests.
  • /_emulate/state returns the current store snapshot.
  • /_emulate/reset resets state, webhooks, faults, and the request ledger, then replays seed data.
  • /_emulate/services returns a machine-readable catalog of every hosted service and is available from any host, including the apex.

Service manifests are hand-authored metadata derived from the real service. OpenAPI, GraphQL, MCP, OAuth metadata, and provider discovery documents are useful inputs, but emulate only exposes the protocols and auth modes that fit each service.

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, Vercel-style cursor-based pagination

Cloudflare Host

The @emulators/cloudflare package runs the same plugins on Cloudflare Workers with host-based routing. The emulate-hosts worker serves emulators.dev/* and *.emulators.dev/*:

  • The apex emulators.dev is the emulator catalog, a links-out landing built from GET /_emulate/services. It is not the docs site.
  • A service host such as github.emulators.dev serves a service-level control plane and is useful before any instance exists.
  • An instance host such as github.my-run.emulators.dev (or the compatibility path form emulators.dev/github/my-run) serves one stateful instance.

Each instance is backed by one Cloudflare Durable Object. The EmulatorDurableObject class is declared through a wrangler migrations entry (new_classes), and both the instance state and the request ledger are snapshotted to Durable Object storage so an instance survives eviction. Instances are created lazily through POST /_emulate/instances.

Docs are a separate site on the emulate-docs worker at docs.emulators.dev, with per-service docs at https://docs.emulators.dev/<service>. Because that host is more specific than the apex, it wins for the docs subdomain. See Deployment.