@signaldb/core 2.0.0-beta.4 → 2.0.0-beta.5
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/dist/.vite/manifest.json +27 -21
- package/dist/Collection/Observer.d.ts +2 -0
- package/dist/Collection/index.d.ts +11 -10
- package/dist/Collection/types.d.ts +7 -0
- package/dist/DefaultDataAdapter.d.ts +2 -0
- package/dist/index.cjs.js +8 -5
- package/dist/index.cjs12.js +41 -346
- package/dist/index.cjs13.js +308 -359
- package/dist/index.cjs14.js +387 -177
- package/dist/index.cjs15.js +182 -364
- package/dist/index.cjs16.js +287 -478
- package/dist/index.cjs17.js +563 -136
- package/dist/index.cjs18.js +154 -23
- package/dist/index.cjs19.js +23 -39
- package/dist/index.cjs2.js +1 -1
- package/dist/index.cjs20.js +39 -13
- package/dist/index.cjs21.js +14 -102
- package/dist/index.cjs22.js +93 -118
- package/dist/index.cjs23.js +127 -5
- package/dist/index.cjs24.js +5 -25
- package/dist/index.cjs25.js +24 -7
- package/dist/index.cjs26.js +8 -27
- package/dist/index.cjs27.js +25 -42
- package/dist/index.cjs28.js +44 -6
- package/dist/index.cjs29.js +6 -7
- package/dist/index.cjs3.js +9 -26
- package/dist/index.cjs30.js +5 -3
- package/dist/index.cjs31.js +40 -5
- package/dist/index.cjs33.js +3 -40
- package/dist/index.cjs34.js +9 -0
- package/dist/index.cjs7.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +10 -7
- package/dist/index12.mjs +40 -346
- package/dist/index13.mjs +308 -359
- package/dist/index14.mjs +387 -177
- package/dist/index15.mjs +182 -364
- package/dist/index16.mjs +287 -478
- package/dist/index17.mjs +563 -136
- package/dist/index18.mjs +154 -23
- package/dist/index19.mjs +23 -38
- package/dist/index2.mjs +1 -1
- package/dist/index20.mjs +38 -13
- package/dist/index21.mjs +14 -102
- package/dist/index22.mjs +93 -117
- package/dist/index23.mjs +126 -5
- package/dist/index24.mjs +5 -25
- package/dist/index25.mjs +24 -7
- package/dist/index26.mjs +8 -27
- package/dist/index27.mjs +25 -42
- package/dist/index28.mjs +44 -6
- package/dist/index29.mjs +6 -7
- package/dist/index3.mjs +9 -26
- package/dist/index30.mjs +5 -3
- package/dist/index31.mjs +40 -5
- package/dist/index33.mjs +3 -40
- package/dist/index34.mjs +10 -0
- package/dist/index7.mjs +1 -1
- package/dist/utils/reactiveOrAsync.d.ts +59 -0
- package/package.json +1 -1
package/dist/index23.mjs
CHANGED
|
@@ -1,8 +1,129 @@
|
|
|
1
|
-
import
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import intersection from "./index30.mjs";
|
|
2
|
+
function getMergedIndexInfo(queryFunctions, selector) {
|
|
3
|
+
return queryFunctions.reduce((memoOrPromise, queryFunction) => {
|
|
4
|
+
const resultOrPromise = queryFunction(selector);
|
|
5
|
+
const processResult = (memo2, result) => {
|
|
6
|
+
if (!result.matched)
|
|
7
|
+
return memo2;
|
|
8
|
+
const optimizedSelector = result.keepSelector ? memo2.optimizedSelector : Object.fromEntries(Object.entries(memo2.optimizedSelector).filter(([key]) => !result.fields.includes(key)));
|
|
9
|
+
return {
|
|
10
|
+
matched: true,
|
|
11
|
+
ids: [...new Set(memo2.matched ? intersection(memo2.ids, result.ids) : result.ids)],
|
|
12
|
+
optimizedSelector
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
if (resultOrPromise instanceof Promise) {
|
|
16
|
+
return resultOrPromise.then(async (result) => {
|
|
17
|
+
const memo2 = memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise;
|
|
18
|
+
return processResult(memo2, result);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const memo = memoOrPromise;
|
|
22
|
+
if (memo instanceof Promise)
|
|
23
|
+
throw new Error("Mixing async and sync index providers is not supported");
|
|
24
|
+
return processResult(memo, resultOrPromise);
|
|
25
|
+
}, {
|
|
26
|
+
matched: false,
|
|
27
|
+
ids: [],
|
|
28
|
+
optimizedSelector: { ...selector }
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function optimizeLogicGate(queryFunctions, logicGate, idsCallback) {
|
|
32
|
+
return logicGate.reduce((memoOrPromise, sel) => {
|
|
33
|
+
const getSelector = (indexInfo) => {
|
|
34
|
+
const { matched: selMatched, ids: selIds, optimizedSelector: optimizedSelector2 } = indexInfo;
|
|
35
|
+
if (selMatched) {
|
|
36
|
+
idsCallback(true, selIds);
|
|
37
|
+
if (Object.keys(optimizedSelector2).length > 0) {
|
|
38
|
+
return optimizedSelector2;
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
idsCallback(false, []);
|
|
42
|
+
return sel;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const indexInfoOrPromise = getIndexInfo(queryFunctions, sel);
|
|
46
|
+
if (indexInfoOrPromise instanceof Promise) {
|
|
47
|
+
return indexInfoOrPromise.then(async (indexInfo) => {
|
|
48
|
+
const memo2 = memoOrPromise instanceof Promise ? await memoOrPromise : memoOrPromise;
|
|
49
|
+
const optimizedSelector2 = getSelector(indexInfo);
|
|
50
|
+
if (optimizedSelector2)
|
|
51
|
+
memo2.push(optimizedSelector2);
|
|
52
|
+
return memo2;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const memo = memoOrPromise;
|
|
56
|
+
if (memo instanceof Promise)
|
|
57
|
+
throw new Error("Mixing async and sync index providers is not supported");
|
|
58
|
+
const optimizedSelector = getSelector(indexInfoOrPromise);
|
|
59
|
+
if (optimizedSelector)
|
|
60
|
+
memo.push(optimizedSelector);
|
|
61
|
+
return memo;
|
|
62
|
+
}, []);
|
|
63
|
+
}
|
|
64
|
+
function getIndexInfo(queryFunctions, selector) {
|
|
65
|
+
if (selector == null || Object.keys(selector).length <= 0) {
|
|
66
|
+
return {
|
|
67
|
+
matched: false,
|
|
68
|
+
ids: [],
|
|
69
|
+
optimizedSelector: selector
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const { $and, $or, ...rest } = selector;
|
|
73
|
+
const flatInfoOrPromise = getMergedIndexInfo(queryFunctions, rest);
|
|
74
|
+
const processFlatInfo = (flatInfo) => {
|
|
75
|
+
let { matched, ids } = flatInfo;
|
|
76
|
+
const newSelector = flatInfo.optimizedSelector;
|
|
77
|
+
const $andNewOrPromise = Array.isArray($and) ? optimizeLogicGate(queryFunctions, $and, (match, selIds) => {
|
|
78
|
+
if (!match)
|
|
79
|
+
return;
|
|
80
|
+
ids = matched ? intersection(ids, selIds) : selIds;
|
|
81
|
+
matched = true;
|
|
82
|
+
}) : void 0;
|
|
83
|
+
const process$and = ($andNew) => {
|
|
84
|
+
if ($andNew && $andNew.length > 0)
|
|
85
|
+
newSelector.$and = $andNew;
|
|
86
|
+
let hasNonIndexField = false;
|
|
87
|
+
const matchedBefore = matched;
|
|
88
|
+
const idsBefore = ids;
|
|
89
|
+
const process$or = ($orNew) => {
|
|
90
|
+
if ($orNew && $orNew.length > 0)
|
|
91
|
+
newSelector.$or = $orNew;
|
|
92
|
+
if (hasNonIndexField) {
|
|
93
|
+
newSelector.$or = $or;
|
|
94
|
+
matched = matchedBefore;
|
|
95
|
+
ids = idsBefore;
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
matched,
|
|
99
|
+
ids: ids || [],
|
|
100
|
+
optimizedSelector: newSelector
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const $orNewOrPromise = Array.isArray($or) ? optimizeLogicGate(queryFunctions, $or, (match, selIds) => {
|
|
104
|
+
if (match) {
|
|
105
|
+
ids = [.../* @__PURE__ */ new Set([...ids, ...selIds])];
|
|
106
|
+
matched = true;
|
|
107
|
+
} else {
|
|
108
|
+
hasNonIndexField = true;
|
|
109
|
+
}
|
|
110
|
+
}) : void 0;
|
|
111
|
+
if ($orNewOrPromise instanceof Promise) {
|
|
112
|
+
return $orNewOrPromise.then(($orNew) => process$or($orNew));
|
|
113
|
+
}
|
|
114
|
+
return process$or($orNewOrPromise);
|
|
115
|
+
};
|
|
116
|
+
if ($andNewOrPromise instanceof Promise) {
|
|
117
|
+
return $andNewOrPromise.then(($andNew) => process$and($andNew));
|
|
118
|
+
}
|
|
119
|
+
return process$and($andNewOrPromise);
|
|
120
|
+
};
|
|
121
|
+
if (flatInfoOrPromise instanceof Promise) {
|
|
122
|
+
return flatInfoOrPromise.then(processFlatInfo);
|
|
123
|
+
}
|
|
124
|
+
return processFlatInfo(flatInfoOrPromise);
|
|
5
125
|
}
|
|
6
126
|
export {
|
|
7
|
-
|
|
127
|
+
getIndexInfo as default,
|
|
128
|
+
getMergedIndexInfo
|
|
8
129
|
};
|
package/dist/index24.mjs
CHANGED
|
@@ -1,28 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (allFieldsDeactivated) {
|
|
6
|
-
const result2 = { ...item };
|
|
7
|
-
Object.keys(fields).forEach((key) => {
|
|
8
|
-
const fieldValue = get(item, key);
|
|
9
|
-
if (fieldValue === void 0)
|
|
10
|
-
return;
|
|
11
|
-
set(result2, key, void 0, true);
|
|
12
|
-
});
|
|
13
|
-
return result2;
|
|
14
|
-
}
|
|
15
|
-
const result = {};
|
|
16
|
-
Object.entries(fields).forEach(([key, value]) => {
|
|
17
|
-
const fieldValue = get(item, key);
|
|
18
|
-
if (fieldValue === void 0)
|
|
19
|
-
return;
|
|
20
|
-
if (fieldValue == null && value !== 1)
|
|
21
|
-
return;
|
|
22
|
-
set(result, key, value === 1 ? fieldValue : void 0);
|
|
23
|
-
});
|
|
24
|
-
return result;
|
|
1
|
+
import { Query } from "mingo";
|
|
2
|
+
function match(item, selector) {
|
|
3
|
+
const query = new Query(selector);
|
|
4
|
+
return query.test(item);
|
|
25
5
|
}
|
|
26
6
|
export {
|
|
27
|
-
|
|
7
|
+
match as default
|
|
28
8
|
};
|
package/dist/index25.mjs
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
|
-
import { sort } from "fast-sort";
|
|
2
1
|
import get from "./index10.mjs";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import set from "./index32.mjs";
|
|
3
|
+
function project(item, fields) {
|
|
4
|
+
const allFieldsDeactivated = Object.values(fields).every((value) => value === 0);
|
|
5
|
+
if (allFieldsDeactivated) {
|
|
6
|
+
const result2 = { ...item };
|
|
7
|
+
Object.keys(fields).forEach((key) => {
|
|
8
|
+
const fieldValue = get(item, key);
|
|
9
|
+
if (fieldValue === void 0)
|
|
10
|
+
return;
|
|
11
|
+
set(result2, key, void 0, true);
|
|
12
|
+
});
|
|
13
|
+
return result2;
|
|
14
|
+
}
|
|
15
|
+
const result = {};
|
|
16
|
+
Object.entries(fields).forEach(([key, value]) => {
|
|
17
|
+
const fieldValue = get(item, key);
|
|
18
|
+
if (fieldValue === void 0)
|
|
19
|
+
return;
|
|
20
|
+
if (fieldValue == null && value !== 1)
|
|
21
|
+
return;
|
|
22
|
+
set(result, key, value === 1 ? fieldValue : void 0);
|
|
23
|
+
});
|
|
24
|
+
return result;
|
|
8
25
|
}
|
|
9
26
|
export {
|
|
10
|
-
|
|
27
|
+
project as default
|
|
11
28
|
};
|
package/dist/index26.mjs
CHANGED
|
@@ -1,30 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (fieldSelector == null)
|
|
9
|
-
return result;
|
|
10
|
-
if (isFieldExpression(fieldSelector)) {
|
|
11
|
-
if (fieldSelector.$ne != null) {
|
|
12
|
-
result.exclude = [serializeValue(fieldSelector.$ne)];
|
|
13
|
-
return result;
|
|
14
|
-
}
|
|
15
|
-
if (Array.isArray(fieldSelector.$in) && fieldSelector.$in.length > 0) {
|
|
16
|
-
result.include = fieldSelector.$in.map(serializeValue);
|
|
17
|
-
return result;
|
|
18
|
-
}
|
|
19
|
-
if (Array.isArray(fieldSelector.$nin) && fieldSelector.$nin.length > 0) {
|
|
20
|
-
result.exclude = fieldSelector.$nin.map(serializeValue);
|
|
21
|
-
return result;
|
|
22
|
-
}
|
|
23
|
-
return { include: null, exclude: null };
|
|
24
|
-
}
|
|
25
|
-
result.include = [serializeValue(fieldSelector)];
|
|
26
|
-
return result;
|
|
1
|
+
import { sort } from "fast-sort";
|
|
2
|
+
import get from "./index10.mjs";
|
|
3
|
+
function sortItems(items, sortFields) {
|
|
4
|
+
return sort(items).by(Object.entries(sortFields).map(([key, value]) => {
|
|
5
|
+
const order = value === 1 ? "asc" : "desc";
|
|
6
|
+
return { [order]: (i) => get(i, key) };
|
|
7
|
+
}));
|
|
27
8
|
}
|
|
28
9
|
export {
|
|
29
|
-
|
|
10
|
+
sortItems as default
|
|
30
11
|
};
|
package/dist/index27.mjs
CHANGED
|
@@ -1,47 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
async function flush(key) {
|
|
24
|
-
const q = queues.get(key);
|
|
25
|
-
if (!q || q.items.length === 0)
|
|
26
|
-
return;
|
|
27
|
-
if (q.timer != null) {
|
|
28
|
-
clearTimeout(q.timer);
|
|
29
|
-
q.timer = null;
|
|
1
|
+
import isFieldExpression from "./index31.mjs";
|
|
2
|
+
import serializeValue from "./index11.mjs";
|
|
3
|
+
function getMatchingKeys(field, selector) {
|
|
4
|
+
const result = { include: null, exclude: null };
|
|
5
|
+
const fieldSelector = selector[field];
|
|
6
|
+
if (fieldSelector instanceof RegExp)
|
|
7
|
+
return result;
|
|
8
|
+
if (fieldSelector == null)
|
|
9
|
+
return result;
|
|
10
|
+
if (isFieldExpression(fieldSelector)) {
|
|
11
|
+
if (fieldSelector.$ne != null) {
|
|
12
|
+
result.exclude = [serializeValue(fieldSelector.$ne)];
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(fieldSelector.$in) && fieldSelector.$in.length > 0) {
|
|
16
|
+
result.include = fieldSelector.$in.map(serializeValue);
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
if (Array.isArray(fieldSelector.$nin) && fieldSelector.$nin.length > 0) {
|
|
20
|
+
result.exclude = fieldSelector.$nin.map(serializeValue);
|
|
21
|
+
return result;
|
|
30
22
|
}
|
|
31
|
-
|
|
32
|
-
onFlush(key, items.map((i) => i.args)).then((results) => {
|
|
33
|
-
for (const [index, result] of results.entries()) {
|
|
34
|
-
const { resolve } = items[index];
|
|
35
|
-
resolve(result);
|
|
36
|
-
}
|
|
37
|
-
}).catch((error) => {
|
|
38
|
-
for (const { reject } of items) {
|
|
39
|
-
reject(error);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
23
|
+
return { include: null, exclude: null };
|
|
42
24
|
}
|
|
43
|
-
|
|
25
|
+
result.include = [serializeValue(fieldSelector)];
|
|
26
|
+
return result;
|
|
44
27
|
}
|
|
45
28
|
export {
|
|
46
|
-
|
|
29
|
+
getMatchingKeys as default
|
|
47
30
|
};
|
package/dist/index28.mjs
CHANGED
|
@@ -1,9 +1,47 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
function batchOnNextTick(onFlush) {
|
|
2
|
+
const queues = /* @__PURE__ */ new Map();
|
|
3
|
+
function enqueue(key, args) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
let q = queues.get(key);
|
|
6
|
+
if (!q) {
|
|
7
|
+
q = {
|
|
8
|
+
timer: null,
|
|
9
|
+
items: [],
|
|
10
|
+
flush: () => flush(key)
|
|
11
|
+
};
|
|
12
|
+
queues.set(key, q);
|
|
13
|
+
}
|
|
14
|
+
q.items.push({ args, resolve, reject });
|
|
15
|
+
if (q.timer == null) {
|
|
16
|
+
q.timer = setTimeout(() => {
|
|
17
|
+
q.timer = null;
|
|
18
|
+
void q.flush();
|
|
19
|
+
}, 0);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async function flush(key) {
|
|
24
|
+
const q = queues.get(key);
|
|
25
|
+
if (!q || q.items.length === 0)
|
|
26
|
+
return;
|
|
27
|
+
if (q.timer != null) {
|
|
28
|
+
clearTimeout(q.timer);
|
|
29
|
+
q.timer = null;
|
|
30
|
+
}
|
|
31
|
+
const items = q.items.splice(0);
|
|
32
|
+
onFlush(key, items.map((i) => i.args)).then((results) => {
|
|
33
|
+
for (const [index, result] of results.entries()) {
|
|
34
|
+
const { resolve } = items[index];
|
|
35
|
+
resolve(result);
|
|
36
|
+
}
|
|
37
|
+
}).catch((error) => {
|
|
38
|
+
for (const { reject } of items) {
|
|
39
|
+
reject(error);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return { enqueue, flush };
|
|
6
44
|
}
|
|
7
45
|
export {
|
|
8
|
-
|
|
46
|
+
batchOnNextTick as default
|
|
9
47
|
};
|
package/dist/index29.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
});
|
|
1
|
+
function truthy(value) {
|
|
2
|
+
return !!value;
|
|
3
|
+
}
|
|
4
|
+
function compact(array) {
|
|
5
|
+
return array.filter(truthy);
|
|
7
6
|
}
|
|
8
7
|
export {
|
|
9
|
-
|
|
8
|
+
compact as default
|
|
10
9
|
};
|
package/dist/index3.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import EventEmitter from "./index9.mjs";
|
|
2
|
-
import createSignal from "./
|
|
2
|
+
import createSignal from "./index19.mjs";
|
|
3
3
|
import randomId from "./index8.mjs";
|
|
4
|
-
import DefaultDataAdapter from "./
|
|
4
|
+
import DefaultDataAdapter from "./index13.mjs";
|
|
5
5
|
import modify from "./index7.mjs";
|
|
6
|
-
import deepClone from "./
|
|
7
|
-
import queryId from "./
|
|
6
|
+
import deepClone from "./index20.mjs";
|
|
7
|
+
import queryId from "./index21.mjs";
|
|
8
8
|
import Cursor from "./index2.mjs";
|
|
9
9
|
class Collection extends EventEmitter {
|
|
10
10
|
static collections = [];
|
|
@@ -244,14 +244,6 @@ class Collection extends EventEmitter {
|
|
|
244
244
|
Collection.collections = Collection.collections.filter((collection) => collection !== this);
|
|
245
245
|
Collection.onDisposeCallbacks.forEach((callback) => callback(this));
|
|
246
246
|
}
|
|
247
|
-
/**
|
|
248
|
-
* Finds multiple items in the collection based on a selector and optional options.
|
|
249
|
-
* Returns a cursor for reactive data queries.
|
|
250
|
-
* @template O - The options type for the find operation.
|
|
251
|
-
* @param [selector] - The criteria to select items.
|
|
252
|
-
* @param [options] - Options for the find operation, such as limit and sort.
|
|
253
|
-
* @returns A cursor to fetch and observe the matching items.
|
|
254
|
-
*/
|
|
255
247
|
find(selector = {}, options) {
|
|
256
248
|
if (this.isDisposed)
|
|
257
249
|
throw new Error("Collection is disposed");
|
|
@@ -281,7 +273,8 @@ class Collection extends EventEmitter {
|
|
|
281
273
|
requery();
|
|
282
274
|
};
|
|
283
275
|
const listeners = this.queryListeners({ selector, options });
|
|
284
|
-
|
|
276
|
+
const didRegister = listeners === 0;
|
|
277
|
+
if (didRegister)
|
|
285
278
|
this.backend.registerQuery(selector, options || {});
|
|
286
279
|
this.queryListeners({ selector, options }, listeners + 1);
|
|
287
280
|
const queryStateChangeCleanup = this.backend.onQueryStateChange(selector, options || {}, (state) => {
|
|
@@ -291,14 +284,14 @@ class Collection extends EventEmitter {
|
|
|
291
284
|
});
|
|
292
285
|
this.emit("observer.created", selector, options);
|
|
293
286
|
return () => {
|
|
294
|
-
|
|
287
|
+
queueMicrotask(() => {
|
|
295
288
|
const newListeners = Math.max(0, this.queryListeners({ selector, options }) - 1);
|
|
296
|
-
if (newListeners === 0)
|
|
289
|
+
if (newListeners === 0 && didRegister)
|
|
297
290
|
this.backend.unregisterQuery(selector, options || {});
|
|
298
291
|
this.queryListeners({ selector, options }, newListeners);
|
|
299
292
|
queryStateChangeCleanup();
|
|
300
293
|
this.emit("observer.disposed", selector, options);
|
|
301
|
-
}
|
|
294
|
+
});
|
|
302
295
|
};
|
|
303
296
|
}
|
|
304
297
|
});
|
|
@@ -306,16 +299,6 @@ class Collection extends EventEmitter {
|
|
|
306
299
|
this.executeInDebugMode((callstack) => this.emit("_debug.find", callstack, selector, options, cursor));
|
|
307
300
|
return cursor;
|
|
308
301
|
}
|
|
309
|
-
/**
|
|
310
|
-
* Finds a single item in the collection based on a selector and optional options.
|
|
311
|
-
* ⚡️ this function is reactive!
|
|
312
|
-
* Returns the found item or undefined if no item matches.
|
|
313
|
-
* @template Async - Whether to perform the operation asynchronously.
|
|
314
|
-
* @template O - The options type for the find operation.
|
|
315
|
-
* @param selector - The criteria to select the item.
|
|
316
|
-
* @param [options] - Options for the find operation, such as projection.
|
|
317
|
-
* @returns The found item or `undefined`.
|
|
318
|
-
*/
|
|
319
302
|
findOne(selector, options) {
|
|
320
303
|
if (this.isDisposed)
|
|
321
304
|
throw new Error("Collection is disposed");
|
package/dist/index30.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
1
|
+
function intersection(...arrays) {
|
|
2
|
+
if (arrays.length === 0)
|
|
3
|
+
return [];
|
|
4
|
+
return [...new Set(arrays.reduce((a, b) => a.filter((c) => b.includes(c))))];
|
|
3
5
|
}
|
|
4
6
|
export {
|
|
5
|
-
|
|
7
|
+
intersection as default
|
|
6
8
|
};
|
package/dist/index31.mjs
CHANGED
|
@@ -1,8 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const expressionKeys = /* @__PURE__ */ new Set([
|
|
2
|
+
"$eq",
|
|
3
|
+
"$gt",
|
|
4
|
+
"$gte",
|
|
5
|
+
"$lt",
|
|
6
|
+
"$lte",
|
|
7
|
+
"$in",
|
|
8
|
+
"$nin",
|
|
9
|
+
"$ne",
|
|
10
|
+
"$exists",
|
|
11
|
+
"$not",
|
|
12
|
+
"$expr",
|
|
13
|
+
"$jsonSchema",
|
|
14
|
+
"$mod",
|
|
15
|
+
"$regex",
|
|
16
|
+
"$options",
|
|
17
|
+
"$text",
|
|
18
|
+
"$where",
|
|
19
|
+
"$all",
|
|
20
|
+
"$elemMatch",
|
|
21
|
+
"$size",
|
|
22
|
+
"$bitsAllClear",
|
|
23
|
+
"$bitsAllSet",
|
|
24
|
+
"$bitsAnyClear",
|
|
25
|
+
"$bitsAnySet"
|
|
26
|
+
]);
|
|
27
|
+
function isFieldExpression(expression) {
|
|
28
|
+
if (typeof expression !== "object" || expression == null) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const keys = Object.keys(expression);
|
|
32
|
+
if (keys.length === 0) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const hasInvalidKeys = keys.some((key) => !expressionKeys.has(key));
|
|
36
|
+
if (hasInvalidKeys)
|
|
37
|
+
return false;
|
|
38
|
+
const hasValidKeys = keys.every((key) => expressionKeys.has(key));
|
|
39
|
+
return hasValidKeys;
|
|
5
40
|
}
|
|
6
41
|
export {
|
|
7
|
-
|
|
42
|
+
isFieldExpression as default
|
|
8
43
|
};
|
package/dist/index33.mjs
CHANGED
|
@@ -1,43 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
"$gt",
|
|
4
|
-
"$gte",
|
|
5
|
-
"$lt",
|
|
6
|
-
"$lte",
|
|
7
|
-
"$in",
|
|
8
|
-
"$nin",
|
|
9
|
-
"$ne",
|
|
10
|
-
"$exists",
|
|
11
|
-
"$not",
|
|
12
|
-
"$expr",
|
|
13
|
-
"$jsonSchema",
|
|
14
|
-
"$mod",
|
|
15
|
-
"$regex",
|
|
16
|
-
"$options",
|
|
17
|
-
"$text",
|
|
18
|
-
"$where",
|
|
19
|
-
"$all",
|
|
20
|
-
"$elemMatch",
|
|
21
|
-
"$size",
|
|
22
|
-
"$bitsAllClear",
|
|
23
|
-
"$bitsAllSet",
|
|
24
|
-
"$bitsAnyClear",
|
|
25
|
-
"$bitsAnySet"
|
|
26
|
-
]);
|
|
27
|
-
function isFieldExpression(expression) {
|
|
28
|
-
if (typeof expression !== "object" || expression == null) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
const keys = Object.keys(expression);
|
|
32
|
-
if (keys.length === 0) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
const hasInvalidKeys = keys.some((key) => !expressionKeys.has(key));
|
|
36
|
-
if (hasInvalidKeys)
|
|
37
|
-
return false;
|
|
38
|
-
const hasValidKeys = keys.every((key) => expressionKeys.has(key));
|
|
39
|
-
return hasValidKeys;
|
|
1
|
+
function createIndexProvider(definition) {
|
|
2
|
+
return definition;
|
|
40
3
|
}
|
|
41
4
|
export {
|
|
42
|
-
|
|
5
|
+
createIndexProvider as default
|
|
43
6
|
};
|
package/dist/index34.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function uniqueBy(array, fn) {
|
|
2
|
+
const set = /* @__PURE__ */ new Set();
|
|
3
|
+
return array.filter((element) => {
|
|
4
|
+
const value = typeof fn === "function" ? fn(element) : element[fn];
|
|
5
|
+
return !set.has(value) && set.add(value);
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
uniqueBy as default
|
|
10
|
+
};
|
package/dist/index7.mjs
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
2
|
+
/**
|
|
3
|
+
* Options that control execution mode (and potential future mode-specific behavior).
|
|
4
|
+
* Keep this minimal; you can extend it later (e.g. signal, timeoutMs, debugLabel).
|
|
5
|
+
*/
|
|
6
|
+
export type ModeOptions = {
|
|
7
|
+
async?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A generator helper that makes TypeScript infer the “synchronous value type” for maybe-async expressions.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const doc = yield* unwrap(Collection.findOne(...))
|
|
14
|
+
* const list = yield* unwrap(Collection.find(...).fetch())
|
|
15
|
+
*
|
|
16
|
+
* Runtime note:
|
|
17
|
+
* This does not “unwrap” Promises by itself. It yields the value/Promise to the runner and returns the
|
|
18
|
+
* value that the runner feeds back via `.next(...)`.
|
|
19
|
+
* @param value The value (or Promise of a value) to yield to the runner.
|
|
20
|
+
* @returns A generator that yields `value` and resolves to the runner-supplied unwrapped `T`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function unwrap<T>(value: MaybePromise<T>): Generator<MaybePromise<T>, T, T>;
|
|
23
|
+
/**
|
|
24
|
+
* Generator shape used by the factory.
|
|
25
|
+
*
|
|
26
|
+
* `TThis` is the type of `this` inside the generator.
|
|
27
|
+
* `Args` are the method parameters (excluding the mode flag).
|
|
28
|
+
* `TReturn` is the final return value of the workflow.
|
|
29
|
+
* `TNext` is the type that is yielded/awaited and fed back via `.next(...)`.
|
|
30
|
+
*
|
|
31
|
+
* Note:
|
|
32
|
+
* - For best inference at yield sites, prefer `yield* unwrap(expr)` for maybe-async expressions.
|
|
33
|
+
*/
|
|
34
|
+
export type ReactiveOrAsyncGen<TThis, Arguments extends any[], TReturn, TNext> = (this: TThis, a: boolean, ...args: Arguments) => Generator<MaybePromise<TNext>, TReturn, TNext>;
|
|
35
|
+
/**
|
|
36
|
+
* The method type produced from the generator signature.
|
|
37
|
+
* Adds overloads so that `{ async: true }` yields a `Promise<...>` return type.
|
|
38
|
+
*/
|
|
39
|
+
export type ReactiveOrAsyncMethod<TThis, P extends any[], R, N> = {
|
|
40
|
+
(this: TThis, ...args: P): R;
|
|
41
|
+
(this: TThis, ...args: [...P, ModeOptions?]): MaybePromise<R>;
|
|
42
|
+
(this: TThis, ...args: [...P, {
|
|
43
|
+
async: true;
|
|
44
|
+
}]): Promise<R>;
|
|
45
|
+
} & {
|
|
46
|
+
/** Exposes the underlying generator for composition via `yield* method.generator.call(this, a, ...)` */
|
|
47
|
+
generator: (this: TThis, a: boolean, ...args: P) => Generator<MaybePromise<N>, R, N>;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Factory that turns a generator workflow into a callable method that can run in sync (reactive) or async mode.
|
|
51
|
+
*
|
|
52
|
+
* Call style:
|
|
53
|
+
* fn(a, b) -> sync/reactive return
|
|
54
|
+
* await fn(a, b, { async: true }) -> async return
|
|
55
|
+
* @param gen Generator workflow. Receives `(a)` which indicates async mode and should `yield`/`yield* unwrap(...)`
|
|
56
|
+
* any values that may be Promises.
|
|
57
|
+
* @returns A callable method with overloads plus a `.generator` property for composition.
|
|
58
|
+
*/
|
|
59
|
+
export default function reactiveOrAsync<TThis, P extends any[], R, N>(gen: (this: TThis, a: boolean, ...args: P) => Generator<MaybePromise<N>, R, N>): ReactiveOrAsyncMethod<TThis, P, R, N>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signaldb/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.5",
|
|
4
4
|
"description": "SignalDB is a client-side database that provides a simple MongoDB-like interface to the data with first-class typescript support to achieve an optimistic UI. Data persistence can be achieved by using storage providers that store the data through a JSON interface to places such as localStorage.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "rimraf dist && vite build",
|