PGlite
Scrii cod PostgreSQL nativ în unul sau mai multe fișiere .sql. Platforma rulează o instanță PostgreSQL în browser prin intermediul @electric-sql/pglite — fiecare fișier .sql care nu este de test se execută automat la salvare în aceeași bază de date în memorie, în ordine lexicografică.
Proiectul de pornire include un fișier script.sql care creează un tabel greetings, introduce rândul (1, 'Hello, World!') și îl selectează înapoi — extinde-l adăugând mai multă schemă, date de inițializare (seed) și interogări.
Fișierul de intrare
Fișierele soluției se află în rădăcina proiectului:
script.sql— fișierul de soluție editabil. Starterul conține un ghid TODO pentru crearea tabeluluigreetingsși selectarea mesajului.- Poți redenumi
script.sqlîn orice dorești și poți crea fișiere.sqlsuplimentare (le poți organiza în submape dacă dorești). Instrumentul de rulare automată descoperă fiecare fișier.sqlcare nu este de test din structură.
Fișierele rulează în ordine lexicografică după calea completă. Pune un prefix numelor de fișiere (01-schema.sql, 02-data.sql, 03-queries.sql) atunci când ordinea de execuție contează.
Playground-ul pentru baza de date
Panoul din dreapta este o filă live Database care comunică cu aceeași instanță PGlite în memorie:
- Rezultatul rulării automate — fiecare SELECT (sau altă instrucțiune care produce rânduri) din fișierele tale
.sqleste redat aici, grupat după fișierul sursă, la fiecare salvare. - Tables — o bară laterală cu schema care listează fiecare tabel public, plus coloanele și tipurile sale. Fă clic pe Preview pe un tabel pentru a rula instantaneu
SELECT * FROM <table> LIMIT 20în fila ad-hoc. - Ad-hoc query — un editor SQL bazat pe Monaco pentru interogări unice pe baza de date activă. Ctrl/⌘ + Enter rulează interogarea fără a modifica fișierele sursă.
Baza de date este în memorie: reîmprospătarea previzualizării o va șterge. Pentru a curăța baza de date fără a reîncărca, rulează DROP TABLE … în orice fișier sursă sau în fila ad-hoc.
Versiune
Rulează PGlite v0.2.17 (PostgreSQL WASM) cu Vitest v3.2.4 pe Node v22.
Limbaje acceptate
SQL (dialectul PostgreSQL)
Framework de testare
Vitest cu helperul @dojocode/sql-test-helpers.
Memento-uri speciale și detalii de implementare
- Dialect standard PostgreSQL. Folosește
SERIAL/BIGSERIALpentru ID-uri cu auto-incrementare,ON CONFLICTpentru upsert-uri,RETURNINGpentru a obține rândurile introduse. - Convertește
COUNT(*)la::intîn teste — PGlite returnează în mod implicitbigint(ca șir de caractere), care se compară dificil cu numerele din JS. - Fișierele care se potrivesc cu
*.test.sqlsunt ignorate de rularea automată — rezervat pentru un viitor runner de teste SQL simple (raw-SQL). - Testele sunt scrise în TypeScript (
*.test.ts) folosind helperul comuncreatePgliteTestDb(import.meta.url). Helperul pornește o instanță nouă PGlite și încarcă automat fiecare fișier.sqlcare nu este de test, alături de test, înainte de a rula aserțiunile. - PGlite acceptă CTE-uri, funcții fereastră (window functions), JSON, căutare full-text și majoritatea funcționalităților PostgreSQL.
Exemplu cu Vitest:
import { describe, it, expect, beforeAll } from 'vitest';
import { createPgliteTestDb, type PgliteTestDb } from '@dojocode/sql-test-helpers/pglite';
let db: PgliteTestDb;
beforeAll(async () => {
db = await createPgliteTestDb(import.meta.url);
});
describe('greetings', () => {
it("contains the row with message 'Hello, World!'", async () => {
const rows = await db.query<{ message: string }>(
'SELECT message FROM greetings WHERE id = 1'
);
expect(rows[0]?.message).toBe('Hello, World!');
});
it('has exactly one row', async () => {
const rows = await db.query<{ n: number }>('SELECT COUNT(*)::int AS n FROM greetings');
expect(rows[0].n).toBe(1);
});
});Helperul returnează { query<T>(sql, params?): Promise<T[]>, exec(sql): Promise<void>, raw: PGlite }. query este async iar rândurile sunt returnate deja despachetate (fără a fi nevoie de proprietatea intermediară .rows). Folosește raw doar pentru cazuri avansate (tranzacții, interogări live, listen/notify).
Biblioteci incluse
- @electric-sql/pglite
- @dojocode/sql-test-helpers
- hono (mediu de rulare server in-WC)
- @hono/node-server
- vitest
Cum se face depanarea
Trei moduri de a verifica ce face codul tău SQL:
1. Fila cu rezultatul rulării automate (Auto-run result)
Fiecare rezultat SELECT este redat acolo împreună cu eticheta fișierului sursă. Dacă o interogare nu returnează nimic, secțiunea este omisă — acest lucru în sine este un semnal util că un rând nu a fost introdus sau că un filtru WHERE este prea restrictiv.
2. Fila Tables
Confirmă ce tabele există și tipurile coloanelor acestora în acest moment. Dacă primești erori de tipul "relation does not exist", înseamnă că tabelul nu a fost creat — de obicei din cauza unei erori de sintaxă într-o instrucțiune CREATE de deasupra.
3. Fila Ad-hoc query
Rulează SELECT-uri specifice pe baza de date activă fără a modifica fișierele sursă:
SELECT * FROM information_schema.tables WHERE table_schema = 'public';
SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'greetings';
SELECT * FROM greetings WHERE id = 1;Greșeli frecvente
- Omiterea
ON CONFLICT DO NOTHING— rularea repetată a scriptului poate eșua cu erori de încălcare a constrângerilor de unicitate (unique-constraint) dacă o rulare anterioară a introdus deja aceleași rânduri. bigintvsintîn teste —SELECT COUNT(*) FROM usersreturnează un șir de caractere; folosește conversia::intpentru a putea compara cuexpect(n).toBe(2).- Ordinea de execuție între directoare — fișierele sunt sortate după calea completă, deci
a/02-init.sqlrulează ÎNAINTE deb/01-init.sql. Pune un prefix și directoarelor atunci când ordinea contează între directoare diferite.