Generazione dello Schema
Panoramica
Sezione intitolata “Panoramica”Rebase usa una pipeline schema-come-codice in cui le tue definizioni di collezioni TypeScript sono l’unica fonte di verità. La CLI le trasforma attraverso una pipeline deterministica:
Collections (TypeScript) → Drizzle Schema → SQL Migrations → PostgreSQLQuesta pagina copre ogni comando CLI coinvolto in quella pipeline.
La Pipeline
Sezione intitolata “La Pipeline”1. Collezioni → Schema Drizzle
Sezione intitolata “1. Collezioni → Schema Drizzle”Le tue definizioni di collezioni in config/collections/ descrivono tabelle, colonne, tipi, relazioni ed enum. Il comando schema generate le legge e produce un file di schema Drizzle ORM.
2. Schema Drizzle → Migrazioni
Sezione intitolata “2. Schema Drizzle → Migrazioni”Dallo schema Drizzle generato, db generate confronta con le migrazioni già presenti in backend/drizzle/migrations/, rieseguite su un database scratch, e produce file di migrazione SQL con timestamp. Non legge mai il tuo database: una colonna che l’avvio o db push hanno già aggiunto risulta comunque come ADD COLUMN.
3. Migrazioni → PostgreSQL
Sezione intitolata “3. Migrazioni → PostgreSQL”Il comando db migrate applica le migrazioni in sospeso al tuo database PostgreSQL.
Comandi
Sezione intitolata “Comandi”rebase schema generate
Sezione intitolata “rebase schema generate”Genera un file di schema Drizzle ORM dalle tue definizioni di collezioni:
rebase schema generateCosa fa:
- Legge tutte le collezioni da
config/collections/ - Genera
backend/src/schema.generated.tscon le definizioni di tabelle, enum e relazioni di Drizzle
Opzioni:
| Flag | Descrizione |
|---|---|
--collections, -c |
Directory delle collezioni (predefinito: config/collections/); i percorsi relativi vengono risolti dalla posizione in cui esegui il comando |
--output, -o |
Percorso di output per il file di schema generato; i percorsi relativi vengono risolti dalla posizione in cui esegui il comando |
--watch, -w |
Osservare le modifiche e rigenerare automaticamente |
La modalità watch è utile durante lo sviluppo — modifica un file di collezione e lo schema si rigenera istantaneamente:
rebase schema generate --watchrebase schema stale
Sezione intitolata “rebase schema stale”Verifica se lo schema generato corrisponde ancora alle collezioni:
rebase schema stale # report, and exit 1 if anything is stalerebase schema stale --fix # regenerate the file insteadCosa fa:
- Produce ciò che generano le collezioni in
config/collections/e lo confronta, dichiarazione per dichiarazione, conbackend/src/schema.generated.ts - Nomina ogni differenza — una tabella mancante, una colonna con tipo cambiato, un’etichetta di enum eliminata, o chiavi esterne nominate come le derivava una release precedente — ed esce con un codice diverso da zero
- Con
--fix, rigenera il file invece di riportare
rebase dev mantiene il file aggiornato da sé, quindi questo è il controllo per una build
o per un passaggio di CI. Accetta --collections e --output come rebase schema generate.
rebase schema introspect
Sezione intitolata “rebase schema introspect”Esegui il reverse engineering delle definizioni di collezioni da un database PostgreSQL esistente:
rebase schema introspectCosa fa:
- Si connette al database di questo progetto, quello che stampa
rebase db url(se è quello gestito, viene avviato);--database-urlne indica un altro e--dockerusa quello di compose - Ispeziona tutte le tabelle, colonne, tipi e chiavi esterne
- Genera i file di definizione delle collezioni
- Legge le policy di
row-level security di ogni tabella nelle
securityRulesdella sua collezione: nome, comando, modalità, elencoTO,USINGeWITH CHECK. Le policy<table>_default_*che Rebase aggiunge da sé restano fuori. Così ildb pushche segue ricrea ogni policy com’era. Su 0.24 le policy restano fuori dai file, e un push può eliminarne una il cui nome ha la forma di una policy generata (<table>_<op>_<hash>) - Legge ogni
espressione (il
USINGdi una policy, un CHECK, il default di una colonna) con ilsearch_pathche usa il server,public, così una funzione nello schemarebaseviene scrittarebase.roles(). Con una connessione come ruolo chiamatorebase, il percorso predefinito metteva quello schema per primo e la regola tornava comeroles(), che il push non riusciva a trovare - Mantiene le policy di una giunzione
many-to-many. Le policy
<junction>_default_edge_write_*di una giunzione derivano dalle regole di aggiornamento della collezione che dichiara la relazione, e una giunzione può ereditare solo una regola che sa leggere. Una regola di ruolo torna come l’SQL che Postgres memorizza per essa,string_to_array(rebase.roles(), ','::text) && ARRAY['admin'::text], e questo si legge di nuovo come la regola di ruolo, quindi il push deriva le stesse policy. Su 0.25.0 veniva letta come SQL grezzo: il dry run elencava le tre policy come policy che nessuna collezione descrive, il push le lasciava in vigore, e una modifica successiva alla regola non le raggiungeva più - Scrive
disableDefaultPolicies: truesu una tabella che ha la row-level security attiva e non possiede l’intera baseline admin, così il push non aggiunge alcuna policy<table>_default_admin_*e l’accesso alla tabella resta com’era; qualsiasi parte della baseline che la tabella ha viene scritta come regola. Elimina la riga per dare al server e agli admin ogni riga. Una tabella con la RLS disattivata mantiene la baseline, e l’introspezione dice, una sola volta, quali sono: il push attiva la RLS qualunque cosa dica una collezione. Su 0.24 il push dopo un’introspezione aggiungeva la baseline a ogni tabella - Genera come entità nella
navigazione una tabella le cui policy danno a ogni utente le proprie righe (leggono
rebase.uid(),app.uido il JWT), per quanto poche righe abbia. Su 0.24 una tabella piccola è un elenco di codici, e una tabella posseduta tramite un’altra è nascosta come suo figlio - Contro un database non in
esecuzione, stampa una sola volta lo stesso banner di
db pushe non crea nulla. Stampa la directory di output come percorso assoluto - Lascia nel database i vincoli CHECK ed EXCLUDE di
una tabella, e il
db pushsuccessivo li mantiene. Una collezione non può dichiarare né gli uni né gli altri; un CHECK che l’introspezione sa leggere (total >= 0) diventa anche lavalidationdella proprietà. Su 0.24 quel push li eliminava
Opzioni:
| Flag | Descrizione |
|---|---|
--output, -o |
Directory di output per i file di collezione generati |
--schema |
Lo schema Postgres da leggere (predefinito: public) |
--force, -f |
Sovrascrive i file di collezione già esistenti; senza, un file esistente viene saltato |
--database-url |
Legge questo database invece di quello del progetto |
--docker |
Legge il database di compose, avviandolo se necessario |
--data-inference / --no-data-inference |
Campiona fino a 100 righe per tabella per rilevare formati, vincoli e impostazioni dell’interfaccia, oppure legge solo la struttura. Senza nessuno dei due lo chiede, e senza un terminale legge solo la struttura |
Questo è utile quando si adotta Rebase su un database esistente — prima esegui l’introspezione, poi personalizza le collezioni generate.
Introspezione, poi push, non cambia nulla. Le proprietà generate dicono esattamente cos’è ogni colonna — columnType, precision/scale, defaultValue, required, l’isId di una chiave ("increment" per un’identity intera, columnType: "serial" per una serial, "manual" per una chiave senza default), l’onDelete di una relazione — e il suo index: false dove al database manca l’indice che Rebase deriverebbe sulla colonna della chiave, dato che un belongsTo è indicizzato per impostazione predefinita. Dove nessun indice serve la colonna, la riga lo dice (eliminala per farne costruire uno); dove un altro indice inizia già con essa (orders_customer_id_idx, uno composito, uno univoco), la riga nomina quell’indice, e senza quella riga il push ne costruirebbe un secondo. Su 0.24 diceva di eliminare la riga in ogni caso — e il blocco search di una collezione letto a ritroso dalla colonna che ha costruito — quindi rebase db push --dry-run eseguito subito dopo un’introspezione non pianifica alcuna modifica. L’eccezione è una tabella con la row-level security disattivata: il push la attiva, e il dry run lo elenca insieme alla baseline admin che aggiunge. Dove nessuna proprietà può rappresentare una colonna — un timestamp senza time zone, un interval, un inet, un tipo enum che non si chiama <table>_<column>, un default come CURRENT_DATE — l’introspezione lo segnala, colonna per colonna, sul terminale e in testa al file, con ciò che un push le farebbe e, quando esiste, l’istruzione che fa coincidere le due cose (ALTER TYPE "mood" RENAME TO "customers_current_mood";). Una tabella con chiave su più di una colonna torna come una chiave composita, con il suo isId su ogni colonna della chiave. Viene esclusa, con il relativo motivo, quando una colonna della chiave non può portare isId (un timestamp, per esempio) o la chiave esterna di un’altra tabella punta a essa, cosa che una relazione su una sola colonna non può fare; db push lascia stare una tabella che non è una collezione. Sulla 0.23 il push eseguito subito dopo un’introspezione può ancora pianificare cambi di tipo, default rimossi e NOT NULL, e una chiave id fantasma.
Come sono fatti i file generati
L’introspezione scrive le collezioni con defineCollection, che mantiene le chiavi delle proprietà letterali — così propertiesOrder, listProperties, sort e display.title si completano sui nomi delle tue colonne, e una chiave rimasta dopo la ridenominazione di una colonna è un errore di compilazione anziché una riga che silenziosamente non fa nulla. Quale importare dipende da ciò da cui dipende il tuo progetto, ed è deciso a ogni esecuzione:
| Il tuo progetto dichiara | Le collezioni generate usano | Blocco admin |
|---|---|---|
@rebasepro/cms-types (un progetto con il pannello) |
defineCollection da @rebasepro/cms-types |
sì |
@rebasepro/common (un progetto --headless) |
defineCollection da @rebasepro/common |
no |
| nessuno dei due | un’annotazione PostgresCollectionConfig, con un avviso |
no |
Un progetto headless non ha un pannello di amministrazione, e i tipi core non dichiarano alcun campo admin: per questo il blocco lì non viene emesso. È presentazione (icon, propertiesOrder, multiline); nulla nello schema, nell’API o nei tuoi dati ne dipende.
rebase db push
Sezione intitolata “rebase db push”Applica le modifiche allo schema direttamente al database senza file di migrazione:
rebase db pushCosa fa:
- Legge lo schema Drizzle generato
- Applica le modifiche direttamente al database (CREATE, ALTER, DROP)
- Esegue prima il piano in modalità dry run e si ferma prima di tutto ciò che distrugge dati: una tabella, colonna, schema, vista o tipo eliminati, un
TRUNCATE, un cambio di tipo di colonna che può perdere valori (timestamptz→date,numeric→integer), o un cambio di chiave primaria:(id)→(id, locale)dà a ogni riga un nuovo id, così link, chiavi esterne e id salvati altrove non trovano più la loro riga. Si ferma anche prima dell’eliminazione di un vincolo CHECK o EXCLUDE che il database contiene: nessuna riga va persa, ma da quel momento il database accetta righe che rifiutava. In un terminale chiede conferma, dove Ctrl-C o Ctrl-D rispondono no, altrimenti rifiuta;--allow-destructiveapplica comunque la modifica. Anche--yeslo fa ancora in questa release, con un avviso di deprecazione; dalla prossima release approverà solo i push che non distruggono nulla. Un push che si ferma lì elimina all’uscita il proprio database di appoggio<db>_dev_diff - Attiva la sicurezza a livello di riga su ogni tabella di collezione, tabelle di giunzione comprese, subito dopo la modifica dello schema e prima di qualsiasi passaggio che possa fallire: un push che si interrompe a metà lascia una nuova tabella che nega ogni richiesta invece che aperta a tutte
- Applica le policy RLS delle tue collezioni e rimuove le policy sostituite da un push precedente
- Lascia com’è ogni vincolo CHECK ed EXCLUDE sulla
tabella di una collezione. Una collezione non può dichiarare né gli uni né gli altri, quindi sono
regole proprie del database, scritte a mano o portate da un database che
schema introspectha adottato; per rimuoverne uno, eliminalo a mano (ALTER TABLE … DROP CONSTRAINT …). Anche i trigger e le funzioni che hai scritto non vengono toccati. Su 0.24 il primo push dopo un’introspezione eliminava ogni vincolo CHECK ed EXCLUDE senza chiedere conferma - Riconosce per nome esatto tutto ciò che lascia
stare, compreso un
.,[,]o*al suo interno. Su 0.24 un indice scritto a mano con un nome comeorders_idx[v1]veniva eliminato senza conferma, e un.nel nome di una tabella o di un indice faceva fallire ogni push contoo many parts in pattern - Costruisce ogni
indice di chiave esterna che Rebase deriva
e che a una tabella esistente manca prima di pianificare, con
CREATE INDEX CONCURRENTLY, così le scritture sulla tabella proseguono durante la build; Atlas lo trova poi già al suo posto.--dry-runli nomina e non costruisce nulla - Marca le policy che applica nello stesso modo dell’avvio del server, così il primo avvio dopo un push le lascia stare invece di ricreare ognuna
--dry-runelenca la row-level security che il push cambierebbe, sotto “Planned row-level security changes”: le tabelle su cui attiva la RLS, e ogni policy che crea, sostituisce o elimina, calcolate nello stesso modo in cui le decidono i passaggi del push stesso. Dice “No changes” solo quando non cambierebbero né lo schema né la row-level security. Dove la marcatura di una policy non corrisponde alla sua regola, o la policy non ne ha (una creata dadb migrate, una scritta a mano), il dry run la ricrea dalla sua regola con un altro nome, in una transazione che annulla, e confronta ciò che Postgres ha memorizzato: una che risulta uguale non è una modifica. Così una regola cheschema introspectha riletto come SQL non pianifica nulla, e nemmeno le policy applicate dadb migrate. Solo una che non ha potuto confrontare (per esempio, il lock della sua tabella non concesso entro due secondi) è elencata a parte. Il push stesso stampa una riga che conta le modifiche. Su 0.24 il dry run mostrava solo il piano di Atlas, che non contiene policy- Mostra una sola volta
ogni istruzione che Atlas applica. Atlas si connette senza SSL a un database su questa
macchina (
localhost,127.x,::1) il cui URL non indica alcunsslmode, come fa l’app, invece di fallire conSSL is not enabled on the server; un URL che indicasslmode, o un altro host, viene passato così com’è scritto. Un’esecuzione di Atlas che fallisce prima di pianificare non lascia dietro di sé alcun database<db>_dev_diff --dry-runnon scrive nulla del progetto:src/schema.generated.tsresta com’è, e le copiedrizzle/*.sqlche una release precedente aveva committato vengono nominate, non eliminate. Solo l’input del piano va in.rebase/sql/, che non viene committato- Non crea file di migrazione
Quanto tempo richiede. Quasi tutto di un push è Atlas che calcola il piano: costruisce lo schema desiderato in un database scratch e lo confronta con quello reale, e quel costo cresce più in fretta del numero di tabelle — su un laptop tranquillo circa 0,25 s per piano con 11 tabelle, 0,9 s con 111 e 5,5 s con 411. Un push che non cambia nulla pianifica una volta; uno che cambia qualcosa pianifica due volte (il dry-run che legge il gate delle modifiche distruttive, poi l’applicazione). Quindi un push su uno schema di 400 o più tabelle richiede decine di secondi, e di più su una macchina occupata o lenta. Quel tempo è di Atlas, non del tuo database: i passaggi intorno — generare l’SQL, il lock RLS, la ricerca, i trigger, le policy, il ruolo — richiedono pochi secondi a quella dimensione, su una sola connessione al tuo database.
I file che genera lungo il percorso, tutti sotto .rebase/sql/ nella directory del backend. db push e db generate scrivono tutti e cinque a partire dalle tue collezioni a ogni esecuzione, prima di leggerne uno qualsiasi, quindi una copia committata non verrebbe letta da nulla. La directory ha il proprio .gitignore e non viene mai committata.
| File | Contiene |
|---|---|
schema.sql |
Tabelle, colonne, vincoli e indici — lo stato desiderato di Atlas, e l’unico che confronta |
policies.sql |
Le policy RLS in cui vengono compilate le tue securityRules |
search.sql |
Le funzioni di ricerca full-text e le colonne generate, per le collezioni con un blocco search |
vector.sql |
Le estensioni pgvector e gli indici ANN |
triggers.sql |
rebase.set_updated_at() e i trigger BEFORE UPDATE dietro autoValue: "on_update" |
Atlas gestisce il primo e nient’altro, quindi db push e l’allineamento dello schema all’avvio applicano da soli gli altri quattro. Un deployment solo con migrazioni — uno che esegue db migrate e mai db push — deve includere quei quattro in una migrazione a mano; db generate lo segnala quando una modifica è invisibile ad Atlas.
Se un progetto ha committato questi file in drizzle/ con una release precedente, quelle copie vengono eliminate alla prima esecuzione, e il comando le nomina una per una così puoi committare l’eliminazione. Elimina solo i file che iniziano con l’intestazione del generatore. Un file che hai scritto tu resta, così come drizzle/migrations/.
rebase db generate
Sezione intitolata “rebase db generate”Genera file di migrazione SQL dalle modifiche allo schema:
rebase db generateCosa fa:
- Confronta lo schema Drizzle con lo stato che costruiscono le migrazioni in
drizzle/migrations/, non con il tuo database - Produce file di migrazione SQL con timestamp in
backend/drizzle/migrations/ - I file possono essere revisionati, modificati e committati nel controllo di versione
- Nomina ogni istruzione della nuova
migrazione che distrugge dati, usando il controllo che
db pushesegue prima di applicare: una tabella, colonna, schema, vista o tipo eliminati, unTRUNCATE, un cambio di tipo di colonna che può perdere valori, una modifica della chiave primaria, o l’eliminazione di un vincolo CHECK o EXCLUDE che il database contiene. Scrive comunque il file ed esce con 0, quindi avvisa e non rifiuta. - Termina con che cosa
fare dopo:
rebase db migratee, per la prima migrazione di un progetto, il--baseline <version>di cui ha bisogno invece un database che l’avvio ha già preparato. Una migrazione successiva non riceve alcuna riga di baseline, poiché una distruttiva registrata con la baseline salterebbe il suoDROP, e un’esecuzione che non scrive alcuna migrazione dice solo questo.
Un CHECK aggiunto da una tua migrazione viene eliminato dalla successiva. db generate
confronta i tuoi file di migrazione, non il database, e Atlas non ha modo di escludere un
oggetto da quel confronto. Quindi un vincolo CHECK o EXCLUDE che hai scritto a mano in una
migrazione, e che nessuna collezione può dichiarare, ritorna come
ALTER TABLE … DROP CONSTRAINT … nella migrazione successiva che scrive, fuso nella stessa
istruzione della modifica vera e propria. Il rapporto qui sopra nomina quell’eliminazione quando
il database contiene già il vincolo; non la toglie dal file. Elimina la clausola prima di
rebase db migrate, oppure lascia che rebase db migrate --refuse-destructive si fermi su di
essa. db push legge il database e mantiene il vincolo.
Le migrazioni generate sono semplici file SQL — puoi ispezionarle e modificarle prima di applicarle.
rebase db migrate
Sezione intitolata “rebase db migrate”Esegui tutte le migrazioni in sospeso:
rebase db migrateCosa fa:
- Legge
drizzle/migrations/per le migrazioni non applicate - Le applica in ordine al database
- Tiene traccia di quali migrazioni sono state applicate
- Marca le
policy di row-level security nello stesso modo di
db pushe dell’avvio del server, così il primo avvio dopo un migrate le lascia stare invece di ricreare ognuna. Una migrazione è stata scritta a partire dalle collezioni del suo tempo, quindi una policy viene marcata solo quando è esattamente ciò che la sua regola produce adesso: migrate la ricrea dalla sua regola con un altro nome, in una transazione che annulla, e confronta ciò che Postgres ha memorizzato, come fadb push --dry-run. Una policy che differisce non riceve alcuna marcatura, e il successivo avvio riapplica la sua tabella
--refuse-destructive
la fa invece rifiutare. Prima esegue una prova a secco (dry run) delle migrazioni in sospeso. Se
un’istruzione distrugge dati, con lo stesso controllo usato da db push e db generate, elenca
quelle istruzioni ed esce con 1. Non applica nulla, nemmeno i file
precedenti a quell’istruzione. Senza il flag, db migrate si comporta come prima e
applica ogni file in sospeso:
rebase db migrate --refuse-destructiveUna migrazione che ricostruisce una colonna di ricerca la elimina prima, quindi questo flag rifiuta
anche quella migrazione. Leggi l’elenco che stampa, poi esegui rebase db migrate
senza il flag per applicarla.
Impostare una baseline su un database che Rebase ha già avviato
Sezione intitolata “Impostare una baseline su un database che Rebase ha già avviato”Ogni avvio di Rebase assicura lo schema, e rebase db push lo applica direttamente. Un database su cui uno dei due sia mai stato eseguito ha quindi già le tabelle e i tipi che la prima migrazione creerebbe, e rebase db migrate si ferma su pq: type "posts_status" already exists (42710).
Nella migrazione non c’è nulla di sbagliato: il database è stato predisposto in un altro modo. Registrate dove si trova già, poi migrate normalmente:
rebase db migrate --baseline 20260906101530rebase db migrateLa versione è il prefisso numerico del file di migrazione che descrive ciò che c’è nel database adesso. Quella migrazione e tutte le precedenti risultano applicate; tutto ciò che viene dopo viene eseguito. Su un database che non è mai stato avviato non serve alcuna baseline: migrate direttamente.
Lo stesso accade più avanti nel ciclo ordinario: modifica una collezione mentre rebase dev è in esecuzione, e l’avvio aggiunge la colonna prima che rebase db generate scriva la migrazione che la aggiunge, così rebase db migrate si ferma su column … already exists (42701). Imposta la baseline di quella migrazione allo stesso modo. --baseline funziona su un database che registra già delle migrazioni: segna come applicato tutto fino alla versione con atlas migrate set, e lo dice, oppure dice che non c’è nulla da registrare quando la cronologia la raggiunge già. Su 0.24 Atlas ignora --baseline una volta registrata una qualsiasi migrazione, quindi lo stesso errore ritorna. Una versione che non corrisponde ad alcun file in drizzle/migrations viene rifiutata prima di eseguire qualsiasi cosa, e il messaggio nomina le versioni presenti.
rebase db branch
Sezione intitolata “rebase db branch”Branching del database per lo sviluppo parallelo:
rebase db branch create feature_authrebase db branch switch feature_authrebase db branch listrebase db branch switch --off
rebase db branch info feature_authrebase db branch delete feature_authrebase db branch switch (e switch --off) e rebase db branch prune sono
novità. create, list, info e delete sono stati rilasciati nella 0.17.
Ogni branch è una copia completa del database creata con CREATE DATABASE ... TEMPLATE,
quindi richiede un vero server PostgreSQL e occupa lo stesso spazio su disco della sua origine.
rebase doctor
Sezione intitolata “rebase doctor”Rileva la deriva a tre vie tra le tue definizioni di collezioni, lo schema Drizzle generato e il database PostgreSQL in esecuzione:
rebase doctorCosa controlla:
- Collezioni ↔ Schema generato — sono sincronizzati?
- Schema generato ↔ Database — ci sono modifiche non applicate?
- Collezioni ↔ Database — c’è qualche deriva imprevista?
Esegui doctor ogni volta che qualcosa sembra non sincronizzato. Individua esattamente dove si trova la discrepanza.
Il confronto con il database include quello che l’avvio esegue prima di avvisare che schema.generated.ts e il database non concordano, eseguito tramite lo stesso codice. Così ogni differenza di cui l’avvio avvisa è anche nel rapporto, con le stesse parole: una colonna che è NOT NULL da una parte e nullable dall’altra, e una colonna che il database ha ancora e il file no (l’avvio non ne elimina mai una, quindi una proprietà rinominata lascia indietro la sua vecchia colonna). Ognuna è un avviso, e la correzione nomina rebase db push.
Il confronto con il database legge il database del progetto, risolto come lo risolve rebase db url — su uno scaffold appena creato quello gestito, che doctor avvia. Quando non se ne può risolvere nessuno, quella fase viene riportata come saltata anziché superata, e l’esecuzione non si chiude mai con “All schemas are in sync”: un controllo che non è avvenuto non è un certificato di buona salute.
Nomina anche ogni collezione priva di un blocco search la cui tabella contiene più di circa 10.000 righe. Una ricerca lì — la casella di ricerca dell’admin, .search(), ?searchString= — è un ILIKE '%term%' sulle colonne di testo, che nessun indice può servire, quindi ognuna legge l’intera tabella, e il suo conteggio la legge di nuovo (circa un terzo di secondo a 100.000 righe, in crescita con la tabella). Il numero di righe è la stima di Postgres stesso, quindi il controllo non scansiona nulla. È un suggerimento: non cambia il codice di uscita, e nulla viene indicizzato per te.
Nomina una giunzione orfana: una tabella public con la forma di una giunzione many-to-many che nessuna collezione dichiara. La forma è due colonne che insieme formano la chiave primaria, ciascuna una chiave esterna verso la tabella di una collezione. Rinominare o rimuovere una manyToMany lascia indietro la vecchia giunzione, perché push e avvio creano soltanto tabelle, e ogni riga di collegamento è ancora al suo interno. La nota è solo informativa, quindi non cambia il codice di uscita. La correzione è l’istruzione DROP TABLE, che doctor mostra e non esegue mai.
rebase generate-sdk
Sezione intitolata “rebase generate-sdk”Genera un SDK tipizzato dalle tue definizioni di collezioni:
rebase generate-sdkCosa fa:
- Legge ogni file di collezione in
config/collections/— i file che il backend serve, che siano elencati o no nel barrelindex.ts— e si interrompe su uno che non si carica - Genera tipi TypeScript per tutte le entità in
generated/sdk/ - Produce un file
database.types.tsda usare concreateRebaseClient<Database>()
rebase dev lo esegue per te all’avvio e a ogni salvataggio sotto config/collections/. Eseguilo tu stesso in CI, in un repository che non ha collezioni (vedi --from più sotto), o ovunque rebase dev non sia in esecuzione.
Sulla 0.23 il comando legge solo i file elencati dal barrel index.ts, salta con un
avviso quello che non si carica, e accetta la directory come --collections-dir; e
rebase dev rigenera solo lo schema, quindi rigenerare i tipi dell’SDK spetta a te.
Opzioni:
| Flag | Descrizione |
|---|---|
-c, --collections |
Directory delle collezioni (predefinito: config/collections/); i percorsi relativi vengono risolti dalla posizione in cui esegui il comando. Anche --collections-dir è accettato. |
-o, --output |
Directory di output per l’SDK (predefinito: generated/sdk/) |
--from <link|url> |
Legge lo schema da un progetto in esecuzione anziché dal codice locale. link usa il progetto collegato a questo checkout. |
--token |
Token Bearer per l’endpoint del contratto (predefinito: $REBASE_SERVICE_KEY dalla shell; .env non viene letto) |
--from è ciò che permette a un repository privo di collezioni — un frontend separato, una seconda web app, un’app mobile — di generare un client tipizzato dal progetto con cui parla. REBASE_SERVICE_KEY viene inviato solo al progetto collegato a questo checkout; per qualsiasi altro host, passa --token esplicitamente. La chiave in
.env appartiene al tuo backend locale e non viene mai inviata.
Un rifiuto dice quale di queste
cose è successa: un --token rifiutato, una chiave della shell rifiutata, una chiave
trattenuta per un host non collegato, una chiave presente solo in .env, oppure nessuna
chiave. Su 0.24 dice sempre di passare --token o di impostare REBASE_SERVICE_KEY.
Utilizzo dopo la generazione:
import { createRebaseClient } from "@rebasepro/client";import { collectionsDictionary, type Database } from "./generated/sdk/database.types";
const client = createRebaseClient<Database>({ baseUrl: import.meta.env.VITE_API_URL, collections: collectionsDictionary,});
// Full type safety and autocompleteconst { data } = await client.data.products.find();I nomi dei campi nei tipi generati sono quelli che l’API serve. Il nome di un campo sul filo
è la chiave della sua proprietà, e l’API è camelCase ovunque: l’introspezione genera una
colonna created_at come proprietà createdAt con columnName: "created_at", e la serve
come row.createdAt. La colonna in sé non viene toccata. L’accessor della collezione
diventa un nome di proprietà allo stesso modo (my-notes → client.data.myNotes), ed è
questo che collectionsDictionary rimappa sullo slug.
Flusso di Lavoro di Sviluppo
Sezione intitolata “Flusso di Lavoro di Sviluppo”Il flusso di lavoro a iterazione rapida per lo sviluppo:
# 1. Edit your collection in config/collections/# 2. Generate the Drizzle schemarebase schema generate
# 3. Push directly to dev databaserebase db pushFlusso di Lavoro di Produzione
Sezione intitolata “Flusso di Lavoro di Produzione”Il flusso di lavoro sicuro e revisionabile per la produzione:
# 1. Edit your collection in config/collections/# 2. Generate the Drizzle schemarebase schema generate
# 3. Generate SQL migration filesrebase db generate
# 4. Review the generated SQL in backend/drizzle/migrations/# 5. Commit the migration to version controlgit add backend/drizzle/migrations/
# 6. Apply in production# A database Rebase has already booted needs a baseline the first time —# see "Baselining a database Rebase has already booted" above.rebase db migrateRisoluzione dei Problemi
Sezione intitolata “Risoluzione dei Problemi”| Sintomo | Soluzione |
|---|---|
Could not detect an active database plugin |
Installa @rebasepro/server-postgres in backend/package.json |
| Il file di schema non si aggiorna | Controlla che il percorso --collections punti alla directory corretta |
| La migrazione mostra modifiche impreviste | Esegui rebase doctor per identificare la deriva |
db push fallisce in produzione |
Usa db generate + db migrate invece |
| Una migrazione non deve eliminare dati in CI o in produzione | rebase db migrate --refuse-destructive esce con 1 e non applica nulla quando un’istruzione in sospeso distrugge dati |
db migrate fallisce con already exists (42710) |
L’avvio o db push hanno già predisposto lo schema — registratelo con rebase db migrate --baseline <version> |
db migrate fallisce con column … already exists (42701) |
rebase dev ha aggiunto la colonna all’avvio — imposta la baseline di quella migrazione allo stesso modo |
db push sul database gestito fallisce con Error: EOF |
Atlas ha perso una connessione che tiene il rebase dev in esecuzione. Riesegui; se continua a fallire, ferma prima rebase dev |
Prossimi Passi
Sezione intitolata “Prossimi Passi”- Collezioni — Definisci il tuo modello di dati
- Riferimento CLI — Tutti i comandi CLI
- SDK tipizzato — Usa l’SDK generato