@ngutil/data 0.0.18 → 0.0.19
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/esm2022/provider/local.mjs +1 -1
- package/esm2022/provider/provider.mjs +1 -1
- package/esm2022/query/common.mjs +33 -0
- package/esm2022/query/executor.mjs +1 -1
- package/esm2022/query/filter.mjs +82 -109
- package/esm2022/query/grouper.mjs +19 -1
- package/esm2022/query/index.mjs +4 -3
- package/esm2022/query/query-property.mjs +28 -61
- package/esm2022/query/query.mjs +19 -6
- package/esm2022/query/slimer.mjs +18 -1
- package/esm2022/query/sorter.mjs +67 -36
- package/esm2022/source/proxy.directive.mjs +11 -15
- package/esm2022/source/source.mjs +23 -24
- package/fesm2022/ngutil-data.mjs +309 -294
- package/fesm2022/ngutil-data.mjs.map +1 -1
- package/package.json +8 -8
- package/provider/local.d.ts +5 -5
- package/provider/provider.d.ts +4 -4
- package/query/common.d.ts +2 -0
- package/query/executor.d.ts +2 -2
- package/query/filter.d.ts +32 -0
- package/query/grouper.d.ts +11 -0
- package/query/index.d.ts +3 -3
- package/query/query-property.d.ts +14 -19
- package/query/query.d.ts +14 -12
- package/query/slimer.d.ts +12 -2
- package/query/sorter.d.ts +16 -3
- package/source/proxy.directive.d.ts +1 -1
- package/source/source.d.ts +7 -14
- package/esm2022/source/properties/abstract.mjs +0 -33
- package/esm2022/source/properties/filter.mjs +0 -16
- package/esm2022/source/properties/grouper.mjs +0 -16
- package/esm2022/source/properties/index.mjs +0 -5
- package/esm2022/source/properties/slimer.mjs +0 -16
- package/esm2022/source/properties/sorter.mjs +0 -43
- package/source/properties/abstract.d.ts +0 -17
- package/source/properties/filter.d.ts +0 -11
- package/source/properties/grouper.d.ts +0 -11
- package/source/properties/index.d.ts +0 -4
- package/source/properties/slimer.d.ts +0 -11
- package/source/properties/sorter.d.ts +0 -20
package/fesm2022/ngutil-data.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { flattenDepth, intersection, flattenDeep
|
|
1
|
+
import { flattenDepth, isEqual, intersection, flattenDeep } from 'lodash';
|
|
2
2
|
import * as i1 from '@ngutil/common';
|
|
3
|
-
import {
|
|
4
|
-
import { BehaviorSubject,
|
|
3
|
+
import { deepClone, deepFreeze, isPlainObject, toSorted } from '@ngutil/common';
|
|
4
|
+
import { BehaviorSubject, Observable, combineLatest, map, shareReplay, take, of, ReplaySubject, switchMap, distinctUntilChanged, tap, debounceTime, finalize, Subject, takeUntil, share, Subscription, throwError } from 'rxjs';
|
|
5
5
|
import { DataSource as DataSource$1 } from '@angular/cdk/collections';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
7
|
import { Directive, Optional, Input } from '@angular/core';
|
|
@@ -24,6 +24,91 @@ function makeGetter(part, parent) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function readonlyProp(o, n, v) {
|
|
28
|
+
Object.defineProperty(o, n, {
|
|
29
|
+
value: v,
|
|
30
|
+
configurable: false,
|
|
31
|
+
enumerable: true,
|
|
32
|
+
writable: false
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const NORMALIZED = Symbol("NORMALIZED");
|
|
36
|
+
const IS_NORMALIZED = Symbol("IS_NORMALIZED");
|
|
37
|
+
function normalize(obj, normalizer) {
|
|
38
|
+
if (obj[IS_NORMALIZED]) {
|
|
39
|
+
return obj;
|
|
40
|
+
}
|
|
41
|
+
if (obj[NORMALIZED] == null) {
|
|
42
|
+
const normalized = normalizer(obj);
|
|
43
|
+
Object.defineProperty(obj, NORMALIZED, {
|
|
44
|
+
value: normalized,
|
|
45
|
+
configurable: false,
|
|
46
|
+
enumerable: false,
|
|
47
|
+
writable: false
|
|
48
|
+
});
|
|
49
|
+
Object.defineProperty(normalize, IS_NORMALIZED, {
|
|
50
|
+
value: true,
|
|
51
|
+
configurable: false,
|
|
52
|
+
enumerable: false,
|
|
53
|
+
writable: false
|
|
54
|
+
});
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
return obj[NORMALIZED];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class QueryProperty extends BehaviorSubject {
|
|
61
|
+
set(value) {
|
|
62
|
+
this.#nextClone(value != null ? this.norm(value) : undefined);
|
|
63
|
+
}
|
|
64
|
+
update(value) {
|
|
65
|
+
const norm = value != null ? this.norm(value) : undefined;
|
|
66
|
+
if (!isEqual(this.value, norm)) {
|
|
67
|
+
this.#next(this.merge(this.value, norm));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
del() {
|
|
71
|
+
this.set(undefined);
|
|
72
|
+
}
|
|
73
|
+
#next(value) {
|
|
74
|
+
if (!isEqual(this.value, value)) {
|
|
75
|
+
if (value == null) {
|
|
76
|
+
this.next(undefined);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.next(value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
#nextClone(value) {
|
|
84
|
+
if (!isEqual(this.value, value)) {
|
|
85
|
+
if (value == null) {
|
|
86
|
+
this.next(undefined);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.next(deepClone(value));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
class QueryPropertySet extends Observable {
|
|
95
|
+
#combined;
|
|
96
|
+
constructor(...names) {
|
|
97
|
+
super(dest => this.#combined.subscribe(dest));
|
|
98
|
+
const observables = [];
|
|
99
|
+
const props = {};
|
|
100
|
+
for (const name of names) {
|
|
101
|
+
const o = this.newProperty();
|
|
102
|
+
observables.push(o);
|
|
103
|
+
props[name] = o;
|
|
104
|
+
}
|
|
105
|
+
this.#combined = combineLatest(observables).pipe(map(values => deepFreeze(this.merge(...values))), shareReplay(1));
|
|
106
|
+
for (const [k, v] of Object.entries(props)) {
|
|
107
|
+
readonlyProp(this, k, v);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
27
112
|
const OPERATORS = [
|
|
28
113
|
"==" /* FilterOp.Eq */,
|
|
29
114
|
"===" /* FilterOp.EqStrict */,
|
|
@@ -70,107 +155,81 @@ function asOperators(value) {
|
|
|
70
155
|
function filterBy(filters) {
|
|
71
156
|
return _filterCompile(filters);
|
|
72
157
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// return _normalizeFilter(filters)
|
|
87
|
-
// }
|
|
88
|
-
// function _normalizeFilter(filters: any, path?: string): any {
|
|
89
|
-
// const result = {} as any
|
|
90
|
-
// for (const [path, v] of Object.entries(filters)) {
|
|
91
|
-
// switch (path) {
|
|
92
|
-
// case FilterOp.And:
|
|
93
|
-
// if (!Array.isArray(v)) {
|
|
94
|
-
// throw new Error("The '&' (AND) operator must have array type")
|
|
95
|
-
// }
|
|
96
|
-
// if (!result[FilterOp.And]) {
|
|
97
|
-
// result[FilterOp.And] = []
|
|
98
|
-
// }
|
|
99
|
-
// result[FilterOp.And] = result[FilterOp.And].concat(v.map(f => _normalizeFilter(f)))
|
|
100
|
-
// break
|
|
101
|
-
// case FilterOp.Or:
|
|
102
|
-
// if (!Array.isArray(v)) {
|
|
103
|
-
// throw new Error("The '|' (OR) operator must have array type")
|
|
104
|
-
// }
|
|
105
|
-
// if (!result[FilterOp.Or]) {
|
|
106
|
-
// result[FilterOp.Or] = []
|
|
107
|
-
// }
|
|
108
|
-
// result[FilterOp.Or] = result[FilterOp.Or].concat(v.map(f => _normalizeFilter(f)))
|
|
109
|
-
// break
|
|
110
|
-
// default:
|
|
111
|
-
// for (const entry of asOperators(v)) {
|
|
112
|
-
// switch (entry.op) {
|
|
113
|
-
// case FilterOp.And:
|
|
114
|
-
// if (!result[FilterOp.And]) {
|
|
115
|
-
// result[FilterOp.And] = []
|
|
116
|
-
// }
|
|
117
|
-
// result[FilterOp.And] = result[FilterOp.And].concat(
|
|
118
|
-
// entry.value.map((v: any) => _normalizeFilter(v, path))
|
|
119
|
-
// )
|
|
120
|
-
// break
|
|
121
|
-
// case FilterOp.Or:
|
|
122
|
-
// if (!result[FilterOp.Or]) {
|
|
123
|
-
// result[FilterOp.Or] = []
|
|
124
|
-
// }
|
|
125
|
-
// result[FilterOp.Or] = result[FilterOp.Or].concat(
|
|
126
|
-
// entry.value.map((v: any) => _normalizeFilter(v, path))
|
|
127
|
-
// )
|
|
128
|
-
// break
|
|
129
|
-
// default:
|
|
130
|
-
// if (!result[FilterOp.And]) {
|
|
131
|
-
// result[FilterOp.And] = []
|
|
132
|
-
// }
|
|
133
|
-
// result[FilterOp.And].push({ path, ...entry })
|
|
134
|
-
// }
|
|
135
|
-
// }
|
|
136
|
-
// }
|
|
137
|
-
// }
|
|
138
|
-
// return result
|
|
139
|
-
// }
|
|
140
|
-
function _filterCompile(filters) {
|
|
141
|
-
let getter;
|
|
142
|
-
const result = [];
|
|
143
|
-
for (const [pth, value] of Object.entries(filters)) {
|
|
144
|
-
switch (pth) {
|
|
158
|
+
/**
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* filterNormalize({id: {">": 0, "<": 10}})
|
|
162
|
+
* {op: "&", value: [{path: "id", op: ">", value: 0}, {path: "id", op: "<", value: 10}]}
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
function filterNormalize(filters) {
|
|
166
|
+
return _normalizeFilter(filters);
|
|
167
|
+
}
|
|
168
|
+
function _normalizeFilter(filters, parent) {
|
|
169
|
+
const norm = flattenDeep(Object.entries(filters).map(([path, value]) => {
|
|
170
|
+
switch (path) {
|
|
145
171
|
case "&" /* FilterOp.And */:
|
|
146
172
|
if (!Array.isArray(value)) {
|
|
147
|
-
throw new Error("
|
|
173
|
+
throw new Error(`Operator AND (${"&" /* FilterOp.And */}) must have array type`);
|
|
148
174
|
}
|
|
149
|
-
|
|
150
|
-
break;
|
|
175
|
+
return { op: "&" /* FilterOp.And */, value: value.map(v => _normalizeFilter(v, parent)) };
|
|
151
176
|
case "|" /* FilterOp.Or */:
|
|
152
177
|
if (!Array.isArray(value)) {
|
|
153
|
-
throw new Error("
|
|
178
|
+
throw new Error(`Operator OR (${"|" /* FilterOp.Or */}) must have array type`);
|
|
154
179
|
}
|
|
155
|
-
|
|
156
|
-
|
|
180
|
+
return { op: "|" /* FilterOp.Or */, value: value.map(v => _normalizeFilter(v, parent)) };
|
|
181
|
+
// TODO: check all filter, and if not found filter key, taht object maybne not a filter
|
|
157
182
|
default:
|
|
158
|
-
getter = pathGetterCompile(pth);
|
|
159
183
|
if (isPlainObject(value)) {
|
|
160
|
-
|
|
184
|
+
return _normalizeFilter(value, path);
|
|
185
|
+
}
|
|
186
|
+
if (parent != null) {
|
|
187
|
+
return { path: parent, op: path, value };
|
|
161
188
|
}
|
|
162
189
|
else {
|
|
163
|
-
|
|
190
|
+
return { path, op: "===" /* FilterOp.EqStrict */, value };
|
|
164
191
|
}
|
|
165
|
-
break;
|
|
166
192
|
}
|
|
193
|
+
}));
|
|
194
|
+
if (norm.length === 0) {
|
|
195
|
+
return norm;
|
|
196
|
+
}
|
|
197
|
+
else if (norm.length === 1) {
|
|
198
|
+
return norm[0];
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
return { op: "&" /* FilterOp.And */, value: norm };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function _filterCompile(filters) {
|
|
205
|
+
const pathCache = {};
|
|
206
|
+
const getPath = (pth) => {
|
|
207
|
+
if (pathCache[pth] != null) {
|
|
208
|
+
return pathCache[pth];
|
|
209
|
+
}
|
|
210
|
+
return (pathCache[pth] = pathGetterCompile(pth));
|
|
211
|
+
};
|
|
212
|
+
const normalized = filterNormalize(filters);
|
|
213
|
+
return _filterCompileNorm(normalized, getPath);
|
|
214
|
+
}
|
|
215
|
+
function _filterCompileNorm(filter, getPath) {
|
|
216
|
+
switch (filter.op) {
|
|
217
|
+
case "&" /* FilterOp.And */:
|
|
218
|
+
return and_(filter.value.map(v => _filterCompileNorm(v, getPath)));
|
|
219
|
+
case "|" /* FilterOp.Or */:
|
|
220
|
+
return or_(filter.value.map(v => _filterCompileNorm(v, getPath)));
|
|
221
|
+
default:
|
|
222
|
+
return _filterComplileNormPath(getPath(filter.path), filter.op, filter.value, getPath);
|
|
167
223
|
}
|
|
168
|
-
return and_(result);
|
|
169
224
|
}
|
|
170
|
-
function
|
|
225
|
+
function _filterComplileNormPath(getter, op, value, getPath) {
|
|
171
226
|
let lower;
|
|
172
227
|
let regex;
|
|
173
228
|
switch (op) {
|
|
229
|
+
case "&" /* FilterOp.And */:
|
|
230
|
+
return and_(value.map(v => _filterCompileNorm(v, getPath)));
|
|
231
|
+
case "|" /* FilterOp.Or */:
|
|
232
|
+
return or_(value.map(v => _filterCompileNorm(v, getPath)));
|
|
174
233
|
case "==" /* FilterOp.Eq */:
|
|
175
234
|
// eslint-disable-next-line eqeqeq
|
|
176
235
|
return matcher(getter, v => v == value);
|
|
@@ -231,30 +290,6 @@ function filterCompileOp(getter, op, value) {
|
|
|
231
290
|
case "~*" /* FilterOp.RegexpInsesitive */:
|
|
232
291
|
regex = value instanceof RegExp ? value : new RegExp(value, "msvi");
|
|
233
292
|
return matcher(getter, v => regex.test(v));
|
|
234
|
-
case "&" /* FilterOp.And */:
|
|
235
|
-
if (!Array.isArray(value)) {
|
|
236
|
-
throw new Error("Root '&' (AND) operator must have array type");
|
|
237
|
-
}
|
|
238
|
-
return and_(flattenDeep(value.map(v => {
|
|
239
|
-
if (isPlainObject(v)) {
|
|
240
|
-
return Object.entries(v).map(([op, opv]) => filterCompileOp(getter, op, opv));
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
return filterCompileOp(getter, "==" /* FilterOp.Eq */, v);
|
|
244
|
-
}
|
|
245
|
-
})));
|
|
246
|
-
case "|" /* FilterOp.Or */:
|
|
247
|
-
if (!Array.isArray(value)) {
|
|
248
|
-
throw new Error("Root '|' (OR) operator must have array type");
|
|
249
|
-
}
|
|
250
|
-
return or_(flattenDeep(value.map(v => {
|
|
251
|
-
if (isPlainObject(v)) {
|
|
252
|
-
return Object.entries(v).map(([op, opv]) => filterCompileOp(getter, op, opv));
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
return filterCompileOp(getter, "==" /* FilterOp.Eq */, v);
|
|
256
|
-
}
|
|
257
|
-
})));
|
|
258
293
|
}
|
|
259
294
|
throw new Error(`Unexpected operator: ${op}`);
|
|
260
295
|
}
|
|
@@ -265,6 +300,9 @@ function and_(fns) {
|
|
|
265
300
|
if (fns.length === 0) {
|
|
266
301
|
return _ => true;
|
|
267
302
|
}
|
|
303
|
+
if (fns.length === 1) {
|
|
304
|
+
return fns[0];
|
|
305
|
+
}
|
|
268
306
|
return item => {
|
|
269
307
|
for (const fn of fns) {
|
|
270
308
|
if (!fn(item)) {
|
|
@@ -278,6 +316,9 @@ function or_(fns) {
|
|
|
278
316
|
if (fns.length === 0) {
|
|
279
317
|
return _ => true;
|
|
280
318
|
}
|
|
319
|
+
if (fns.length === 1) {
|
|
320
|
+
return fns[0];
|
|
321
|
+
}
|
|
281
322
|
return item => {
|
|
282
323
|
for (const fn of fns) {
|
|
283
324
|
if (fn(item)) {
|
|
@@ -308,6 +349,22 @@ function filterMerge(...filters) {
|
|
|
308
349
|
}
|
|
309
350
|
return result;
|
|
310
351
|
}
|
|
352
|
+
class FilterProperty extends QueryProperty {
|
|
353
|
+
merge(a, b) {
|
|
354
|
+
return filterMerge(a, b);
|
|
355
|
+
}
|
|
356
|
+
norm(a) {
|
|
357
|
+
return filterNormalize(a);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
class FilterPropertySet extends QueryPropertySet {
|
|
361
|
+
newProperty() {
|
|
362
|
+
return new FilterProperty(undefined);
|
|
363
|
+
}
|
|
364
|
+
merge(...args) {
|
|
365
|
+
return filterMerge(...args);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
311
368
|
|
|
312
369
|
function groupBy(grouper) {
|
|
313
370
|
return grouperCompile(grouper);
|
|
@@ -318,6 +375,7 @@ function grouperCompile(grouper) {
|
|
|
318
375
|
function grouperMerge(...groupers) {
|
|
319
376
|
return undefined;
|
|
320
377
|
}
|
|
378
|
+
function grouperNormalize(grouper) { }
|
|
321
379
|
// import { Primitive } from "utility-types"
|
|
322
380
|
// import { Eval, Flatten } from "@ngutil/common"
|
|
323
381
|
// import { type Model } from "./query"
|
|
@@ -375,6 +433,22 @@ function grouperMerge(...groupers) {
|
|
|
375
433
|
// ): Grouper<T, F> | undefined {
|
|
376
434
|
// return undefined
|
|
377
435
|
// }
|
|
436
|
+
class GrouperProperty extends QueryProperty {
|
|
437
|
+
norm(a) {
|
|
438
|
+
return grouperNormalize;
|
|
439
|
+
}
|
|
440
|
+
merge(a, b) {
|
|
441
|
+
return grouperMerge(a, b);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
class GrouperPropertySet extends QueryPropertySet {
|
|
445
|
+
newProperty() {
|
|
446
|
+
return new GrouperProperty(undefined);
|
|
447
|
+
}
|
|
448
|
+
merge(...args) {
|
|
449
|
+
return grouperMerge(...args);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
378
452
|
|
|
379
453
|
/**
|
|
380
454
|
* @example
|
|
@@ -398,22 +472,39 @@ function sortBy(sorters) {
|
|
|
398
472
|
* ```
|
|
399
473
|
*/
|
|
400
474
|
function sorterNormalize(sorters) {
|
|
401
|
-
return
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
else {
|
|
414
|
-
throw new Error(`Invalid sorter: ${v}`);
|
|
475
|
+
return _sorterNormalize(sorters);
|
|
476
|
+
}
|
|
477
|
+
function _sorterNormalize(sorters) {
|
|
478
|
+
if (!Array.isArray(sorters)) {
|
|
479
|
+
sorters = [sorters];
|
|
480
|
+
}
|
|
481
|
+
return flattenDeep(sorters.map((s) => {
|
|
482
|
+
if (isPlainObject(s)) {
|
|
483
|
+
// entry is normalized
|
|
484
|
+
if (s["path"] != null && s["isAsc"] != null && s["emptyFirst"] != null) {
|
|
485
|
+
return s;
|
|
486
|
+
}
|
|
415
487
|
}
|
|
416
|
-
|
|
488
|
+
return Object.entries(s).map(([k, v]) => {
|
|
489
|
+
if (v == null) {
|
|
490
|
+
return { path: k, remove: true };
|
|
491
|
+
}
|
|
492
|
+
else if (typeof v === "string") {
|
|
493
|
+
const isAsc = v.toLowerCase() === "asc";
|
|
494
|
+
return { path: k, isAsc, emptyFirst: isAsc ? false : true };
|
|
495
|
+
}
|
|
496
|
+
else if (isPlainObject(v)) {
|
|
497
|
+
return {
|
|
498
|
+
path: k,
|
|
499
|
+
isAsc: (v.dir || "asc").toLowerCase() === "asc",
|
|
500
|
+
emptyFirst: v.emptyFirst == null ? true : !!v.emptyFirst
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
throw new Error(`Invalid sorter: ${v}`);
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
}));
|
|
417
508
|
}
|
|
418
509
|
function _sorterCompile(sorters) {
|
|
419
510
|
if (sorters.length === 0) {
|
|
@@ -524,24 +615,18 @@ function sorterMerge(...sorters) {
|
|
|
524
615
|
continue;
|
|
525
616
|
}
|
|
526
617
|
for (const sentry of sorter) {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
delete existing[k];
|
|
532
|
-
if (Object.keys(existing).length === 0) {
|
|
533
|
-
result.splice(result.indexOf(existing), 1);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
else {
|
|
537
|
-
;
|
|
538
|
-
existing[k] = deepClone(v);
|
|
539
|
-
}
|
|
618
|
+
const existingIndex = result.findIndex(value => value.path === sentry.path);
|
|
619
|
+
if (existingIndex > -1) {
|
|
620
|
+
if (sentry.remove) {
|
|
621
|
+
result.splice(existingIndex, 1);
|
|
540
622
|
}
|
|
541
|
-
else
|
|
542
|
-
result
|
|
623
|
+
else {
|
|
624
|
+
result[existingIndex] = deepClone(sentry);
|
|
543
625
|
}
|
|
544
626
|
}
|
|
627
|
+
else if (!sentry.remove) {
|
|
628
|
+
result.push(deepClone(sentry));
|
|
629
|
+
}
|
|
545
630
|
}
|
|
546
631
|
}
|
|
547
632
|
if (result?.length === 0) {
|
|
@@ -549,12 +634,30 @@ function sorterMerge(...sorters) {
|
|
|
549
634
|
}
|
|
550
635
|
return result;
|
|
551
636
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
637
|
+
class SorterProperty extends QueryProperty {
|
|
638
|
+
norm(a) {
|
|
639
|
+
return sorterNormalize(a);
|
|
640
|
+
}
|
|
641
|
+
merge(a, b) {
|
|
642
|
+
return sorterMerge(a, b);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
class SorterPropertySet extends QueryPropertySet {
|
|
646
|
+
of(name) {
|
|
647
|
+
return this.pipe(map(sorters => (sorters == null ? undefined : sorters.find(value => value.path === name))));
|
|
648
|
+
}
|
|
649
|
+
isAsc(name) {
|
|
650
|
+
return this.of(name).pipe(map(v => (v != null ? v.isAsc : undefined)));
|
|
651
|
+
}
|
|
652
|
+
isDesc(name) {
|
|
653
|
+
return this.of(name).pipe(map(v => (v != null ? !v.isAsc : undefined)));
|
|
654
|
+
}
|
|
655
|
+
newProperty() {
|
|
656
|
+
return new SorterProperty(undefined);
|
|
657
|
+
}
|
|
658
|
+
merge(...args) {
|
|
659
|
+
return sorterMerge(...args);
|
|
556
660
|
}
|
|
557
|
-
return undefined;
|
|
558
661
|
}
|
|
559
662
|
|
|
560
663
|
function slimBy(slimer) { }
|
|
@@ -563,6 +666,22 @@ function slimerCompile(slimer) {
|
|
|
563
666
|
return item => item;
|
|
564
667
|
}
|
|
565
668
|
function slimerMerge(...slimers) { }
|
|
669
|
+
class SlimerProperty extends QueryProperty {
|
|
670
|
+
norm(a) {
|
|
671
|
+
return slimerNormalize(a);
|
|
672
|
+
}
|
|
673
|
+
merge(a, b) {
|
|
674
|
+
return slimerMerge(a, b);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
class SlimerPropertySet extends QueryPropertySet {
|
|
678
|
+
newProperty() {
|
|
679
|
+
return new SlimerProperty(undefined);
|
|
680
|
+
}
|
|
681
|
+
merge(...args) {
|
|
682
|
+
return slimerMerge(...args);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
566
685
|
|
|
567
686
|
function sliceMerge(...slices) {
|
|
568
687
|
let result = undefined;
|
|
@@ -624,6 +743,19 @@ function sliceEq(a, b) {
|
|
|
624
743
|
// TODO: sliceConcat(...slices: Slice[]): Slice[]
|
|
625
744
|
// TODO: sliceDiff(slice: Slice): Slice[]
|
|
626
745
|
|
|
746
|
+
function querySubject(...names) {
|
|
747
|
+
const filter = new FilterPropertySet(...names);
|
|
748
|
+
const sorter = new SorterPropertySet(...names);
|
|
749
|
+
const slimer = new SlimerPropertySet(...names);
|
|
750
|
+
const grouper = new GrouperPropertySet(...names);
|
|
751
|
+
const result = combineLatest({ filter, sorter, slimer, grouper }).pipe(shareReplay(1));
|
|
752
|
+
readonlyProp(result, "filter", filter);
|
|
753
|
+
readonlyProp(result, "sorter", sorter);
|
|
754
|
+
readonlyProp(result, "slimer", slimer);
|
|
755
|
+
readonlyProp(result, "grouper", grouper);
|
|
756
|
+
return result;
|
|
757
|
+
}
|
|
758
|
+
|
|
627
759
|
const INPUT = Symbol("INPUT");
|
|
628
760
|
function queryExecutor(query, previous) {
|
|
629
761
|
const executors = {
|
|
@@ -899,148 +1031,33 @@ class MemoryStore extends CollectionStore {
|
|
|
899
1031
|
}
|
|
900
1032
|
}
|
|
901
1033
|
|
|
902
|
-
class Property extends BehaviorSubject {
|
|
903
|
-
// readonly #signal: Signal<DeepReadonly<T> | undefined> = toSignal(this, { requireSync: true })
|
|
904
|
-
set(value, clone = true) {
|
|
905
|
-
if (!isEqual(this.value, value)) {
|
|
906
|
-
if (value != null) {
|
|
907
|
-
this.next(deepFreeze(clone ? deepClone(value) : value));
|
|
908
|
-
}
|
|
909
|
-
else {
|
|
910
|
-
this.next(undefined);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
get() {
|
|
915
|
-
return this.value;
|
|
916
|
-
}
|
|
917
|
-
del() {
|
|
918
|
-
this.set(undefined);
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
class PropertyCombined {
|
|
922
|
-
}
|
|
923
|
-
function mergedProperty(merger, ...props) {
|
|
924
|
-
if (props.length > 1) {
|
|
925
|
-
return combineLatest(props).pipe(map(values => deepFreeze(merger(...values))), shareReplay(1));
|
|
926
|
-
}
|
|
927
|
-
else {
|
|
928
|
-
return props[0];
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
class FilterProperty extends Property {
|
|
933
|
-
update(other) {
|
|
934
|
-
this.set(filterMerge(this.value, other), false);
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
class FilterCombined extends PropertyCombined {
|
|
938
|
-
constructor() {
|
|
939
|
-
super(...arguments);
|
|
940
|
-
this.normal = new FilterProperty(undefined);
|
|
941
|
-
this.forced = new FilterProperty(undefined);
|
|
942
|
-
this.merged$ = mergedProperty(filterMerge, this.normal, this.forced);
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
class SorterProperty extends Property {
|
|
947
|
-
update(other) {
|
|
948
|
-
this.set(sorterMerge(this.value, other), false);
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
class SorterCombined extends PropertyCombined {
|
|
952
|
-
constructor() {
|
|
953
|
-
super(...arguments);
|
|
954
|
-
this.normal = new SorterProperty(undefined);
|
|
955
|
-
this.forced = new SorterProperty(undefined);
|
|
956
|
-
// TODO: normalized sorter
|
|
957
|
-
this.merged$ = mergedProperty(sorterMerge, this.normal, this.forced);
|
|
958
|
-
}
|
|
959
|
-
of(name) {
|
|
960
|
-
return this.merged$.pipe(map((sorters) => (sorters == null ? undefined : sorterFind(sorters, name))));
|
|
961
|
-
}
|
|
962
|
-
directionOf(name) {
|
|
963
|
-
return this.of(name).pipe(map(value => {
|
|
964
|
-
if (value == null) {
|
|
965
|
-
return undefined;
|
|
966
|
-
}
|
|
967
|
-
else if (typeof value === "string") {
|
|
968
|
-
return value;
|
|
969
|
-
}
|
|
970
|
-
else {
|
|
971
|
-
return value.dir;
|
|
972
|
-
}
|
|
973
|
-
}));
|
|
974
|
-
}
|
|
975
|
-
isSet(name) {
|
|
976
|
-
return this.directionOf(name).pipe(map(v => v != null));
|
|
977
|
-
}
|
|
978
|
-
isAsc(name) {
|
|
979
|
-
return this.directionOf(name).pipe(map(v => v === "asc" /* SortDirection.Asc */));
|
|
980
|
-
}
|
|
981
|
-
isDesc(name) {
|
|
982
|
-
return this.directionOf(name).pipe(map(v => v === "desc" /* SortDirection.Desc */));
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
class SlimerProperty extends Property {
|
|
987
|
-
update(other) {
|
|
988
|
-
this.set(slimerMerge(this.value, other), false);
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
class SlimerCombined extends PropertyCombined {
|
|
992
|
-
constructor() {
|
|
993
|
-
super(...arguments);
|
|
994
|
-
this.normal = new SlimerProperty(undefined);
|
|
995
|
-
this.forced = new SlimerProperty(undefined);
|
|
996
|
-
this.merged$ = mergedProperty(slimerMerge, this.normal, this.forced);
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
class GrouperProperty extends Property {
|
|
1001
|
-
update(other) {
|
|
1002
|
-
this.set(grouperMerge(this.value, other), false);
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
class GrouperCombined extends PropertyCombined {
|
|
1006
|
-
constructor() {
|
|
1007
|
-
super(...arguments);
|
|
1008
|
-
this.normal = new GrouperProperty(undefined);
|
|
1009
|
-
this.forced = new GrouperProperty(undefined);
|
|
1010
|
-
this.merged$ = mergedProperty(grouperMerge, this.normal, this.forced);
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
1034
|
const DEBOUNCE_TIME = 50;
|
|
1015
1035
|
class DataSource extends DataSource$1 {
|
|
1016
|
-
#queryBase;
|
|
1017
1036
|
#slice;
|
|
1018
1037
|
#reload;
|
|
1019
|
-
|
|
1038
|
+
#query;
|
|
1039
|
+
constructor(provider, store = new MemoryStore(), query$ = querySubject("normal", "forced")) {
|
|
1020
1040
|
super();
|
|
1021
1041
|
this.provider = provider;
|
|
1042
|
+
this.store = store;
|
|
1043
|
+
this.query$ = query$;
|
|
1022
1044
|
this.busy$ = new BehaviorSubject(false);
|
|
1023
1045
|
this.total$ = new BehaviorSubject(undefined);
|
|
1024
|
-
this.filter = new FilterCombined();
|
|
1025
|
-
this.sorter = new SorterCombined();
|
|
1026
|
-
this.slimer = new SlimerCombined();
|
|
1027
|
-
this.grouper = new GrouperCombined();
|
|
1028
|
-
this.#queryBase = combineLatest({
|
|
1029
|
-
filter: this.filter.merged$,
|
|
1030
|
-
sorter: this.sorter.merged$,
|
|
1031
|
-
slimer: this.slimer.merged$,
|
|
1032
|
-
grouper: this.grouper.merged$
|
|
1033
|
-
}).pipe(shareReplay(1));
|
|
1034
1046
|
this.#slice = new ReplaySubject(1);
|
|
1035
1047
|
this.slice$ = this.#slice.pipe(switchMap(slice => this.provider.clampSlice(slice)), distinctUntilChanged(isEqual), map(slice => deepFreeze(deepClone(slice))), shareReplay(1));
|
|
1036
1048
|
this.#reload = new BehaviorSubject(undefined);
|
|
1037
|
-
this
|
|
1049
|
+
this.#query = combineLatest({
|
|
1050
|
+
query: this.query$,
|
|
1051
|
+
reload: this.#reload
|
|
1052
|
+
}).pipe(tap(() => this.#setBusy(true)),
|
|
1038
1053
|
// TODO: maybe silent reset or prevent items$ chenges
|
|
1039
1054
|
// TODO: alternative solution use cacheId, and query item from store with this cacheId
|
|
1040
|
-
switchMap(({
|
|
1041
|
-
return { ...
|
|
1055
|
+
switchMap(({ query }) => this.store.clear().pipe(map(() => query))), switchMap(query => this.slice$.pipe(tap(() => this.#setBusy(true)), map(slice => {
|
|
1056
|
+
return { ...query, slice };
|
|
1042
1057
|
}))), shareReplay(1));
|
|
1043
|
-
this.items$ = this.
|
|
1058
|
+
this.items$ = this.#query.pipe(tap(() => this.#setBusy(true)), debounceTime(DEBOUNCE_TIME),
|
|
1059
|
+
// tap(query => console.log(query)),
|
|
1060
|
+
switchMap(query => this.store.hasSlice(query.slice).pipe(take(1), switchMap(hasSlice => {
|
|
1044
1061
|
if (hasSlice) {
|
|
1045
1062
|
return this.store.getSlice(query.slice).pipe(take(1));
|
|
1046
1063
|
}
|
|
@@ -1054,10 +1071,6 @@ class DataSource extends DataSource$1 {
|
|
|
1054
1071
|
}
|
|
1055
1072
|
}))), finalize(() => this.#setBusy(false)), shareReplay(1));
|
|
1056
1073
|
this.#cvSubs = new Map();
|
|
1057
|
-
if (store == null) {
|
|
1058
|
-
store = new MemoryStore();
|
|
1059
|
-
}
|
|
1060
|
-
this.store = store;
|
|
1061
1074
|
}
|
|
1062
1075
|
setSlice(slice) {
|
|
1063
1076
|
this.#slice.next(slice);
|
|
@@ -1070,19 +1083,25 @@ class DataSource extends DataSource$1 {
|
|
|
1070
1083
|
this.#reload.next();
|
|
1071
1084
|
}
|
|
1072
1085
|
getItem(ref) {
|
|
1086
|
+
return this.watchItem(ref).pipe(take(1));
|
|
1087
|
+
}
|
|
1088
|
+
watchItem(ref) {
|
|
1073
1089
|
const refn = this.provider.meta.normalizeRef(ref);
|
|
1074
1090
|
return this.#storeFirst(query => this.store.get(refn), query => this.provider.queryItem(refn, query));
|
|
1075
1091
|
}
|
|
1076
1092
|
getItemPosition(ref) {
|
|
1093
|
+
return this.watchItemPosition(ref).pipe(take(1));
|
|
1094
|
+
}
|
|
1095
|
+
watchItemPosition(ref) {
|
|
1077
1096
|
const refn = this.provider.meta.normalizeRef(ref);
|
|
1078
1097
|
return this.#storeFirst(query => this.store.indexOf(refn).pipe(map(i => (i < 0 ? undefined : i))), query => this.provider.queryPosition(refn, query));
|
|
1079
1098
|
}
|
|
1080
1099
|
realodItem(ref, insertPosition) {
|
|
1081
1100
|
const refn = this.provider.meta.normalizeRef(ref);
|
|
1082
|
-
return this.
|
|
1101
|
+
return this.#query.pipe(take(1), switchMap(query => this.provider.queryItem(refn, query).pipe(take(1))), switchMap(item => item != null ? this.store.updateOrInsert(refn, item, insertPosition).pipe(map(() => item)) : of(item)));
|
|
1083
1102
|
}
|
|
1084
1103
|
#storeFirst(storeFn, selfFn) {
|
|
1085
|
-
return this.
|
|
1104
|
+
return this.#query.pipe(take(1), switchMap(query => storeFn(query).pipe(switchMap(result => (result == null ? selfFn(query) : of(result))))));
|
|
1086
1105
|
}
|
|
1087
1106
|
#setBusy(busy) {
|
|
1088
1107
|
if (this.provider.isAsync) {
|
|
@@ -1155,12 +1174,8 @@ class DataSourceProxy extends DataSource$1 {
|
|
|
1155
1174
|
}))
|
|
1156
1175
|
.subscribe(this.#value);
|
|
1157
1176
|
}
|
|
1158
|
-
get value() {
|
|
1159
|
-
return this.#valueSig();
|
|
1160
|
-
}
|
|
1161
1177
|
#valueSub;
|
|
1162
1178
|
#value;
|
|
1163
|
-
#valueSig;
|
|
1164
1179
|
set forcedFilterInput(value) {
|
|
1165
1180
|
// this.query.filter.forced.update(value)
|
|
1166
1181
|
this.#filter.next(value);
|
|
@@ -1183,7 +1198,7 @@ class DataSourceProxy extends DataSource$1 {
|
|
|
1183
1198
|
super();
|
|
1184
1199
|
this.#value = new ReplaySubject(1);
|
|
1185
1200
|
this.value$ = this.#value.pipe(takeUntilDestroyed());
|
|
1186
|
-
this
|
|
1201
|
+
this.query$ = this.value$.pipe(map(value => value.query$), shareReplay(1));
|
|
1187
1202
|
this.items$ = this.value$.pipe(switchMap(value => value.items$), share());
|
|
1188
1203
|
this.busy$ = this.value$.pipe(switchMap(value => value.busy$), share());
|
|
1189
1204
|
this.isBusy = toSignal(this.busy$, { rejectErrors: true, initialValue: false });
|
|
@@ -1196,17 +1211,17 @@ class DataSourceProxy extends DataSource$1 {
|
|
|
1196
1211
|
if (busy != null) {
|
|
1197
1212
|
this.#subs.add(busy.connect(this.busy$).subscribe());
|
|
1198
1213
|
}
|
|
1199
|
-
this.#subs.add(combineLatest({
|
|
1200
|
-
|
|
1214
|
+
this.#subs.add(combineLatest({ query: this.query$, filter: this.#filter }).subscribe(({ query, filter }) => {
|
|
1215
|
+
query.filter.forced.set(filter);
|
|
1201
1216
|
}));
|
|
1202
|
-
this.#subs.add(combineLatest({
|
|
1203
|
-
|
|
1217
|
+
this.#subs.add(combineLatest({ query: this.query$, sorter: this.#sorter }).subscribe(({ query, sorter }) => {
|
|
1218
|
+
query.sorter.forced.set(sorter);
|
|
1204
1219
|
}));
|
|
1205
|
-
this.#subs.add(combineLatest({
|
|
1206
|
-
|
|
1220
|
+
this.#subs.add(combineLatest({ query: this.query$, grouper: this.#grouper }).subscribe(({ query, grouper }) => {
|
|
1221
|
+
query.grouper.forced.set(grouper);
|
|
1207
1222
|
}));
|
|
1208
|
-
this.#subs.add(combineLatest({
|
|
1209
|
-
|
|
1223
|
+
this.#subs.add(combineLatest({ query: this.query$, slimer: this.#slimer }).subscribe(({ query, slimer }) => {
|
|
1224
|
+
query.slimer.forced.set(slimer);
|
|
1210
1225
|
}));
|
|
1211
1226
|
}
|
|
1212
1227
|
#cvSubs;
|
|
@@ -1322,5 +1337,5 @@ class ObservableProvider extends LocalProvider {
|
|
|
1322
1337
|
* Generated bundle index. Do not edit.
|
|
1323
1338
|
*/
|
|
1324
1339
|
|
|
1325
|
-
export { ArrayProvider, CollectionStore, DataProvider, DataSource, DataSourceProxy, LocalProvider, MemoryStore, ModelMeta, ModelRefByIndex, ModelRefByKey, ModelRefNorm, ObservableProvider, UnknownMeta, filterBy, filterMerge, groupBy, grouperMerge, pathGetterCompile, queryExecutor, sliceApply, sliceClamp, sliceEq, sliceInsert, sliceMerge, sliceToPages, slimBy, slimerMerge, sortBy,
|
|
1340
|
+
export { ArrayProvider, CollectionStore, DataProvider, DataSource, DataSourceProxy, LocalProvider, MemoryStore, ModelMeta, ModelRefByIndex, ModelRefByKey, ModelRefNorm, ObservableProvider, UnknownMeta, filterBy, filterMerge, filterNormalize, groupBy, grouperMerge, pathGetterCompile, queryExecutor, querySubject, sliceApply, sliceClamp, sliceEq, sliceInsert, sliceMerge, sliceToPages, slimBy, slimerMerge, sortBy, sorterMerge, sorterNormalize };
|
|
1326
1341
|
//# sourceMappingURL=ngutil-data.mjs.map
|