Salta ai contenuti

Aggiornare da 0.17 a 0.18

La 0.18.0 è pubblicata. Sono le voci ### Breaking della sua sezione del changelog, una alla volta, con ciò che ciascuna ti chiede di modificare. In 0.x è la minor a rompere, quindi questo è il muro tra la 0.17.3 e la 0.18.0: leggilo prima di aggiornare, non dopo.

Ognuna di esse è un errore di compilazione o un avvio rifiutato, non un cambio silenzioso di comportamento, tranne l’ultima, che riscrive un vincolo che il prossimo db push pianificherà per te.


Erano tre overload — Postgres, Firestore, MongoDB — e una chiamata errata produceva un’unica diagnostica su defineCollection(, che elencava il primo errore di ciascun overload. Ora c’è una sola firma, discriminata su engine (Postgres quando manca), e gli errori vengono segnalati sulla chiave sbagliata, tutti insieme.

Cosa cambiare: nulla, in una chiamata che già compilava. Cambia dove atterra la sottolineatura rossa. Con essa si sono spostati due export di tipo: UnknownPropertyKey ora si chiama NoSuchKey (e ha un membro didYouMean), e PropertyTypeNotOnThisEngine è nuovo. Entrambi sono meccanismi interni del builder, quindi solo il codice che importava il vecchio nome ha qualcosa da modificare.

21. defineCollection continua a controllare dopo la prima proprietà errata

Sezione intitolata “21. defineCollection continua a controllare dopo la prima proprietà errata”

Il builder vincolava la propria mappa di proprietà, e un vincolo che TypeScript non riesce a soddisfare è uno da cui ripiega in silenzio — così un singolo defaultValue errato allargava l’entità inferita a Record<string, unknown> e spegneva ogni controllo su display.title, listProperties, propertiesOrder e previewProperties.

Cosa cambiare: niente da scrivere, ma aspettati errori nuovi in file di collection che prima compilavano. Erano già sbagliati allora; il compilatore aveva smesso di guardare. Correggi la proprietà indicata dal primo errore e ricompila — il resto di quel file viene controllato per la prima volta.

22. Il campo di collegamento di una relazione deve appartenere al suo kind

Sezione intitolata “22. Il campo di collegamento di una relazione deve appartenere al suo kind”

Relation è un’unione chiusa dalla 0.11 — belongsTo possiede localKey, hasOne/hasMany possiedono foreignKeyOnTarget, manyToMany possiede through, via possiede joinPath — ma il controllo delle proprietà in eccesso veniva eseguito sull’unione nel suo complesso, quindi { kind: "belongsTo", foreignKeyOnTarget: "author_id" } compilava e poi si risolveva in un collegamento diverso da quello scritto.

Cosa cambiare: scrivi il campo di collegamento che quel tipo di relazione possiede.

author: {
type: "relation",
relation: { kind: "belongsTo", foreignKeyOnTarget: "author_id", target: () => authors }
relation: { kind: "belongsTo", localKey: "author_id", target: () => authors }
}

Il validatore di avvio le rifiutava già, quindi questo sposta la segnalazione da un deploy fallito a un errore di compilazione. Se il tuo progetto parte oggi, compila oggi.

23. La validation di una relazione sale sulla proprietà

Sezione intitolata “23. La validation di una relazione sale sulla proprietà”

RelationBase.validation e ResolvedRelationBase.validation sono rimossi. C’erano due posti dove scrivere required e due generatori che ne leggevano uno diverso: il DDL interrogava la proprietà (così la colonna risultava NOT NULL) mentre il generatore di tipi dell’SDK interrogava la relazione (così il tipo Insert generato rendeva il campo opzionale), e un create() che ometteva la relazione passava il controllo dei tipi e poi falliva sul database.

Cosa cambiare: spostala di un livello, accanto a quella di ogni altro campo.

author: {
type: "relation",
validation: { required: true },
relation: { kind: "belongsTo", validation: { required: true }, target: () => authors }
relation: { kind: "belongsTo", target: () => authors }
}

L’avvio rifiuta la vecchia chiave per nome anziché ignorarla. Il codice che chiedeva a una relazione se fosse obbligatoria ora usa import { isRelationRequired, relationDeclaringProperty } from "@rebasepro/common".

24. Un belongsTo obbligatorio cancella con RESTRICT, non CASCADE

Sezione intitolata “24. Un belongsTo obbligatorio cancella con RESTRICT, non CASCADE”

validation: { required: true } dice che il figlio non può esistere senza un padre. Non dice che eliminare il padre debba eliminare il figlio — ma è ciò che il generatore deduceva, quindi ogni DELETE FROM authors andava in cascata sui post, sui loro commenti e su tutto ciò che vi era appeso. Ora il valore predefinito è RESTRICT: l’eliminazione fallisce e indica il vincolo. Le relazioni opzionali non cambiano (SET NULL), e neppure la tabella di giunzione di un manyToMany (CASCADE — la riga che elimina è il collegamento).

Questa è una modifica DDL. Il prossimo rebase db push pianifica un DROP CONSTRAINT / ADD CONSTRAINT per ogni relazione obbligatoria che non ha mai indicato un onDelete, e dopo di essa le cancellazioni del padre iniziano a fallire dove prima andavano in cascata.

Cosa cambiare: per mantenere il comportamento precedente, scrivilo.

relation: { kind: "belongsTo", target: () => authors }
relation: { kind: "belongsTo", onDelete: "cascade", target: () => authors }

Poi leggi il piano prima di applicarlo — rebase db push stampa le istruzioni.

In 0.17.3 ogni pacchetto pubblicato dichiarava >=20 — @rebasepro/cli non dichiarava alcun engines — e su main tutti dichiarano >=22.22.0. L’unica fonte è il .nvmrc del repository.

Cosa cambiare: passa a Node 22.22.0 prima di aggiornare. pnpm install risponde a un disallineamento di engines con [WARN] Unsupported engine e installa comunque, quindi l’errore non arriva all’installazione: arriva dopo, in un punto in cui Node non viene mai nominato.

RebaseServerClient ha tolto data dal proprio tipo perché il codice lato server debba dire sotto quale identità gira una lettura, e la proprietà era poi rimasta sull’oggetto come alias a runtime. Ora viene cancellata al boot: rebase.data è undefined.

Cosa cambiare: nel codice server — funzioni, cron, callback — scrivi rebase.dataAsAdmin dove intendi il piano di amministrazione e context.data dove intendi quello del chiamante. Il codice tipizzato riceveva l’errore già dal cambio di tipo; quello che si rompe adesso è il codice non tipizzato, e l’ai-instructions.md di uno scaffold che dice ancora a un assistente di usare rebase.data.<slug> — rebase init riscrive quel file, quindi rigeneralo o correggi la regola a mano. Il codice browser non cambia: rebase.data nell’SDK tipizzato è il piano dell’utente e resta.

src/index.ts riesportava sedici moduli e metteva 95 nomi su npm. Ora esporta entry, manifest e bundle.

Cosa cambiare: nulla, a meno che tu non faccia import da @rebasepro/cli — cosa improbabile, dato che non lo facevano né questo repository né il control plane. Se lo fai, la CLI è un binario: invoca rebase <command> come processo invece di chiamare le sue funzioni di comando, le cui firme non sono mai state un contratto.

ui, forms, firebase, plugin-insights e cms-types dichiaravano react >=19.0.0, un intervallo la cui metà inferiore non può soddisfare app e cms a 19.2.7 — quindi un installer che sceglieva 19.0.0 produceva un albero che si risolveva pulito e si rompeva al render. Tutti e cinque dicono ^19.2.7. Il peer typescript di @rebasepro/app passa da >=5.0.0 a ^6.0.0.

Cosa cambiare: stai su React 19.2.7 o successivo, e su TypeScript 6 se usi il plugin Vite di @rebasepro/app. Se la tua installazione risolveva React 19.0.x vedrai ora un avviso di peer finché non sali di versione; quell’avviso è l’albero che stavi già eseguendo, detto ad alta voce.

29. rebase cloud webhooks create prende --endpoint

Sezione intitolata “29. rebase cloud webhooks create prende --endpoint”

--url nomina il control plane per tutti i comandi di questa famiglia, quindi il secondo --url che questo dichiarava per l’endpoint del cliente non poteva mai vincere: l’esempio documentato inviava l’URL del webhook al client come host su cui autenticarsi.

Cosa cambiare: rebase cloud webhooks create --endpoint https://… in ogni script che ne crea uno. La vecchia grafia non poteva funzionare, quindi non c’è comportamento da preservare — solo righe da correggere.

Il leaf encoder condiviso interpreta in modo permissivo, perché uno short code arriva dalla rete, ed emette in modo stretto, perché chi ne passa uno al serializzatore ha costruito la condizione a mano. serializeFilter({ a: ["gt", 5] }) solleva un errore invece di restituire gte.

Cosa cambiare: solo se chiami direttamente i serializzatori di @rebasepro/common. Usa i nomi di operatore che i tipi dichiarano (>, >=, <, <=, …) invece degli short code REST (gt, gte, …). I query builder e l’SDK li scrivevano già così; la novità è che la grafia sbagliata ora lo dice.


Avanti: la checklist di aggiornamento · 0.14 → 0.17, il passaggio precedente a questo · Changelog, le note di rilascio che queste sezioni riassumono.