muya 2.4.2 → 2.4.4
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/esm/sqlite/create-sqlite.js +1 -1
- package/esm/sqlite/select-sql.js +1 -1
- package/esm/sqlite/use-sqlite.js +1 -1
- package/package.json +1 -1
- package/src/sqlite/__tests__/use-sqlite.test.tsx +7 -7
- package/src/sqlite/create-sqlite.ts +74 -30
- package/src/sqlite/select-sql.ts +2 -2
- package/src/sqlite/use-sqlite.ts +13 -3
- package/types/sqlite/create-sqlite.d.ts +2 -1
- package/types/sqlite/use-sqlite.d.ts +8 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{STATE_SCHEDULER as
|
|
1
|
+
import{STATE_SCHEDULER as y}from"../create";import{getId as v}from"../utils/id";import{shallow as N}from"../utils/shallow";import{selectSql as C}from"./select-sql";import{createTable as M,DEFAULT_STEP_SIZE as B}from"./table/table";function L(g){const x=v();function u(e){return`state-${x}-search-${e}`}let f;async function r(){if(!f){const{backend:e,...t}=g,n=e instanceof Promise?await e:e;f=await M({backend:n,...t})}return f}const s=new Map,d=new Map,S=new Map;async function p(e,t,n){const a=S.get(e),{options:o={}}=t,{stepSize:c=B}=o;if(!a)return{isOk:!1};const i=[];n&&t.keys.clear();for(let h=0;h<c;h++){const l=await a.next();if(l.done){S.delete(e);break}t.keys.has(String(l.value.key))||(i.push(l.value.document),t.keys.add(String(l.value.key)))}return i.length===0?{isOk:!0,newItems:n?[]:t.items,isDone:!0}:N(t.items,i)?{isOk:!1}:n?{isOk:!0,newItems:i}:{newItems:[...t.items,...i],isOk:!0}}function w(e){const t=d.get(e);if(t)for(const[,n]of t)n()}async function O(e){const t=await r(),n=s.get(e);if(!n)return;const{options:a}=n,o=t.search({...a,select:(h,{rowId:l,key:P})=>({document:h,rowId:l,key:P})});S.set(e,o);const{isOk:c,newItems:i}=await p(e,n,!0);c&&(n.items=i)}async function b(e){await O(e),w(e)}function T(e){const{key:t,op:n}=e,a=new Set;for(const[o,{keys:c}]of s)switch(n){case"delete":case"update":{c.has(String(t))&&a.add(o);break}case"insert":{a.add(o);break}}return a}async function m(e){const t=new Set;for(const n of e){const a=T(n);for(const o of a)t.add(o)}for(const n of t){const a=u(n);y.schedule(a,{})}}const D=new Set;function I(e,t){if(!s.has(e)){const a={items:[],options:t,keys:new Set,wasInitialized:!1};s.set(e,a)}const n=s.get(e);return t&&(n.options=t),n}const k={load(e){const t=s.get(e);if(t&&!t.wasInitialized){t.wasInitialized=!0;const n=u(e);y.schedule(n,{searchId:e})}},clear(e){s.delete(e)},async set(e){const n=await(await r()).set(e);return await m([n]),n},async batchSet(e){const n=await(await r()).batchSet(e);return await m(n),n},async delete(e){const n=await(await r()).delete(e);return n&&await m([n]),n},async deleteBy(e){const n=await(await r()).deleteBy(e);return await m(n),n},async get(e,t){return(await r()).get(e,t)},async*search(e={}){const t=await r();for await(const n of t.search(e))yield n},async count(e){return await(await r()).count(e)},updateSearchOptions(e,t){const n=I(e,t);n.options=t;const a=u(e);y.schedule(a,{searchId:e})},subscribe(e,t,n){const a=u(e),o=y.add(a,{onScheduleDone(){b(e)}});this.load(e),D.add(o),d.has(e)||d.set(e,new Map);const c=d.get(e);return c.set(t,n),()=>{c.delete(t),c.size===0&&d.delete(e),o()}},getSnapshot(e){return I(e).items},refresh:b,destroy(){for(const e of D)e();s.clear(),d.clear()},async next(e){const t=s.get(e);if(t){const n=await p(e,t,!1);return n.isOk&&(t.items=n.newItems,w(e)),n.isDone??!1}return!1},select(e){return C(k,e)}};return k}export{L as createSqliteState};
|
package/esm/sqlite/select-sql.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createState as
|
|
1
|
+
import{createState as l}from"../create-state";let n=0;function o(){return n++,`${n.toString(36)}-sql`}function S(r,a){const{subscribe:c,updateSearchOptions:s}=r,m=o();return(...u)=>{const e=o(),p=c(e,m,()=>{t.emitter.emit()}),i=a(...u),t=l({destroy(){p(),t.emitter.clear(),t.cache.current=void 0},get(){return r.getSnapshot(e)},getSnapshot(){return r.getSnapshot(e)}});return s(e,i),t}}export{S as selectSql};
|
package/esm/sqlite/use-sqlite.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useCallback as
|
|
1
|
+
import{useCallback as f,useDebugValue as p,useEffect as a,useId as y,useLayoutEffect as D,useMemo as S}from"react";import{isError as h,isPromise as x}from"../utils/is";import{useSyncExternalStoreWithSelector as b}from"use-sync-external-store/shim/with-selector";function q(t){const{limit:o,offset:s,order:c,sortBy:e,where:i,stepSize:u,select:d}=t;let n="";return o!==void 0&&(n+=`l${o}`),s!==void 0&&(n+=`o${s}`),c!==void 0&&(n+=`r${c}`),e!==void 0&&(n+=`s${e}`),i!==void 0&&(n+=`w${JSON.stringify(i)}`),u!==void 0&&(n+=`t${u}`),d!==void 0&&(n+=`f${d.toString()}`),n}function w(t,o={},s=[]){const{select:c}=o,e=S(()=>q({...o,select:void 0}),[o]),i=y();D(()=>{t.updateSearchOptions(e,{...o,select:void 0})},s),a(()=>()=>{t.clear(e)},[]);const u=f(l=>c?l.map(c):l,[c]),d=f(l=>t.subscribe(e,i,l),[t,e,i]),n=f(()=>t.getSnapshot(e),[t,e]),r=b(d,n,n,u);if(p(r),x(r)||h(r))throw r;const m=S(()=>({next:()=>t.next(e),reset:()=>t.refresh(e)}),[e,t]);return[r,m]}export{w as useSqliteValue};
|
package/package.json
CHANGED
|
@@ -230,13 +230,13 @@ describe('use-sqlite-state', () => {
|
|
|
230
230
|
})
|
|
231
231
|
|
|
232
232
|
act(() => {
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
while (!result.current[1].next()) {
|
|
234
|
+
/* empty */
|
|
235
235
|
}
|
|
236
236
|
})
|
|
237
237
|
|
|
238
238
|
await waitFor(() => {
|
|
239
|
-
expect(reRenders).toBe(
|
|
239
|
+
expect(reRenders).toBe(3)
|
|
240
240
|
expect(result.current[0].length).toBe(ITEMS_COUNT)
|
|
241
241
|
})
|
|
242
242
|
|
|
@@ -244,7 +244,7 @@ describe('use-sqlite-state', () => {
|
|
|
244
244
|
result.current[1].reset()
|
|
245
245
|
})
|
|
246
246
|
await waitFor(() => {
|
|
247
|
-
expect(reRenders).toBe(
|
|
247
|
+
expect(reRenders).toBe(4)
|
|
248
248
|
expect(result.current[0].length).toBe(stepSize)
|
|
249
249
|
})
|
|
250
250
|
})
|
|
@@ -305,7 +305,7 @@ describe('use-sqlite-state', () => {
|
|
|
305
305
|
)
|
|
306
306
|
})
|
|
307
307
|
await waitFor(() => {
|
|
308
|
-
expect(reRenders).toBe(
|
|
308
|
+
expect(reRenders).toBe(1)
|
|
309
309
|
expect(result1.current[0].length).toBe(0)
|
|
310
310
|
})
|
|
311
311
|
|
|
@@ -341,7 +341,7 @@ describe('use-sqlite-state', () => {
|
|
|
341
341
|
})
|
|
342
342
|
|
|
343
343
|
await waitFor(() => {
|
|
344
|
-
expect(reRenders).toBe(
|
|
344
|
+
expect(reRenders).toBe(1)
|
|
345
345
|
expect(result.current[0].length).toBe(0)
|
|
346
346
|
})
|
|
347
347
|
|
|
@@ -358,7 +358,7 @@ describe('use-sqlite-state', () => {
|
|
|
358
358
|
sql.set({ person: { id: 'some_id', name: 'Alice', age: 31 } })
|
|
359
359
|
})
|
|
360
360
|
await waitFor(() => {
|
|
361
|
-
|
|
361
|
+
expect(reRenders).toBe(4)
|
|
362
362
|
expect(result.current[0]).toEqual([{ person: { id: 'some_id', name: 'Alice', age: 31 } }])
|
|
363
363
|
})
|
|
364
364
|
|
|
@@ -17,7 +17,7 @@ export interface CreateSqliteOptions<Document extends DocType> extends Omit<DbOp
|
|
|
17
17
|
export interface SyncTable<Document extends DocType> {
|
|
18
18
|
// readonly registerSearch: <Selected = Document>(searchId: SearchId, options: SearchOptions<Document, Selected>) => () => void
|
|
19
19
|
readonly updateSearchOptions: <Selected = Document>(searchId: SearchId, options: SearchOptions<Document, Selected>) => void
|
|
20
|
-
readonly subscribe: (searchId: SearchId, listener: () => void) => () => void
|
|
20
|
+
readonly subscribe: (searchId: SearchId, componentId: string, listener: () => void) => () => void
|
|
21
21
|
readonly getSnapshot: (searchId: SearchId) => Document[]
|
|
22
22
|
readonly refresh: (searchId: SearchId) => Promise<void>
|
|
23
23
|
|
|
@@ -32,16 +32,18 @@ export interface SyncTable<Document extends DocType> {
|
|
|
32
32
|
readonly destroy: () => void
|
|
33
33
|
readonly next: (searchId: SearchId) => Promise<boolean>
|
|
34
34
|
readonly clear: (searchId: SearchId) => void
|
|
35
|
+
readonly load: (searchId: SearchId) => void
|
|
35
36
|
|
|
36
37
|
readonly select: <Params extends unknown[]>(
|
|
37
38
|
compute: (...args: Params) => SearchOptions<Document>,
|
|
38
39
|
) => CreateState<Document, Params>
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
interface
|
|
42
|
+
interface CachedItem<Document extends DocType> {
|
|
42
43
|
items: Document[]
|
|
43
44
|
keys: Set<Key>
|
|
44
45
|
options?: SearchOptions<Document, unknown>
|
|
46
|
+
wasInitialized: boolean
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
/**
|
|
@@ -80,22 +82,40 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
80
82
|
key: Key
|
|
81
83
|
}
|
|
82
84
|
// const emitter = createEmitter<Table<Document>>()
|
|
83
|
-
const cachedData = new Map<SearchId,
|
|
84
|
-
const listeners = new Map<SearchId, () => void
|
|
85
|
+
const cachedData = new Map<SearchId, CachedItem<Document>>()
|
|
86
|
+
const listeners = new Map<SearchId, Map<string, () => void>>()
|
|
85
87
|
const iterators = new Map<SearchId, AsyncIterableIterator<NextResult>>()
|
|
86
88
|
|
|
89
|
+
interface GetNextBase {
|
|
90
|
+
readonly newItems?: Document[]
|
|
91
|
+
readonly isOk: boolean
|
|
92
|
+
readonly isDone?: boolean
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
interface GetNextTrue extends GetNextBase {
|
|
96
|
+
readonly isOk: true
|
|
97
|
+
readonly newItems: Document[]
|
|
98
|
+
}
|
|
99
|
+
interface GetNextFalse extends GetNextBase {
|
|
100
|
+
readonly isOk: false
|
|
101
|
+
}
|
|
102
|
+
type GetNext = GetNextTrue | GetNextFalse
|
|
87
103
|
/**
|
|
88
104
|
* Next step in the iterator
|
|
89
105
|
* @param searchId The search ID
|
|
90
106
|
* @param data The data items to process
|
|
107
|
+
* @param shouldReset Whether to reset the items
|
|
91
108
|
* @returns boolean indicating if new items were added
|
|
92
109
|
*/
|
|
93
|
-
async function
|
|
110
|
+
async function getNext(searchId: SearchId, data: CachedItem<Document>, shouldReset: boolean): Promise<GetNext> {
|
|
94
111
|
const iterator = iterators.get(searchId)
|
|
95
112
|
const { options: nextOptions = {} } = data
|
|
96
113
|
const { stepSize = DEFAULT_STEP_SIZE } = nextOptions
|
|
97
|
-
if (!iterator) return false
|
|
114
|
+
if (!iterator) return { isOk: false }
|
|
98
115
|
const newItems: Document[] = []
|
|
116
|
+
if (shouldReset) {
|
|
117
|
+
data.keys.clear()
|
|
118
|
+
}
|
|
99
119
|
|
|
100
120
|
for (let index = 0; index < stepSize; index++) {
|
|
101
121
|
const result = await iterator.next()
|
|
@@ -110,10 +130,10 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
110
130
|
}
|
|
111
131
|
}
|
|
112
132
|
|
|
113
|
-
if (newItems.length === 0) return
|
|
114
|
-
if (shallow(data.items, newItems)) return false
|
|
115
|
-
|
|
116
|
-
return true
|
|
133
|
+
if (newItems.length === 0) return { isOk: true, newItems: shouldReset ? [] : data.items, isDone: true }
|
|
134
|
+
if (shallow(data.items, newItems)) return { isOk: false }
|
|
135
|
+
if (shouldReset) return { isOk: true, newItems }
|
|
136
|
+
return { newItems: [...data.items, ...newItems], isOk: true }
|
|
117
137
|
}
|
|
118
138
|
|
|
119
139
|
/**
|
|
@@ -123,7 +143,9 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
123
143
|
function notifyListeners(searchId: SearchId) {
|
|
124
144
|
const searchListeners = listeners.get(searchId)
|
|
125
145
|
if (searchListeners) {
|
|
126
|
-
searchListeners
|
|
146
|
+
for (const [, listener] of searchListeners) {
|
|
147
|
+
listener()
|
|
148
|
+
}
|
|
127
149
|
}
|
|
128
150
|
}
|
|
129
151
|
|
|
@@ -138,9 +160,10 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
138
160
|
const { options: refreshOptions } = data
|
|
139
161
|
const iterator = table.search({ ...refreshOptions, select: (document, { rowId, key }) => ({ document, rowId, key }) })
|
|
140
162
|
iterators.set(searchId, iterator)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
163
|
+
const { isOk, newItems } = await getNext(searchId, data, true)
|
|
164
|
+
if (isOk) {
|
|
165
|
+
data.items = newItems
|
|
166
|
+
}
|
|
144
167
|
}
|
|
145
168
|
/**
|
|
146
169
|
* Refresh the data and notify listeners
|
|
@@ -156,7 +179,7 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
156
179
|
* @param mutationResult The mutation result
|
|
157
180
|
* @returns A set of search IDs that need to be updated
|
|
158
181
|
*/
|
|
159
|
-
function
|
|
182
|
+
function getChangedKeys(mutationResult: MutationResult) {
|
|
160
183
|
const { key, op } = mutationResult
|
|
161
184
|
// find all cached data with key
|
|
162
185
|
const searchIds = new Set<SearchId>()
|
|
@@ -186,16 +209,15 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
186
209
|
async function handleChanges(mutationResults: MutationResult[]) {
|
|
187
210
|
const updateSearchIds = new Set<SearchId>()
|
|
188
211
|
for (const mutationResult of mutationResults) {
|
|
189
|
-
const searchIds =
|
|
212
|
+
const searchIds = getChangedKeys(mutationResult)
|
|
190
213
|
for (const searchId of searchIds) {
|
|
191
214
|
updateSearchIds.add(searchId)
|
|
192
215
|
}
|
|
193
216
|
}
|
|
194
217
|
|
|
195
|
-
// const promises = []
|
|
196
218
|
for (const searchId of updateSearchIds) {
|
|
197
219
|
const scheduleId = getScheduleId(searchId)
|
|
198
|
-
STATE_SCHEDULER.schedule(scheduleId, {
|
|
220
|
+
STATE_SCHEDULER.schedule(scheduleId, {})
|
|
199
221
|
}
|
|
200
222
|
}
|
|
201
223
|
|
|
@@ -209,19 +231,32 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
209
231
|
*/
|
|
210
232
|
function registerData(searchId: SearchId, registerDataOptions?: SearchOptions<Document, unknown>) {
|
|
211
233
|
if (!cachedData.has(searchId)) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
234
|
+
const cachedItem: CachedItem<Document> = {
|
|
235
|
+
items: [],
|
|
236
|
+
options: registerDataOptions,
|
|
237
|
+
keys: new Set(),
|
|
238
|
+
wasInitialized: false,
|
|
215
239
|
}
|
|
240
|
+
cachedData.set(searchId, cachedItem)
|
|
216
241
|
}
|
|
217
|
-
const
|
|
242
|
+
const cachedItem = cachedData.get(searchId)!
|
|
243
|
+
|
|
218
244
|
if (registerDataOptions) {
|
|
219
|
-
|
|
245
|
+
cachedItem.options = registerDataOptions
|
|
220
246
|
}
|
|
221
|
-
return
|
|
247
|
+
return cachedItem
|
|
222
248
|
}
|
|
223
249
|
|
|
224
250
|
const state: SyncTable<Document> = {
|
|
251
|
+
load(searchId: SearchId) {
|
|
252
|
+
const cachedItem = cachedData.get(searchId)
|
|
253
|
+
if (!cachedItem) return
|
|
254
|
+
if (!cachedItem.wasInitialized) {
|
|
255
|
+
cachedItem.wasInitialized = true
|
|
256
|
+
const scheduleId = getScheduleId(searchId)
|
|
257
|
+
STATE_SCHEDULER.schedule(scheduleId, { searchId })
|
|
258
|
+
}
|
|
259
|
+
},
|
|
225
260
|
clear(searchId: SearchId) {
|
|
226
261
|
cachedData.delete(searchId)
|
|
227
262
|
},
|
|
@@ -273,20 +308,28 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
273
308
|
STATE_SCHEDULER.schedule(scheduleId, { searchId })
|
|
274
309
|
},
|
|
275
310
|
|
|
276
|
-
subscribe(searchId, listener) {
|
|
311
|
+
subscribe(searchId, componentId, listener) {
|
|
277
312
|
const scheduleId = getScheduleId(searchId)
|
|
278
313
|
const clearScheduler = STATE_SCHEDULER.add(scheduleId, {
|
|
279
314
|
onScheduleDone() {
|
|
280
315
|
refresh(searchId)
|
|
281
316
|
},
|
|
282
317
|
})
|
|
318
|
+
// console.log('Subscribing to searchId:', searchId)
|
|
319
|
+
this.load(searchId)
|
|
283
320
|
clearSchedulers.add(clearScheduler)
|
|
284
321
|
|
|
285
322
|
if (!listeners.has(searchId)) {
|
|
286
|
-
listeners.set(searchId,
|
|
323
|
+
listeners.set(searchId, new Map())
|
|
287
324
|
}
|
|
325
|
+
const searchListeners = listeners.get(searchId)!
|
|
326
|
+
searchListeners.set(componentId, listener)
|
|
327
|
+
|
|
288
328
|
return () => {
|
|
289
|
-
|
|
329
|
+
searchListeners.delete(componentId)
|
|
330
|
+
if (searchListeners.size === 0) {
|
|
331
|
+
listeners.delete(searchId)
|
|
332
|
+
}
|
|
290
333
|
clearScheduler()
|
|
291
334
|
}
|
|
292
335
|
},
|
|
@@ -303,11 +346,12 @@ export function createSqliteState<Document extends DocType>(options: CreateSqlit
|
|
|
303
346
|
async next(searchId) {
|
|
304
347
|
const data = cachedData.get(searchId)
|
|
305
348
|
if (data) {
|
|
306
|
-
const hasNext = await
|
|
307
|
-
if (hasNext) {
|
|
349
|
+
const hasNext = await getNext(searchId, data, false)
|
|
350
|
+
if (hasNext.isOk) {
|
|
351
|
+
data.items = hasNext.newItems
|
|
308
352
|
notifyListeners(searchId)
|
|
309
353
|
}
|
|
310
|
-
return hasNext
|
|
354
|
+
return hasNext.isDone ?? false
|
|
311
355
|
}
|
|
312
356
|
return false
|
|
313
357
|
},
|
package/src/sqlite/select-sql.ts
CHANGED
|
@@ -36,10 +36,10 @@ export function selectSql<Document extends DocType, Params extends unknown[] = [
|
|
|
36
36
|
compute: (...args: Params) => SqlSeachOptions<Document>,
|
|
37
37
|
): CreateState<Document, Params> {
|
|
38
38
|
const { subscribe, updateSearchOptions } = state
|
|
39
|
-
|
|
39
|
+
const componentId = getStateId()
|
|
40
40
|
const result: CreateState<Document, Params> = (...params) => {
|
|
41
41
|
const searchId = getStateId()
|
|
42
|
-
const destroy = subscribe(searchId, () => {
|
|
42
|
+
const destroy = subscribe(searchId, componentId, () => {
|
|
43
43
|
getState.emitter.emit()
|
|
44
44
|
})
|
|
45
45
|
|
package/src/sqlite/use-sqlite.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useDebugValue, useEffect, useLayoutEffect, useMemo, type DependencyList } from 'react'
|
|
1
|
+
import { useCallback, useDebugValue, useEffect, useId, useLayoutEffect, useMemo, type DependencyList } from 'react'
|
|
2
2
|
import type { SyncTable } from './create-sqlite'
|
|
3
3
|
import type { DocType } from './table/table.types'
|
|
4
4
|
import { isError, isPromise } from '../utils/is'
|
|
@@ -6,7 +6,15 @@ import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/w
|
|
|
6
6
|
import type { SqlSeachOptions } from './select-sql'
|
|
7
7
|
|
|
8
8
|
export interface SqLiteActions {
|
|
9
|
+
/**
|
|
10
|
+
* Load the next page of results and return if isDone to show more results.
|
|
11
|
+
* @returns isDone: boolean
|
|
12
|
+
*/
|
|
9
13
|
readonly next: () => Promise<boolean>
|
|
14
|
+
/**
|
|
15
|
+
* Reset the pagination and load the first page of results.
|
|
16
|
+
* @returns void
|
|
17
|
+
*/
|
|
10
18
|
readonly reset: () => Promise<void>
|
|
11
19
|
}
|
|
12
20
|
|
|
@@ -65,6 +73,7 @@ export function useSqliteValue<Document extends DocType, Selected = Document>(
|
|
|
65
73
|
const { select } = options
|
|
66
74
|
|
|
67
75
|
const searchId = useMemo(() => generateCacheKey({ ...options, select: undefined }), [options])
|
|
76
|
+
const componentId = useId()
|
|
68
77
|
|
|
69
78
|
useLayoutEffect(() => {
|
|
70
79
|
state.updateSearchOptions(searchId, { ...options, select: undefined })
|
|
@@ -72,6 +81,7 @@ export function useSqliteValue<Document extends DocType, Selected = Document>(
|
|
|
72
81
|
}, deps)
|
|
73
82
|
|
|
74
83
|
useEffect(() => {
|
|
84
|
+
// state.load(searchId)
|
|
75
85
|
return () => {
|
|
76
86
|
state.clear(searchId)
|
|
77
87
|
}
|
|
@@ -88,9 +98,9 @@ export function useSqliteValue<Document extends DocType, Selected = Document>(
|
|
|
88
98
|
|
|
89
99
|
const subscribe = useCallback(
|
|
90
100
|
(onStorageChange: () => void) => {
|
|
91
|
-
return state.subscribe(searchId, onStorageChange)
|
|
101
|
+
return state.subscribe(searchId, componentId, onStorageChange)
|
|
92
102
|
},
|
|
93
|
-
[state, searchId],
|
|
103
|
+
[state, searchId, componentId],
|
|
94
104
|
)
|
|
95
105
|
|
|
96
106
|
const getSnapshot = useCallback(() => {
|
|
@@ -8,7 +8,7 @@ export interface CreateSqliteOptions<Document extends DocType> extends Omit<DbOp
|
|
|
8
8
|
}
|
|
9
9
|
export interface SyncTable<Document extends DocType> {
|
|
10
10
|
readonly updateSearchOptions: <Selected = Document>(searchId: SearchId, options: SearchOptions<Document, Selected>) => void;
|
|
11
|
-
readonly subscribe: (searchId: SearchId, listener: () => void) => () => void;
|
|
11
|
+
readonly subscribe: (searchId: SearchId, componentId: string, listener: () => void) => () => void;
|
|
12
12
|
readonly getSnapshot: (searchId: SearchId) => Document[];
|
|
13
13
|
readonly refresh: (searchId: SearchId) => Promise<void>;
|
|
14
14
|
readonly set: (document: Document) => Promise<MutationResult>;
|
|
@@ -23,6 +23,7 @@ export interface SyncTable<Document extends DocType> {
|
|
|
23
23
|
readonly destroy: () => void;
|
|
24
24
|
readonly next: (searchId: SearchId) => Promise<boolean>;
|
|
25
25
|
readonly clear: (searchId: SearchId) => void;
|
|
26
|
+
readonly load: (searchId: SearchId) => void;
|
|
26
27
|
readonly select: <Params extends unknown[]>(compute: (...args: Params) => SearchOptions<Document>) => CreateState<Document, Params>;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
@@ -3,7 +3,15 @@ import type { SyncTable } from './create-sqlite';
|
|
|
3
3
|
import type { DocType } from './table/table.types';
|
|
4
4
|
import type { SqlSeachOptions } from './select-sql';
|
|
5
5
|
export interface SqLiteActions {
|
|
6
|
+
/**
|
|
7
|
+
* Load the next page of results and return if isDone to show more results.
|
|
8
|
+
* @returns isDone: boolean
|
|
9
|
+
*/
|
|
6
10
|
readonly next: () => Promise<boolean>;
|
|
11
|
+
/**
|
|
12
|
+
* Reset the pagination and load the first page of results.
|
|
13
|
+
* @returns void
|
|
14
|
+
*/
|
|
7
15
|
readonly reset: () => Promise<void>;
|
|
8
16
|
}
|
|
9
17
|
export interface UseSearchOptions<Document extends DocType, Selected = Document> extends SqlSeachOptions<Document> {
|