Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/presets/nuxthub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,16 @@ export default definePreset({
}
}

const database = nitroConfig.runtimeConfig?.content?.database
// Only a remote database migrated during build is the database the runtime will use,
// a local file database is discarded with the build machine
const isRemoteDatabase = database?.type === 'd1'
|| database?.type === 'postgresql'
|| database?.type === 'postgres'
|| (database?.type === 'libsql' && !!database.url && !database.url.startsWith('file:'))

// apply migrations during build if enabled
if (!nuxt.options.dev && hubConfig.db?.applyMigrationsDuringBuild) {
if (!nuxt.options.dev && hubConfig.db?.applyMigrationsDuringBuild && isRemoteDatabase) {
// Write SQL dump to database queries when not in dev mode
await mkdir(resolve(nitroConfig.rootDir!, hubConfig.dir, 'db/queries'), { recursive: true })
let i = 1
Expand Down Expand Up @@ -122,10 +130,11 @@ export default definePreset({
nitroConfig.runtimeConfig!.content.integrityCheck = false
}
// Handle local database (cannot be populated during build)
const database = nitroConfig.runtimeConfig?.content?.database
if (!nuxt.options.dev && database?.type === 'libsql' && database?.url?.startsWith('file:') && !database?.url?.startsWith('file:/tmp/')) {
logger.warn('Deploying local libsql database with Nuxthub is possible only in `/tmp` directory. Using `/tmp/sqlite.db` instead.')
database.url = 'file:/tmp/sqlite.db'
if (!nuxt.options.dev && database?.type === 'libsql' && database.url?.startsWith('file:')) {
if (!database.url.startsWith('file:/tmp/')) {
logger.warn('Deploying local libsql database with Nuxthub is possible only in `/tmp` directory. Using `/tmp/sqlite.db` instead.')
database.url = 'file:/tmp/sqlite.db'
}
// Enable integrity check in production as local database cannot be re-used after build
nitroConfig.runtimeConfig!.content ||= {}
nitroConfig.runtimeConfig!.content.integrityCheck = true
Expand Down
44 changes: 44 additions & 0 deletions test/unit/nuxthubPreset.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { existsSync } from 'node:fs'
import { mkdtemp, readFile, readdir } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'pathe'
import { describe, expect, test, vi } from 'vitest'
import type { Nuxt } from '@nuxt/schema'
import type { Resolver } from '@nuxt/kit'
Expand Down Expand Up @@ -148,3 +152,43 @@ describe('nuxthub preset setupNitro', () => {
expect(nitroConfig.runtimeConfig!.content!.integrityCheck).toBe(true)
})
})

describe('nuxthub preset setupNitro dump handoff', () => {
const dumpManifest = { collections: [], dump: { posts: ['INSERT INTO posts VALUES (1);'] } } as unknown as Manifest

async function runSetupNitro(runtimeDb: Record<string, unknown>) {
const nuxt = createNuxt(
{ db: { dialect: 'sqlite' } },
{ db: runtimeDb, dir: '.data/hub' },
)
const rootDir = await mkdtemp(join(tmpdir(), 'nuxthub-preset-'))
const nitroConfig = { runtimeConfig: { content: {} }, rootDir } as unknown as NitroConfig
await nuxthubPreset.setupNitro(nitroConfig, { ...opts, manifest: dumpManifest, moduleOptions: {} as ModuleOptions, nuxt })
return { nitroConfig, queriesDir: join(rootDir, '.data/hub/db/queries') }
}

test('skips the handoff for a local file database and keeps the integrity check', async () => {
const { nitroConfig, queriesDir } = await runSetupNitro({ driver: 'libsql', connection: { url: 'file:.data/hub/db/sqlite.db' }, applyMigrationsDuringBuild: true })

expect(existsSync(queriesDir)).toBe(false)
expect(nitroConfig.runtimeConfig!.content!.database).toEqual({ type: 'libsql', url: 'file:/tmp/sqlite.db' })
expect(nitroConfig.runtimeConfig!.content!.integrityCheck).toBe(true)
})

test('keeps the integrity check when the local database is already in /tmp', async () => {
const { nitroConfig, queriesDir } = await runSetupNitro({ driver: 'libsql', connection: { url: 'file:/tmp/sqlite.db' }, applyMigrationsDuringBuild: true })

expect(existsSync(queriesDir)).toBe(false)
expect(nitroConfig.runtimeConfig!.content!.database).toEqual({ type: 'libsql', url: 'file:/tmp/sqlite.db' })
expect(nitroConfig.runtimeConfig!.content!.integrityCheck).toBe(true)
})

test('hands off the dump for a remote database and disables the integrity check', async () => {
const { nitroConfig, queriesDir } = await runSetupNitro({ driver: 'libsql', connection: { url: 'libsql://content.turso.io' }, applyMigrationsDuringBuild: true })

expect(await readdir(queriesDir)).toEqual(['content-database-001.sql'])
expect(await readFile(join(queriesDir, 'content-database-001.sql'), 'utf8')).toContain('INSERT INTO posts VALUES (1);')
expect(nitroConfig.runtimeConfig!.content!.database).toEqual({ type: 'libsql', url: 'libsql://content.turso.io' })
expect(nitroConfig.runtimeConfig!.content!.integrityCheck).toBe(false)
})
})
Loading