0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-03 22:29:08 -05:00

refactor: move dev to use filesystem to run seed at right time

This commit is contained in:
bholmesdev 2024-01-11 15:40:36 -05:00 committed by Nate Moore
parent 6ad4e00cd0
commit 4e941af5fb
3 changed files with 38 additions and 73 deletions

View file

@ -3,29 +3,29 @@ import { vitePluginDb } from './vite-plugin-db.js';
import { vitePluginInjectEnvTs } from './vite-plugin-inject-env-ts.js';
import { typegen } from './typegen.js';
import { collectionsSchema } from './types.js';
import { seed } from './seed.js';
import { existsSync } from 'fs';
import { rm } from 'fs/promises';
import { getDbUrl } from './consts.js';
import { createDb, setupDbTables } from './internal.js';
export function integration(): AstroIntegration {
return {
name: 'astro:db',
hooks: {
async 'astro:config:setup'({ updateConfig, config, command }) {
async 'astro:config:setup'({ logger, updateConfig, config, command }) {
if (command === 'preview') return;
// TODO: refine where we load collections
// @matthewp: may want to load collections by path at runtime
const collections = collectionsSchema.parse(config.db?.collections ?? {});
const isDev = command === 'dev';
if (command === 'build') {
const dbUrl = getDbUrl(config.root);
if (existsSync(dbUrl)) {
await rm(dbUrl);
}
await seed({ collections, root: config.root });
}
const db = await createDb({ dbUrl: dbUrl.href });
await setupDbTables({ db, collections, logger });
logger.info('Collections set up 🚀');
updateConfig({
vite: {
plugins: [
@ -34,7 +34,6 @@ export function integration(): AstroIntegration {
vitePluginDb({
collections,
root: config.root,
isDev,
}),
// @ts-ignore
vitePluginInjectEnvTs(config),

View file

@ -24,6 +24,7 @@ import {
} from 'drizzle-orm/sqlite-core';
import { z } from 'zod';
import { nanoid } from 'nanoid';
import type { AstroIntegrationLogger } from 'astro';
export type SqliteDB = SqliteRemoteDatabase;
export type {
@ -38,25 +39,21 @@ export type {
const sqlite = new SQLiteAsyncDialect();
export async function createDb({
collections,
dbUrl,
createTables = false,
}: {
collections: DBCollections;
dbUrl: string;
createTables?: boolean;
}) {
export async function createDb({ dbUrl }: { dbUrl: string }) {
const client = createClient({ url: dbUrl });
const db = drizzle(client);
if (createTables) {
await createDbTables(db, collections);
}
return db;
}
async function createDbTables(db: LibSQLDatabase, collections: DBCollections) {
export async function setupDbTables({
db,
collections,
logger,
}: {
db: LibSQLDatabase;
collections: DBCollections;
logger: AstroIntegrationLogger;
}) {
const setupQueries: SQL[] = [];
for (const [name, collection] of Object.entries(collections)) {
const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${name}`);
@ -66,6 +63,20 @@ async function createDbTables(db: LibSQLDatabase, collections: DBCollections) {
for (const q of setupQueries) {
await db.run(q);
}
for (const [name, collection] of Object.entries(collections)) {
if (!collection.data) continue;
const table = collectionToTable(name, collection);
try {
await db.insert(table).values(await collection.data());
} catch (e) {
logger.error(
`Failed to seed ${bold(
name
)} data. Did you update to match recent schema changes? Full error:\n\n${e}`
);
}
}
}
export function getCreateTableQuery(collectionName: string, collection: DBCollection) {
@ -83,22 +94,6 @@ export function getCreateTableQuery(collectionName: string, collection: DBCollec
return query;
}
export async function executeCollectionDataFn({
db,
collectionName,
collection,
}: {
db: LibSQLDatabase;
collectionName: string;
collection: DBCollection;
}) {
const { data } = collection;
if (!data) return;
const table = collectionToTable(collectionName, collection);
await db.insert(table).values(await data());
}
function schemaTypeToSqlType(type: FieldType): 'text' | 'integer' {
switch (type) {
case 'date':

View file

@ -1,13 +1,5 @@
import { existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { red } from 'kleur/colors';
import {
DRIZZLE_MOD_IMPORT,
INTERNAL_MOD_IMPORT,
SUPPORTED_SEED_FILES,
VIRTUAL_MODULE_ID,
getDbUrl,
} from './consts.js';
import { DRIZZLE_MOD_IMPORT, INTERNAL_MOD_IMPORT, VIRTUAL_MODULE_ID, getDbUrl } from './consts.js';
import type { DBCollections } from './types.js';
import type { Plugin as VitePlugin } from 'vite';
@ -16,11 +8,9 @@ const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;
export function vitePluginDb({
collections,
root,
isDev,
}: {
collections: DBCollections;
root: URL;
isDev: boolean;
}): VitePlugin {
return {
name: 'astro:db',
@ -32,29 +22,20 @@ export function vitePluginDb({
},
load(id) {
if (id !== resolvedVirtualModuleId) return;
return getVirtualModContents({ collections, root, isDev });
return getVirtualModContents({ collections, root });
},
};
}
const seedErrorMessage = `${red(
'⚠️ Failed to seed data.'
)} Is the seed file out-of-date with recent schema changes?`;
export function getVirtualModContents({
collections,
root,
isDev,
}: {
collections: DBCollections;
root: URL;
isDev: boolean;
}) {
const seedFile = SUPPORTED_SEED_FILES.map((f) => fileURLToPath(new URL(f, root))).find((f) =>
existsSync(f)
);
const dbUrl = isDev ? ':memory:' : getDbUrl(root).href;
const shouldSetUpDb = isDev || !existsSync(getDbUrl(root));
const dbUrl = getDbUrl(root).href;
const shouldSetUpDb = !existsSync(getDbUrl(root));
return `
import { collectionToTable, createDb } from ${INTERNAL_MOD_IMPORT};
@ -66,16 +47,6 @@ export const db = await createDb(${JSON.stringify({
export * from ${DRIZZLE_MOD_IMPORT};
${getStringifiedCollectionExports(collections)}
${
seedFile && isDev
? `try {
await import(${JSON.stringify(seedFile)});
} catch {
console.error(${JSON.stringify(seedErrorMessage)});
}`
: ''
}
`;
}