@@ -12,6 +12,7 @@ export interface QueryLayer {
1212
1313let dbPromise : Promise < QueryLayer > | null = null ;
1414let currentEngine : QueryLayerConfig [ 'engine' ] | null = null ;
15+ let duckdbFallbackWarned = false ;
1516
1617const duckdbWasmMvp = new URL ( '@duckdb/duckdb-wasm/dist/duckdb-mvp.wasm' , import . meta. url ) . href ;
1718const duckdbWasmEh = new URL ( '@duckdb/duckdb-wasm/dist/duckdb-eh.wasm' , import . meta. url ) . href ;
@@ -96,6 +97,22 @@ async function instantiateLayer(config: QueryLayerConfig): Promise<QueryLayer> {
9697 // breaking term_state persistence and to keep the app usable.
9798 return / ^ D U C K D B _ O P F S _ ( U N S U P P O R T E D | L O C K E D | O P E N _ F A I L E D ) / . test ( msg ) ;
9899 } ;
100+
101+ const warnDuckdbFallback = ( error : unknown ) => {
102+ if ( duckdbFallbackWarned ) return ;
103+ duckdbFallbackWarned = true ;
104+ console . warn ( '[DB] DuckDB-Wasm 初始化失败,回退至 sql.js' , toErrorInfo ( error ) ) ;
105+ } ;
106+
107+ const canUseDuckdbOpfs = ( ) => {
108+ if ( ! isBrowserEnv ( ) ) return false ;
109+ try {
110+ // DuckDB OPFS persistence relies on OPFS Sync Access Handles.
111+ return typeof ( globalThis as any ) . FileSystemFileHandle ?. prototype ?. createSyncAccessHandle === 'function' ;
112+ } catch {
113+ return false ;
114+ }
115+ } ;
99116 if ( currentEngine && config . engine === currentEngine && dbPromise ) {
100117 return dbPromise ;
101118 }
@@ -106,25 +123,24 @@ async function instantiateLayer(config: QueryLayerConfig): Promise<QueryLayer> {
106123 return await initDuckDB ( ) ;
107124 } catch ( error ) {
108125 if ( config . strictEngine && ! shouldForceFallback ( error ) ) throw error ;
109- // OPFS access handles are not available in all browsers/contexts; fall back silently.
110- if ( ! shouldForceFallback ( error ) ) {
111- console . warn ( '[DB] DuckDB-Wasm 初始化失败,回退至 sql.js' , toErrorInfo ( error ) ) ;
112- }
126+ warnDuckdbFallback ( error ) ;
113127 currentEngine = 'sqljs' ;
114128 return createFallbackLayer ( ) ;
115129 }
116130 case 'sqljs' :
117131 currentEngine = 'sqljs' ;
118132 return createFallbackLayer ( ) ;
119133 default :
134+ if ( ! canUseDuckdbOpfs ( ) ) {
135+ currentEngine = 'sqljs' ;
136+ return createFallbackLayer ( ) ;
137+ }
120138 try {
121139 currentEngine = 'duckdb' ;
122140 return await initDuckDB ( ) ;
123141 } catch ( error ) {
124142 if ( config . strictEngine && ! shouldForceFallback ( error ) ) throw error ;
125- if ( ! shouldForceFallback ( error ) ) {
126- console . warn ( '[DB] DuckDB-Wasm 初始化失败,回退至 sql.js' , toErrorInfo ( error ) ) ;
127- }
143+ warnDuckdbFallback ( error ) ;
128144 currentEngine = 'sqljs' ;
129145 return createFallbackLayer ( ) ;
130146 }
0 commit comments