Salta ai contenuti

Astro DB

Astro DB è un database SQL completamente gestito progettato esclusivamente per Astro. Sviluppa localmente o connettiti a un database ospitato gestito sulla nostra piattaforma Astro Studio.

Aggiungi Astro DB a un nuovo o esistente progetto Astro (richiede astro@4.5 o successivo) con l’integrazione @astrojs/db (v0.8.0 o successivo). Astro include un comando integrato astro add per automatizzare questo processo di configurazione per te.

Terminal window
npx astro add db

Se preferisci, puoi installare @astrojs/db manualmente invece.

Astro DB è una soluzione completa per configurare, sviluppare e interrogare i tuoi dati. Un database locale viene creato ogni volta che esegui astro dev, utilizzando LibSQL per gestire i tuoi dati senza la necessità di Docker o di una connessione di rete.

Installare @astrojs/db con il comando astro add creerà un file db/config.ts nel tuo progetto dove definirai le tabelle del tuo database:

db/config.ts
import { defineDb } from 'astro:db';
export default defineDb({
tables: { },
})

I dati in Astro DB sono memorizzati utilizzando tabelle SQL. Le tabelle strutturano i tuoi dati in righe e colonne, dove le colonne impongono il tipo di ogni valore di riga.

Quando definisci una tabella, Astro genererà un’interfaccia TypeScript per interrogare quella tabella dal tuo progetto. Il risultato è un supporto completo di TypeScript quando accedi ai tuoi dati con il completamento automatico delle proprietà e type-checking.

Per configurare una tabella del database, importa e utilizza le utility defineTable() e column da astro:db.

Questo esempio configura una tabella Comment con colonne di testo obbligatorie per author e body. Quindi, rendila disponibile al tuo progetto attraverso l’esportazione defineDb().

db/config.ts
import { defineDb, defineTable, column } from 'astro:db';
const Comment = defineTable({
columns: {
author: column.text(),
body: column.text(),
}
})
export default defineDb({
tables: { Comment },
})
Vedi il riferimento alla configurazione delle tabelle per un riferimento completo delle opzioni delle tabelle.

Astro DB supporta i seguenti tipi di colonne:

db/config.ts
import { defineTable, column } from 'astro:db';
const Comment = defineTable({
columns: {
// Una stringa di testo.
author: column.text(),
// Un valore intero.
likes: column.number(),
// Un valore vero o falso.
flagged: column.boolean(),
// Valori di data/ora interrogati come oggetti Date JavaScript.
published: column.date(),
// Un oggetto JSON non tipizzato.
metadata: column.json(),
}
});
Consulta il riferimento delle colonne delle tabelle per ulteriori dettagli.

Le relazioni tra tabelle sono un modello comune nella progettazione dei database. Ad esempio, una tabella Blog può essere strettamente correlata ad altre tabelle di Comment, Author e Category.

Puoi definire queste tabelle di relazioni e salvarle nel tuo schema di database utilizzando colonne di riferimento. Per stabilire una relazione, avrai bisogno di:

  • Una colonna identificativa sulla tabella di riferimento. Solitamente si tratta di una colonna id con la proprietà primaryKey.
  • Una colonna sulla tabella base per memorizzare l’id di riferimento. Questo utilizza la proprietà references per stabilire una relazione.

Questo esempio mostra la colonna authorId di una tabella Comment che fa riferimento alla colonna id di una tabella Author.

db/config.ts
const Author = defineTable({
columns: {
id: column.number({ primaryKey: true }),
name: column.text(),
}
});
const Comment = defineTable({
columns: {
authorId: column.number({ references: () => Author.columns.id }),
content: column.text(),
}
});

In fase di sviluppo, Astro utilizzerà la tua configurazione DB per generare tipi locali in base ai tuoi schemi. Questi verranno generati nuovamente ogni volta che il server di sviluppo viene avviato e ti permetteranno di interrogare e lavorare con la forma dei tuoi dati con sicurezza dei tipi e autocompletamento.

Per popolare dati di sviluppo per test e debug nel tuo progetto Astro, crea un file db/seed.ts. Importa sia l’oggetto db che qualsiasi tabella configurata da astro:db. Usa la funzione db.insert() per fornire un array di oggetti di dati di righe di tabella.

L’esempio seguente definisce due righe di dati di sviluppo per una tabella Comment:

db/seed.ts
import { db, Comment } from 'astro:db';
export default async function() {
await db.insert(Comment).values([
{ authorId: 1, body: 'Spero ti piaccia Astro DB!' },
{ authorId: 2, body: 'Divertiti!'},
])
}

Il tuo server di sviluppo riavvierà automaticamente il tuo database ogni volta che questo file cambia, rigenerando i tuoi tipi e popolando i tuoi dati di sviluppo da seed.ts.

Puoi interrogare il tuo database da qualsiasi pagina Astro o endpoint nel tuo progetto utilizzando l’ORM db fornito e il costruttore di query.

import { db } from 'astro:db';

Astro DB include un client Drizzle ORM integrato. Non è necessaria alcuna configurazione o impostazione manuale per utilizzare il client. Il client db di Astro DB è automaticamente configurato per comunicare con il tuo database (locale o remoto) quando esegui Astro. Utilizza la tua esatta definizione dello schema del database per query SQL type-safe con errori TypeScript quando fai riferimento a una colonna o tabella che non esiste.

L’esempio seguente seleziona tutte le righe di una tabella Comment. Questo restituisce l’intero array di dati di sviluppo popolati da db/seed.ts che è quindi disponibile per l’uso nel tuo template di pagina:

src/pages/index.astro
---
import { db, Comment } from 'astro:db';
const comments = await db.select().from(Comment);
---
<h2>Commenti</h2>
{
comments.map(({ author, body }) => (
<article>
<p>Autore: {author}</p>
<p>{body}</p>
</article>
))
}
Vedi il riferimento all’API select() di Drizzle per una panoramica completa.

Per accettare input dell’utente, come gestire richieste di form e inserire dati nel tuo database ospitato remoto, configura il tuo progetto Astro per la rendering on-demand e aggiungi un adattatore SSR per il tuo ambiente di distribuzione.

Questo esempio inserisce una riga in una tabella Comment in base a una richiesta POST di un form analizzata:

src/pages/index.astro
---
import { db, Comment } from 'astro:db';
if (Astro.request.method === 'POST') {
// analizza i dati del form
const formData = await Astro.request.formData();
const author = formData.get('author');
const content = formData.get('content');
if (typeof author === 'string' && typeof content === 'string') {
// inserisci i dati del form nella tabella Comment
await db.insert(Comment).values({ author, content });
}
}
// renderizza la nuova lista di commenti ad ogni richiesta
const comments = await db.select().from(Comment);
---
<form method="POST" style="display: grid">
<label for="author">Autore</label>
<input id="author" name="author" />
<label for="content">Contenuto</label>
<textarea id="content" name="content"></textarea>
<button type="submit">Invia</button>
</form>
<!--renderizza `comments`-->

Puoi anche interrogare il tuo database da un endpoint API. Questo esempio elimina una riga da una tabella Comment tramite il parametro id:

src/pages/api/comments/[id].ts
import type { APIRoute } from "astro";
import { db, Comment, eq } from 'astro:db';
export const DELETE: APIRoute = async (ctx) => {
await db.delete(Comment).where(eq(Comment.id, ctx.params.id ));
return new Response(null, { status: 204 });
}

Vedi il riferimento all’API insert() di Drizzle per una panoramica completa.

Per interrogare i risultati delle tabelle per una proprietà specifica, usa le opzioni Drizzle per selezioni parziali. Ad esempio, aggiungi una chiamata .where() alla tua query select() e passa il confronto che vuoi fare.

L’esempio seguente interroga tutte le righe in una tabella Comment che contengono la frase “Astro DB”. Usa l’operatore like() per verificare se una frase è presente all’interno del body:

src/pages/index.astro
---
import { db, Comment, like } from 'astro:db';
const comments = await db.select().from(Comment).where(
like(Comment.body, '%Astro DB%')
);
---

Tutte le utilità Drizzle per costruire query sono esposte dal modulo astro:db. Questo include:

import { eq, gt, count, sql } from 'astro:db';

Puoi interrogare dati correlati da più tabelle utilizzando un join SQL. Per creare una query di join, estendi la tua dichiarazione db.select() con un operatore di join. Ogni funzione accetta una tabella con cui unirsi e una condizione per abbinare le righe tra le due tabelle.

Questo esempio utilizza una funzione innerJoin() per unire gli autori dei Comment con le loro informazioni Author correlate in base alla colonna authorId. Questo restituisce un array di oggetti con ogni riga Author e Comment come proprietà di primo livello:

src/pages/index.astro
---
import { db, eq, Comment, Author } from 'astro:db';
const comments = await db.select()
.from(Comment)
.innerJoin(Author, eq(Comment.authorId, Author.id));
---
<h2>Commenti</h2>
{
comments.map(({ Author, Comment }) => (
<article>
<p>Autore: {Author.name}</p>
<p>{Comment.body}</p>
</article>
))
}

Vedi il riferimento join di Drizzle per tutti gli operatori di join disponibili e le opzioni di configurazione.

Tutte le query al database remoto vengono effettuate come una richiesta di rete. Potresti aver bisogno di “raggruppare” le query insieme in una singola transazione quando effettui un gran numero di query, o per avere rollback automatici se una query fallisce.

Questo esempio inserisce più righe in una singola richiesta utilizzando il metodo db.batch():

db/seed.ts
import { db, Author, Comment } from 'astro:db';
export default async function () {
const queries = [];
// Inserisci 100 commenti di esempio nel tuo database remoto
// con una singola richiesta di rete.
for (let i = 0; i < 100; i++) {
queries.push(db.insert(Comment).values({ body: `Test comment ${i}` }));
}
await db.batch(queries);
}

Vedi i documenti db.batch() di Drizzle per maggiori dettagli.

Funzionalità Studio

Astro DB può connettersi alla piattaforma Astro Studio per aggiungere rapidamente un database ospitato al tuo progetto. Puoi visualizzare, gestire e distribuire nuovi database ospitati direttamente dalla dashboard di Astro Studio.

Per creare un nuovo progetto, puoi utilizzare un template già pronto o visitare la guida di Astro Studio.

Pubblicazione degli schemi delle tabelle

Sezione intitolata Pubblicazione degli schemi delle tabelle
Funzionalità Studio

Il tuo schema delle tabelle cambierà nel tempo man mano che il tuo progetto cresce. Puoi testare in sicurezza le modifiche alla configurazione localmente e spingerle al tuo database Studio quando effettui il deploy.

Quando crei un progetto Studio dalla dashboard, avrai l’opzione di creare un’azione CI di GitHub. Questo migrerà automaticamente le modifiche allo schema quando si fonde con il ramo principale del tuo repository.

Puoi anche pubblicare le modifiche allo schema locale ad Astro Studio tramite la CLI utilizzando il comando astro db push --remote:

Terminal window
npm run astro db push --remote

Questo comando verificherà che le modifiche locali possano essere effettuate senza perdita di dati e, se necessario, suggerirà come apportare in sicurezza modifiche allo schema per risolvere i conflitti.

Pubblicare modifiche distruttive allo schema

Sezione intitolata Pubblicare modifiche distruttive allo schema

Se devi modificare lo schema della tabella in un modo incompatibile con i tuoi dati esistenti ospitati su Astro Studio, dovrai resettare il tuo database di produzione.

Per pubblicare un aggiornamento dello schema della tabella che include una modifica di rottura, aggiungi il flag --force-reset per resettare tutti i dati di produzione:

Terminal window
npm run astro db push --remote --force-reset
Funzionalità Studio

È possibile rinominare una tabella dopo aver pubblicato lo schema su Astro Studio.

Se non hai dati di produzione importanti, puoi resettare il tuo database utilizzando il flag --force-reset. Questo flag eliminerà tutte le tabelle nel database e ne creerà di nuove in modo che corrisponda esattamente al tuo schema attuale.

Per rinominare una tabella preservando i dati di produzione, devi eseguire una serie di modifiche non di rottura per pubblicare in sicurezza lo schema locale su Astro Studio.

L’esempio seguente rinomina una tabella da Comment a Feedback:

  1. Nel file di configurazione del database, aggiungi la proprietà deprecated: true alla tabella che vuoi rinominare:

    db/config.ts
    const Comment = defineTable({
    deprecated: true,
    columns: {
    author: column.text(),
    body: column.text(),
    }
    });
  2. Aggiungi un nuovo schema di tabella (corrispondente esattamente alle proprietà della tabella esistente) con il nuovo nome:

    db/config.ts
    const Comment = defineTable({
    deprecated: true,
    columns: {
    author: column.text(),
    body: column.text(),
    }
    });
    const Feedback = defineTable({
    columns: {
    author: column.text(),
    body: column.text(),
    }
    });
  3. Pubblica su Astro Studio con astro db push --remote. Questo aggiungerà la nuova tabella e segnerà la vecchia come deprecata.

  4. Aggiorna qualsiasi codice del tuo progetto locale per utilizzare la nuova tabella invece della vecchia. Potresti anche dover migrare i dati nella nuova tabella.

  5. Una volta che sei sicuro che la vecchia tabella non viene più utilizzata nel tuo progetto, puoi rimuovere lo schema dal tuo config.ts:

    db/config.ts
    const Comment = defineTable({
    deprecated: true,
    columns: {
    author: column.text(),
    body: column.text(),
    }
    });
    const Feedback = defineTable({
    columns: {
    author: column.text(),
    body: column.text(),
    }
    });
  6. Pubblica di nuovo su Astro Studio con astro db push --remote. La vecchia tabella verrà eliminata, lasciando solo la nuova tabella rinominata.

Funzionalità Studio

Potresti aver bisogno di spingere dati al tuo database Studio per seeding o migrazioni di dati. Puoi scrivere un file .ts con il modulo astro:db per scrivere query type-safe. Poi, esegui il file contro il tuo database Studio usando il comando astro db execute <file-path> --remote:

I seguenti Commenti possono essere inseriti utilizzando il comando astro db execute db/seed.ts --remote:

db/seed.ts
import { Comment } from 'astro:db';
export default async function () {
await db.insert(Comment).values([
{ authorId: 1, body: 'Spero ti piaccia Astro DB!' },
{ authorId: 2, body: 'Divertiti!' },
])
}

Vedi il riferimento CLI per un elenco completo dei comandi.

Funzionalità Studio

Per impostazione predefinita, Astro utilizzerà un file di database locale ogni volta che esegui i comandi dev o build. Le tabelle vengono ricreate da zero ogni volta che viene eseguito un comando e i dati di seed di sviluppo verranno inseriti.

Per collegarti al tuo database ospitato Studio, puoi aggiungere il flag --remote. Usa questo flag per i deploy di produzione per avere accesso sia in lettura che in scrittura al tuo database Studio. Questo ti permetterà di accettare e persistere i dati degli utenti.

Terminal window
# Costruisci con una connessione remota
astro build --remote
# Sviluppa con una connessione remota
astro dev --remote

Per utilizzare una connessione remota, avrai bisogno di un token dell’app per autenticarti con Studio. Visita la dashboard di Studio per le istruzioni sulla creazione e configurazione del token.

Quando sei pronto per il deploy, consulta la nostra guida al Deploy con una Connessione Studio.

Le integrazioni Astro possono estendere i progetti degli utenti con tabelle Astro DB aggiuntive e dati di seed.

Usa il metodo extendDb() nell’hook astro:db:setup per registrare ulteriori configurazioni Astro DB e file di seed. L’helper defineDbIntegration() fornisce supporto TypeScript e autocompletamento per l’hook astro:db:setup.

my-integration/index.ts
import { defineDbIntegration } from '@astrojs/db/utils';
export default function MyIntegration() {
return defineDbIntegration({
name: 'my-astro-db-powered-integration',
hooks: {
'astro:db:setup': ({ extendDb }) => {
extendDb({
configEntrypoint: '@astronaut/my-package/config',
seedEntrypoint: '@astronaut/my-package/seed',
});
},
// Altri hook di integrazione...
},
});
}

I file di configurazione e seed delle integrazioni seguono lo stesso formato dei loro equivalenti definiti dall’utente.

Operazioni tipizzate nelle integrazioni

Sezione intitolata Operazioni tipizzate nelle integrazioni

Lavorando sulle integrazioni, potresti non essere in grado di beneficiare dei tipi di tabella generati da Astro esportati da astro:db. Per la piena sicurezza dei tipi, usa l’utilità asDrizzleTable() per creare un oggetto di riferimento della tabella che puoi usare per le operazioni sul database.

Ad esempio, data un’integrazione che configura la seguente tabella del database Pets:

my-integration/config.ts
import { defineDb, defineTable, column } from 'astro:db';
export const Pets = defineTable({
columns: {
name: column.text(),
species: column.text(),
},
});
export default defineDb({ tables: { Pets } });

Il file seed può importare Pets e usare asDrizzleTable() per inserire righe nella tua tabella con il controllo dei tipi:

my-integration/seed.ts
import { asDrizzleTable } from '@astrojs/db/utils';
import { db } from 'astro:db';
import { Pets } from './config';
export default async function() {
const typeSafePets = asDrizzleTable('Pets', Pets);
await db.insert(typeSafePets).values([
{ name: 'Palomita', species: 'cat' },
{ name: 'Pan', species: 'dog' },
]);
}

Il valore restituito da asDrizzleTable('Pets', Pets) è equivalente a import { Pets } from 'astro:db', ma è disponibile anche quando la generazione dei tipi di Astro non può essere eseguita. Puoi usarlo in qualsiasi codice di integrazione che necessita di interrogare o inserire nel database.

Distribuzione di produzione self-hosted

Sezione intitolata Distribuzione di produzione self-hosted

Se distribuisci il tuo sito su un host autogestito come un server privato virtuale, puoi scegliere di utilizzare un file di database invece di connetterti a un database ospitato su Astro Studio.

Se sei a tuo agio con i rischi e puoi gestire la distribuzione autonomamente, puoi utilizzare un file di database invece di connetterti a Studio.

Imposta la variabile d’ambiente ASTRO_DATABASE_FILE su un percorso che punta al tuo file .db all’interno dell’ambiente host durante la build:

Terminal window
ASTRO_DATABASE_FILE=/srv/files/database.db astro build

La build compilerà staticamente con questo percorso come database di produzione. Quando distribuisci e avvii il server, si connetterà al file in questo percorso sull’host di produzione.

Inoltre, la pubblicazione di eventuali modifiche allo schema delle tabelle (note anche come “migrazioni dello schema”) deve essere gestita manualmente utilizzando questa variabile d’ambiente.