Skip to content

GraphQL Module ​

The GraphQL module provides comprehensive GraphQL support for the api.zig framework, featuring multiple UI providers (GraphiQL, Playground, Apollo Sandbox, Altair, Voyager), schema definition, query parsing, execution, subscriptions, and production-ready features like persisted queries, caching, and federation support.

Overview ​

zig
const graphql = @import("api").graphql;

Features ​

  • Multiple UI Providers: GraphiQL, GraphQL Playground, Apollo Sandbox, Altair, Voyager
  • Schema Definition: Complete type system with scalars, objects, interfaces, unions, enums
  • Query Execution: Full query/mutation/subscription support
  • Production Features: Persisted queries, complexity analysis, depth limiting
  • Federation: Apollo Federation v1/v2 support for microservices
  • Caching: Response caching with configurable TTL
  • Tracing: APM integration with OpenTelemetry, Datadog, etc.
  • Security: Error masking, introspection control, rate limiting

Quick Start ​

zig
const std = @import("std");
const api = @import("api");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    var app = try api.App.init(allocator, .{
        .title = "My GraphQL API",
    });
    defer app.deinit();

    // Create schema
    var schema = api.GraphQLSchema.init(allocator);
    defer schema.deinit();

    try schema.setQueryType(.{
        .name = "Query",
        .fields = &.{
            .{ .name = "hello", .type_name = "String", .is_non_null = true },
        },
    });

    // Enable GraphQL with all UIs
    try app.enableGraphQL(&schema, .{
        .schema = &schema,
        .path = "/graphql",
        .playground_path = "/graphql/playground",
        .graphiql_path = "/graphql/graphiql",
        .apollo_sandbox_path = "/graphql/sandbox",
        .enable_introspection = true,
    });

    try app.run(.{ .port = 8000 });
}

GraphQL Configuration ​

GraphQLConfig ​

Complete configuration for GraphQL endpoints:

zig
const GraphQLConfig = struct {
    /// GraphQL schema (required)
    schema: *Schema,
    /// GraphQL endpoint path
    path: []const u8 = "/graphql",
    /// Playground path (null to disable)
    playground_path: ?[]const u8 = "/graphql/playground",
    /// GraphiQL path (null to disable)
    graphiql_path: ?[]const u8 = "/graphql/graphiql",
    /// Apollo Sandbox path (null to disable)
    apollo_sandbox_path: ?[]const u8 = null,
    /// Altair path (null to disable)
    altair_path: ?[]const u8 = null,
    /// Voyager path (null to disable)
    voyager_path: ?[]const u8 = null,
    /// Enable playground/UI
    enable_playground: bool = true,
    /// Enable introspection
    enable_introspection: bool = true,
    /// Maximum query depth
    max_depth: u32 = 15,
    /// Maximum query complexity
    max_complexity: u32 = 1000,
    /// Enable query batching
    enable_batching: bool = false,
    /// Maximum batch size
    max_batch_size: u32 = 10,
    /// Enable tracing
    enable_tracing: bool = false,
    /// Enable persisted queries
    enable_persisted_queries: bool = false,
    /// Only allow persisted queries (security feature)
    persisted_queries_only: bool = false,
    /// Mask errors in production
    mask_errors: bool = true,
    /// Enable response caching
    enable_caching: bool = false,
    /// Cache TTL in milliseconds
    cache_ttl_ms: u64 = 60000,
    /// Enable CORS
    enable_cors: bool = true,
    /// Enable subscriptions
    enable_subscriptions: bool = false,
    // ... and more
};

UI Providers ​

api.zig provides 5 different GraphQL UI providers, similar to Swagger UI for REST APIs.

GraphiQL ​

Modern GraphQL IDE with explorer plugin:

zig
// Simple usage
const html = api.graphiql("/graphql");

// With configuration
const html = api.graphiqlWithConfig(.{
    .provider = .graphiql,
    .theme = .dark,
    .title = "My GraphQL API",
    .endpoint = "/graphql",
    .show_docs = true,
    .show_history = true,
    .enable_persistence = true,
    .code_completion = true,
});

GraphQL Playground ​

Feature-rich GraphQL IDE:

zig
const html = api.graphqlPlayground("/graphql");

// With configuration
const html = api.graphqlPlaygroundWithConfig(.{
    .theme = .dark,
    .schema_polling = true,
    .schema_polling_interval_ms = 2000,
});

Apollo Sandbox ​

Apollo's embeddable GraphQL IDE:

zig
const html = api.apolloSandbox("/graphql");

// With configuration
const html = api.apolloSandboxWithConfig(.{
    .title = "Apollo Sandbox",
    .credentials = .include,
});

Altair GraphQL Client ​

Full-featured GraphQL client:

zig
const html = api.altairGraphQL("/graphql");

GraphQL Voyager ​

Interactive schema visualization:

zig
const html = api.graphqlVoyager("/graphql");

Generate UI by Provider ​

zig
const html = api.generateGraphQLUI(.{
    .provider = .playground,  // or .graphiql, .apollo_sandbox, .altair, .voyager
    .theme = .dark,
    .title = "My API",
});

UI Configuration ​

GraphQLUIConfig ​

zig
pub const GraphQLUIConfig = struct {
    /// UI provider to use
    provider: GraphQLUIProvider = .graphiql,
    /// Theme preference (light, dark, system)
    theme: GraphQLUITheme = .dark,
    /// Title shown in the UI
    title: []const u8 = "GraphQL Explorer",
    /// GraphQL endpoint URL
    endpoint: []const u8 = "/graphql",
    /// WebSocket endpoint for subscriptions
    subscription_endpoint: ?[]const u8 = null,
    /// Enable schema polling
    schema_polling: bool = false,
    /// Schema polling interval in milliseconds
    schema_polling_interval_ms: u32 = 2000,
    /// Show documentation explorer
    show_docs: bool = true,
    /// Show history panel
    show_history: bool = true,
    /// Enable query persistence
    enable_persistence: bool = true,
    /// Custom headers to include
    default_headers: []const HeaderPair = &.{},
    /// Initial query to display
    default_query: ?[]const u8 = null,
    /// Enable keyboard shortcuts
    enable_shortcuts: bool = true,
    /// Tab size for editor
    editor_tab_size: u8 = 2,
    /// Font size for editor
    editor_font_size: u8 = 14,
    /// Enable syntax highlighting
    syntax_highlighting: bool = true,
    /// Enable code completion
    code_completion: bool = true,
    /// Custom CSS for styling
    custom_css: ?[]const u8 = null,
    /// Custom JavaScript
    custom_js: ?[]const u8 = null,
    /// Logo URL for branding
    logo_url: ?[]const u8 = null,
    /// Credentials policy
    credentials: CredentialsPolicy = .same_origin,
};

Schema Definition ​

Creating a Schema ​

zig
var schema = api.GraphQLSchema.init(allocator);
defer schema.deinit();

// Define Query type
try schema.setQueryType(.{
    .name = "Query",
    .description = "Root query type",
    .fields = &.{
        .{
            .name = "users",
            .type_name = "User",
            .is_list = true,
            .description = "Get all users",
        },
        .{
            .name = "user",
            .type_name = "User",
            .args = &.{
                .{ .name = "id", .type_name = "ID", .is_non_null = true },
            },
            .description = "Get user by ID",
        },
    },
});

// Define Mutation type
try schema.setMutationType(.{
    .name = "Mutation",
    .fields = &.{
        .{
            .name = "createUser",
            .type_name = "User",
            .args = &.{
                .{ .name = "name", .type_name = "String", .is_non_null = true },
                .{ .name = "email", .type_name = "String", .is_non_null = true },
            },
        },
    },
});

// Define custom object type
try schema.addObjectType(.{
    .name = "User",
    .fields = &.{
        .{ .name = "id", .type_name = "ID", .is_non_null = true },
        .{ .name = "name", .type_name = "String", .is_non_null = true },
        .{ .name = "email", .type_name = "String" },
        .{ .name = "posts", .type_name = "Post", .is_list = true },
    },
});

Scalar Types ​

api.zig provides 30+ built-in scalar types:

ScalarDescription
IDUnique identifier
StringUTF-8 string
Int32-bit integer
Float64-bit float
Booleantrue/false
DateTimeISO 8601 date-time
JSONArbitrary JSON
DateISO 8601 date
TimeISO 8601 time
BigIntArbitrary precision integer
DecimalArbitrary precision decimal
UUIDUUID v4
EmailRFC 5322 email
URLRFC 3986 URI
IPv4IPv4 address
IPv6IPv6 address
PhoneE.164 phone number
CurrencyISO 4217 currency
DurationISO 8601 duration
TimestampUnix timestamp
UploadFile upload
BytesBase64 binary
PositiveIntInteger > 0
NonNegativeIntInteger >= 0

Enum Types ​

zig
try schema.addEnumType("UserRole", &.{
    .{ .name = "ADMIN", .description = "Administrator" },
    .{ .name = "USER", .description = "Regular user" },
    .{ .name = "GUEST", .description = "Guest user", .is_deprecated = true },
}, "User role enumeration");

Input Types ​

zig
try schema.addInputType("CreateUserInput", &.{
    .{ .name = "name", .type_name = "String", .is_non_null = true },
    .{ .name = "email", .type_name = "Email", .is_non_null = true },
    .{ .name = "role", .type_name = "UserRole", .default_value = "USER" },
}, "Input for creating a user");

Interface Types ​

zig
try schema.addInterfaceType("Node", &.{
    .{ .name = "id", .type_name = "ID", .is_non_null = true },
}, "Relay Node interface");

Union Types ​

zig
try schema.addUnionType("SearchResult", &.{
    "User", "Post", "Comment",
}, "Search result union");

Production Features ​

Query Complexity Analysis ​

zig
const config = api.ComplexityConfig{
    .enabled = true,
    .max_complexity = 1000,
    .default_field_complexity = 1,
    .list_multiplier = 10,
};

Query Depth Limiting ​

zig
const config = api.DepthConfig{
    .enabled = true,
    .max_depth = 15,
    .ignore_introspection = true,
};

Persisted Queries ​

zig
const config = api.PersistedQueriesConfig{
    .enabled = true,
    .only_persisted = false,  // Set to true for security
    .use_sha256 = true,
};

Response Caching ​

zig
const config = api.ResponseCacheConfig{
    .enabled = true,
    .max_size = 1000,
    .default_ttl_ms = 60000,
    .skip_mutations = true,
};

Error Handling ​

zig
const config = api.ErrorConfig{
    .mask_errors = true,
    .generic_message = "An unexpected error occurred",
    .include_stack_traces = false,
    .include_error_codes = true,
};

Tracing & APM ​

zig
const config = api.TracingConfig{
    .enabled = true,
    .include_resolver_timings = true,
    .include_parsing = true,
    .include_validation = true,
    .apm_provider = .opentelemetry,
};

Federation Support ​

zig
const config = api.FederationConfig{
    .enabled = true,
    .version = .v2,
    .service_name = "users-service",
    .service_url = "http://localhost:4001/graphql",
};

Subscriptions ​

Configuration ​

zig
const config = api.SubscriptionConfig{
    .protocol = .graphql_ws,
    .keep_alive = true,
    .keep_alive_interval_ms = 30000,
    .connection_timeout_ms = 30000,
    .max_retry_attempts = 5,
    .lazy = true,
};

GraphQL Middleware ​

Basic Middleware ​

zig
const mw = api.graphqlMiddleware(.{
    .enable_complexity_analysis = true,
    .max_complexity = 1000,
    .enable_depth_limiting = true,
    .max_depth = 15,
    .enable_introspection = true,
    .paths = &.{"/graphql"},
});

try app.use(mw.handle);

GraphQL CORS ​

zig
const cors_mw = api.graphqlCors(.{
    .allowed_origins = &.{"https://example.com"},
    .allow_credentials = true,
});

try app.use(cors_mw.handle);

GraphQL Rate Limiting ​

zig
const rate_mw = api.graphqlRateLimit(.{
    .query_limit = 100,
    .mutation_limit = 50,
    .subscription_limit = 10,
    .window_seconds = 60,
});

try app.use(rate_mw.handle);

GraphQL Tracing Middleware ​

zig
const trace_mw = api.graphqlTracing(.{
    .enabled = true,
    .include_resolver_timings = true,
    .sample_rate = 1.0,
});

try app.use(trace_mw.handle);

Full Example ​

zig
const std = @import("std");
const api = @import("api");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    var app = try api.App.init(allocator, .{
        .title = "Production GraphQL API",
        .version = "1.0.0",
    });
    defer app.deinit();

    // Create schema
    var schema = api.GraphQLSchema.init(allocator);
    defer schema.deinit();

    try schema.setQueryType(.{
        .name = "Query",
        .fields = &.{
            .{ .name = "users", .type_name = "User", .is_list = true },
            .{ .name = "user", .type_name = "User", .args = &.{
                .{ .name = "id", .type_name = "ID", .is_non_null = true },
            }},
        },
    });

    try schema.addObjectType(.{
        .name = "User",
        .fields = &.{
            .{ .name = "id", .type_name = "ID", .is_non_null = true },
            .{ .name = "name", .type_name = "String", .is_non_null = true },
            .{ .name = "email", .type_name = "Email" },
        },
    });

    // Enable GraphQL with production config
    try app.enableGraphQL(&schema, .{
        .schema = &schema,
        .path = "/graphql",
        .playground_path = "/graphql/playground",
        .graphiql_path = "/graphql/graphiql",
        .apollo_sandbox_path = "/graphql/sandbox",
        .voyager_path = "/graphql/voyager",
        .enable_introspection = true,
        .enable_tracing = true,
        .mask_errors = true,
        .max_depth = 15,
        .max_complexity = 1000,
        .enable_caching = true,
        .cache_ttl_ms = 60000,
        .ui_config = .{
            .theme = .dark,
            .title = "My GraphQL API",
            .show_docs = true,
            .code_completion = true,
        },
    });

    // Add GraphQL middleware
    const gql_mw = api.graphqlMiddleware(.{
        .enable_complexity_analysis = true,
        .enable_depth_limiting = true,
    });
    try app.use(gql_mw.handle);

    try app.run(.{ .port = 8000 });
}

See Also ​

Released under the MIT License.