diff --git a/packages/db/src/config.ts b/packages/db/src/config.ts index 6cd00a3b6d..85ce6e1f85 100644 --- a/packages/db/src/config.ts +++ b/packages/db/src/config.ts @@ -14,6 +14,8 @@ import { z } from 'zod'; export const dbConfigSchema = z.object({ studio: z.boolean().optional(), collections: collectionsSchema.optional(), + // TODO: strict types + data: z.function().args(z.any()).optional(), }); export type DBUserConfig = z.input; diff --git a/packages/db/src/integration.ts b/packages/db/src/integration.ts index 8f3e536471..27fcd73d73 100644 --- a/packages/db/src/integration.ts +++ b/packages/db/src/integration.ts @@ -55,7 +55,13 @@ export function integration(): AstroIntegration { dbUrl: dbUrl.href, seeding: true, }); - await setupDbTables({ db, collections, logger }); + await setupDbTables({ + db, + collections, + data: configWithDb.db?.data, + logger, + mode: command === 'dev' ? 'dev' : 'build', + }); logger.info('Collections set up 🚀'); dbPlugin = vitePluginDb({ connectToStudio: false, collections, dbUrl: dbUrl.href }); diff --git a/packages/db/src/internal.ts b/packages/db/src/internal.ts index c0047dd029..df8a0132d5 100644 --- a/packages/db/src/internal.ts +++ b/packages/db/src/internal.ts @@ -91,12 +91,16 @@ export async function createLocalDatabaseClient({ export async function setupDbTables({ db, + data, collections, logger, + mode, }: { db: LibSQLDatabase; + data?: (...params: any) => any; collections: DBCollections; logger: AstroIntegrationLogger; + mode: 'dev' | 'build'; }) { const setupQueries: SQL[] = []; for (const [name, collection] of Object.entries(collections)) { @@ -107,6 +111,16 @@ export async function setupDbTables({ for (const q of setupQueries) { await db.run(q); } + if (data) { + const ormObjects = Object.fromEntries( + Object.entries(collections).map(([name, collection]) => { + const table = collectionToTable(name, collection, false); + return [name, table]; + }) + ); + await data({ db, ...ormObjects, mode }); + } + // TODO: decide on removing collection-level data for (const [name, collection] of Object.entries(collections)) { if (!isReadableCollection(collection) || !collection.data) continue; @@ -127,8 +141,8 @@ export function getCreateTableQuery(collectionName: string, collection: DBCollec let query = `CREATE TABLE ${sqlite.escapeName(collectionName)} (`; const colQueries = []; - const colHasPrimaryKey = Object.entries(collection.fields).find( - ([, field]) => hasPrimaryKey(field) + const colHasPrimaryKey = Object.entries(collection.fields).find(([, field]) => + hasPrimaryKey(field) ); if (!colHasPrimaryKey) { colQueries.push('_id INTEGER PRIMARY KEY'); @@ -173,7 +187,6 @@ export function getModifiers(fieldName: string, field: DBField) { return modifiers; } - // Using `DBField` will not narrow `default` based on the column `type` // Handle each field separately type WithDefaultDefined = T & Required>; @@ -289,7 +302,7 @@ function columnMapper(fieldName: string, field: DBField, isJsonSerializable: boo case 'number': { c = integer(fieldName); if (field.default !== undefined) c = c.default(field.default); - if (field.primaryKey === true) c = c.primaryKey({autoIncrement: true}); + if (field.primaryKey === true) c = c.primaryKey({ autoIncrement: true }); break; } case 'boolean': {