Receber por email
← Voltar para o catálogo

portable-schema-generator

Emit Postgres.sql and SQLite.sql from a single schema spec so tools work across both drivers without duplicating DDL by hand. Use when designing a schema that needs to support both shared Postgres deployments and zero-config SQLite. Reduces two-file sync burden to a single source edit.

65estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: NOASSERTION

Como adicionar

/plugin marketplace add Tibsfox/gsd-skill-creator

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/portable-schema-generator-tibsfox/svg)](https://www.skillteca.com.br/skills/portable-schema-generator-tibsfox)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Portable Schema Generator

Two-driver schemas mean two migration files. Hand-keeping them in sync drifts fast. This skill captures the translation rules and the minimal tooling that keeps them aligned.

When to Use

  • Your tool needs to work on both Postgres and SQLite
  • You want fresh-project onboarding to be zero-config (SQLite default)

while shared-infra deployments keep Postgres

  • A single schema change should land in both driver files with no manual

diff-copying

Core Differences

| Concern | Postgres | SQLite | |---------|----------|--------| | Schemas | CREATE SCHEMA foo; SET search_path TO foo | Namespace-flat — prefix names instead | | Autoincrement | BIGSERIAL PRIMARY KEY | INTEGER PRIMARY KEY AUTOINCREMENT | | Timestamps | TIMESTAMPTZ DEFAULT now() | TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')) | | Booleans | BOOLEAN | INTEGER (0/1) | | Enums via CHECK | CHECK (col IN ('a','b')) | Same — both support inline CHECK | | Foreign keys | On by default | PRAGMA foreign_keys = ON required at connect | | Updated-at trigger | CREATE TRIGGER ... EXECUTE FUNCTION touch_updated_at() | CREATE TRIGGER ... BEGIN UPDATE ... END | | Cascading drops | ON DELETE CASCADE | Same, but only enforced with foreign_keys = ON | | Reserved-word casing | Case-insensitive | Case-insensitive, but be consistent |

Translation Rules

When authoring the Postgres version first:

  1. Strip schema prefix for SQLite — CREATE SCHEMA IF NOT EXISTS foo;

and SET search_path are removed. Keep bare table names.

  1. Replace BIGSERIAL with INTEGER PRIMARY KEY AUTOINCREMENT.
  2. Replace TIMESTAMPTZ with TEXT; default becomes

(strftime('%Y-%m-%dT%H:%M:%fZ','now')).

  1. Replace BOOLEAN with INTEGER (values 0/1 at insert time — use an

adapter coercion).

  1. Drop RESTART IDENTITY on truncates (SQLite uses

DELETE FROM sqlite_sequence WHERE name = 'table' instead).

  1. Rewrite function-style triggers to inline BEGIN ... END trigger

bodies.

File Layout

migrations/<feature>/
  001-init.postgres.sql
  001-init.sqlite.sql
  002-next.postgres.sql
  002-next.sqlite.sql

Numbered pairs. The adapter picks the right one based on cfg.db.driver.

Adapter Runtime Responsibilities

The query adapter at runtime should:

  • Rewrite $N placeholders → ? for SQLite
  • Strip release_history. schema prefix for SQLite
  • Translate now() → strftime(...), ::type casts → drop
  • Coerce JS booleans → 0/1 on param bindings
  • Provide a portable truncate(table) helper

Reference implementation: tools/release-history/db.mjs in this repo.

Workflow

  1. Author the Postgres version first (richer type system reduces ambiguity).
  2. Translate row-by-row using the rules above into the SQLite version.
  3. Test both: apply each migration to a disposable DB, run schema-check

script against the adapter.

  1. Commit both files together; never commit one without the other.

Anti-patterns to avoid

  • Single mixed-syntax file — both drivers will try to parse it and one or

both will fail.

  • Runtime translation of whole migration files — too many edge cases.
  • Letting the Postgres file diverge "just for now" — alignment rots quickly.

Example (from this repo)

See migrations/release-history/001-init.postgres.sql and migrations/release-history/001-init.sqlite.sql. Six tables (release, feature, metric, retrospective, lesson, publish_target). Same semantics, driver-idiomatic DDL.

Related

  • env-setup — database credentials and .env conventions
  • file-operation-patterns — migration file naming discipline
Compartilhar X LinkedIn