Skip to content

tejgokani/sqlsmith

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

27 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SQLSmith

JavaScript Schema to Postgres (Supabase) Migration Generator

SQLSmith converts JavaScript object schemas into clean, safe, Supabase-ready Postgres SQL migration files with schema diffing, CLI tools, and type overrides.

πŸš€ Features

  • ✨ JS β†’ SQL Schema Generation - Write schemas in JavaScript, get clean SQL
  • πŸ”„ Schema Diffing - Generate ALTER statements from schema changes
  • πŸ“¦ Supabase-Ready - Timestamped migrations in the Supabase format
  • 🎯 Shorthand Notation - Concise column definitions ("uuid:pk", "text:unique:notnull")
  • πŸ” RLS Policy Templates - Optional Supabase Row Level Security policy generation
  • βš™οΈ Highly Configurable - Type overrides, naming strategies, timestamps, and more
  • πŸ§ͺ Well-Tested - Comprehensive test suite included
  • πŸ› οΈ CLI + Programmatic API - Use from command line or Node.js code

πŸ“¦ Installation

npm install -D sqlsmith
# or
yarn add -D sqlsmith

🏁 Quick Start

1. Initialize SQLSmith

npx sqlsmith init

This creates:

  • sqlsmith.config.js - Configuration file
  • schema.example.js - Example schema file

2. Define Your Schema

Edit schema.example.js:

export default {
  users: {
    id: "uuid:pk",
    name: "text:notnull",
    email: "text:unique:notnull",
    age: "integer:default=18",
    profile: {
      bio: "text",
      avatar_url: "text"
    },
    created_at: "timestamptz:default=now()"
  },
  profiles: {
    id: "uuid:pk",
    user_id: "uuid:fk=users.id",
    visibility: "text:default='public'"
  }
};

3. Generate SQL

# Generate SQL file
npx sqlsmith generate --schema=schema.example.js --out=schema.sql

# Or create a timestamped migration
npx sqlsmith migrate --schema=schema.example.js --message="init"

4. Output

Generated SQL:

CREATE TABLE IF NOT EXISTS public.users (
  id uuid PRIMARY KEY,
  name text NOT NULL,
  email text UNIQUE NOT NULL,
  age integer DEFAULT 18,
  profile jsonb,
  created_at timestamptz DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.profiles (
  id uuid PRIMARY KEY,
  user_id uuid REFERENCES public.users(id),
  visibility text DEFAULT 'public'
);

πŸ“š CLI Commands

init

Create configuration and example schema files

npx sqlsmith init

generate

Generate SQL from schema

npx sqlsmith generate --schema=schema.js --out=schema.sql

migrate

Create timestamped migration file

npx sqlsmith migrate --schema=schema.js --message="create users table"

diff

Generate ALTER statements from schema differences

npx sqlsmith diff --from=old-schema.js --to=new-schema.js --out=diff.sql

policies

Generate Supabase RLS policy templates

npx sqlsmith policies --table=users --out=policies.sql

πŸ’» Programmatic API

import { generateSQL, diffSchemas, migrate } from "sqlsmith";

// Generate SQL from schema
const sql = generateSQL(schemaObject);

// Generate ALTER statements
const diff = diffSchemas(oldSchema, newSchema);

// Create migration file
const filePath = migrate(schemaObject, "./supabase/migrations", "init");

πŸ“ Schema Notation

Shorthand Format

Column definitions use the format: "<type>[:modifier1][:modifier2]..."

{
  id: "uuid:pk",                           // Primary key
  email: "text:unique:notnull",            // Unique and NOT NULL
  age: "integer:default=18",               // Default value
  created_at: "timestamptz:default=now()", // Function default
  user_id: "uuid:fk=users.id",            // Foreign key
  settings: "jsonb:default='{}'"          // JSON default
}

Supported Modifiers

  • pk - Primary key (implies NOT NULL)
  • notnull - NOT NULL constraint
  • unique - UNIQUE constraint
  • default=<value> - Default value
  • fk=<table>.<column> - Foreign key reference

Type Mapping

JavaScript types to PostgreSQL:

string   β†’ text
number   β†’ integer
boolean  β†’ boolean
uuid     β†’ uuid
object   β†’ jsonb
array    β†’ jsonb

Explicit PostgreSQL types supported:

  • text, varchar, integer, bigint, smallint
  • numeric, decimal, real, double precision
  • uuid, boolean, date, timestamp, timestamptz
  • json, jsonb, text[], integer[], etc.

Nested Objects

Nested objects are automatically converted to jsonb:

{
  users: {
    profile: {
      bio: "text",
      avatar_url: "text"
    }
  }
}

Becomes:

profile jsonb

βš™οΈ Configuration

sqlsmith.config.js:

export default {
  schema: 'public',              // PostgreSQL schema
  namingStrategy: 'snake_case',  // snake_case or camelCase
  timestamps: true,              // Add created_at/updated_at
  jsonForObjects: true,          // Convert nested objects to jsonb
  foreignKeyStrategy: 'inline',  // inline or separateTable
  policyGeneration: false,       // Generate RLS policies
  supabaseDir: './supabase/migrations',
  typeOverrides: {
    // Custom type mappings
    id: 'uuid',
    email: 'varchar(255)'
  }
};

Options

Option Type Default Description
schema string 'public' PostgreSQL schema name
namingStrategy string 'snake_case' Naming convention
timestamps boolean/object false Auto-add timestamps
jsonForObjects boolean true Convert objects to jsonb
foreignKeyStrategy string 'inline' FK strategy
policyGeneration boolean false Generate RLS policies
supabaseDir string './supabase/migrations' Migration directory
typeOverrides object {} Custom type mappings

πŸ”„ Schema Diffing

SQLSmith can generate ALTER statements by comparing two schemas:

// old-schema.js
export default {
  users: {
    id: "uuid:pk",
    name: "text"
  }
};

// new-schema.js
export default {
  users: {
    id: "uuid:pk",
    name: "text",
    email: "text:unique:notnull"  // Added column
  }
};
npx sqlsmith diff --from=old-schema.js --to=new-schema.js

Output:

ALTER TABLE public.users ADD COLUMN email text UNIQUE NOT NULL;

Destructive Changes

SQLSmith warns about destructive changes:

-- WARNING: DROP_COLUMN on users.name is DESTRUCTIVE!
-- ALTER TABLE public.users DROP COLUMN name;

πŸ” Supabase Integration

Migrations

SQLSmith generates timestamped migration files compatible with Supabase:

supabase/migrations/
  20251121143022_create_users.sql
  20251121143045_add_profiles.sql

RLS Policies

Generate Row Level Security policy templates:

npx sqlsmith policies --table=users

Output:

-- Enable Row Level Security
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;

-- Policy: Authenticated users can view all records
CREATE POLICY "authenticated_select_policy" ON public.users
  FOR SELECT
  TO authenticated
  USING (true);

-- Policy: Users can update their own records
CREATE POLICY "user_update_own_policy" ON public.users
  FOR UPDATE
  TO authenticated
  USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);

πŸ§ͺ Testing

Run the test suite:

npm test

Tests include:

  • Parser validation
  • SQL generation
  • Schema diffing
  • Type mapping
  • Configuration handling

πŸ“ Project Structure

sqlsmith/
β”œβ”€β”€ bin/
β”‚   └── sqlsmith.js           # CLI entry point
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.js              # Main API
β”‚   β”œβ”€β”€ cli.js                # CLI commands
β”‚   β”œβ”€β”€ parser/
β”‚   β”‚   β”œβ”€β”€ parseSchema.js    # Schema parser
β”‚   β”‚   └── validateSchema.js # Schema validator
β”‚   β”œβ”€β”€ generator/
β”‚   β”‚   β”œβ”€β”€ sqlCreate.js      # CREATE TABLE generator
β”‚   β”‚   β”œβ”€β”€ sqlAlter.js       # ALTER TABLE generator
β”‚   β”‚   └── typeMapper.js     # Type mapping
β”‚   β”œβ”€β”€ integrator/
β”‚   β”‚   β”œβ”€β”€ supabaseWriter.js # Migration file writer
β”‚   β”‚   └── policyGenerator.js# RLS policy generator
β”‚   └── utils/
β”‚       β”œβ”€β”€ fileWriter.js     # File utilities
β”‚       β”œβ”€β”€ logger.js         # Logger
β”‚       └── timestamp.js      # Timestamp generator
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ migration.sql.tpl     # Migration template
β”‚   └── policy.template.sql   # Policy template
β”œβ”€β”€ examples/
β”‚   └── schema.example.js     # Example schema
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ parser.test.js        # Parser tests
β”‚   └── generator.test.js     # Generator tests
└── package.json

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

MIT Β© Your Name

πŸ”— Links

✨ Examples

Basic Schema

export default {
  posts: {
    id: "uuid:pk",
    title: "text:notnull",
    content: "text",
    author_id: "uuid:fk=users.id",
    published: "boolean:default=false",
    created_at: "timestamptz:default=now()"
  }
};

With Timestamps Config

// sqlsmith.config.js
export default {
  timestamps: {
    created_at: true,
    updated_at: true
  }
};

// schema.js
export default {
  articles: {
    id: "uuid:pk",
    title: "text:notnull"
    // created_at and updated_at added automatically
  }
};

Complex Schema

export default {
  organizations: {
    id: "uuid:pk",
    name: "text:notnull",
    settings: "jsonb:default='{}'",
    created_at: "timestamptz:default=now()"
  },
  users: {
    id: "uuid:pk",
    email: "text:unique:notnull",
    org_id: "uuid:fk=organizations.id",
    role: "text:default='member'",
    metadata: {
      bio: "text",
      avatar: "text",
      preferences: {}
    }
  },
  posts: {
    id: "uuid:pk",
    author_id: "uuid:fk=users.id",
    org_id: "uuid:fk=organizations.id",
    title: "text:notnull",
    content: "text",
    tags: "text[]",
    published_at: "timestamptz"
  }
};

Built with ❀️ for the Supabase and PostgreSQL community

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Installation

npm install

Installation

npm install

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Usage

See the documentation for more details.

Installation

npm install

Installation

npm install

About

The simplest way to turn JavaScript objects into production-ready SQL schemas and migration files.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors