README
ยถ
Mithril GraphQL Example
This example demonstrates Phase 15: GraphQL Support, showcasing how to integrate GraphQL into a Mithril application.
Features Demonstrated
๐ GraphQL Integration
- Schema Generation: Automatic GraphQL schema generation from Go models
- Resolver System: Flexible resolver architecture for custom business logic
- Type Safety: Strong typing with Go structs and GraphQL types
- Playground: Interactive GraphQL playground for testing queries
๐ GraphQL Features
- Queries: Single item and list queries with filtering
- Mutations: Create, update, and delete operations
- Introspection: Full schema introspection support
- Complexity Limiting: Query complexity analysis and limiting
- CORS Support: Cross-origin resource sharing for web clients
๐ ๏ธ Developer Experience
- Auto-generation: Schema and resolvers generated from models
- CLI Commands: Easy GraphQL setup and management
- Hot Reload: Development-friendly with live schema updates
- Documentation: Automatic API documentation generation
API Endpoints
GraphQL
POST /graphql- GraphQL endpointGET /graphql- GraphQL endpoint (for queries)GET /graphql/playground- Interactive GraphQL playgroundGET /graphql/info- GraphQL configuration info
REST API
GET /- Welcome message with GraphQL infoGET /docs- Swagger API documentation
GraphQL Schema
The example includes two models with full CRUD operations:
User Model
type User {
id: UUID!
name: String!
email: String!
created_at: Time!
updated_at: Time!
}
input UserInput {
name: String!
email: String!
}
Product Model
type Product {
id: UUID!
name: String!
description: String
price: Float!
in_stock: Boolean!
created_at: Time!
updated_at: Time!
}
input ProductInput {
name: String!
description: String
price: Float!
in_stock: Boolean!
}
Usage Examples
Queries
Get All Users
query {
users {
id
name
email
created_at
}
}
Get User by ID
query {
user(id: "user-id-here") {
id
name
email
created_at
}
}
Get All Products
query {
products {
id
name
description
price
in_stock
}
}
Mutations
Create User
mutation {
createUser(input: {
name: "John Doe"
email: "john@example.com"
}) {
id
name
email
created_at
}
}
Update Product
mutation {
updateProduct(id: "product-id-here", input: {
name: "Updated Product"
price: 199.99
in_stock: true
}) {
id
name
price
in_stock
}
}
Delete User
mutation {
deleteUser(id: "user-id-here")
}
Running the Example
Prerequisites
- Go 1.21 or later
- Mithril framework installed
Installation
# Clone the repository
git clone https://github.com/mithril-framework/mithril.git
cd mithril
# Install dependencies
go mod tidy
# Run the example
cd example-graphql
go run main.go
Access Points
- Application: http://localhost:3000
- GraphQL Playground: http://localhost:3000/graphql/playground
- Swagger Docs: http://localhost:3000/docs
GraphQL Playground
The GraphQL playground provides an interactive interface for:
- Query Testing: Write and test GraphQL queries
- Schema Exploration: Browse the complete GraphQL schema
- Documentation: View field descriptions and types
- Variable Testing: Test queries with variables
CLI Commands
Add GraphQL to Existing Project
# Add GraphQL support to current project
mithril add graphql
# Add GraphQL support to specific project
mithril add graphql /path/to/project
Generate GraphQL Files
# Generate complete GraphQL setup
mithril graphql generate --output ./graphql --models ./app/models
# Generate schema only
mithril graphql schema --output ./schema.graphql --models ./app/models
Start GraphQL Playground
# Start standalone playground
mithril graphql playground --port 8080 --endpoint http://localhost:3000/graphql
Code Examples
Basic GraphQL Setup
import "github.com/mithril-framework/mithril/pkg/graphql"
// Create GraphQL configuration
config := &graphql.GraphQLConfig{
Path: "/graphql",
Playground: true,
Introspection: true,
ComplexityLimit: 1000,
}
// Create integration
integration := graphql.NewGraphQLIntegration(config)
// Add models
integration.AddModel(&User{})
integration.AddModel(&Product{})
// Register resolvers
integration.RegisterResolver("User", userResolver)
integration.RegisterResolver("Product", productResolver)
// Register routes
integration.RegisterRoutes(app)
Custom Resolver Implementation
type UserResolver struct {
users []User
}
func (ur *UserResolver) GetByID(ctx context.Context, id string) (interface{}, error) {
// Custom logic to fetch user by ID
for _, user := range ur.users {
if user.ID.String() == id {
return user, nil
}
}
return nil, fmt.Errorf("user not found")
}
func (ur *UserResolver) List(ctx context.Context, limit, offset int) ([]interface{}, error) {
// Custom logic to fetch users with pagination
users := make([]interface{}, len(ur.users))
for i, user := range ur.users {
users[i] = user
}
return users, nil
}
func (ur *UserResolver) Create(ctx context.Context, input map[string]interface{}) (interface{}, error) {
// Custom logic to create user
user := User{
ID: uuid.New(),
Name: input["name"].(string),
Email: input["email"].(string),
}
ur.users = append(ur.users, user)
return user, nil
}
Schema Generation
// Generate schema from models
schema, err := integration.GenerateSchema()
if err != nil {
log.Fatal(err)
}
// Save schema to file
err = integration.GenerateSchemaFile("schema.graphql")
if err != nil {
log.Fatal(err)
}
Integration with Generated Projects
When you create a new Mithril project with GraphQL support:
- Automatic Setup: GraphQL is automatically configured
- Model Integration: All models are automatically added to the schema
- Resolver Generation: Base resolvers are generated for all models
- CLI Integration: GraphQL commands are available in the project
Advanced Features
Custom Scalar Types
// UUID scalar type
type UUID string
// Time scalar type
type Time time.Time
Field Resolvers
func (ur *UserResolver) ResolveField(ctx context.Context, obj interface{}, field string) (interface{}, error) {
user := obj.(User)
switch field {
case "full_name":
return user.FirstName + " " + user.LastName, nil
case "age":
return time.Since(user.BirthDate).Hours() / 24 / 365, nil
default:
return nil, fmt.Errorf("unknown field: %s", field)
}
}
Middleware Integration
// Add authentication middleware
integration.AddMiddleware(func(next graphql.ResolverFunc) graphql.ResolverFunc {
return func(ctx context.Context, obj interface{}, info graphql.ResolveInfo) (interface{}, error) {
// Check authentication
if !isAuthenticated(ctx) {
return nil, fmt.Errorf("unauthorized")
}
return next(ctx, obj, info)
}
})
Performance Considerations
- Query Complexity: Set appropriate complexity limits
- DataLoader: Implement DataLoader for N+1 query prevention
- Caching: Add caching for frequently accessed data
- Pagination: Use cursor-based pagination for large datasets
Security Considerations
- Input Validation: Validate all input data
- Rate Limiting: Implement rate limiting for GraphQL endpoints
- Authentication: Secure GraphQL endpoints with proper authentication
- Authorization: Implement field-level authorization
This GraphQL integration provides a powerful and flexible way to build APIs with Mithril, combining the best of both REST and GraphQL paradigms.
Documentation
ยถ
There is no documentation for this package.
Click to show internal directories.
Click to hide internal directories.