Skip to content

refactor: replace REST/OpenAPI management API with GraphQL (gqlgen) - #42

Merged
dimiro1 merged 2 commits into
mainfrom
dimiro1/explore-graphql-migration
Jun 3, 2026
Merged

refactor: replace REST/OpenAPI management API with GraphQL (gqlgen)#42
dimiro1 merged 2 commits into
mainfrom
dimiro1/explore-graphql-migration

Conversation

@dimiro1

@dimiro1 dimiro1 commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

Rewrites the management API (functions, versions, executions, tokens) from a hand-maintained REST/OpenAPI surface to GraphQL via gqlgen. The schema in internal/graph/schema is the single source of truth: resolvers are generated interfaces bound directly to internal/store (no DTOs), so the compiler enforces the contract and it can't drift.

/fn/* execution and /api/auth/* (login + device flow) intentionally stay REST.

Server

  • gqlgen at POST /graphql (auth-protected) + GraphiQL at GET /graphql, wired as its own fx module.
  • Lazy field resolvers for envVars/scopedData/globalData (the overfetch fix), a Map scalar, and a CronStatus enum.
  • Relation edges make the graph traversable both ways: Function.versions/executions/nextRun, Execution.function/version/logs/aiRequests/emailRequests, and reverse edges (FunctionVersion.function, AIRequest/EmailRequest.execution).
  • Removed all REST /api/* management routes/handlers, the hand-written openapi.yaml, and Swagger /docs; shared validation moved to internal/validation.

CLI

  • lunar-cli now talks GraphQL via hasura/go-graphql-client with hand-written commands, replacing oapi-codegen and the custom Cobra generator.

Frontend

  • api.js is a thin GraphQL anti-corruption layer; detail views use combined queries to cut round-trips (execution-detail: 5 → 1).

Docs & tooling

  • ADR-0012, docs/rest-endpoints.md, README updates, a mise seed task, and generate-graphql replacing generate-cli.

Verification

Full server + CLI build/vet/test, e2e (real browser), golangci-lint (0 issues), deno fmt, and idempotent codegen all green.

🤖 Generated with Claude Code

dimiro1 added 2 commits June 3, 2026 12:48
Rewrite the management API (functions, versions, executions, tokens) from a
hand-maintained REST/OpenAPI surface to GraphQL via gqlgen. The schema in
internal/graph/schema is the single source of truth: resolvers are generated
interfaces, so the compiler enforces the contract and it can't drift.

Server:
- gqlgen at POST /graphql (auth-protected) + GraphiQL at GET /graphql, wired as
  its own fx module; GraphQL types bound directly to internal/store (no DTOs).
- Lazy field resolvers for envVars/scopedData/globalData (the overfetch fix), a
  Map scalar, a CronStatus enum, and relation edges making the graph traversable
  both ways (Function.versions/executions/nextRun, Execution.function/version/
  logs/aiRequests/emailRequests, and reverse edges).
- Removed all REST /api/* management routes and handlers, the hand-written
  openapi.yaml, and Swagger /docs; shared validation moved to internal/validation.
  /fn/* execution and /api/auth/* (login + device flow) stay REST by design.

CLI:
- lunar-cli now talks GraphQL via hasura/go-graphql-client with hand-written
  commands, replacing oapi-codegen and the custom Cobra generator.

Frontend:
- api.js is a thin GraphQL anti-corruption layer; detail views use combined
  queries to cut round-trips (execution-detail goes from 5 to 1).

Docs/tooling:
- ADR-0012, docs/rest-endpoints.md, README updates, a mise seed task, and
  generate-graphql replacing generate-cli.
Two breakages surfaced once the integration module actually compiled:

- go.sum was missing 99designs/gqlgen (the server now imports it) and still
  referenced the removed oapi-codegen/runtime. `go mod tidy` on the nested
  lunar-cli/integration module adds the former and drops the latter, fixing the
  "missing go.sum entry" setup failure.
- The in-memory test DB used a plain ":memory:" DSN, which is private per pooled
  connection. The GraphQL server resolves sibling fields (envVars/scopedData/
  globalData) concurrently, so the pool handed out fresh, unmigrated connections
  ("no such table"). Pin the pool to a single connection so every query uses the
  one migrated database.
@dimiro1
dimiro1 merged commit 5d17265 into main Jun 3, 2026
2 checks passed
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