@sqlrooms/duckdb 0.29.0-rc.8 → 0.29.0-rc.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -7
- package/dist/DuckDbSlice.d.ts +9 -0
- package/dist/DuckDbSlice.d.ts.map +1 -1
- package/dist/DuckDbSlice.js +122 -42
- package/dist/DuckDbSlice.js.map +1 -1
- package/dist/connectors/WasmDuckDbConnector.d.ts.map +1 -1
- package/dist/connectors/WasmDuckDbConnector.js +8 -0
- package/dist/connectors/WasmDuckDbConnector.js.map +1 -1
- package/dist/connectors/WebSocketDuckDbConnector.d.ts +23 -0
- package/dist/connectors/WebSocketDuckDbConnector.d.ts.map +1 -1
- package/dist/connectors/WebSocketDuckDbConnector.js +62 -0
- package/dist/connectors/WebSocketDuckDbConnector.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loadTableSchemas.d.ts +2 -0
- package/dist/loadTableSchemas.d.ts.map +1 -1
- package/dist/loadTableSchemas.js +18 -10
- package/dist/loadTableSchemas.js.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -57,6 +57,33 @@ function UserList() {
|
|
|
57
57
|
|
|
58
58
|
For more information and examples on using the `useSql` hook, see the [useSql API documentation](/api/duckdb/functions/useSql).
|
|
59
59
|
|
|
60
|
+
### Monitoring WebSocket DuckDB Connections
|
|
61
|
+
|
|
62
|
+
`createWebSocketDuckDbConnector()` exposes the persistent WebSocket lifecycle
|
|
63
|
+
through `connectionStatus`, `subscribeConnectionStatus()`, and the optional
|
|
64
|
+
`onConnectionStatusChange` callback. Use this for live UI affordances such as
|
|
65
|
+
lost-connection dialogs. Call `reconnect()` to reopen the socket and rerun the
|
|
66
|
+
connector initialization SQL without destroying the connector instance.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import {createWebSocketDuckDbConnector} from '@sqlrooms/duckdb';
|
|
70
|
+
|
|
71
|
+
const connector = createWebSocketDuckDbConnector({
|
|
72
|
+
wsUrl: 'ws://localhost:4000',
|
|
73
|
+
onConnectionStatusChange: (status) => {
|
|
74
|
+
console.log('DuckDB WebSocket status:', status);
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const unsubscribe = connector.subscribeConnectionStatus((status) => {
|
|
79
|
+
if (status === 'disconnected') {
|
|
80
|
+
console.warn('DuckDB WebSocket disconnected');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await connector.reconnect();
|
|
85
|
+
```
|
|
86
|
+
|
|
60
87
|
### Looking up Table Metadata
|
|
61
88
|
|
|
62
89
|
Use `useDataTable()` in React components or `db.findTable()` from the room
|
|
@@ -229,15 +256,12 @@ function DatabaseManager() {
|
|
|
229
256
|
### Working with Qualified Table Names
|
|
230
257
|
|
|
231
258
|
```tsx
|
|
232
|
-
import {
|
|
233
|
-
makeQualifiedTableName,
|
|
234
|
-
quoteTableReference,
|
|
235
|
-
resolveTableReference,
|
|
236
|
-
} from '@sqlrooms/duckdb';
|
|
259
|
+
import {quoteTableReference, resolveTableReference} from '@sqlrooms/duckdb';
|
|
237
260
|
import {useRoomStore} from './store';
|
|
238
261
|
import {Button} from '@sqlrooms/ui';
|
|
239
262
|
|
|
240
263
|
function QualifiedTableOps() {
|
|
264
|
+
const qualifyTableName = useRoomStore((state) => state.db.qualifyTableName);
|
|
241
265
|
const createTableFromQuery = useRoomStore(
|
|
242
266
|
(state) => state.db.createTableFromQuery,
|
|
243
267
|
);
|
|
@@ -245,17 +269,20 @@ function QualifiedTableOps() {
|
|
|
245
269
|
const checkTableExists = useRoomStore((state) => state.db.checkTableExists);
|
|
246
270
|
|
|
247
271
|
const run = async () => {
|
|
248
|
-
//
|
|
249
|
-
const qualifiedTable =
|
|
272
|
+
// Store-aware qualification knows which database is the default.
|
|
273
|
+
const qualifiedTable = qualifyTableName({
|
|
250
274
|
database: 'mydb',
|
|
251
275
|
schema: 'public',
|
|
252
276
|
table: 'users',
|
|
253
277
|
});
|
|
278
|
+
// toString() is the canonical portable table ID; toFullString() includes
|
|
279
|
+
// the database when explicit catalog qualification is needed.
|
|
254
280
|
const tableSql = quoteTableReference(qualifiedTable.toString());
|
|
255
281
|
const resolved = resolveTableReference([{table: qualifiedTable}], 'users');
|
|
256
282
|
|
|
257
283
|
await createTableFromQuery(qualifiedTable, 'SELECT * FROM source_table');
|
|
258
284
|
console.log('Quoted table reference:', tableSql);
|
|
285
|
+
console.log('Fully qualified reference:', qualifiedTable.toFullString());
|
|
259
286
|
console.log('Resolved table:', resolved.table?.table.toString());
|
|
260
287
|
const tableExists = await checkTableExists(qualifiedTable);
|
|
261
288
|
console.log('Table exists after create:', tableExists);
|
package/dist/DuckDbSlice.d.ts
CHANGED
|
@@ -34,6 +34,13 @@ export type DuckDbSliceState = {
|
|
|
34
34
|
schema: string;
|
|
35
35
|
currentSchema: string | undefined;
|
|
36
36
|
currentDatabase: string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Create a context-aware qualified table name.
|
|
39
|
+
*
|
|
40
|
+
* String inputs are treated as table identifier names, not SQL references;
|
|
41
|
+
* use findTable() when resolving an existing table reference.
|
|
42
|
+
*/
|
|
43
|
+
qualifyTableName(tableName: string | QualifiedTableNameInput): QualifiedTableName;
|
|
37
44
|
/**
|
|
38
45
|
* Cache of refreshed table schemas
|
|
39
46
|
*/
|
|
@@ -198,6 +205,7 @@ export type DuckDbSliceState = {
|
|
|
198
205
|
}>;
|
|
199
206
|
};
|
|
200
207
|
};
|
|
208
|
+
type QualifiedTableNameInput = Pick<QualifiedTableName, 'database' | 'schema' | 'table' | 'defaultDatabase'>;
|
|
201
209
|
export type CreateDuckDbSliceProps = {
|
|
202
210
|
connector?: DuckDbConnector;
|
|
203
211
|
/**
|
|
@@ -228,4 +236,5 @@ export declare function createDuckDbSlice({ connector, loadTableSchemasFilter, l
|
|
|
228
236
|
* @returns The selected value of type `T`
|
|
229
237
|
*/
|
|
230
238
|
export declare function useStoreWithDuckDb<T>(selector: (state: BaseRoomStoreState & DuckDbSliceState) => T): T;
|
|
239
|
+
export {};
|
|
231
240
|
//# sourceMappingURL=DuckDbSlice.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbSlice.d.ts","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"DuckDbSlice.d.ts","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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"}
|
package/dist/DuckDbSlice.js
CHANGED
|
@@ -15,7 +15,7 @@ const DUCKDB_TEMP_DATABASE = 'temp';
|
|
|
15
15
|
* Hides `__sqlrooms_*` names and DuckDB's `temp` database.
|
|
16
16
|
*/
|
|
17
17
|
export const defaultLoadTableSchemasFilter = (table) => {
|
|
18
|
-
if (table.table
|
|
18
|
+
if (table.table.startsWith(INTERNAL_SQLROOMS_PREFIX) ||
|
|
19
19
|
table.database?.startsWith(INTERNAL_SQLROOMS_PREFIX) ||
|
|
20
20
|
table.schema?.startsWith(INTERNAL_SQLROOMS_PREFIX)) {
|
|
21
21
|
return false;
|
|
@@ -95,17 +95,55 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
95
95
|
return defaultLoadSchemaCatalogFilter(entry);
|
|
96
96
|
}));
|
|
97
97
|
return createSlice((set, get, store) => {
|
|
98
|
+
const parseTableReferenceParts = (tableName) => {
|
|
99
|
+
const parsed = parseQualifiedSqlIdentifier(tableName);
|
|
100
|
+
return parsed?.table
|
|
101
|
+
? {
|
|
102
|
+
database: parsed.database,
|
|
103
|
+
schema: parsed.schema,
|
|
104
|
+
table: parsed.table,
|
|
105
|
+
}
|
|
106
|
+
: { table: tableName };
|
|
107
|
+
};
|
|
98
108
|
/**
|
|
99
109
|
* Internal helper to load a table schema by exact name, bypassing the visibility filter.
|
|
100
110
|
* Used when performing exact lookups (e.g., checking if a specific table exists).
|
|
101
111
|
*/
|
|
102
112
|
const loadTableSchemaByName = async (tableName) => {
|
|
103
|
-
const
|
|
104
|
-
? tableName
|
|
105
|
-
:
|
|
113
|
+
const tableNameParts = typeof tableName === 'string'
|
|
114
|
+
? parseTableReferenceParts(tableName)
|
|
115
|
+
: tableName;
|
|
116
|
+
const qualifiedName = get().db.qualifyTableName(tableNameParts);
|
|
106
117
|
const connector = await get().db.getConnector();
|
|
107
|
-
const [table] = await loadTableSchemas(connector,
|
|
108
|
-
|
|
118
|
+
const [table] = await loadTableSchemas(connector, {
|
|
119
|
+
database: qualifiedName.database,
|
|
120
|
+
schema: qualifiedName.schema,
|
|
121
|
+
table: qualifiedName.table,
|
|
122
|
+
defaultDatabase: get().db.currentDatabase,
|
|
123
|
+
});
|
|
124
|
+
return table &&
|
|
125
|
+
table.table.table === qualifiedName.table &&
|
|
126
|
+
(!qualifiedName.schema ||
|
|
127
|
+
table.table.schema === qualifiedName.schema) &&
|
|
128
|
+
(!qualifiedName.database ||
|
|
129
|
+
table.table.database === qualifiedName.database)
|
|
130
|
+
? table
|
|
131
|
+
: undefined;
|
|
132
|
+
};
|
|
133
|
+
const throwIfUnresolvedExplicitDatabaseReference = (tableName, table) => {
|
|
134
|
+
if (table) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const database = typeof tableName === 'string'
|
|
138
|
+
? parseTableReferenceParts(tableName).database
|
|
139
|
+
: tableName.database;
|
|
140
|
+
if (!database) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const qualifiedName = isQualifiedTableName(tableName)
|
|
144
|
+
? get().db.qualifyTableName(tableName)
|
|
145
|
+
: get().db.qualifyTableName(parseTableReferenceParts(tableName));
|
|
146
|
+
throw new Error(`Relation "${qualifiedName}" not found.`);
|
|
109
147
|
};
|
|
110
148
|
return {
|
|
111
149
|
db: {
|
|
@@ -118,6 +156,16 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
118
156
|
tableRowCounts: {},
|
|
119
157
|
schemaTrees: undefined,
|
|
120
158
|
queryCache: {},
|
|
159
|
+
qualifyTableName(tableName) {
|
|
160
|
+
const { currentDatabase, currentSchema } = get().db;
|
|
161
|
+
const parts = typeof tableName === 'string' ? { table: tableName } : tableName;
|
|
162
|
+
return makeQualifiedTableName({
|
|
163
|
+
database: parts.database ?? currentDatabase,
|
|
164
|
+
schema: parts.schema ?? currentSchema,
|
|
165
|
+
table: parts.table,
|
|
166
|
+
defaultDatabase: parts.defaultDatabase ?? currentDatabase,
|
|
167
|
+
});
|
|
168
|
+
},
|
|
121
169
|
setConnector: (connector) => {
|
|
122
170
|
set(produce((state) => {
|
|
123
171
|
state.config.dataSources = [];
|
|
@@ -172,14 +220,13 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
172
220
|
async createTableFromQuery(tableName, query, options) {
|
|
173
221
|
const { replace = true, temp = false, view = false, allowMultipleStatements = false, abortSignal, } = options || {};
|
|
174
222
|
// For temp tables/views, DuckDB requires the "temp" database
|
|
175
|
-
const baseQualifiedName =
|
|
176
|
-
? tableName
|
|
177
|
-
: makeQualifiedTableName({ table: tableName });
|
|
223
|
+
const baseQualifiedName = get().db.qualifyTableName(tableName);
|
|
178
224
|
const qualifiedName = temp
|
|
179
225
|
? makeQualifiedTableName({
|
|
180
226
|
table: baseQualifiedName.table,
|
|
181
227
|
schema: baseQualifiedName.schema,
|
|
182
228
|
database: 'temp',
|
|
229
|
+
defaultDatabase: get().db.currentDatabase,
|
|
183
230
|
})
|
|
184
231
|
: baseQualifiedName;
|
|
185
232
|
const connector = await get().db.getConnector();
|
|
@@ -233,14 +280,14 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
233
280
|
* @deprecated Use .loadTableRowCount() instead
|
|
234
281
|
*/
|
|
235
282
|
async getTableRowCount(table, schema = 'main') {
|
|
236
|
-
return get().db.loadTableRowCount({ table, schema });
|
|
283
|
+
return get().db.loadTableRowCount(get().db.qualifyTableName({ table, schema }));
|
|
237
284
|
},
|
|
238
285
|
async loadTableRowCount(tableName) {
|
|
239
286
|
const { schema, database, table } = typeof tableName === 'string'
|
|
240
|
-
?
|
|
241
|
-
: tableName
|
|
287
|
+
? get().db.qualifyTableName(parseTableReferenceParts(tableName))
|
|
288
|
+
: get().db.qualifyTableName(tableName);
|
|
242
289
|
const connector = await get().db.getConnector();
|
|
243
|
-
const result = await connector.query(`SELECT COUNT(*) FROM ${
|
|
290
|
+
const result = await connector.query(`SELECT COUNT(*) FROM ${get().db.qualifyTableName({
|
|
244
291
|
schema,
|
|
245
292
|
database,
|
|
246
293
|
table,
|
|
@@ -258,19 +305,23 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
258
305
|
return loadTableSchemas(connector, {
|
|
259
306
|
...filter,
|
|
260
307
|
filterFunction: loadTableSchemasFilter,
|
|
308
|
+
defaultDatabase: get().db.currentDatabase,
|
|
261
309
|
});
|
|
262
310
|
},
|
|
263
311
|
async checkTableExists(tableName) {
|
|
264
|
-
const table =
|
|
312
|
+
const table = get().db.findTable(tableName) ??
|
|
313
|
+
(await loadTableSchemaByName(tableName));
|
|
265
314
|
return Boolean(table);
|
|
266
315
|
},
|
|
267
316
|
async dropRelation(tableName) {
|
|
268
317
|
const connector = await get().db.getConnector();
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
(
|
|
318
|
+
const table = get().db.findTable(tableName) ??
|
|
319
|
+
(await loadTableSchemaByName(tableName));
|
|
320
|
+
throwIfUnresolvedExplicitDatabaseReference(tableName, table);
|
|
321
|
+
const qualifiedTable = table?.table ??
|
|
322
|
+
(isQualifiedTableName(tableName)
|
|
323
|
+
? get().db.qualifyTableName(tableName)
|
|
324
|
+
: get().db.qualifyTableName(parseTableReferenceParts(tableName)));
|
|
274
325
|
const isView = table?.isView;
|
|
275
326
|
if (isView) {
|
|
276
327
|
await connector.query(`DROP VIEW IF EXISTS ${qualifiedTable};`);
|
|
@@ -282,11 +333,13 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
282
333
|
},
|
|
283
334
|
async dropTable(tableName) {
|
|
284
335
|
const connector = await get().db.getConnector();
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const
|
|
289
|
-
(
|
|
336
|
+
const table = get().db.findTable(tableName) ??
|
|
337
|
+
(await loadTableSchemaByName(tableName));
|
|
338
|
+
throwIfUnresolvedExplicitDatabaseReference(tableName, table);
|
|
339
|
+
const qualifiedTable = table?.table ??
|
|
340
|
+
(isQualifiedTableName(tableName)
|
|
341
|
+
? get().db.qualifyTableName(tableName)
|
|
342
|
+
: get().db.qualifyTableName(parseTableReferenceParts(tableName)));
|
|
290
343
|
if (table?.isView) {
|
|
291
344
|
throw new Error(`"${qualifiedTable}" is a view. Use dropRelation() to remove views.`);
|
|
292
345
|
}
|
|
@@ -294,9 +347,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
294
347
|
get().db.refreshTableSchemas();
|
|
295
348
|
},
|
|
296
349
|
async addTable(tableName, data) {
|
|
297
|
-
const qualifiedName =
|
|
298
|
-
? tableName
|
|
299
|
-
: makeQualifiedTableName({ table: tableName });
|
|
350
|
+
const qualifiedName = get().db.qualifyTableName(tableName);
|
|
300
351
|
const { db } = get();
|
|
301
352
|
if (data instanceof arrow.Table) {
|
|
302
353
|
// TODO: make sure the table is replaced
|
|
@@ -318,9 +369,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
318
369
|
return newTable;
|
|
319
370
|
},
|
|
320
371
|
async setTableRowCount(tableName, rowCount) {
|
|
321
|
-
const qualifiedName =
|
|
322
|
-
? tableName
|
|
323
|
-
: makeQualifiedTableName({ table: tableName });
|
|
372
|
+
const qualifiedName = get().db.qualifyTableName(tableName);
|
|
324
373
|
set((state) => produce(state, (draft) => {
|
|
325
374
|
draft.db.tableRowCounts[qualifiedName.toString()] = rowCount;
|
|
326
375
|
}));
|
|
@@ -335,14 +384,33 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
335
384
|
(!schema || t.table.schema === schema) &&
|
|
336
385
|
(!database || t.table.database === database))
|
|
337
386
|
: undefined;
|
|
338
|
-
const { table, schema,
|
|
387
|
+
const findUniqueMatchingTable = ({ table, schema, }) => {
|
|
388
|
+
if (!table)
|
|
389
|
+
return undefined;
|
|
390
|
+
const matches = tables.filter((t) => t.table.table === table &&
|
|
391
|
+
(!schema || t.table.schema === schema));
|
|
392
|
+
return matches.length === 1 ? matches[0] : undefined;
|
|
393
|
+
};
|
|
394
|
+
const resolvedTableName = typeof tableName === 'string'
|
|
395
|
+
? (parseQualifiedSqlIdentifier(tableName) ?? {})
|
|
396
|
+
: tableName;
|
|
397
|
+
const { table, schema, database, defaultDatabase } = {
|
|
339
398
|
schema: currentSchema,
|
|
340
399
|
database: currentDatabase,
|
|
341
|
-
...
|
|
342
|
-
? (parseQualifiedSqlIdentifier(tableName) ?? {})
|
|
343
|
-
: tableName),
|
|
400
|
+
...resolvedTableName,
|
|
344
401
|
};
|
|
345
|
-
|
|
402
|
+
const exactMatch = findMatchingTable({ table, schema, database });
|
|
403
|
+
if (exactMatch)
|
|
404
|
+
return exactMatch;
|
|
405
|
+
const isStaleDefaultDatabaseReference = typeof tableName !== 'string' &&
|
|
406
|
+
database &&
|
|
407
|
+
defaultDatabase &&
|
|
408
|
+
database === defaultDatabase &&
|
|
409
|
+
database !== currentDatabase;
|
|
410
|
+
if (isStaleDefaultDatabaseReference) {
|
|
411
|
+
return findUniqueMatchingTable({ table, schema });
|
|
412
|
+
}
|
|
413
|
+
return undefined;
|
|
346
414
|
},
|
|
347
415
|
findTableByName(tableName) {
|
|
348
416
|
return get().db.findTable(tableName);
|
|
@@ -362,16 +430,23 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
362
430
|
pendingSchemaRefresh = false;
|
|
363
431
|
const connector = await get().db.getConnector();
|
|
364
432
|
const result = await connector.query(`SELECT current_schema() AS schema, current_database() AS database`);
|
|
433
|
+
const currentSchemaValue = result.getChild('schema')?.get(0);
|
|
434
|
+
const currentDatabaseValue = result
|
|
435
|
+
.getChild('database')
|
|
436
|
+
?.get(0);
|
|
437
|
+
const currentSchema = currentSchemaValue == null
|
|
438
|
+
? undefined
|
|
439
|
+
: String(currentSchemaValue);
|
|
440
|
+
const currentDatabase = currentDatabaseValue == null
|
|
441
|
+
? undefined
|
|
442
|
+
: String(currentDatabaseValue);
|
|
365
443
|
set((state) => produce(state, (draft) => {
|
|
366
|
-
draft.db.currentSchema =
|
|
367
|
-
|
|
368
|
-
?.get(0);
|
|
369
|
-
draft.db.currentDatabase = result
|
|
370
|
-
.getChild('database')
|
|
371
|
-
?.get(0);
|
|
444
|
+
draft.db.currentSchema = currentSchema;
|
|
445
|
+
draft.db.currentDatabase = currentDatabase;
|
|
372
446
|
}));
|
|
373
447
|
schemasWithTables = await loadSchemaCatalog(connector, {
|
|
374
448
|
filterFunction: effectiveSchemaCatalogFilter,
|
|
449
|
+
defaultDatabase: currentDatabase,
|
|
375
450
|
});
|
|
376
451
|
} while (pendingSchemaRefresh);
|
|
377
452
|
const newTables = schemasWithTables.flatMap((s) => s.tables);
|
|
@@ -421,7 +496,12 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
|
|
|
421
496
|
set((state) => produce(state, (draft) => {
|
|
422
497
|
draft.db.queryCache[queryKey] = queryHandle;
|
|
423
498
|
}));
|
|
424
|
-
queryHandle.result
|
|
499
|
+
queryHandle.result
|
|
500
|
+
.catch(() => {
|
|
501
|
+
// Prevent unhandled promise rejection warnings.
|
|
502
|
+
// Callers handle errors via await/try-catch.
|
|
503
|
+
})
|
|
504
|
+
.finally(() => {
|
|
425
505
|
// remove from cache after completion
|
|
426
506
|
set((state) => produce(state, (draft) => {
|
|
427
507
|
delete draft.db.queryCache[queryKey];
|