rocket

package module
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2025 License: MIT Imports: 24 Imported by: 0

README ยถ

๐Ÿš€ Rocket

Developer-friendly GraphQL for Go - Bringing a modern, DX-focused approach to GraphQL development in Golang.

Philosophy

Rocket aims to bring a more developer-friendly approach to GraphQL in Go:

  • Schema-First: Define your API in .graphql files
  • Modular Resolvers: Each module owns its resolvers
  • Declarative: Map-based resolvers, no switch statements
  • Auto-Resolution: Struct fields auto-resolve, override only when needed
  • Field Order: Preserves query field selection order in responses
  • Type-Safe: Leverage Go's type system with minimal boilerplate

Features

  • โœจ TypeScript-like resolver pattern - Map-based resolvers you can spread/merge
  • ๐ŸŽฏ Auto-field resolution - Define custom resolvers only when you need them
  • ๐Ÿ“ฆ Modular architecture - Each module is self-contained
  • ๐Ÿ”„ Schema compilation - Concat .graphql files with smart ordering
  • โšก Hot reload support - Auto-recompile schemas on change
  • ๐ŸŽจ Field order preservation - Responses match query field order
  • ๐Ÿ—๏ธ Built on WunderGraph - Production-grade graphql-go-tools for federation
  • ๐ŸŽฎ Apollo Sandbox - Modern playground with best-in-class DX
  • ๐Ÿ”„ GraphQL Subscriptions - Real-time updates via WebSocket with graphql-ws protocol
  • ๐ŸŒ Federation-ready - Built on DataSource pattern for federated supergraphs
  • ๐Ÿ”ง Fields with Arguments - Nested fields with arguments work naturally (e.g., user { organization(id: $orgId) })

Getting Started

Prerequisites
  • Go 1.25+ - Make sure you have Go installed (download here)
  • Basic understanding of GraphQL (helpful but not required)
Installation

Add Rocket to your Go project:

go get github.com/jest-cloud/rocket@latest

Or specify a version:

go get github.com/jest-cloud/rocket@v0.5.0
Create a Simple GraphQL API

Follow these steps to create your first Rocket-powered GraphQL API:

Step 1: Create Your Project
mkdir my-graphql-api
cd my-graphql-api
go mod init my-graphql-api
go get github.com/jest-cloud/rocket
Step 2: Define Your Schema

Create a schema.graphql file:

type Query {
  hello: String!
  users: [User!]!
}

type User {
  id: ID!
  name: String!
  email: String!
}
Step 3: Create Your Resolvers

Create resolvers.go:

package main

import (
    "github.com/jest-cloud/rocket"
)

type Resolvers struct{}

// User represents a user in our system
type User struct {
    ID    string `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func (r *Resolvers) QueryResolvers() map[string]rocket.FieldResolveFn {
    return map[string]rocket.FieldResolveFn{
        "hello": func(p rocket.ResolveParams) (interface{}, error) {
            return "Hello, Rocket! ๐Ÿš€", nil
        },
        "users": func(p rocket.ResolveParams) (interface{}, error) {
            // Return structs - Rocket will auto-resolve fields!
            return []*User{
                {ID: "1", Name: "Alice", Email: "alice@example.com"},
                {ID: "2", Name: "Bob", Email: "bob@example.com"},
            }, nil
        },
    }
}

func (r *Resolvers) MutationResolvers() map[string]rocket.FieldResolveFn {
    return map[string]rocket.FieldResolveFn{}
}

func (r *Resolvers) SubscriptionResolvers() map[string]rocket.SubscriptionResolveFn {
    return map[string]rocket.SubscriptionResolveFn{}
}

func (r *Resolvers) TypeResolvers() map[string]map[string]rocket.FieldResolveFn {
    // For list types, you may need explicit type resolvers
    // Auto-resolution works best for single objects, not slices
    return map[string]map[string]rocket.FieldResolveFn{
        "User": {
            "id": func(p rocket.ResolveParams) (interface{}, error) {
                switch v := p.Source.(type) {
                case *User:
                    return v.ID, nil
                case User:
                    return v.ID, nil
                default:
                    return nil, nil
                }
            },
            "name": func(p rocket.ResolveParams) (interface{}, error) {
                switch v := p.Source.(type) {
                case *User:
                    return v.Name, nil
                case User:
                    return v.Name, nil
                default:
                    return nil, nil
                }
            },
            "email": func(p rocket.ResolveParams) (interface{}, error) {
                switch v := p.Source.(type) {
                case *User:
                    return v.Email, nil
                case User:
                    return v.Email, nil
                default:
                    return nil, nil
                }
            },
        },
    }
}

Note: Rocket's auto-field resolution works with structs, not maps. Use structs with json tags to match your GraphQL schema field names.

Important: When returning slices/lists, you may need to add explicit type resolvers for the fields. This is a known limitation being investigated. See the working example below with explicit resolvers.

Step 4: Build and Run

Create main.go:

package main

import (
    "log"
    "net/http"
    "github.com/jest-cloud/rocket"
)

func main() {
    resolvers := &Resolvers{}
    
    // Build GraphQL schema
    schema, err := rocket.BuildSchema(
        rocket.Config{
            SchemaPath: "schema.graphql",
        },
        resolvers,
    )
    if err != nil {
        log.Fatal(err)
    }
    
    // Create HTTP handlers
    http.Handle("/graphql", rocket.Handler(schema))
    http.HandleFunc("/playground", rocket.PlaygroundHandler("/graphql"))
    
    log.Println("๐Ÿš€ Server starting on http://localhost:8080")
    log.Println("๐Ÿš€ GraphQL endpoint: http://localhost:8080/graphql")
    log.Println("๐Ÿš€ Playground: http://localhost:8080/playground")
    
    log.Fatal(http.ListenAndServe(":8080", nil))
}
Step 5: Test Your API

Run your server:

go run main.go

Then:

  1. Visit the Playground: Open http://localhost:8080/playground in your browser
  2. Try a Query:
    query {
      hello
      users {
        id
        name
        email
      }
    }
    

That's it! You now have a working GraphQL API powered by Rocket. ๐ŸŽ‰

Next Steps

Documentation

Core Guides
  • Usage Guide - Getting started with Rocket
  • Resolvers - Complete resolver guide (queries, mutations, subscriptions)
Operation Types
  • Queries - Read operations and data fetching
  • Mutations - Write operations and data modification
  • Subscriptions - Real-time subscriptions with WebSockets
Advanced Topics
  • Federation - GraphQL Federation and microservices
  • Playgrounds - GraphQL playground options and configuration
Reference
Examples
  • Subscriptions - Real-time subscriptions with WebSockets
  • Context - Authentication and context patterns (middleware vs Apollo-style)

Quick Start

1. Define Your Schema
# src/user/schema.graphql
type User {
  id: ID!
  email: String!
  firstName: String!
  lastName: String!
}

extend type Query {
  user(id: ID!): User
  users(limit: Int): [User!]!
}
2. Create Module Resolvers
// src/user/resolvers.go
package user

import "github.com/jest-cloud/rocket"

type Resolvers struct {
    service *Service
}

func (r *Resolvers) QueryResolvers() map[string]rocket.FieldResolveFn {
    return map[string]rocket.FieldResolveFn{
        "user": func(p rocket.ResolveParams) (interface{}, error) {
            id := p.Args["id"].(string)
            return r.service.GetUserByID(p.Context, id)
        },
        "users": func(p rocket.ResolveParams) (interface{}, error) {
            limit := p.Args["limit"].(int)
            return r.service.GetAllUsers(p.Context, limit)
        },
    }
}

func (r *Resolvers) MutationResolvers() map[string]rocket.FieldResolveFn {
    return map[string]rocket.FieldResolveFn{}
}

func (r *Resolvers) SubscriptionResolvers() map[string]rocket.SubscriptionResolveFn {
    return map[string]rocket.SubscriptionResolveFn{}
}

func (r *Resolvers) TypeResolvers() map[string]map[string]rocket.FieldResolveFn {
    return map[string]map[string]rocket.FieldResolveFn{
        "User": {
            // Fields auto-resolve from User struct!
            // Only override when you need custom logic:
            "lastName": func(p rocket.ResolveParams) (interface{}, error) {
                user := p.Source.(*User)
                return strings.ToUpper(user.LastName), nil
            },
        },
    }
}
3. Build Schema
// main.go
import "github.com/jest-cloud/rocket"

func main() {
    // Initialize modules
    userModule := user.Initialize(db)
    orgModule := org.Initialize(db)
    
    // Build schema with all resolvers
    schema, err := rocket.BuildSchema(
        rocket.Config{
            SchemaPath: "schema/schema.graphql",
        },
        userModule.Resolvers,
        orgModule.Resolvers,
    )
    
    // Create HTTP handlers
    http.Handle("/graphql", rocket.Handler(schema))
    
    // Optional: Add playground
    http.HandleFunc("/playground", rocket.PlaygroundHandler("/graphql"))
    
    http.ListenAndServe(":8080", nil)
}

Comparison with TypeScript GraphQL

TypeScript GraphQL
const resolvers = {
  Query: {
    user: (parent, args, context) => {
      return userService.getUser(args.id);
    },
  },
  User: {
    // Fields auto-resolve!
    lastName: (parent) => parent.lastName.toUpperCase(),
  },
};
Rocket (Go)
func (r *Resolvers) QueryResolvers() map[string]rocket.FieldResolveFn {
    return map[string]rocket.FieldResolveFn{
        "user": func(p rocket.ResolveParams) (interface{}, error) {
            return r.service.GetUser(p.Args["id"].(string))
        },
    }
}

func (r *Resolvers) TypeResolvers() map[string]map[string]rocket.FieldResolveFn {
    return map[string]map[string]rocket.FieldResolveFn{
        "User": {
            // Fields auto-resolve!
            "lastName": func(p rocket.ResolveParams) (interface{}, error) {
                user := p.Source.(*User)
                return strings.ToUpper(user.LastName), nil
            },
        },
    }
}

Same pattern, same philosophy! ๐ŸŽฏ

Architecture

Rocket Package
โ”œโ”€โ”€ Schema Compiler      - Concatenates .graphql files
โ”œโ”€โ”€ Schema Builder       - Parses and builds executable schema
โ”œโ”€โ”€ Resolver Registry    - Stitches module resolvers together
โ”œโ”€โ”€ Execution Engine     - Executes queries with field order
โ”œโ”€โ”€ HTTP Handler         - Gin/net/http integration
โ””โ”€โ”€ Default Resolvers    - Auto-resolution for struct fields

Why Rocket?

  • ๐Ÿš€ Fast to develop - Write less code, get more done
  • ๐ŸŽฏ Developer-friendly - Intuitive patterns that reduce boilerplate
  • ๐Ÿ’ช Production-ready - Built on Wundergraph's battle-tested tools
  • ๐Ÿ”ง Flexible - Override anything when you need to
  • ๐Ÿ“ฆ Modular - Clean separation of concerns

What's Supported

โœ… All 3 GraphQL Operation Types
Operation Status Transport
Query โœ… Complete HTTP POST
Mutation โœ… Complete HTTP POST
Subscription โœ… Complete WebSocket (graphql-ws)
โœ… Introspection

Rocket fully supports GraphQL introspection queries:

  • __schema - Get the schema structure
  • __type - Get information about a specific type
  • __typename - Get the type name of an object

The GraphQL Playground automatically uses introspection for autocomplete and documentation.

TODO

Testing & Quality
  • Add comprehensive unit tests for core functionality
  • Add integration tests for schema building and execution
  • Add benchmark tests for performance monitoring
  • Add test coverage reporting
  • Set up test examples/demos in separate examples directory
  • Add fuzzing for schema parsing and execution
Error Handling & Validation
  • Improve error messages with better context
  • Add validation for resolver function signatures
  • Add schema validation warnings
  • Better error handling for malformed queries
  • Add panic recovery middleware for resolvers
Features & Functionality
  • Subscriptions support (WebSocket) - โœ… Added in v0.3.0
  • DataLoader implementation for N+1 query prevention
  • Custom scalar types (Date, DateTime, JSON, etc.)
  • Field-level middleware/directives
  • GraphQL Federation support
  • Query complexity analysis
  • Query depth limiting
  • Rate limiting support
  • Caching layer for queries
  • Batch request support
Developer Experience
  • GoDoc comments for all public APIs
  • Code generation tool for resolver boilerplate
  • Schema validation CLI tool
  • Better type safety for ResolveParams Args
  • Middleware support for resolvers
  • Context propagation utilities
  • Logging integration hooks
  • Metrics/observability hooks
Performance
  • Optimize field order preservation
  • Add query result caching
  • Parallel resolver execution where safe
  • Reduce allocations in hot paths
  • Profile and optimize schema building
Documentation
  • Add Go examples to godoc
  • Create interactive tutorials
  • Add migration guide from other GraphQL libraries
  • Add troubleshooting guide
  • API reference documentation
  • Best practices guide
Infrastructure
  • Add Go 1.26+ support
  • Test compatibility across Go versions
  • Add GitHub Actions for automated releases
  • Set up automated dependency updates (Dependabot)
  • Add security scanning (CodeQL)

Coming Soon

These are planned for future releases:

  • Subscriptions support - โœ… Added in v0.3.0
  • DataLoader for N+1 prevention
  • Custom scalar types
  • Field-level middleware/directives
  • GraphQL Federation
  • Query complexity analysis

Contributing

We welcome contributions from anyone who would like to get involved! Rocket is an open-source project and we'd love your help making it better.

How to Contribute
  • Report bugs - Open an issue if you find a bug
  • Suggest features - Share your ideas for improvements
  • Submit pull requests - Pick any item from the TODO list above, or fix bugs
  • Improve documentation - Help make our docs clearer and more comprehensive
  • Write tests - Increase test coverage and improve reliability
Getting Started
  1. Fork the repository
  2. Create a branch for your contribution (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests if applicable
  5. Ensure all tests pass (go test ./...)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to your branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Check out the TODO section above for ideas on what to work on, or feel free to contribute in any way you'd like!

License

MIT


Rocket: A developer-friendly approach to GraphQL in Go ๐Ÿš€

Documentation ยถ

Overview ยถ

Package rocket provides developer-friendly GraphQL patterns for Go Bringing a modern, DX-focused approach to GraphQL development in Golang

Index ยถ

Constants ยถ

View Source
const (
	DefaultPreserveOrder = true
)

Config defaults

Variables ยถ

View Source
var NewResolverRegistry = registry.NewResolverRegistry

NewResolverRegistry creates a new registry by merging module resolvers Re-exported from internal/registry for public API

View Source
var NewSchemaCompiler = compiler.NewSchemaCompiler

NewSchemaCompiler creates a new schema compiler Re-exported from internal/compiler for public API

Functions ยถ

func Handler ยถ

func Handler(schema *Schema) httphandler.HandlerFunc

Handler creates an HTTP handler for GraphQL requests Works with both net/http and Gin (via gin.WrapH)

func PlaygroundHandler ยถ

func PlaygroundHandler(endpoint string) httphandler.HandlerFunc

PlaygroundHandler creates an HTTP handler that serves a GraphQL playground Uses Apollo Sandbox by default (most modern and stable)

func PlaygroundHandlerWithType ยถ

func PlaygroundHandlerWithType(endpoint string, playgroundType PlaygroundType) httphandler.HandlerFunc

PlaygroundHandlerWithType creates a playground handler with a specific type

func WebSocketHandler ยถ added in v0.3.0

func WebSocketHandler(schema *Schema) httphandler.HandlerFunc

WebSocketHandler creates a WebSocket handler for GraphQL subscriptions This implements the graphql-ws protocol for real-time subscriptions

Types ยถ

type Config ยถ

type Config struct {
	SchemaPath       string                                       // Path to the compiled schema.graphql file
	EnablePlayground bool                                         // Enable GraphQL playground (default: false)
	ContextBuilder   func(r *httphandler.Request) context.Context // Optional: Build custom context per-request (Apollo-style pattern)
	Federation       FederationConfig                             // Federation configuration
}

Config holds configuration for building a GraphQL schema

type EntityResolveFn ยถ added in v0.6.0

type EntityResolveFn = types.EntityResolveFn

EntityResolveFn is a function that resolves an entity from its representation Used for GraphQL Federation __resolveReference Re-exported from internal/types for public API

type Error ยถ

type Error = types.Error

Error represents a GraphQL error Re-exported from internal/types for public API

type FederationConfig ยถ added in v0.6.0

type FederationConfig struct {
	Enabled     bool   // Enable GraphQL Federation support
	ServiceName string // Optional: Name of this subgraph (for debugging/tracing)
}

FederationConfig holds federation-specific configuration

type FieldResolveFn ยถ

type FieldResolveFn = types.FieldResolveFn

FieldResolveFn is a function that resolves a field value Re-exported from internal/types for public API

type ModuleResolvers ยถ

type ModuleResolvers = types.ModuleResolvers

ModuleResolvers is the interface that all module resolvers must implement Re-exported from internal/types for public API

type PlaygroundType ยถ

type PlaygroundType string

PlaygroundType determines which playground interface to use

type ResolveInfo ยถ

type ResolveInfo = types.ResolveInfo

ResolveInfo contains metadata about the field being resolved Re-exported from internal/types for public API

type ResolveParams ยถ

type ResolveParams = types.ResolveParams

ResolveParams contains all the information for resolving a field Re-exported from internal/types for public API

type ResolverRegistry ยถ

type ResolverRegistry = registry.ResolverRegistry

ResolverRegistry holds all resolvers stitched together Re-exported from internal/registry for public API

type Result ยถ

type Result = types.Result

Result represents the result of a GraphQL operation Re-exported from internal/types for public API

type Schema ยถ

type Schema struct {
	// contains filtered or unexported fields
}

Schema represents a compiled and executable GraphQL schema

func BuildSchema ยถ

func BuildSchema(config Config, modules ...ModuleResolvers) (*Schema, error)

BuildSchema builds an executable GraphQL schema from .graphql file and module resolvers This is the main entry point for Rocket

func (*Schema) Execute ยถ

func (s *Schema) Execute(ctx context.Context, query string, variables map[string]interface{}, operationName string) *Result

Execute executes a GraphQL query/mutation Field order is always preserved for better developer experience

func (*Schema) ExecuteSubscription ยถ added in v0.3.0

func (s *Schema) ExecuteSubscription(ctx context.Context, query string, variables map[string]interface{}, operationName string) (<-chan interface{}, error)

ExecuteSubscription executes a GraphQL subscription and returns a channel of results This method is called by the WebSocket handler

func (*Schema) GetContextBuilder ยถ added in v0.4.0

func (s *Schema) GetContextBuilder() func(r *httphandler.Request) context.Context

GetContextBuilder returns the context builder function if configured This is used by the HTTP handler to build per-request context (Apollo-style pattern)

type SchemaCompiler ยถ

type SchemaCompiler = compiler.SchemaCompiler

SchemaCompiler compiles multiple .graphql files into a single schema Re-exported from internal/compiler for public API

type SubscriptionResolveFn ยถ added in v0.3.0

type SubscriptionResolveFn = types.SubscriptionResolveFn

SubscriptionResolveFn is a function that resolves a subscription field It returns a channel that emits values over time Re-exported from internal/types for public API

Directories ยถ

Path Synopsis
examples
context command
subscriptions command
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL