🚀 Big News:Socket Has Acquired Secure Annex.Learn More →
Socket
Book a DemoSign in
Socket

@t1mmen/srtd

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@t1mmen/srtd

Supabase Repeatable Template Definitions (srtd): 🪄 Live-reloading SQL templates for Supabase DX. Make your database changes reviewable and migrations maintainable! 🚀

latest
Source
npmnpm
Version
1.0.0
Version published
Maintainers
1
Created
Source

srtd — Live-Reloading, declarative, SQL migration templates for Supabase and Postgres

NPM Version Downloads License: MIT CI/CD

The workflow of Vite or Nodemon—but for SQL. Hot-reload SQL while you iterate. Build as migrations when it's time to ship.

demo

Why srtd exists

Database development usually has a slow, frustrating feedback loop:

  • Edit SQL in your IDE
  • Copy to SQL editor or create migration
  • Run it
    • Hit an error? Fix in IDE, copy again, run again
    • Works? Back to your IDE, until the next change
  • Repeat

Code reviews aren't much better. Changing a single line in a function often shows up as a full rewrite in Git, making it hard to see what actually changed.

srtd exists to fix both problems:

  • Fast local iteration with live reload
  • Clean, reviewable diffs for database logic
  • Real migrations for production safety

After searching for two years while building Timely's Memory Engine on Supabase, the itch needed to be scratched.

The core idea

srtd intentionally separates iteration, review, and execution.

Templates are for humans

  • Plain SQL files
  • Concise and readable
  • The primary thing you review in Git

Migrations are for databases

  • Generated from templates
  • Explicit and deterministic
  • Safe to deploy in CI and production

Templates evolve over time. Migrations are the execution record.

The diff problem—solved

Without templates, changing one line in a function means your PR shows a complete rewrite—the old DROP + CREATE replaced by a new one. Reviewers have to read the whole thing, and manually compare it to the last migration to touch the function to spot changes. Talk about friction!

With srtd, your PR shows what you actually changed;

Without srtd

+ DROP FUNCTION IF EXISTS calculate_total;
+ CREATE FUNCTION calculate_total(order_id uuid)
+ RETURNS numeric AS $fn$
+ BEGIN
+   RETURN (SELECT SUM(price * quantity) FROM order_items);
+ END;
+ $fn$ LANGUAGE plpgsql;

With srtd

  CREATE FUNCTION calculate_total(order_id uuid)
  RETURNS numeric AS $fn$
  BEGIN
-   RETURN (SELECT SUM(price) FROM order_items);
+   RETURN (SELECT SUM(price * quantity) FROM order_items);
  END;
  $fn$ LANGUAGE plpgsql;

git blame works. Code reviews are useful. Your database logic is treated like real code.

How To Use It

Quick start

npm install -g @t1mmen/srtd
cd your-supabase-project

# Create a template
mkdir -p supabase/migrations-templates
cat > supabase/migrations-templates/hello.sql << 'EOF'
DROP FUNCTION IF EXISTS hello;
CREATE FUNCTION hello() RETURNS text AS $$
BEGIN RETURN 'Hello from srtd!'; END;
$$ LANGUAGE plpgsql;
EOF

# Start watch mode
srtd watch

Edit hello.sql, save—it's live on your local database. No migration file, no restart, no waiting.

When ready to deploy:

srtd build            # Creates supabase/migrations/20241226_srtd-hello.sql
supabase migration up # Deploy with Supabase CLI

Already have functions deployed? Create templates for them, then register so srtd knows they're not new:

srtd register existing_function.sql  # Won't rebuild until the template actually changes

Development loop (watch mode)

srtd watch   # Edit template → auto-applied to local DB

Hot reload is a DX feature. It exists to make iteration smooth and fast.

Watch mode demo

Shipping to production (generate migrations)

srtd build            # → migrations/20250109123456_srtd-template-name.sql
supabase migration up # Deploy via Supabase CLI

Generated migrations fully redefine objects—databases prefer explicit redefinition, humans prefer small diffs. srtd optimizes for both in different layers.

WIP templates

Use .wip.sql files for experiments:

my_experiment.wip.sql  → Applies locally, never builds to migration
  • Applied during watch and apply
  • Excluded from build
  • Safe to experiment without affecting production

When ready: srtd promote my_experiment.wip.sql

WIP workflow demo

Template dependencies

Declare dependencies between templates with @depends-on comments:

-- @depends-on: helper_functions.sql
CREATE FUNCTION complex_calc() ...

During apply and build, templates are sorted so dependencies run first. Circular dependencies are detected and reported. Use --no-deps to disable.

What works as templates

Templates need to be idempotent—safe to run multiple times. This works great for:

ObjectPattern
FunctionsDROP FUNCTION IF EXISTS + CREATE FUNCTION
ViewsCREATE OR REPLACE VIEW
RLS PoliciesDROP POLICY IF EXISTS + CREATE POLICY
TriggersDrop + recreate trigger and function
RolesREVOKE ALL + GRANT
EnumsADD VALUE IF NOT EXISTS

Not for templates: Table structures, indexes, data modifications—use regular migrations for those.

Commands

srtd                     # Interactive menu
srtd watch               # Live reload—applies templates on save
srtd build               # Generate migration files
srtd apply               # Apply all templates once (no watch)
srtd register            # Mark templates as already deployed
srtd promote             # Convert .wip template to buildable
srtd clear               # Reset build state
srtd init                # Initialize config file
srtd doctor              # Validate setup and diagnose issues

# Build options
srtd build --force       # Rebuild all templates
srtd build --apply       # Apply immediately after building
srtd build --bundle      # Combine all into single migration
srtd build --no-deps     # Disable dependency ordering

# Apply options
srtd apply --force       # Force apply all templates
srtd apply --no-deps     # Disable dependency ordering

# Clear options
srtd clear --local       # Clear local build log only
srtd clear --shared      # Clear shared build log only
srtd clear --reset       # Reset everything to defaults

# Global options (all commands)
--json                   # Machine-readable output
--non-interactive        # Disable prompts (for scripts)

JSON output

All commands support --json for machine-readable output (CI/CD, LLM integrations):

srtd build --json   # Single JSON object with results array and summary
srtd watch --json   # NDJSON stream (one event per line)

Output includes success, command, timestamp, and command-specific fields. Errors use a top-level error field.

Works great with Claude Code background tasks—pair with the srtd-cli skill and srtd rule for SQL template guidance.

Configuration

Defaults work for standard Supabase projects. Optional srtd.config.json:

{
  "templateDir": "supabase/migrations-templates",
  "migrationDir": "supabase/migrations",
  "pgConnection": "postgresql://postgres:postgres@localhost:54322/postgres",
  "migrationPrefix": "srtd",
  "migrationFilename": "$timestamp_$prefix$migrationName.sql",
  "wipIndicator": ".wip",
  "wrapInTransaction": true,
  "filter": "**/*.sql",
  "banner": "/* Auto-generated by srtd. Edit the template, not this file. */",
  "footer": ""
}

Run srtd doctor to validate your configuration and diagnose setup issues.

Custom migration paths

The migrationFilename option lets you match your project's existing migration structure:

VariableDescriptionExample
$timestampBuild timestamp (YYYYMMDDHHmmss)20240315143022
$migrationNameTemplate name (without .sql)create_users
$prefixMigration prefix with trailing dashsrtd-

Examples

Default (Supabase-style):

{ "migrationFilename": "$timestamp_$prefix$migrationName.sql" }
// → migrations/20240315143022_srtd-create_users.sql

Directory per migration (Prisma-style):

{ "migrationFilename": "$timestamp_$migrationName/migration.sql" }
// → migrations/20240315143022_create_users/migration.sql

Flyway-style (V prefix):

{
  "migrationFilename": "V$timestamp__$migrationName.sql",
  "migrationPrefix": ""
}
// → migrations/V20240315143022__create_users.sql

Nested directories are created automatically.

State tracking

FilePurposeGit
.buildlog.jsonWhat's been built to migrationsCommit
.buildlog.local.jsonWhat's applied to your local DBGitignore

FAQ

Why do generated migrations redefine entire objects?

Full redefinitions ensure deterministic, idempotent execution across environments. Templates encode intent; migrations encode execution.

Can I use hot reload in production?

No. Hot reload is strictly a local development feature. Production deploys always use generated migrations.

Why plain SQL instead of a DSL?

SQL is already the right language. srtd adds workflow improvements, not syntax.

What does "srtd" stand for?

Supabase Repeatable Template Definitions—but then general Postgres support happened, and... naming things is hard.

Contributing

Bug fixes, docs, and test coverage welcome. See CONTRIBUTING.md.

For development: CLAUDE.md.

More

Built by Timm Stokke with Claude, after two years of being annoyed.

Keywords

cli

FAQs

Package last updated on 31 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts