@ngutil/data 0.0.17 → 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 +56 -0
- package/esm2022/query/query.mjs +19 -2
- package/esm2022/query/slimer.mjs +18 -1
- package/esm2022/query/sorter.mjs +70 -36
- package/esm2022/source/proxy.directive.mjs +21 -24
- package/esm2022/source/source.mjs +24 -25
- package/fesm2022/ngutil-data.mjs +323 -304
- package/fesm2022/ngutil-data.mjs.map +1 -1
- package/package.json +10 -10
- 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 +21 -0
- package/query/query.d.ts +16 -5
- package/query/slimer.d.ts +12 -2
- package/query/sorter.d.ts +16 -3
- package/source/proxy.directive.d.ts +6 -6
- 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,34 +615,49 @@ 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
|
}
|
|
632
|
+
if (result?.length === 0) {
|
|
633
|
+
return undefined;
|
|
634
|
+
}
|
|
547
635
|
return result;
|
|
548
636
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
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);
|
|
553
660
|
}
|
|
554
|
-
return undefined;
|
|
555
661
|
}
|
|
556
662
|
|
|
557
663
|
function slimBy(slimer) { }
|
|
@@ -560,6 +666,22 @@ function slimerCompile(slimer) {
|
|
|
560
666
|
return item => item;
|
|
561
667
|
}
|
|
562
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
|
+
}
|
|
563
685
|
|
|
564
686
|
function sliceMerge(...slices) {
|
|
565
687
|
let result = undefined;
|
|
@@ -621,6 +743,19 @@ function sliceEq(a, b) {
|
|
|
621
743
|
// TODO: sliceConcat(...slices: Slice[]): Slice[]
|
|
622
744
|
// TODO: sliceDiff(slice: Slice): Slice[]
|
|
623
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
|
+
|
|
624
759
|
const INPUT = Symbol("INPUT");
|
|
625
760
|
function queryExecutor(query, previous) {
|
|
626
761
|
const executors = {
|
|
@@ -896,150 +1031,35 @@ class MemoryStore extends CollectionStore {
|
|
|
896
1031
|
}
|
|
897
1032
|
}
|
|
898
1033
|
|
|
899
|
-
class Property extends BehaviorSubject {
|
|
900
|
-
// readonly #signal: Signal<DeepReadonly<T> | undefined> = toSignal(this, { requireSync: true })
|
|
901
|
-
set(value, clone = true) {
|
|
902
|
-
if (!isEqual(this.value, value)) {
|
|
903
|
-
if (value != null) {
|
|
904
|
-
this.next(deepFreeze(clone ? deepClone(value) : value));
|
|
905
|
-
}
|
|
906
|
-
else {
|
|
907
|
-
this.next(undefined);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
get() {
|
|
912
|
-
return this.value;
|
|
913
|
-
}
|
|
914
|
-
del() {
|
|
915
|
-
this.set(undefined);
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
class PropertyCombined {
|
|
919
|
-
}
|
|
920
|
-
function mergedProperty(merger, ...props) {
|
|
921
|
-
if (props.length > 1) {
|
|
922
|
-
return combineLatest(props).pipe(map(values => deepFreeze(merger(...values))));
|
|
923
|
-
}
|
|
924
|
-
else {
|
|
925
|
-
return props[0];
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
class FilterProperty extends Property {
|
|
930
|
-
update(other) {
|
|
931
|
-
this.set(filterMerge(this.value, other), false);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
class FilterCombined extends PropertyCombined {
|
|
935
|
-
constructor() {
|
|
936
|
-
super(...arguments);
|
|
937
|
-
this.normal = new FilterProperty(undefined);
|
|
938
|
-
this.forced = new FilterProperty(undefined);
|
|
939
|
-
this.merged$ = mergedProperty(filterMerge, this.normal, this.forced);
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
class SorterProperty extends Property {
|
|
944
|
-
update(other) {
|
|
945
|
-
this.set(sorterMerge(this.value, other), false);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
class SorterCombined extends PropertyCombined {
|
|
949
|
-
constructor() {
|
|
950
|
-
super(...arguments);
|
|
951
|
-
this.normal = new SorterProperty(undefined);
|
|
952
|
-
this.forced = new SorterProperty(undefined);
|
|
953
|
-
// TODO: normalized sorter
|
|
954
|
-
this.merged$ = mergedProperty(sorterMerge, this.normal, this.forced);
|
|
955
|
-
}
|
|
956
|
-
of(name) {
|
|
957
|
-
return this.merged$.pipe(map((sorters) => (sorters == null ? undefined : sorterFind(sorters, name))));
|
|
958
|
-
}
|
|
959
|
-
directionOf(name) {
|
|
960
|
-
return this.of(name).pipe(map(value => {
|
|
961
|
-
if (value == null) {
|
|
962
|
-
return undefined;
|
|
963
|
-
}
|
|
964
|
-
else if (typeof value === "string") {
|
|
965
|
-
return value;
|
|
966
|
-
}
|
|
967
|
-
else {
|
|
968
|
-
return value.dir;
|
|
969
|
-
}
|
|
970
|
-
}));
|
|
971
|
-
}
|
|
972
|
-
isSet(name) {
|
|
973
|
-
return this.directionOf(name).pipe(map(v => v != null));
|
|
974
|
-
}
|
|
975
|
-
isAsc(name) {
|
|
976
|
-
return this.directionOf(name).pipe(map(v => v === "asc" /* SortDirection.Asc */));
|
|
977
|
-
}
|
|
978
|
-
isDesc(name) {
|
|
979
|
-
return this.directionOf(name).pipe(map(v => v === "desc" /* SortDirection.Desc */));
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
class SlimerProperty extends Property {
|
|
984
|
-
update(other) {
|
|
985
|
-
this.set(slimerMerge(this.value, other), false);
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
class SlimerCombined extends PropertyCombined {
|
|
989
|
-
constructor() {
|
|
990
|
-
super(...arguments);
|
|
991
|
-
this.normal = new SlimerProperty(undefined);
|
|
992
|
-
this.forced = new SlimerProperty(undefined);
|
|
993
|
-
this.merged$ = mergedProperty(slimerMerge, this.normal, this.forced);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
class GrouperProperty extends Property {
|
|
998
|
-
update(other) {
|
|
999
|
-
this.set(grouperMerge(this.value, other), false);
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
class GrouperCombined extends PropertyCombined {
|
|
1003
|
-
constructor() {
|
|
1004
|
-
super(...arguments);
|
|
1005
|
-
this.normal = new GrouperProperty(undefined);
|
|
1006
|
-
this.forced = new GrouperProperty(undefined);
|
|
1007
|
-
this.merged$ = mergedProperty(grouperMerge, this.normal, this.forced);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
1034
|
const DEBOUNCE_TIME = 50;
|
|
1012
1035
|
class DataSource extends DataSource$1 {
|
|
1013
|
-
#queryBase;
|
|
1014
1036
|
#slice;
|
|
1015
1037
|
#reload;
|
|
1016
|
-
|
|
1038
|
+
#query;
|
|
1039
|
+
constructor(provider, store = new MemoryStore(), query$ = querySubject("normal", "forced")) {
|
|
1017
1040
|
super();
|
|
1018
1041
|
this.provider = provider;
|
|
1042
|
+
this.store = store;
|
|
1043
|
+
this.query$ = query$;
|
|
1019
1044
|
this.busy$ = new BehaviorSubject(false);
|
|
1020
1045
|
this.total$ = new BehaviorSubject(undefined);
|
|
1021
|
-
this.filter = new FilterCombined();
|
|
1022
|
-
this.sorter = new SorterCombined();
|
|
1023
|
-
this.slimer = new SlimerCombined();
|
|
1024
|
-
this.grouper = new GrouperCombined();
|
|
1025
|
-
this.#queryBase = combineLatest({
|
|
1026
|
-
filter: this.filter.merged$,
|
|
1027
|
-
sorter: this.sorter.merged$,
|
|
1028
|
-
slimer: this.slimer.merged$,
|
|
1029
|
-
grouper: this.grouper.merged$
|
|
1030
|
-
}).pipe(shareReplay(1));
|
|
1031
1046
|
this.#slice = new ReplaySubject(1);
|
|
1032
1047
|
this.slice$ = this.#slice.pipe(switchMap(slice => this.provider.clampSlice(slice)), distinctUntilChanged(isEqual), map(slice => deepFreeze(deepClone(slice))), shareReplay(1));
|
|
1033
1048
|
this.#reload = new BehaviorSubject(undefined);
|
|
1034
|
-
this
|
|
1049
|
+
this.#query = combineLatest({
|
|
1050
|
+
query: this.query$,
|
|
1051
|
+
reload: this.#reload
|
|
1052
|
+
}).pipe(tap(() => this.#setBusy(true)),
|
|
1035
1053
|
// TODO: maybe silent reset or prevent items$ chenges
|
|
1036
1054
|
// TODO: alternative solution use cacheId, and query item from store with this cacheId
|
|
1037
|
-
switchMap(({
|
|
1038
|
-
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 };
|
|
1039
1057
|
}))), shareReplay(1));
|
|
1040
|
-
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 => {
|
|
1041
1061
|
if (hasSlice) {
|
|
1042
|
-
return this.store.getSlice(query.slice);
|
|
1062
|
+
return this.store.getSlice(query.slice).pipe(take(1));
|
|
1043
1063
|
}
|
|
1044
1064
|
else {
|
|
1045
1065
|
return this.provider.queryList(query).pipe(switchMap(result => {
|
|
@@ -1051,10 +1071,6 @@ class DataSource extends DataSource$1 {
|
|
|
1051
1071
|
}
|
|
1052
1072
|
}))), finalize(() => this.#setBusy(false)), shareReplay(1));
|
|
1053
1073
|
this.#cvSubs = new Map();
|
|
1054
|
-
if (store == null) {
|
|
1055
|
-
store = new MemoryStore();
|
|
1056
|
-
}
|
|
1057
|
-
this.store = store;
|
|
1058
1074
|
}
|
|
1059
1075
|
setSlice(slice) {
|
|
1060
1076
|
this.#slice.next(slice);
|
|
@@ -1067,19 +1083,25 @@ class DataSource extends DataSource$1 {
|
|
|
1067
1083
|
this.#reload.next();
|
|
1068
1084
|
}
|
|
1069
1085
|
getItem(ref) {
|
|
1086
|
+
return this.watchItem(ref).pipe(take(1));
|
|
1087
|
+
}
|
|
1088
|
+
watchItem(ref) {
|
|
1070
1089
|
const refn = this.provider.meta.normalizeRef(ref);
|
|
1071
1090
|
return this.#storeFirst(query => this.store.get(refn), query => this.provider.queryItem(refn, query));
|
|
1072
1091
|
}
|
|
1073
1092
|
getItemPosition(ref) {
|
|
1093
|
+
return this.watchItemPosition(ref).pipe(take(1));
|
|
1094
|
+
}
|
|
1095
|
+
watchItemPosition(ref) {
|
|
1074
1096
|
const refn = this.provider.meta.normalizeRef(ref);
|
|
1075
1097
|
return this.#storeFirst(query => this.store.indexOf(refn).pipe(map(i => (i < 0 ? undefined : i))), query => this.provider.queryPosition(refn, query));
|
|
1076
1098
|
}
|
|
1077
1099
|
realodItem(ref, insertPosition) {
|
|
1078
1100
|
const refn = this.provider.meta.normalizeRef(ref);
|
|
1079
|
-
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)));
|
|
1080
1102
|
}
|
|
1081
1103
|
#storeFirst(storeFn, selfFn) {
|
|
1082
|
-
return this.
|
|
1104
|
+
return this.#query.pipe(take(1), switchMap(query => storeFn(query).pipe(switchMap(result => (result == null ? selfFn(query) : of(result))))));
|
|
1083
1105
|
}
|
|
1084
1106
|
#setBusy(busy) {
|
|
1085
1107
|
if (this.provider.isAsync) {
|
|
@@ -1152,25 +1174,22 @@ class DataSourceProxy extends DataSource$1 {
|
|
|
1152
1174
|
}))
|
|
1153
1175
|
.subscribe(this.#value);
|
|
1154
1176
|
}
|
|
1155
|
-
get value() {
|
|
1156
|
-
return this.#valueSig();
|
|
1157
|
-
}
|
|
1158
1177
|
#valueSub;
|
|
1159
1178
|
#value;
|
|
1160
|
-
|
|
1161
|
-
|
|
1179
|
+
set forcedFilterInput(value) {
|
|
1180
|
+
// this.query.filter.forced.update(value)
|
|
1162
1181
|
this.#filter.next(value);
|
|
1163
1182
|
}
|
|
1164
1183
|
#filter;
|
|
1165
|
-
set
|
|
1184
|
+
set forcedSorterInput(value) {
|
|
1166
1185
|
this.#sorter.next(value);
|
|
1167
1186
|
}
|
|
1168
1187
|
#sorter;
|
|
1169
|
-
set
|
|
1188
|
+
set forcedGrouperInput(value) {
|
|
1170
1189
|
this.#grouper.next(value);
|
|
1171
1190
|
}
|
|
1172
1191
|
#grouper;
|
|
1173
|
-
set
|
|
1192
|
+
set forcedSlimerInput(value) {
|
|
1174
1193
|
this.#slimer.next(value);
|
|
1175
1194
|
}
|
|
1176
1195
|
#slimer;
|
|
@@ -1179,7 +1198,7 @@ class DataSourceProxy extends DataSource$1 {
|
|
|
1179
1198
|
super();
|
|
1180
1199
|
this.#value = new ReplaySubject(1);
|
|
1181
1200
|
this.value$ = this.#value.pipe(takeUntilDestroyed());
|
|
1182
|
-
this
|
|
1201
|
+
this.query$ = this.value$.pipe(map(value => value.query$), shareReplay(1));
|
|
1183
1202
|
this.items$ = this.value$.pipe(switchMap(value => value.items$), share());
|
|
1184
1203
|
this.busy$ = this.value$.pipe(switchMap(value => value.busy$), share());
|
|
1185
1204
|
this.isBusy = toSignal(this.busy$, { rejectErrors: true, initialValue: false });
|
|
@@ -1192,17 +1211,17 @@ class DataSourceProxy extends DataSource$1 {
|
|
|
1192
1211
|
if (busy != null) {
|
|
1193
1212
|
this.#subs.add(busy.connect(this.busy$).subscribe());
|
|
1194
1213
|
}
|
|
1195
|
-
this.#subs.add(combineLatest({
|
|
1196
|
-
|
|
1214
|
+
this.#subs.add(combineLatest({ query: this.query$, filter: this.#filter }).subscribe(({ query, filter }) => {
|
|
1215
|
+
query.filter.forced.set(filter);
|
|
1197
1216
|
}));
|
|
1198
|
-
this.#subs.add(combineLatest({
|
|
1199
|
-
|
|
1217
|
+
this.#subs.add(combineLatest({ query: this.query$, sorter: this.#sorter }).subscribe(({ query, sorter }) => {
|
|
1218
|
+
query.sorter.forced.set(sorter);
|
|
1200
1219
|
}));
|
|
1201
|
-
this.#subs.add(combineLatest({
|
|
1202
|
-
|
|
1220
|
+
this.#subs.add(combineLatest({ query: this.query$, grouper: this.#grouper }).subscribe(({ query, grouper }) => {
|
|
1221
|
+
query.grouper.forced.set(grouper);
|
|
1203
1222
|
}));
|
|
1204
|
-
this.#subs.add(combineLatest({
|
|
1205
|
-
|
|
1223
|
+
this.#subs.add(combineLatest({ query: this.query$, slimer: this.#slimer }).subscribe(({ query, slimer }) => {
|
|
1224
|
+
query.slimer.forced.set(slimer);
|
|
1206
1225
|
}));
|
|
1207
1226
|
}
|
|
1208
1227
|
#cvSubs;
|
|
@@ -1222,7 +1241,7 @@ class DataSourceProxy extends DataSource$1 {
|
|
|
1222
1241
|
this.#subs.unsubscribe();
|
|
1223
1242
|
}
|
|
1224
1243
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.6", ngImport: i0, type: DataSourceProxy, deps: [{ token: i1.Busy, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1225
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.6", type: DataSourceProxy, isStandalone: true, selector: "[nuDataSource]", inputs: { value: ["nuDataSource", "value"],
|
|
1244
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.6", type: DataSourceProxy, isStandalone: true, selector: "[nuDataSource]", inputs: { value: ["nuDataSource", "value"], forcedFilterInput: "forcedFilterInput", forcedSorterInput: "forcedSorterInput", forcedGrouperInput: "forcedGrouperInput", forcedSlimerInput: "forcedSlimerInput" }, exportAs: ["nuDataSource"], usesInheritance: true, ngImport: i0 }); }
|
|
1226
1245
|
}
|
|
1227
1246
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.6", ngImport: i0, type: DataSourceProxy, decorators: [{
|
|
1228
1247
|
type: Directive,
|
|
@@ -1236,13 +1255,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.6", ngImpor
|
|
|
1236
1255
|
}] }], propDecorators: { value: [{
|
|
1237
1256
|
type: Input,
|
|
1238
1257
|
args: [{ required: true, alias: "nuDataSource" }]
|
|
1239
|
-
}],
|
|
1258
|
+
}], forcedFilterInput: [{
|
|
1240
1259
|
type: Input
|
|
1241
|
-
}],
|
|
1260
|
+
}], forcedSorterInput: [{
|
|
1242
1261
|
type: Input
|
|
1243
|
-
}],
|
|
1262
|
+
}], forcedGrouperInput: [{
|
|
1244
1263
|
type: Input
|
|
1245
|
-
}],
|
|
1264
|
+
}], forcedSlimerInput: [{
|
|
1246
1265
|
type: Input
|
|
1247
1266
|
}] } });
|
|
1248
1267
|
function coerceDataSource(value) {
|
|
@@ -1318,5 +1337,5 @@ class ObservableProvider extends LocalProvider {
|
|
|
1318
1337
|
* Generated bundle index. Do not edit.
|
|
1319
1338
|
*/
|
|
1320
1339
|
|
|
1321
|
-
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 };
|
|
1322
1341
|
//# sourceMappingURL=ngutil-data.mjs.map
|