Skip to content

feat: add Linear GraphQL API emulator#5

Merged
amondnet merged 2 commits into
mainfrom
amondnet/linear
Jun 8, 2026
Merged

feat: add Linear GraphQL API emulator#5
amondnet merged 2 commits into
mainfrom
amondnet/linear

Conversation

@amondnet

@amondnet amondnet commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Ports vercel-labs/emulate#91 (Phase 1 Linear emulator, by @mvanhorn) into this fork's conventions.

The upstream PR targets a different structure (pnpm, @emulators/* scope, a apps/web docs site, @emulators/core as a workspace dep), so it could not be merged directly. The service core was re-homed to match this fork instead.

What's included

  • New @pleaseai/emulate-linear package under packages/linear/
    • bun export condition, @emulators/core@^0.6.0 + graphql deps, tsgo type-check
  • Registered linear in the CLI service registry (packages/emulate) + dependency wiring
  • Source adapted to fork's core 0.6.0
    • Hono type sourced from @emulators/core (no direct hono dep)
    • explicit 405 handlers for non-POST /graphql (core's router has no all)
    • tests converted from vitestbun:test using createServer
    • lint style aligned (single quotes, multiline if, node:buffer import)
  • Docs: skills/linear/SKILL.md, package README, and root README entries adapted to fork CLI usage (bun packages/emulate/dist/index.js --service linear)

Excluded from the upstream PR

apps/web/* docs site, pnpm-lock.yaml, and emulate.config.example.yaml — these don't exist in this fork.

Surface (read-only GraphQL)

POST /graphql with schema introspection, PAT auth (Authorization: <api_key>), Relay-style pagination, and query resolvers for Issue, Project, Team, User, Organization, Label, and WorkflowState.

Verification

  • ✅ Monorepo build (7) · type-check (13) · test (13, linear 26 pass) · lint
  • ✅ End-to-end: emulate list shows linear; service boots and answers GraphQL queries; missing auth returns 401

Follow-up work: mutations, webhooks, OAuth 2.0, inspector UI.

Port vercel-labs/emulate#91 (Phase 1 Linear emulator) to the @pleaseai
fork conventions:

- New @pleaseai/emulate-linear package under packages/linear/ (bun export
  condition, @emulators/core ^0.6.0 + graphql dependency, tsgo type-check)
- Register linear in the CLI service registry (packages/emulate)
- bun:test instead of vitest; explicit 405 handlers for non-POST /graphql
  since core's router has no `all`; Hono type sourced from @emulators/core
- skills/linear/SKILL.md and README entries adapted to fork CLI usage

Read-only GraphQL: issues, projects, teams, users, organizations, labels,
and workflow states with Relay-style pagination. 26 tests pass.

Original PR: vercel-labs/emulate#91 by @mvanhorn
@codacy-production

codacy-production Bot commented Jun 8, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 4 high

Alerts:
⚠ 4 issues (≤ 0 issues of at least minor severity)

Results:
4 new issues

Category Results
BestPractice 3 high
Security 1 high

View in Codacy

🟢 Metrics 374 complexity · 12 duplication

Metric Results
Complexity 374
Duplication 12

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.84406% with 64 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
packages/linear/src/resolvers.ts 80.17% 45 Missing ⚠️
packages/linear/src/helpers.ts 89.23% 7 Missing ⚠️
packages/linear/src/index.ts 97.69% 7 Missing ⚠️
packages/emulate/src/registry.ts 83.33% 4 Missing ⚠️
packages/linear/src/routes/graphql.ts 98.46% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@codacy-production codacy-production Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

The port of the Linear GraphQL API emulator is largely complete in terms of feature set, but several implementation details pose risks to its reliability. Most critically, the store collections are missing indices for foreign keys (e.g., organization_id, assignee_id); without these, the @emulators/core framework will fail to resolve relationships between entities, effectively breaking graph traversal.

Codacy analysis indicates the PR is not up to standards, primarily due to code duplication in entity resolvers and unsafe property access. Furthermore, 'packages/linear/src/resolvers.ts' and 'packages/linear/src/index.ts' are identified as complex files with insufficient test coverage. While 405 Method Not Allowed handlers were implemented as requested in the acceptance criteria, they currently lack automated verification. These issues, particularly the indexing logic, should be addressed prior to merging to ensure the emulator functions as intended.

About this PR

  • There is a systemic pattern of code duplication across entity resolvers (Organization, User, Team, etc.) regarding standard field mapping. Centralizing this logic into a helper function would improve maintainability.

Test suggestions

  • Execute a valid GraphQL query for an issue by ID and identifier
  • Perform GraphQL schema introspection
  • Verify authentication using a raw PAT in the Authorization header
  • Verify authentication using a Bearer token in the Authorization header
  • Verify that missing or invalid authentication returns a 401 with a Linear-compatible error code
  • Test forward pagination using 'first' and 'after'
  • Test backward pagination using 'last' and 'before'
  • Verify that GET, PUT, PATCH, and DELETE requests to /graphql return a 405 Method Not Allowed error
  • Validate that GraphQL validation errors return a 200 OK with an errors array containing extensions.code
  • Automate verification of relational traversals (e.g., fetching a team's issues) to ensure store indices are working
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Verify that GET, PUT, PATCH, and DELETE requests to /graphql return a 405 Method Not Allowed error
2. Automate verification of relational traversals (e.g., fetching a team's issues) to ensure store indices are working

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment thread packages/linear/src/store.ts
Comment thread packages/linear/src/resolvers.ts Outdated
Comment thread packages/linear/src/routes/graphql.ts
- store: index organization_id (users/teams), lead_id (projects),
  state_id/assignee_id/creator_id (issues) — all fields queried via findBy,
  per the fork's store convention (avoids full-scan fallback)
- resolvers: use Object.hasOwn for directValue field access (own-property only)
- tests: cover 405 responses for non-POST methods on /graphql
@sonarqubecloud

sonarqubecloud Bot commented Jun 8, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot

See analysis details on SonarQube Cloud

@amondnet amondnet merged commit 29840b5 into main Jun 8, 2026
3 of 5 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 8, 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