GraphQL Schema Reader
The GraphQL reader parses GraphQL Schema Definition Language (SDL) files and converts them into RelSpec's internal database model.
Features
- Standard GraphQL SDL support (generic, non-framework-specific)
- Type to Table mapping: GraphQL types become database tables
- Field to Column mapping: GraphQL fields become table columns
- Enum support: GraphQL enums are preserved
- Custom scalars: DateTime, JSON, Date automatically mapped to appropriate SQL types
- Implicit relationships: Detects relationships from field types
- Many-to-many support: Creates junction tables for bidirectional array relationships
- Configurable ID mapping: Choose between bigint (default) or UUID for ID fields
Supported GraphQL Features
Built-in Scalars
ID→ bigint (default) or uuid (configurable)String→ textInt→ integerFloat→ double precisionBoolean→ boolean
Custom Scalars
DateTime→ timestampJSON→ jsonbDate→ dateTime→ timeDecimal→ numeric
Additional custom scalars can be mapped via metadata.
Relationships
Relationships are inferred from field types:
type Post {
id: ID!
title: String!
author: User! # Many-to-one (creates authorId FK column, NOT NULL)
reviewer: User # Many-to-one nullable (creates reviewerId FK column, NULL)
tags: [Tag!]! # One-to-many or many-to-many (depending on reverse)
}
type User {
id: ID!
posts: [Post!]! # Reverse of Post.author (no FK created)
}
type Tag {
id: ID!
posts: [Post!]! # Many-to-many with Post (creates PostTag junction table)
}
Relationship Detection Rules:
- Single type reference (
user: User) → Creates FK column (e.g.,userId) - Array type reference (
posts: [Post!]!) → One-to-many reverse (no FK on this table) - Bidirectional arrays → Many-to-many (creates junction table)
Enums
enum Role {
ADMIN
USER
GUEST
}
type User {
role: Role!
}
Enums are preserved in the schema and can be used as column types.
Usage
Basic Usage
import (
"git.warky.dev/wdevs/relspecgo/pkg/readers"
"git.warky.dev/wdevs/relspecgo/pkg/readers/graphql"
)
opts := &readers.ReaderOptions{
FilePath: "schema.graphql",
}
reader := graphql.NewReader(opts)
db, err := reader.ReadDatabase()
With UUID ID Type
opts := &readers.ReaderOptions{
FilePath: "schema.graphql",
Metadata: map[string]interface{}{
"idType": "uuid", // Map ID scalar to uuid instead of bigint
},
}
reader := graphql.NewReader(opts)
db, err := reader.ReadDatabase()
With Per-Type ID Mapping
opts := &readers.ReaderOptions{
FilePath: "schema.graphql",
Metadata: map[string]interface{}{
"typeIdMappings": map[string]string{
"User": "uuid", // User.id → uuid
"Post": "bigint", // Post.id → bigint
},
},
}
With Custom Scalar Mappings
opts := &readers.ReaderOptions{
FilePath: "schema.graphql",
Metadata: map[string]interface{}{
"customScalarMappings": map[string]string{
"Upload": "bytea",
"Decimal": "numeric(10,2)",
},
},
}
CLI Usage
# Convert GraphQL to JSON
relspec convert --from graphql --from-path schema.graphql \
--to json --to-path schema.json
# Convert GraphQL to GORM models
relspec convert --from graphql --from-path schema.graphql \
--to gorm --to-path models/ --package models
# Convert GraphQL to PostgreSQL SQL
relspec convert --from graphql --from-path schema.graphql \
--to pgsql --to-path schema.sql
Metadata Options
| Option | Type | Description | Default |
|---|---|---|---|
idType |
string | Global ID type mapping ("bigint" or "uuid") | "bigint" |
typeIdMappings |
map[string]string | Per-type ID mappings | {} |
customScalarMappings |
map[string]string | Custom scalar to SQL type mappings | {} |
schemaName |
string | Schema name for all tables | "public" |
Limitations
- Only supports GraphQL SDL (Schema Definition Language), not queries or mutations
- Directives are ignored (except for future extensibility)
- Interfaces and Unions are not supported
- GraphQL's concept of "schema" is different from database schemas; all types go into a single database schema (default: "public")
Example
Input (schema.graphql):
scalar DateTime
enum Role {
ADMIN
USER
}
type User {
id: ID!
email: String!
role: Role!
createdAt: DateTime!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String
published: Boolean!
author: User!
}
Result: Database with:
- 2 tables:
UserandPost Posttable hasauthorIdforeign key toUser.idRoleenum with values: ADMIN, USER- Custom scalar
DateTimemapped totimestamp