Skip to content

feat: add linear service emulator#91

Open
mvanhorn wants to merge 1 commit intovercel-labs:mainfrom
mvanhorn:feat/linear-emulator
Open

feat: add linear service emulator#91
mvanhorn wants to merge 1 commit intovercel-labs:mainfrom
mvanhorn:feat/linear-emulator

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

@mvanhorn mvanhorn commented Apr 29, 2026

Summary

Adds a Linear service emulator. Linear is GraphQL-only, so this is the project's first GraphQL emulator. It exposes POST /graphql with introspection, read-only Query resolvers for Issue / Project / Team / User / Organization / Label / WorkflowState, Relay-style pagination, and PAT authentication via Authorization: <api_key>.

The pattern (reference graphql execution library + programmatic schema + store-backed resolvers) is intentionally minimal so future GraphQL services (Shopify Storefront, parts of GitHub's API, Hashnode) can follow it.

Why this matters

Linear is the dominant project tracker for modern dev teams. The official @linear/sdk has ~50K weekly npm downloads, and Linear-aware integrations are increasingly common — GitHub PR linking, Slack notifications, automation rules, AI agents that file issues. CI tests against Linear today either hit production (rate limits, workspace contamination) or hand-stub each query shape. There's no general-purpose emulator. WireMock can stub HTTP but cannot execute arbitrary GraphQL queries.

emulate's Store lets us back the resolvers with stateful entities; the only new dependency is graphql@16.13.2 (the reference JS execution library — Apollo / Yoga deliberately avoided to keep deps minimal).

Demo

A real GraphQL query against the running emulator:

Linear demo

curl http://localhost:4012/graphql \
  -H "Authorization: lin_api_test" \
  -H "Content-Type: application/json" \
  -d '{"query":"{ issues(first: 5) { nodes { id identifier title state { name } team { key } } pageInfo { hasNextPage } } }"}'

Returns:

{
  "data": {
    "issues": {
      "nodes": [
        {
          "id": "issue-1",
          "identifier": "ENG-1",
          "title": "First issue",
          "state": { "name": "Todo" },
          "team": { "key": "ENG" }
        }
      ],
      "pageInfo": { "hasNextPage": false }
    }
  }
}

Linear API Coverage

Surface Detail
POST /graphql Single endpoint with introspection support
Auth PAT via Authorization: <api_key> header
Issue id, identifier (e.g. ENG-1), title, description, priority, state, assignee, team, project, labels
Project id, name, description, lead, team, state
Team id, name, key, organization
User id, name, email, organization
Organization id, name, urlKey
Label id, name, color, team
WorkflowState id, name, type (unstarted, started, completed, etc.), team
Pagination Relay connections: first, after, last, before, edges, nodes, pageInfo
Errors Linear-shape envelope with extensions.code

Default port

4012 (appended at the end of SERVICE_NAME_LIST after clerk — no other service's port shifts).

What's not yet covered

  • Mutations (issueCreate, issueUpdate, projectCreate, etc.) — separate PR
  • Webhooks via WebhookDispatcher — separate PR
  • OAuth 2.0 flow — separate PR
  • Inspector UI — separate PR
  • Initiatives, roadmaps, customer records — separate plan

Seed config

linear:
  api_keys: [lin_api_test]
  organizations:
    - id: org-1
      name: My Org
  teams:
    - id: team-1
      name: Engineering
      key: ENG
      organization: org-1
  workflow_states:
    - id: ws-1
      name: Todo
      type: unstarted
      team: team-1
  users:
    - id: user-1
      name: Developer
      email: dev@example.com
      organization: org-1
  issues:
    - id: issue-1
      title: First issue
      team: team-1
      state: ws-1
      assignee: user-1

Tests

26 Vitest tests covering Query resolvers (organization, user, team, workflowState, label, project, issue), Relay cursor pagination, schema introspection, error envelope shape, and PAT auth validation.

pnpm --filter @emulators/linear test    # 26 passed
pnpm --filter @emulators/linear build   # passes
pnpm --filter emulate build             # registry integration verified
pnpm format:check                       # passes
pnpm lint                               # passes

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 29, 2026

@mvanhorn is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 29, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​graphql@​16.13.1 ⏵ 16.13.29710010094100

View full report

@mvanhorn mvanhorn force-pushed the feat/linear-emulator branch from c9c4e6f to b2d856f Compare April 29, 2026 14:07
@mvanhorn mvanhorn changed the title feat: add Linear emulator (Phase 1) feat: add linear service emulator Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant