@@ -8,22 +8,6 @@ import type { CacheEntry, D1DatabaseConfig, LocalDevelopmentDatabase, SqliteData
8
8
import type { ModuleOptions } from '../types/module'
9
9
import { logger } from './dev'
10
10
11
- function isSqlite3Available ( ) {
12
- if ( ! isWebContainer ( ) ) {
13
- return false
14
- }
15
-
16
- try {
17
- // eslint-disable-next-line @typescript-eslint/no-require-imports
18
- require ( 'sqlite3' )
19
- return true
20
- }
21
- catch {
22
- logger . error ( 'Nuxt Content requires `sqlite3` module to work in WebContainer environment. Please run `npm install sqlite3` to install it and try again.' )
23
- process . exit ( 1 )
24
- }
25
- }
26
-
27
11
export async function refineDatabaseConfig ( database : ModuleOptions [ 'database' ] , opts : { rootDir : string , updateSqliteFileName ?: boolean } ) {
28
12
if ( database . type === 'd1' ) {
29
13
if ( ! ( 'bindingName' in database ) ) {
@@ -44,14 +28,11 @@ export async function refineDatabaseConfig(database: ModuleOptions['database'],
44
28
}
45
29
}
46
30
47
- export function getDefaultSqliteAdapter ( ) {
48
- return process . versions . bun ? 'bunsqlite' : 'sqlite'
49
- }
50
-
51
- export function resolveDatabaseAdapter ( adapter : 'sqlite' | 'bunsqlite' | 'postgres' | 'libsql' | 'd1' , resolver : Resolver ) {
31
+ export function resolveDatabaseAdapter ( adapter : 'sqlite' | 'bunsqlite' | 'postgres' | 'libsql' | 'd1' | 'nodesqlite' , opts : { resolver : Resolver , nativeSqlite ?: boolean } ) {
52
32
const databaseConnectors = {
53
- sqlite : isSqlite3Available ( ) ? 'db0/connectors/sqlite3' : 'db0/connectors/better-sqlite3' ,
54
- bunsqlite : resolver . resolve ( './runtime/internal/connectors/bunsqlite' ) ,
33
+ sqlite : findBestSqliteAdapter ( { nativeSqlite : opts . nativeSqlite } ) ,
34
+ nodesqlite : 'db0/connectors/node-sqlite' ,
35
+ bunsqlite : opts . resolver . resolve ( './runtime/internal/connectors/bunsqlite' ) ,
55
36
postgres : 'db0/connectors/postgresql' ,
56
37
libsql : 'db0/connectors/libsql/web' ,
57
38
d1 : 'db0/connectors/cloudflare-d1' ,
@@ -65,23 +46,22 @@ export function resolveDatabaseAdapter(adapter: 'sqlite' | 'bunsqlite' | 'postgr
65
46
return databaseConnectors [ adapter ]
66
47
}
67
48
68
- async function getDatabase ( database : SqliteDatabaseConfig | D1DatabaseConfig ) : Promise < Connector > {
49
+ async function getDatabase ( database : SqliteDatabaseConfig | D1DatabaseConfig , opts : { nativeSqlite ?: boolean } ) : Promise < Connector > {
69
50
if ( database . type === 'd1' ) {
70
51
return cloudflareD1Connector ( { bindingName : database . bindingName } )
71
52
}
72
53
73
- const type = getDefaultSqliteAdapter ( )
74
- return import ( type === 'bunsqlite' ? 'db0/connectors/bun-sqlite' : ( isSqlite3Available ( ) ? 'db0/connectors/sqlite3' : 'db0/connectors/better-sqlite3' ) )
54
+ return import ( findBestSqliteAdapter ( opts ) )
75
55
. then ( ( m ) => {
76
56
const connector = ( m . default || m ) as ( config : unknown ) => Connector
77
57
return connector ( { path : database . filename } )
78
58
} )
79
59
}
80
60
81
61
const _localDatabase : Record < string , Connector > = { }
82
- export async function getLocalDatabase ( database : SqliteDatabaseConfig | D1DatabaseConfig , connector ?: Connector ) : Promise < LocalDevelopmentDatabase > {
62
+ export async function getLocalDatabase ( database : SqliteDatabaseConfig | D1DatabaseConfig , { connector, nativeSqlite } : { connector ?: Connector , nativeSqlite ?: boolean } = { } ) : Promise < LocalDevelopmentDatabase > {
83
63
const databaseLocation = database . type === 'sqlite' ? database . filename : database . bindingName
84
- const db = _localDatabase [ databaseLocation ] || connector || await getDatabase ( database )
64
+ const db = _localDatabase [ databaseLocation ] || connector || await getDatabase ( database , { nativeSqlite } )
85
65
86
66
_localDatabase [ databaseLocation ] = db
87
67
await db . exec ( 'CREATE TABLE IF NOT EXISTS _development_cache (id TEXT PRIMARY KEY, checksum TEXT, parsedContent TEXT)' )
@@ -128,3 +108,66 @@ export async function getLocalDatabase(database: SqliteDatabaseConfig | D1Databa
128
108
dropContentTables,
129
109
}
130
110
}
111
+
112
+ function findBestSqliteAdapter ( opts : { nativeSqlite ?: boolean } ) {
113
+ if ( process . versions . bun ) {
114
+ return 'db0/connectors/bun-sqlite'
115
+ }
116
+
117
+ // if node:sqlite is available, use it
118
+ if ( opts . nativeSqlite && isNodeSqliteAvailable ( ) ) {
119
+ return 'db0/connectors/node-sqlite'
120
+ }
121
+
122
+ return isSqlite3Available ( ) ? 'db0/connectors/sqlite3' : 'db0/connectors/better-sqlite3'
123
+ }
124
+
125
+ function isNodeSqliteAvailable ( ) {
126
+ try {
127
+ const module = globalThis . process ?. getBuiltinModule ?.( 'node:sqlite' )
128
+
129
+ if ( module ) {
130
+ // When using the SQLite Node.js prints warnings about the experimental feature
131
+ // This is workaround to surpass the SQLite warning
132
+ // Inspired by Yarn https://github.com/yarnpkg/berry/blob/182046546379f3b4e111c374946b32d92be5d933/packages/yarnpkg-pnp/sources/loader/applyPatch.ts#L307-L328
133
+ const originalEmit = process . emit
134
+ // @ts -expect-error - TS complains about the return type of originalEmit.apply
135
+ process . emit = function ( ...args ) {
136
+ const name = args [ 0 ]
137
+ const data = args [ 1 ] as { name : string , message : string }
138
+ if (
139
+ name === `warning`
140
+ && typeof data === `object`
141
+ && data . name === `ExperimentalWarning`
142
+ && data . message . includes ( `SQLite is an experimental feature` )
143
+ ) {
144
+ return false
145
+ }
146
+ return originalEmit . apply ( process , args as unknown as Parameters < typeof process . emit > )
147
+ }
148
+
149
+ return true
150
+ }
151
+
152
+ return false
153
+ }
154
+ catch {
155
+ return false
156
+ }
157
+ }
158
+
159
+ function isSqlite3Available ( ) {
160
+ if ( ! isWebContainer ( ) ) {
161
+ return false
162
+ }
163
+
164
+ try {
165
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
166
+ require ( 'sqlite3' )
167
+ return true
168
+ }
169
+ catch {
170
+ logger . error ( 'Nuxt Content requires `sqlite3` module to work in WebContainer environment. Please run `npm install sqlite3` to install it and try again.' )
171
+ process . exit ( 1 )
172
+ }
173
+ }
0 commit comments