diff --git a/packages/db/src/core/cli/commands/execute/index.ts b/packages/db/src/core/cli/commands/execute/index.ts index 9a5a1b8e2f..cc316bf596 100644 --- a/packages/db/src/core/cli/commands/execute/index.ts +++ b/packages/db/src/core/cli/commands/execute/index.ts @@ -11,7 +11,7 @@ import { } from '../../../errors.js'; import { getLocalVirtualModContents, - getStudioVirtualModContents, + getRemoteVirtualModContents, } from '../../../integration/vite-plugin-db.js'; import { bundleFile, importBundledFile } from '../../../load-file.js'; import type { DBConfig } from '../../../types.js'; @@ -41,7 +41,7 @@ export async function cmd({ let virtualModContents: string; if (flags.remote) { const appToken = await getManagedRemoteToken(flags.token); - virtualModContents = getStudioVirtualModContents({ + virtualModContents = getRemoteVirtualModContents({ tables: dbConfig.tables ?? {}, appToken: appToken.token, isBuild: false, diff --git a/packages/db/src/core/integration/index.ts b/packages/db/src/core/integration/index.ts index 6debb40176..88949175c4 100644 --- a/packages/db/src/core/integration/index.ts +++ b/packages/db/src/core/integration/index.ts @@ -31,7 +31,12 @@ import { vitePluginDb, } from './vite-plugin-db.js'; -function astroDBIntegration(): AstroIntegration { +type DBOptions = { + remoteClient?: 'native' | 'web'; +}; + +function astroDBIntegration(options?: DBOptions): AstroIntegration { + const { remoteClient = 'native' } = options || {}; let connectToRemote = false; let configFileDependencies: string[] = []; let root: URL; @@ -77,17 +82,22 @@ function astroDBIntegration(): AstroIntegration { if (connectToRemote) { appToken = await getManagedRemoteToken(); dbPlugin = vitePluginDb({ - connectToStudio: connectToRemote, + connectToRemote: true, appToken: appToken.token, tables, root: config.root, srcDir: config.srcDir, output: config.output, seedHandler, + // The web remote client is only used for production builds + // in order to be compatible with non-Node server runtimes. + // For local development and CLI commands, the native client + // is used for greater flexibility. + remoteClientMode: command === 'build' ? remoteClient : 'native', }); } else { dbPlugin = vitePluginDb({ - connectToStudio: false, + connectToRemote: false, tables, seedFiles, root: config.root, diff --git a/packages/db/src/core/integration/vite-plugin-db.ts b/packages/db/src/core/integration/vite-plugin-db.ts index 29e98222ea..c74b601e63 100644 --- a/packages/db/src/core/integration/vite-plugin-db.ts +++ b/packages/db/src/core/integration/vite-plugin-db.ts @@ -34,24 +34,25 @@ export type SeedHandler = { type VitePluginDBParams = | { - connectToStudio: false; - tables: LateTables; - seedFiles: LateSeedFiles; - srcDir: URL; - root: URL; - logger?: AstroIntegrationLogger; - output: AstroConfig['output']; - seedHandler: SeedHandler; - } + connectToRemote: false; + tables: LateTables; + seedFiles: LateSeedFiles; + srcDir: URL; + root: URL; + logger?: AstroIntegrationLogger; + output: AstroConfig['output']; + seedHandler: SeedHandler; + } | { - connectToStudio: true; - tables: LateTables; - appToken: string; - srcDir: URL; - root: URL; - output: AstroConfig['output']; - seedHandler: SeedHandler; - }; + connectToRemote: true; + tables: LateTables; + appToken: string; + srcDir: URL; + root: URL; + output: AstroConfig['output']; + seedHandler: SeedHandler; + remoteClientMode: 'native' | 'web'; + }; export function vitePluginDb(params: VitePluginDBParams): VitePlugin { let command: 'build' | 'serve' = 'build'; @@ -71,12 +72,13 @@ export function vitePluginDb(params: VitePluginDBParams): VitePlugin { async load(id) { if (id !== resolved.module && id !== resolved.importedFromSeedFile) return; - if (params.connectToStudio) { - return getStudioVirtualModContents({ + if (params.connectToRemote) { + return getRemoteVirtualModContents({ appToken: params.appToken, tables: params.tables.get(), isBuild: command === 'build', output: params.output, + remoteClientMode: params.remoteClientMode, }); } @@ -137,16 +139,18 @@ export * from ${RUNTIME_VIRTUAL_IMPORT}; ${getStringifiedTableExports(tables)}`; } -export function getStudioVirtualModContents({ +export function getRemoteVirtualModContents({ tables, appToken, isBuild, output, + remoteClientMode, }: { tables: DBTables; appToken: string; isBuild: boolean; output: AstroConfig['output']; + remoteClientMode?: 'native' | 'web'; }) { const dbInfo = getRemoteDatabaseInfo(); @@ -185,6 +189,7 @@ export const db = await createRemoteDatabaseClient({ dbType: ${JSON.stringify(dbInfo.type)}, remoteUrl: ${dbUrlArg()}, appToken: ${appTokenArg()}, + remoteClientMode: ${JSON.stringify(remoteClientMode)}, }); export * from ${RUNTIME_VIRTUAL_IMPORT}; diff --git a/packages/db/src/runtime/db-client.ts b/packages/db/src/runtime/db-client.ts index 2e49b28f79..35088b02fc 100644 --- a/packages/db/src/runtime/db-client.ts +++ b/packages/db/src/runtime/db-client.ts @@ -1,5 +1,6 @@ import type { InStatement } from '@libsql/client'; import { type Config as LibSQLConfig, createClient } from '@libsql/client'; +import { createClient as createLibSQLWebClient } from '@libsql/client/web'; import type { LibSQLDatabase } from 'drizzle-orm/libsql'; import { drizzle as drizzleLibsql } from 'drizzle-orm/libsql'; import { type SqliteRemoteDatabase, drizzle as drizzleProxy } from 'drizzle-orm/sqlite-proxy'; @@ -46,6 +47,7 @@ type RemoteDbClientOptions = { dbType: 'studio' | 'libsql'; appToken: string; remoteUrl: string | URL; + remoteClientMode?: 'native' | 'web'; }; export function createRemoteDatabaseClient(options: RemoteDbClientOptions) { @@ -53,10 +55,24 @@ export function createRemoteDatabaseClient(options: RemoteDbClientOptions) { return options.dbType === 'studio' ? createStudioDatabaseClient(options.appToken, remoteUrl) - : createRemoteLibSQLClient(options.appToken, remoteUrl, options.remoteUrl.toString()); + : createRemoteLibSQLClient({ + appToken: options.appToken, + remoteDbURL: remoteUrl, + rawUrl: options.remoteUrl.toString(), + remoteClientMode: options.remoteClientMode, + }); } -function createRemoteLibSQLClient(appToken: string, remoteDbURL: URL, rawUrl: string) { +type RemoteLibSQLClientOptions = { + appToken: string; + remoteDbURL: URL; + rawUrl: string; + remoteClientMode?: 'native' | 'web'; +} + +function createRemoteLibSQLClient({ + appToken, remoteDbURL, rawUrl, remoteClientMode, +}: RemoteLibSQLClientOptions) { const options: Partial = Object.fromEntries(remoteDbURL.searchParams.entries()); remoteDbURL.search = ''; @@ -81,7 +97,11 @@ function createRemoteLibSQLClient(appToken: string, remoteDbURL: URL, rawUrl: st url = 'file:' + remoteDbURL.pathname.substring(1); } - const client = createClient({ + const client = ( + remoteClientMode === 'web' + ? createLibSQLWebClient + : createClient + )({ ...options, authToken: appToken, url,