Files
relspecgo/pkg/readers/graphql
2025-12-28 11:41:55 +02:00
..
2025-12-28 11:41:55 +02:00
2025-12-28 11:41:55 +02:00
2025-12-28 11:41:55 +02:00
2025-12-28 11:41:55 +02:00
2025-12-28 11:41:55 +02:00

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 → text
  • Int → integer
  • Float → double precision
  • Boolean → boolean

Custom Scalars

  • DateTime → timestamp
  • JSON → jsonb
  • Date → date
  • Time → time
  • Decimal → 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: User and Post
  • Post table has authorId foreign key to User.id
  • Role enum with values: ADMIN, USER
  • Custom scalar DateTime mapped to timestamp