mirror of
https://github.com/withastro/astro.git
synced 2025-01-20 22:12:38 -05:00
fix: avoid dropping tables on production seed
This commit is contained in:
parent
03277b81e1
commit
bab9871dad
3 changed files with 73 additions and 49 deletions
|
@ -1,10 +1,12 @@
|
|||
import { createClient, type InStatement } from '@libsql/client';
|
||||
import type { AstroConfig } from 'astro';
|
||||
import { drizzle } from 'drizzle-orm/sqlite-proxy';
|
||||
import { drizzle as drizzleProxy } from 'drizzle-orm/sqlite-proxy';
|
||||
import { drizzle as drizzleLibsql } from 'drizzle-orm/libsql';
|
||||
import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core';
|
||||
import { red } from 'kleur/colors';
|
||||
import prompts from 'prompts';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import { setupDbTables } from '../../../queries.js';
|
||||
import { recreateTables, seedData } from '../../../queries.js';
|
||||
import { getManagedAppTokenOrExit } from '../../../tokens.js';
|
||||
import { collectionsSchema, type AstroConfigWithDB, type DBSnapshot } from '../../../types.js';
|
||||
import { getRemoteDatabaseUrl } from '../../../utils.js';
|
||||
|
@ -128,6 +130,8 @@ async function pushSchema({
|
|||
await runMigrateQuery({ queries, migrations, snapshot: currentSnapshot, appToken, isDryRun });
|
||||
}
|
||||
|
||||
const sqlite = new SQLiteAsyncDialect();
|
||||
|
||||
async function pushData({
|
||||
config,
|
||||
appToken,
|
||||
|
@ -140,13 +144,28 @@ async function pushData({
|
|||
const queries: InStatement[] = [];
|
||||
if (config.db?.data) {
|
||||
const libsqlClient = createClient({ url: ':memory:' });
|
||||
// Use proxy to trace all queries to queue up in a batch
|
||||
const db = await drizzle(async (sqlQuery, params, method) => {
|
||||
// Stand up tables locally to mirror inserts.
|
||||
// Needed to generate return values.
|
||||
await recreateTables({
|
||||
db: drizzleLibsql(libsqlClient),
|
||||
collections: collectionsSchema.parse(config.db.collections ?? {}),
|
||||
});
|
||||
|
||||
for (const [collectionName, { writable }] of Object.entries(config.db.collections ?? {})) {
|
||||
if (!writable) {
|
||||
queries.push({
|
||||
sql: `DELETE FROM ${sqlite.escapeName(collectionName)}`,
|
||||
args: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Use proxy to trace all queries to queue up in a batch.
|
||||
const db = await drizzleProxy(async (sqlQuery, params, method) => {
|
||||
const stmt: InStatement = { sql: sqlQuery, args: params };
|
||||
queries.push(stmt);
|
||||
// Use in-memory database to generate results for `returning()`
|
||||
// Use in-memory database to generate results for `returning()`.
|
||||
const { rows } = await libsqlClient.execute(stmt);
|
||||
// Drizzle expects each row as an array of its values
|
||||
const rowValues: unknown[][] = [];
|
||||
for (const row of rows) {
|
||||
if (row != null && typeof row === 'object') {
|
||||
|
@ -158,10 +177,9 @@ async function pushData({
|
|||
}
|
||||
return { rows: rowValues };
|
||||
});
|
||||
await setupDbTables({
|
||||
await seedData({
|
||||
db,
|
||||
mode: 'build',
|
||||
collections: collectionsSchema.parse(config.db.collections ?? {}),
|
||||
data: config.db.data,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import { dirname } from 'path';
|
|||
import { fileURLToPath } from 'url';
|
||||
import { blue, yellow } from 'kleur/colors';
|
||||
import { fileURLIntegration } from './file-url.js';
|
||||
import { setupDbTables } from '../queries.js';
|
||||
import { recreateTables, seedData } from '../queries.js';
|
||||
import { getManagedAppTokenOrExit, type ManagedAppToken } from '../tokens.js';
|
||||
|
||||
function astroDBIntegration(): AstroIntegration {
|
||||
|
@ -63,13 +63,15 @@ function astroDBIntegration(): AstroIntegration {
|
|||
dbUrl: dbUrl.toString(),
|
||||
seeding: true,
|
||||
});
|
||||
await setupDbTables({
|
||||
await recreateTables({ db, collections });
|
||||
if (configWithDb.db?.data) {
|
||||
await seedData({
|
||||
db,
|
||||
collections,
|
||||
data: configWithDb.db?.data,
|
||||
data: configWithDb.db.data,
|
||||
logger,
|
||||
mode: command === 'dev' ? 'dev' : 'build',
|
||||
});
|
||||
}
|
||||
logger.debug('Database setup complete.');
|
||||
|
||||
dbPlugin = vitePluginDb({
|
||||
|
|
|
@ -20,19 +20,12 @@ import { isSerializedSQL } from '../runtime/types.js';
|
|||
|
||||
const sqlite = new SQLiteAsyncDialect();
|
||||
|
||||
export async function setupDbTables({
|
||||
export async function recreateTables({
|
||||
db,
|
||||
data,
|
||||
collections,
|
||||
logger,
|
||||
mode,
|
||||
// TODO: Remove once Turso has foreign key PRAGMA support
|
||||
}: {
|
||||
db: SqliteRemoteDatabase;
|
||||
data?: DBUserConfig['data'];
|
||||
collections: DBCollections;
|
||||
logger?: AstroIntegrationLogger;
|
||||
mode: 'dev' | 'build';
|
||||
}) {
|
||||
const setupQueries: SQL[] = [];
|
||||
for (const [name, collection] of Object.entries(collections)) {
|
||||
|
@ -44,7 +37,19 @@ export async function setupDbTables({
|
|||
for (const q of setupQueries) {
|
||||
await db.run(q);
|
||||
}
|
||||
if (data) {
|
||||
}
|
||||
|
||||
export async function seedData({
|
||||
db,
|
||||
data,
|
||||
logger,
|
||||
mode,
|
||||
}: {
|
||||
db: SqliteRemoteDatabase;
|
||||
data: DBUserConfig['data'];
|
||||
logger?: AstroIntegrationLogger;
|
||||
mode: 'dev' | 'build';
|
||||
}) {
|
||||
try {
|
||||
await data({
|
||||
seed: async ({ table }, values) => {
|
||||
|
@ -69,7 +74,6 @@ export async function setupDbTables({
|
|||
(logger ?? console).error(error as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getCreateTableQuery(collectionName: string, collection: DBCollection) {
|
||||
let query = `CREATE TABLE ${sqlite.escapeName(collectionName)} (`;
|
||||
|
@ -192,7 +196,7 @@ export function getReferencesConfig(field: DBField) {
|
|||
// Using `DBField` will not narrow `default` based on the column `type`
|
||||
// Handle each field separately
|
||||
type WithDefaultDefined<T extends DBField> = T & {
|
||||
schema: Required<Pick<T['schema'], 'default'>>
|
||||
schema: Required<Pick<T['schema'], 'default'>>;
|
||||
};
|
||||
type DBFieldWithDefault =
|
||||
| WithDefaultDefined<TextField>
|
||||
|
|
Loading…
Add table
Reference in a new issue