@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.
Files changed (41) hide show
  1. package/esm2022/provider/local.mjs +1 -1
  2. package/esm2022/provider/provider.mjs +1 -1
  3. package/esm2022/query/common.mjs +33 -0
  4. package/esm2022/query/executor.mjs +1 -1
  5. package/esm2022/query/filter.mjs +82 -109
  6. package/esm2022/query/grouper.mjs +19 -1
  7. package/esm2022/query/index.mjs +4 -3
  8. package/esm2022/query/query-property.mjs +28 -61
  9. package/esm2022/query/query.mjs +19 -6
  10. package/esm2022/query/slimer.mjs +18 -1
  11. package/esm2022/query/sorter.mjs +67 -36
  12. package/esm2022/source/proxy.directive.mjs +11 -15
  13. package/esm2022/source/source.mjs +23 -24
  14. package/fesm2022/ngutil-data.mjs +309 -294
  15. package/fesm2022/ngutil-data.mjs.map +1 -1
  16. package/package.json +8 -8
  17. package/provider/local.d.ts +5 -5
  18. package/provider/provider.d.ts +4 -4
  19. package/query/common.d.ts +2 -0
  20. package/query/executor.d.ts +2 -2
  21. package/query/filter.d.ts +32 -0
  22. package/query/grouper.d.ts +11 -0
  23. package/query/index.d.ts +3 -3
  24. package/query/query-property.d.ts +14 -19
  25. package/query/query.d.ts +14 -12
  26. package/query/slimer.d.ts +12 -2
  27. package/query/sorter.d.ts +16 -3
  28. package/source/proxy.directive.d.ts +1 -1
  29. package/source/source.d.ts +7 -14
  30. package/esm2022/source/properties/abstract.mjs +0 -33
  31. package/esm2022/source/properties/filter.mjs +0 -16
  32. package/esm2022/source/properties/grouper.mjs +0 -16
  33. package/esm2022/source/properties/index.mjs +0 -5
  34. package/esm2022/source/properties/slimer.mjs +0 -16
  35. package/esm2022/source/properties/sorter.mjs +0 -43
  36. package/source/properties/abstract.d.ts +0 -17
  37. package/source/properties/filter.d.ts +0 -11
  38. package/source/properties/grouper.d.ts +0 -11
  39. package/source/properties/index.d.ts +0 -4
  40. package/source/properties/slimer.d.ts +0 -11
  41. package/source/properties/sorter.d.ts +0 -20
@@ -1,7 +1,7 @@
1
- import { flattenDepth, intersection, flattenDeep, isEqual } from 'lodash';
1
+ import { flattenDepth, isEqual, intersection, flattenDeep } from 'lodash';
2
2
  import * as i1 from '@ngutil/common';
3
- import { isPlainObject, deepClone, toSorted, deepFreeze } from '@ngutil/common';
4
- import { BehaviorSubject, map, combineLatest, take, of, shareReplay, ReplaySubject, switchMap, distinctUntilChanged, tap, debounceTime, finalize, Subject, Observable, takeUntil, share, Subscription, throwError } from 'rxjs';
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
- // TODO: Normalize filter
74
- // type _Filter = { path: string; op: FilterOp; value: any }
75
- // type _Or = { "|": Array<_Filter> }
76
- // type _And = { "&": Array<_Filter> }
77
- // export type NormalizedFilter = _Or | _And
78
- // /**
79
- // * @example
80
- // * ```ts
81
- // * normalizeFilter({id: 2, name: {"=*": "AnyName"}}) -> {id: {"==": 2}, name: {"=*": "AnyName"}}}
82
- // * normalizeFilter({id: {">": 0, "<": 10}}) -> {"&": [{id: {">": 0}}, {id: {"<": 10}}]}
83
- // * ```
84
- // */
85
- // export function normalizeFilter<T extends Model>(filters: Filters<T>): Filters<T> {
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("Root '&' (AND) operator must have array type");
173
+ throw new Error(`Operator AND (${"&" /* FilterOp.And */}) must have array type`);
148
174
  }
149
- result.splice(result.length, 0, ...value.map((_filterCompile)));
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("Root '|' (OR) operator must have array type");
178
+ throw new Error(`Operator OR (${"|" /* FilterOp.Or */}) must have array type`);
154
179
  }
155
- result.push(or_(value.map((_filterCompile))));
156
- break;
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
- result.push(and_(Object.entries(value).map(([op, opv]) => filterCompileOp(getter, op, opv))));
184
+ return _normalizeFilter(value, path);
185
+ }
186
+ if (parent != null) {
187
+ return { path: parent, op: path, value };
161
188
  }
162
189
  else {
163
- result.push(filterCompileOp(getter, "==" /* FilterOp.Eq */, value));
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 filterCompileOp(getter, op, value) {
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 flattenDeep(sorters.map((s) => Object.entries(s).map(([k, v]) => {
402
- if (typeof v === "string") {
403
- const isAsc = v.toLowerCase() === "asc";
404
- return { path: k, isAsc, emptyFirst: isAsc ? false : true };
405
- }
406
- else if (isPlainObject(v)) {
407
- return {
408
- path: k,
409
- isAsc: (v.dir || "asc").toLowerCase() === "asc",
410
- emptyFirst: v.emptyFirst == null ? true : !!v.emptyFirst
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
- for (const [k, v] of Object.entries(sentry)) {
528
- const existing = result.find((value) => value[k] != null);
529
- if (existing) {
530
- if (v == null) {
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 if (v != null) {
542
- result.push({ [k]: deepClone(v) });
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
- function sorterFind(sorters, name) {
553
- const sorter = sorters.find(v => v[name] != null);
554
- if (sorter != null) {
555
- return sorter[name];
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
- constructor(provider, store) {
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.query$ = combineLatest({ base: this.#queryBase, reload: this.#reload }).pipe(tap(() => this.#setBusy(true)),
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(({ base }) => this.store.clear().pipe(map(() => base))), switchMap(queryBase => this.slice$.pipe(tap(() => this.#setBusy(true)), map(slice => {
1041
- return { ...queryBase, slice };
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.query$.pipe(tap(() => this.#setBusy(true)), debounceTime(DEBOUNCE_TIME), switchMap(query => this.store.hasSlice(query.slice).pipe(take(1), switchMap(hasSlice => {
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.query$.pipe(switchMap(query => this.provider.queryItem(refn, query)), switchMap(item => item != null ? this.store.updateOrInsert(refn, item, insertPosition).pipe(map(() => item)) : of(item)), take(1));
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.query$.pipe(take(1), switchMap(query => storeFn(query).pipe(switchMap(result => (result == null ? selfFn(query) : of(result))))));
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.#valueSig = toSignal(this.value$);
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({ src: this.value$, filter: this.#filter }).subscribe(({ src, filter }) => {
1200
- src.filter.forced.set(filter);
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({ src: this.value$, sorter: this.#sorter }).subscribe(({ src, sorter }) => {
1203
- src.sorter.forced.set(sorter);
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({ src: this.value$, grouper: this.#grouper }).subscribe(({ src, grouper }) => {
1206
- src.grouper.forced.set(grouper);
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({ src: this.value$, slimer: this.#slimer }).subscribe(({ src, slimer }) => {
1209
- src.slimer.forced.set(slimer);
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, sorterFind, sorterMerge };
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