@signaldb/svelte 2.0.0-beta.19 → 2.0.0-beta.20
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.
|
@@ -26,8 +26,10 @@ export interface QueryChangeset<T extends BaseItem> {
|
|
|
26
26
|
* the query after all:
|
|
27
27
|
* - `limit` or `skip`: the result is a window onto a larger set, and an item leaving the window has
|
|
28
28
|
* to be replaced by one the previous result never contained.
|
|
29
|
-
* - `fields` together with `sort
|
|
30
|
-
*
|
|
29
|
+
* - `fields` together with a `sort` the projection does not keep: the previous items are
|
|
30
|
+
* projected, so a sort key the projection dropped is no longer there to sort by. A projection
|
|
31
|
+
* that keeps every sort key is fine, and is the common case — a list sorted by the same date it
|
|
32
|
+
* displays.
|
|
31
33
|
* - a `null` selector, which matches nothing and is not worth a special case.
|
|
32
34
|
* @template T - The type of the items.
|
|
33
35
|
* @param previous - The query's previous result.
|
|
@@ -21,8 +21,10 @@ const sortItems_1 = __importDefault(require("./sortItems"));
|
|
|
21
21
|
* the query after all:
|
|
22
22
|
* - `limit` or `skip`: the result is a window onto a larger set, and an item leaving the window has
|
|
23
23
|
* to be replaced by one the previous result never contained.
|
|
24
|
-
* - `fields` together with `sort
|
|
25
|
-
*
|
|
24
|
+
* - `fields` together with a `sort` the projection does not keep: the previous items are
|
|
25
|
+
* projected, so a sort key the projection dropped is no longer there to sort by. A projection
|
|
26
|
+
* that keeps every sort key is fine, and is the common case — a list sorted by the same date it
|
|
27
|
+
* displays.
|
|
26
28
|
* - a `null` selector, which matches nothing and is not worth a special case.
|
|
27
29
|
* @template T - The type of the items.
|
|
28
30
|
* @param previous - The query's previous result.
|
|
@@ -37,12 +39,48 @@ function incrementalQueryUpdate(previous, selector, options, changes) {
|
|
|
37
39
|
const { sort, skip, limit, fields } = options || {};
|
|
38
40
|
if (skip != null)
|
|
39
41
|
return null;
|
|
40
|
-
if (fields != null && sort != null)
|
|
42
|
+
if (fields != null && sort != null && !sortKeysSurviveProjection(sort, fields))
|
|
41
43
|
return null;
|
|
42
44
|
if (limit != null && !windowStaysClosed(previous, selector, options, changes))
|
|
43
45
|
return null;
|
|
44
46
|
return mergeChangesetIntoResult(previous, selector, options, changes);
|
|
45
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether a projection keeps every field a sort is keyed on.
|
|
50
|
+
*
|
|
51
|
+
* The previous result is the projected items, so this decides whether they still carry what the
|
|
52
|
+
* sort needs. Both projection modes are covered, because `project` treats an all-zero spec as an
|
|
53
|
+
* exclusion and anything else as an inclusion:
|
|
54
|
+
*
|
|
55
|
+
* - An inclusion keeps a key when the key itself is included, or an ancestor of it is (`{a: 1}`
|
|
56
|
+
* keeps `a.b`), and always keeps `id` unless the spec excludes it outright.
|
|
57
|
+
* - An exclusion keeps a key unless the key or an ancestor of it is excluded.
|
|
58
|
+
*
|
|
59
|
+
* Anything it cannot account for is a "no": re-executing is slower, not wrong.
|
|
60
|
+
* @template T - The type of the items.
|
|
61
|
+
* @param sort - The query's sort.
|
|
62
|
+
* @param fields - The query's projection.
|
|
63
|
+
* @returns `true` when every sort key survives the projection.
|
|
64
|
+
*/
|
|
65
|
+
function sortKeysSurviveProjection(sort, fields) {
|
|
66
|
+
const entries = Object.entries(fields);
|
|
67
|
+
if (entries.length === 0)
|
|
68
|
+
return true;
|
|
69
|
+
const isExclusion = entries.every(([, value]) => value === 0);
|
|
70
|
+
// `a.b.c` is kept by `a`, by `a.b` and by `a.b.c`, and dropped by any of them under an
|
|
71
|
+
// exclusion — so both modes ask about the key and each of its ancestors.
|
|
72
|
+
const pathsFor = (key) => key
|
|
73
|
+
.split('.')
|
|
74
|
+
.map((_, index, parts) => parts.slice(0, index + 1).join('.'));
|
|
75
|
+
return Object.keys(sort).every((key) => {
|
|
76
|
+
const paths = pathsFor(key);
|
|
77
|
+
if (isExclusion)
|
|
78
|
+
return paths.every(path => fields[path] !== 0);
|
|
79
|
+
if (key === 'id')
|
|
80
|
+
return fields.id !== 0;
|
|
81
|
+
return paths.some(path => fields[path] === 1);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
46
84
|
/**
|
|
47
85
|
* Whether two items are in the given order under the given sort, deciding ties against the caller.
|
|
48
86
|
*
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signaldb/svelte",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.20",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsc -d --noEmit false",
|
|
7
7
|
"analyze-bundle": "bundle-analyzer ./dist --upload-token=$BUNDLE_ANALYZER_UPLOAD_TOKEN --bundle-name=@signaldb/svelte",
|