@livequery/client 2.0.23 → 2.0.24
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/build/Collection.js +61 -70
- package/package.json +1 -1
package/build/Collection.js
CHANGED
|
@@ -42,25 +42,23 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
42
42
|
set_realtime(realtime) {
|
|
43
43
|
this.collection_options.realtime = realtime;
|
|
44
44
|
}
|
|
45
|
-
#sync(stream,
|
|
45
|
+
#sync(stream, from, direction) {
|
|
46
|
+
if (from == 'realtime' && this.collection_options.realtime == false)
|
|
47
|
+
return;
|
|
46
48
|
const state = this.getValue();
|
|
47
|
-
const
|
|
48
|
-
const actions = { update: false, reindex: false };
|
|
49
|
+
const actions = { reindex: false };
|
|
49
50
|
for (const { data, error, code, message, } of stream) {
|
|
50
|
-
if (
|
|
51
|
+
if (from == 'request') {
|
|
51
52
|
state.loading = false;
|
|
52
|
-
actions.update = true;
|
|
53
53
|
}
|
|
54
54
|
// Error & paging
|
|
55
55
|
if (error) {
|
|
56
56
|
state.error = true;
|
|
57
57
|
state.code = code;
|
|
58
58
|
state.message = message;
|
|
59
|
-
actions.update = true;
|
|
60
59
|
}
|
|
61
60
|
if (data?.summary) {
|
|
62
61
|
state.summary = data.summary;
|
|
63
|
-
actions.update = true;
|
|
64
62
|
}
|
|
65
63
|
// Sync
|
|
66
64
|
for (const change of data?.changes || []) {
|
|
@@ -72,35 +70,32 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
72
70
|
if (index == -1 && type == 'added') {
|
|
73
71
|
if (
|
|
74
72
|
// Is first value from HTTP query
|
|
75
|
-
|
|
73
|
+
from == 'request'
|
|
76
74
|
|| (
|
|
77
75
|
// Is realtime update that match filters
|
|
78
|
-
|
|
76
|
+
from == 'realtime' && Object
|
|
79
77
|
.keys(state.options || {})
|
|
80
78
|
.filter(key => !key.includes('_'))
|
|
81
79
|
.every(key => {
|
|
80
|
+
const [field, expression] = key.split(':');
|
|
81
|
+
const a = payload[field];
|
|
82
|
+
const b = state.options?.[field];
|
|
83
|
+
const map = {
|
|
84
|
+
'default': () => a == b,
|
|
85
|
+
eq: () => a == b,
|
|
86
|
+
ne: () => a != b,
|
|
87
|
+
lt: () => typeof a == 'number' && typeof b == 'number' && a < b,
|
|
88
|
+
lte: () => typeof a == 'number' && typeof b == 'number' && a <= b,
|
|
89
|
+
gt: () => typeof a == 'number' && typeof b == 'number' && a > b,
|
|
90
|
+
gte: () => typeof a == 'number' && typeof b == 'number' && a >= b,
|
|
91
|
+
in: () => Array.isArray(a) && a?.includes(b),
|
|
92
|
+
like: () => typeof a == 'string' && a.includes(`${b}`),
|
|
93
|
+
between: () => typeof a == 'number' && Array.isArray(b) && typeof b[0] == 'number' && b[0] <= a && typeof b[1] == 'number' && a <= b[1]
|
|
94
|
+
};
|
|
82
95
|
try {
|
|
83
|
-
const [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (!expression)
|
|
87
|
-
return a == b;
|
|
88
|
-
if (expression == 'ne')
|
|
89
|
-
return a != b;
|
|
90
|
-
if (expression == 'lt')
|
|
91
|
-
return typeof a == 'number' && typeof b == 'number' && a < b;
|
|
92
|
-
if (expression == 'lte')
|
|
93
|
-
return typeof a == 'number' && typeof b == 'number' && a <= b;
|
|
94
|
-
if (expression == 'gt')
|
|
95
|
-
return typeof a == 'number' && typeof b == 'number' && a > b;
|
|
96
|
-
if (expression == 'gte')
|
|
97
|
-
return typeof a == 'number' && typeof b == 'number' && a >= b;
|
|
98
|
-
if (expression == 'in' || expression == 'like')
|
|
99
|
-
return Array.isArray(a) && a?.includes(b);
|
|
100
|
-
if (expression == 'between') {
|
|
101
|
-
const [x, y] = b;
|
|
102
|
-
return x <= a && a <= y;
|
|
103
|
-
}
|
|
96
|
+
const fn = map[expression || 'default'];
|
|
97
|
+
if (fn)
|
|
98
|
+
return fn();
|
|
104
99
|
}
|
|
105
100
|
catch (e) { }
|
|
106
101
|
return false;
|
|
@@ -119,12 +114,10 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
119
114
|
};
|
|
120
115
|
direction == 'forward' ? state.items.push(item) : state.items.unshift(item);
|
|
121
116
|
actions.reindex = true;
|
|
122
|
-
actions.update = true;
|
|
123
117
|
}
|
|
124
118
|
}
|
|
125
|
-
if (index >= 0
|
|
119
|
+
if (index >= 0) {
|
|
126
120
|
if (type == 'added' || type == 'modified') {
|
|
127
|
-
actions.update = true;
|
|
128
121
|
const sort_key_value_updated = this.#sorters.some(({ key }) => {
|
|
129
122
|
const value = payload[key];
|
|
130
123
|
if (typeof value == 'string' || typeof value == 'number')
|
|
@@ -142,7 +135,6 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
142
135
|
};
|
|
143
136
|
}
|
|
144
137
|
if (type == 'removed') {
|
|
145
|
-
actions.update = true;
|
|
146
138
|
state.items.splice(index, 1);
|
|
147
139
|
for (const [document_id, i] of this.#IdMap) {
|
|
148
140
|
i == index && this.#IdMap.delete(document_id);
|
|
@@ -206,23 +198,30 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
206
198
|
}
|
|
207
199
|
};
|
|
208
200
|
}
|
|
209
|
-
|
|
201
|
+
this.next(state);
|
|
210
202
|
}
|
|
211
203
|
fetch_data(options = {}, loading, flush = false) {
|
|
204
|
+
if (flush) {
|
|
205
|
+
this.#pages.clear();
|
|
206
|
+
this.#queries.forEach(s => s.unsubscribe());
|
|
207
|
+
this.#queries.clear();
|
|
208
|
+
this.#IdMap.clear();
|
|
209
|
+
}
|
|
212
210
|
if (!this.ref)
|
|
213
211
|
return;
|
|
214
212
|
if (this.#refs.length == 0)
|
|
215
213
|
return;
|
|
216
|
-
if (this.getValue().loading)
|
|
214
|
+
if (this.getValue().loading && !flush)
|
|
217
215
|
return;
|
|
218
|
-
this.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return
|
|
216
|
+
const remain_data_refs = this.#refs.filter(ref => {
|
|
217
|
+
const paging = this.#pages.get(ref);
|
|
218
|
+
if (!paging)
|
|
219
|
+
return true;
|
|
220
|
+
return loading == 'forward' ? paging.has?.next : paging.has?.prev;
|
|
223
221
|
});
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
if (remain_data_refs.length == 0)
|
|
223
|
+
return;
|
|
224
|
+
this.next({
|
|
226
225
|
...this.getValue(),
|
|
227
226
|
items: flush ? [] : this.getValue().items,
|
|
228
227
|
loading,
|
|
@@ -230,23 +229,14 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
230
229
|
...this.getValue().options || {},
|
|
231
230
|
...options
|
|
232
231
|
}
|
|
233
|
-
};
|
|
234
|
-
if (flush) {
|
|
235
|
-
this.#pages.clear();
|
|
236
|
-
this.#queries.forEach(s => s.unsubscribe());
|
|
237
|
-
this.#queries.clear();
|
|
238
|
-
this.#IdMap.clear();
|
|
239
|
-
}
|
|
240
|
-
const remain_data_refs = this.#refs.filter(ref => {
|
|
241
|
-
const paging = this.#pages.get(ref);
|
|
242
|
-
if (!paging)
|
|
243
|
-
return true;
|
|
244
|
-
return loading == 'forward' ? paging.has?.next : paging.has?.prev;
|
|
245
232
|
});
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
233
|
+
this.collection_options.options = options;
|
|
234
|
+
this.#sorters = Object.keys(options).filter(k => k.endsWith(':sort')).map(k => {
|
|
235
|
+
const key = k.split(':sort')[0];
|
|
236
|
+
const order = options[k] == 1 ? 1 : -1;
|
|
237
|
+
return { key, order };
|
|
238
|
+
});
|
|
239
|
+
this.#sorters.every(a => a.key != 'id') && this.#sorters.push({ key: 'id', order: -1 });
|
|
250
240
|
const queries = remain_data_refs.map((ref, index) => {
|
|
251
241
|
const cursor = this.#pages.get(ref)?.cursor;
|
|
252
242
|
const opts = {
|
|
@@ -262,8 +252,8 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
262
252
|
ref
|
|
263
253
|
})), share());
|
|
264
254
|
});
|
|
265
|
-
const first_values = merge(...queries.map(q => q.pipe(filter(r => !!r.data?.paging || !!r.error), first()))).pipe(toArray(), tap(list => this.#sync(list,
|
|
266
|
-
const subscription = merge(...queries.map(q => q.pipe(skip(1)))).pipe(bufferTime(this.collection_options?.sync_delay || 500), filter(list => list.length > 0), map(data => this.#sync(data,
|
|
255
|
+
const first_values = merge(...queries.map(q => q.pipe(filter(r => !!r.data?.paging || !!r.error), first()))).pipe(toArray(), tap(list => this.#sync(list, 'request', loading))).subscribe();
|
|
256
|
+
const subscription = merge(...queries.map(q => q.pipe(skip(1)))).pipe(bufferTime(this.collection_options?.sync_delay || 500), filter(list => list.length > 0), map(data => this.#sync(data, 'realtime', loading)), finalize(() => first_values.unsubscribe())).subscribe();
|
|
267
257
|
this.#queries.add(subscription);
|
|
268
258
|
}
|
|
269
259
|
reset() {
|
|
@@ -282,17 +272,18 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
282
272
|
}
|
|
283
273
|
#find_ref_by_id(id) {
|
|
284
274
|
if (!id || !this.ref)
|
|
285
|
-
return { ref: this.ref, collection_ref: this.ref };
|
|
275
|
+
return { ref: this.ref, collection_ref: this.ref, doc: null };
|
|
286
276
|
const index = this.#IdMap.get(id);
|
|
287
277
|
if (index == undefined)
|
|
288
278
|
return {};
|
|
289
|
-
const
|
|
279
|
+
const doc = this.getValue().items[index];
|
|
280
|
+
const origin_ref = doc.__ref;
|
|
290
281
|
if (!origin_ref)
|
|
291
282
|
throw 'COLLECTION_REF_NOT_FOUND';
|
|
292
283
|
const refs = origin_ref.split('/');
|
|
293
284
|
const collection_ref = refs.slice(0, refs.length - (refs.length % 2 == 1 ? 0 : 1)).join('/');
|
|
294
285
|
const ref = `${collection_ref}/${id}`;
|
|
295
|
-
return { ref, id, collection_ref, index };
|
|
286
|
+
return { ref, id, collection_ref, index, doc };
|
|
296
287
|
}
|
|
297
288
|
async add(payload) {
|
|
298
289
|
const r = await this.collection_options.transporter.add(`${this.ref}`, payload);
|
|
@@ -302,7 +293,7 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
302
293
|
return r;
|
|
303
294
|
}
|
|
304
295
|
async update({ id: update_payload_id, ...payload }) {
|
|
305
|
-
const { id, ref } = this.#find_ref_by_id(update_payload_id);
|
|
296
|
+
const { id, ref, doc } = this.#find_ref_by_id(update_payload_id);
|
|
306
297
|
if (!ref)
|
|
307
298
|
return;
|
|
308
299
|
// Trigger local update
|
|
@@ -315,7 +306,7 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
315
306
|
type: 'modified'
|
|
316
307
|
}]
|
|
317
308
|
}
|
|
318
|
-
}],
|
|
309
|
+
}], 'local');
|
|
319
310
|
try {
|
|
320
311
|
return await this.collection_options.transporter.update(ref, payload);
|
|
321
312
|
}
|
|
@@ -324,12 +315,12 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
324
315
|
ref,
|
|
325
316
|
data: {
|
|
326
317
|
changes: [{
|
|
327
|
-
data: { id, __updating: false },
|
|
318
|
+
data: { ...doc || {}, id, __updating: false },
|
|
328
319
|
ref,
|
|
329
320
|
type: 'modified'
|
|
330
321
|
}]
|
|
331
322
|
}
|
|
332
|
-
}],
|
|
323
|
+
}], 'local');
|
|
333
324
|
throw e;
|
|
334
325
|
}
|
|
335
326
|
}
|
|
@@ -346,7 +337,7 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
346
337
|
type: 'modified'
|
|
347
338
|
}]
|
|
348
339
|
}
|
|
349
|
-
}],
|
|
340
|
+
}], 'local');
|
|
350
341
|
// Trigger
|
|
351
342
|
try {
|
|
352
343
|
return await this.collection_options.transporter.remove(ref);
|
|
@@ -361,7 +352,7 @@ export class CollectionObservable extends BehaviorSubject {
|
|
|
361
352
|
type: 'modified'
|
|
362
353
|
}]
|
|
363
354
|
}
|
|
364
|
-
}],
|
|
355
|
+
}], 'local');
|
|
365
356
|
throw e;
|
|
366
357
|
}
|
|
367
358
|
}
|