@signaldb/core 2.0.0-beta.2 → 2.0.0-beta.21
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 +183 -80
- package/dist/AsyncDataAdapter.d.ts +53 -7
- package/dist/AutoFetchDataAdapter.d.ts +4 -6
- package/dist/Collection/Cursor.d.ts +56 -4
- package/dist/Collection/Observer.d.ts +33 -0
- package/dist/Collection/index.d.ts +66 -19
- package/dist/Collection/types.d.ts +9 -2
- package/dist/DataAdapter.d.ts +24 -6
- package/dist/DefaultDataAdapter.d.ts +5 -5
- package/dist/WorkerDataAdapter.d.ts +57 -5
- package/dist/WorkerDataAdapterHost.d.ts +9 -7
- package/dist/createIndex.d.ts +2 -2
- package/dist/createIndexProvider.d.ts +2 -2
- package/dist/createReactivityAdapter.d.ts +2 -2
- package/dist/createStorageAdapter.d.ts +1 -1
- package/dist/getIndexInfo.d.ts +3 -4
- package/dist/index.cjs.js +33 -31
- package/dist/index.d.ts +6 -1
- package/dist/index.mjs +17 -32
- package/dist/index10.cjs.js +11 -0
- package/dist/index10.mjs +10 -18
- package/dist/index11.cjs.js +23 -0
- package/dist/index11.mjs +22 -15
- package/dist/index12.cjs.js +45 -0
- package/dist/index12.mjs +44 -353
- package/dist/index13.cjs.js +22 -0
- package/dist/index13.mjs +21 -419
- package/dist/index14.cjs.js +45 -0
- package/dist/index14.mjs +44 -206
- package/dist/index15.cjs.js +86 -0
- package/dist/index15.mjs +85 -388
- package/dist/index16.cjs.js +15 -0
- package/dist/index16.mjs +14 -579
- package/dist/index17.cjs.js +141 -0
- package/dist/index17.mjs +140 -152
- package/dist/index18.cjs.js +47 -0
- package/dist/index18.mjs +46 -26
- package/dist/index19.cjs.js +15 -0
- package/dist/index19.mjs +14 -41
- package/dist/index2.cjs.js +33 -0
- package/dist/index2.mjs +32 -258
- package/dist/index20.cjs.js +23 -0
- package/dist/index20.mjs +22 -16
- package/dist/index21.cjs.js +37 -0
- package/dist/index21.mjs +36 -104
- package/dist/index22.cjs.js +35 -0
- package/dist/index22.mjs +34 -128
- package/dist/index23.cjs.js +21 -0
- package/dist/index23.mjs +20 -7
- package/dist/index24.cjs.js +19 -0
- package/dist/index24.mjs +18 -27
- package/dist/index25.cjs.js +157 -0
- package/dist/index25.mjs +156 -11
- package/dist/index26.cjs.js +38 -0
- package/dist/index26.mjs +37 -29
- package/dist/index27.cjs.js +42 -0
- package/dist/index27.mjs +41 -46
- package/dist/index28.cjs.js +347 -0
- package/dist/index28.mjs +345 -7
- package/dist/index29.cjs.js +602 -0
- package/dist/index29.mjs +601 -7
- package/dist/index3.cjs.js +19 -0
- package/dist/index3.mjs +18 -556
- package/dist/index30.cjs.js +11 -0
- package/dist/index30.mjs +10 -42
- package/dist/index31.cjs.js +11 -0
- package/dist/index31.mjs +10 -29
- package/dist/index32.cjs.js +90 -0
- package/dist/index32.mjs +89 -10
- package/dist/index33.cjs.js +53 -0
- package/dist/index33.mjs +52 -5
- package/dist/index34.cjs.js +453 -0
- package/dist/index34.mjs +453 -0
- package/dist/index35.cjs.js +72 -0
- package/dist/index35.mjs +72 -0
- package/dist/index36.cjs.js +580 -0
- package/dist/index36.mjs +580 -0
- package/dist/index37.cjs.js +21 -0
- package/dist/index37.mjs +21 -0
- package/dist/index38.cjs.js +363 -0
- package/dist/index38.mjs +363 -0
- package/dist/index39.cjs.js +513 -0
- package/dist/index39.mjs +513 -0
- package/dist/index4.cjs.js +209 -0
- package/dist/index4.mjs +204 -5
- package/dist/index5.cjs.js +187 -0
- package/dist/index5.mjs +186 -5
- package/dist/index6.cjs.js +303 -0
- package/dist/index6.mjs +301 -28
- package/dist/index7.cjs.js +125 -0
- package/dist/index7.mjs +124 -12
- package/dist/index8.cjs.js +33 -0
- package/dist/index8.mjs +32 -5
- package/dist/index9.cjs.js +12 -0
- package/dist/index9.mjs +11 -133
- package/dist/types/IndexProvider.d.ts +2 -2
- package/dist/types/Modifier.d.ts +1 -1
- package/dist/types/ReactivityAdapter.d.ts +1 -1
- package/dist/types/StorageAdapter.d.ts +9 -1
- package/dist/utils/applyQueryOptions.d.ts +15 -0
- package/dist/utils/createSignal.d.ts +2 -2
- package/dist/utils/getMatchingKeys.d.ts +2 -2
- package/dist/utils/idIndexQuery.d.ts +20 -0
- package/dist/utils/incrementalQueryUpdate.d.ts +62 -0
- package/dist/utils/isFieldExpression.d.ts +1 -1
- package/dist/utils/match.d.ts +1 -1
- package/dist/utils/modify.d.ts +1 -1
- package/dist/utils/projectItems.d.ts +12 -0
- package/dist/utils/queryDelta.d.ts +83 -0
- package/dist/utils/queryId.d.ts +2 -2
- package/dist/utils/reactiveOrAsync.d.ts +59 -0
- package/dist/utils/storageIndexQuery.d.ts +20 -0
- package/package.json +1 -1
- package/dist/index.cjs10.js +0 -18
- package/dist/index.cjs11.js +0 -15
- package/dist/index.cjs12.js +0 -353
- package/dist/index.cjs13.js +0 -419
- package/dist/index.cjs14.js +0 -206
- package/dist/index.cjs15.js +0 -388
- package/dist/index.cjs16.js +0 -579
- package/dist/index.cjs17.js +0 -152
- package/dist/index.cjs18.js +0 -26
- package/dist/index.cjs19.js +0 -42
- package/dist/index.cjs2.js +0 -259
- package/dist/index.cjs20.js +0 -16
- package/dist/index.cjs21.js +0 -104
- package/dist/index.cjs22.js +0 -129
- package/dist/index.cjs23.js +0 -7
- package/dist/index.cjs24.js +0 -27
- package/dist/index.cjs25.js +0 -10
- package/dist/index.cjs26.js +0 -29
- package/dist/index.cjs27.js +0 -46
- package/dist/index.cjs28.js +0 -8
- package/dist/index.cjs29.js +0 -7
- package/dist/index.cjs3.js +0 -557
- package/dist/index.cjs30.js +0 -42
- package/dist/index.cjs31.js +0 -29
- package/dist/index.cjs32.js +0 -9
- package/dist/index.cjs33.js +0 -5
- package/dist/index.cjs4.js +0 -5
- package/dist/index.cjs5.js +0 -5
- package/dist/index.cjs6.js +0 -29
- package/dist/index.cjs7.js +0 -12
- package/dist/index.cjs8.js +0 -5
- package/dist/index.cjs9.js +0 -133
package/dist/index10.mjs
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (current == null)
|
|
10
|
-
return;
|
|
11
|
-
current = current[key];
|
|
12
|
-
}
|
|
13
|
-
if (current === void 0)
|
|
14
|
-
return;
|
|
15
|
-
return current;
|
|
1
|
+
//#region src/createIndexProvider.ts
|
|
2
|
+
/**
|
|
3
|
+
* Creates an IndexProvider based on the given definition.
|
|
4
|
+
* @param definition - The definition of the IndexProvider.
|
|
5
|
+
* @returns The created IndexProvider.
|
|
6
|
+
*/
|
|
7
|
+
function createIndexProvider(definition) {
|
|
8
|
+
return definition;
|
|
16
9
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { createIndexProvider as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/utils/get.ts
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves the value at a specified path within an object.
|
|
4
|
+
* Supports dot and bracket notation for navigating nested properties.
|
|
5
|
+
* @template T - The type of the object to retrieve the value from.
|
|
6
|
+
* @param value - The object to navigate.
|
|
7
|
+
* @param path - The path (dot or bracket notation) to the desired value.
|
|
8
|
+
* @returns The value at the specified path, or `undefined` if the path does not exist.
|
|
9
|
+
*/
|
|
10
|
+
function get(value, path) {
|
|
11
|
+
const normalized = path.replaceAll(/\[(\w+)\]/g, ".$1");
|
|
12
|
+
if (normalized.includes("..") || normalized.startsWith(".") || normalized.endsWith(".")) return;
|
|
13
|
+
const segments = normalized.split(".");
|
|
14
|
+
let current = value;
|
|
15
|
+
for (const key of segments) {
|
|
16
|
+
if (current == null) return;
|
|
17
|
+
current = current[key];
|
|
18
|
+
}
|
|
19
|
+
if (current === void 0) return;
|
|
20
|
+
return current;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.default = get;
|
package/dist/index11.mjs
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
//#region src/utils/get.ts
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves the value at a specified path within an object.
|
|
4
|
+
* Supports dot and bracket notation for navigating nested properties.
|
|
5
|
+
* @template T - The type of the object to retrieve the value from.
|
|
6
|
+
* @param value - The object to navigate.
|
|
7
|
+
* @param path - The path (dot or bracket notation) to the desired value.
|
|
8
|
+
* @returns The value at the specified path, or `undefined` if the path does not exist.
|
|
9
|
+
*/
|
|
10
|
+
function get(value, path) {
|
|
11
|
+
const normalized = path.replaceAll(/\[(\w+)\]/g, ".$1");
|
|
12
|
+
if (normalized.includes("..") || normalized.startsWith(".") || normalized.endsWith(".")) return;
|
|
13
|
+
const segments = normalized.split(".");
|
|
14
|
+
let current = value;
|
|
15
|
+
for (const key of segments) {
|
|
16
|
+
if (current == null) return;
|
|
17
|
+
current = current[key];
|
|
18
|
+
}
|
|
19
|
+
if (current === void 0) return;
|
|
20
|
+
return current;
|
|
13
21
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { get as default };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/utils/isFieldExpression.ts
|
|
2
|
+
var expressionKeys = new Set([
|
|
3
|
+
"$eq",
|
|
4
|
+
"$gt",
|
|
5
|
+
"$gte",
|
|
6
|
+
"$lt",
|
|
7
|
+
"$lte",
|
|
8
|
+
"$in",
|
|
9
|
+
"$nin",
|
|
10
|
+
"$ne",
|
|
11
|
+
"$exists",
|
|
12
|
+
"$not",
|
|
13
|
+
"$expr",
|
|
14
|
+
"$jsonSchema",
|
|
15
|
+
"$mod",
|
|
16
|
+
"$regex",
|
|
17
|
+
"$options",
|
|
18
|
+
"$text",
|
|
19
|
+
"$where",
|
|
20
|
+
"$all",
|
|
21
|
+
"$elemMatch",
|
|
22
|
+
"$size",
|
|
23
|
+
"$bitsAllClear",
|
|
24
|
+
"$bitsAllSet",
|
|
25
|
+
"$bitsAnyClear",
|
|
26
|
+
"$bitsAnySet"
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* Determines whether a given object is a valid field expression.
|
|
30
|
+
* A field expression is an object containing query operators supported by MongoDB-style queries.
|
|
31
|
+
* @template T - The type of the field expression.
|
|
32
|
+
* @param expression - The object to test.
|
|
33
|
+
* @returns A boolean indicating whether the object is a valid field expression.
|
|
34
|
+
* - `true` if the object contains only recognized query operators.
|
|
35
|
+
* - `false` otherwise.
|
|
36
|
+
*/
|
|
37
|
+
function isFieldExpression(expression) {
|
|
38
|
+
if (typeof expression !== "object" || expression == null) return false;
|
|
39
|
+
const keys = Object.keys(expression);
|
|
40
|
+
if (keys.length === 0) return false;
|
|
41
|
+
if (keys.some((key) => !expressionKeys.has(key))) return false;
|
|
42
|
+
return keys.every((key) => expressionKeys.has(key));
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
exports.default = isFieldExpression;
|
package/dist/index12.mjs
CHANGED
|
@@ -1,354 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
//#region src/utils/isFieldExpression.ts
|
|
2
|
+
var expressionKeys = new Set([
|
|
3
|
+
"$eq",
|
|
4
|
+
"$gt",
|
|
5
|
+
"$gte",
|
|
6
|
+
"$lt",
|
|
7
|
+
"$lte",
|
|
8
|
+
"$in",
|
|
9
|
+
"$nin",
|
|
10
|
+
"$ne",
|
|
11
|
+
"$exists",
|
|
12
|
+
"$not",
|
|
13
|
+
"$expr",
|
|
14
|
+
"$jsonSchema",
|
|
15
|
+
"$mod",
|
|
16
|
+
"$regex",
|
|
17
|
+
"$options",
|
|
18
|
+
"$text",
|
|
19
|
+
"$where",
|
|
20
|
+
"$all",
|
|
21
|
+
"$elemMatch",
|
|
22
|
+
"$size",
|
|
23
|
+
"$bitsAllClear",
|
|
24
|
+
"$bitsAllSet",
|
|
25
|
+
"$bitsAnyClear",
|
|
26
|
+
"$bitsAnySet"
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* Determines whether a given object is a valid field expression.
|
|
30
|
+
* A field expression is an object containing query operators supported by MongoDB-style queries.
|
|
31
|
+
* @template T - The type of the field expression.
|
|
32
|
+
* @param expression - The object to test.
|
|
33
|
+
* @returns A boolean indicating whether the object is a valid field expression.
|
|
34
|
+
* - `true` if the object contains only recognized query operators.
|
|
35
|
+
* - `false` otherwise.
|
|
36
|
+
*/
|
|
37
|
+
function isFieldExpression(expression) {
|
|
38
|
+
if (typeof expression !== "object" || expression == null) return false;
|
|
39
|
+
const keys = Object.keys(expression);
|
|
40
|
+
if (keys.length === 0) return false;
|
|
41
|
+
if (keys.some((key) => !expressionKeys.has(key))) return false;
|
|
42
|
+
return keys.every((key) => expressionKeys.has(key));
|
|
14
43
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
options;
|
|
18
|
-
storageAdapters = /* @__PURE__ */ new Map();
|
|
19
|
-
indices = /* @__PURE__ */ new Map();
|
|
20
|
-
activeQueries = /* @__PURE__ */ new Map();
|
|
21
|
-
queryEmitters = /* @__PURE__ */ new Map();
|
|
22
|
-
queuedQueryUpdates = /* @__PURE__ */ new Map();
|
|
23
|
-
cachedQueryResults = /* @__PURE__ */ new Map();
|
|
24
|
-
constructor(options) {
|
|
25
|
-
this.options = options || {};
|
|
26
|
-
}
|
|
27
|
-
ensureStorageAdapter(name) {
|
|
28
|
-
if (this.storageAdapters.get(name))
|
|
29
|
-
return;
|
|
30
|
-
if (!this.options.storage)
|
|
31
|
-
return;
|
|
32
|
-
const adapter = this.options.storage(name);
|
|
33
|
-
if (!adapter)
|
|
34
|
-
return;
|
|
35
|
-
this.storageAdapters.set(name, adapter);
|
|
36
|
-
}
|
|
37
|
-
rebuildIndices(collection) {
|
|
38
|
-
const items = this.items.get(collection.name);
|
|
39
|
-
if (!items)
|
|
40
|
-
throw new Error(`Items not found for collection ${collection.name}`);
|
|
41
|
-
const indices = this.indices.get(collection.name);
|
|
42
|
-
if (!indices)
|
|
43
|
-
throw new Error(`Indices not found for collection ${collection.name}`);
|
|
44
|
-
indices.forEach((index) => index.rebuild([...items.values()]));
|
|
45
|
-
}
|
|
46
|
-
async setupStorageAdapter(collection) {
|
|
47
|
-
const storageAdapter = this.storageAdapters.get(collection.name);
|
|
48
|
-
if (!storageAdapter)
|
|
49
|
-
return;
|
|
50
|
-
return storageAdapter.setup().then(async () => {
|
|
51
|
-
const items = await storageAdapter.readAll();
|
|
52
|
-
this.items.set(collection.name, items.reduce((map, item) => {
|
|
53
|
-
map.set(serializeValue(item.id), item);
|
|
54
|
-
return map;
|
|
55
|
-
}, /* @__PURE__ */ new Map()));
|
|
56
|
-
this.rebuildIndices(collection);
|
|
57
|
-
}).catch((error) => {
|
|
58
|
-
if (!this.options.onError) {
|
|
59
|
-
console.error(`Error during data persistence operation in collection ${collection.name}`, error);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
this.options.onError(collection.name, error instanceof Error ? error : new Error(error));
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
getIndexInfo(collection, selector) {
|
|
66
|
-
if (selector != null && Object.keys(selector).length === 1 && "id" in selector && typeof selector.id !== "object") {
|
|
67
|
-
return {
|
|
68
|
-
matched: true,
|
|
69
|
-
ids: [serializeValue(selector.id)],
|
|
70
|
-
optimizedSelector: {}
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
if (selector == null) {
|
|
74
|
-
return {
|
|
75
|
-
matched: false,
|
|
76
|
-
ids: [],
|
|
77
|
-
optimizedSelector: {}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
return getIndexInfo((this.indices.get(collection.name) ?? []).map((i) => i.query.bind(i)), selector);
|
|
81
|
-
}
|
|
82
|
-
applyIndexDeltas(collection, changes) {
|
|
83
|
-
const indices = this.indices.get(collection.name) ?? [];
|
|
84
|
-
for (const index of indices) {
|
|
85
|
-
if (changes.modified)
|
|
86
|
-
index.update(changes.modified);
|
|
87
|
-
if (changes.added && changes.added.length > 0)
|
|
88
|
-
index.insert(changes.added);
|
|
89
|
-
if (changes.removed && changes.removed.length > 0)
|
|
90
|
-
index.remove(changes.removed);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
getItem(collection, selector) {
|
|
94
|
-
const memory = this.items.get(collection.name) ?? /* @__PURE__ */ new Map();
|
|
95
|
-
const indexInfo = this.getIndexInfo(collection, selector);
|
|
96
|
-
const items = indexInfo.matched ? indexInfo.ids.map((id) => memory.get(serializeValue(id))).filter((i) => i != null) : [...memory.values()];
|
|
97
|
-
const item = items.find((document) => match(document, selector));
|
|
98
|
-
return item;
|
|
99
|
-
}
|
|
100
|
-
queryItems(collection, selector) {
|
|
101
|
-
const indexInfo = this.getIndexInfo(collection, selector);
|
|
102
|
-
const matchItems = (item) => {
|
|
103
|
-
if (indexInfo.optimizedSelector == null)
|
|
104
|
-
return true;
|
|
105
|
-
if (Object.keys(indexInfo.optimizedSelector).length <= 0)
|
|
106
|
-
return true;
|
|
107
|
-
const matches = match(item, indexInfo.optimizedSelector);
|
|
108
|
-
return matches;
|
|
109
|
-
};
|
|
110
|
-
const items = this.items.get(collection.name);
|
|
111
|
-
if (!indexInfo.matched) {
|
|
112
|
-
if (isEqual(selector, {}))
|
|
113
|
-
return [...items.values()];
|
|
114
|
-
return [...items.values()].filter(matchItems);
|
|
115
|
-
}
|
|
116
|
-
const foundItems = indexInfo.ids.map((ids) => items.get(serializeValue(ids))).filter((i) => i != null);
|
|
117
|
-
if (isEqual(indexInfo.optimizedSelector, {}))
|
|
118
|
-
return foundItems;
|
|
119
|
-
return foundItems.filter(matchItems);
|
|
120
|
-
}
|
|
121
|
-
executeQuery(collection, selector, options) {
|
|
122
|
-
const items = this.queryItems(collection, selector || {});
|
|
123
|
-
const { sort, skip, limit, fields } = options || {};
|
|
124
|
-
const sorted = sort ? sortItems(items, sort) : items;
|
|
125
|
-
const skipped = skip ? sorted.slice(skip) : sorted;
|
|
126
|
-
const limited = limit ? skipped.slice(0, limit) : skipped;
|
|
127
|
-
const idExcluded = fields && fields.id === 0;
|
|
128
|
-
return limited.map((item) => {
|
|
129
|
-
if (!fields)
|
|
130
|
-
return item;
|
|
131
|
-
return {
|
|
132
|
-
...idExcluded ? {} : { id: item.id },
|
|
133
|
-
...project(item, fields)
|
|
134
|
-
};
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
flushQueuedQueryUpdates(collection) {
|
|
138
|
-
if (!this.queuedQueryUpdates.get(collection.name))
|
|
139
|
-
return;
|
|
140
|
-
const changes = this.queuedQueryUpdates.get(collection.name);
|
|
141
|
-
if (!changes || !hasPendingUpdates(changes))
|
|
142
|
-
return;
|
|
143
|
-
this.queuedQueryUpdates.set(collection.name, { added: [], modified: [], removed: [] });
|
|
144
|
-
const flatItems = [...changes.added, ...changes.modified, ...changes.removed];
|
|
145
|
-
const itemIds = new Set(flatItems.map((i) => i.id));
|
|
146
|
-
const queries = [
|
|
147
|
-
...this.activeQueries.get(collection.name)?.values() ?? []
|
|
148
|
-
].filter(({ selector, options }) => {
|
|
149
|
-
const idsInQuery = this.cachedQueryResults.get(collection.name)?.get(queryId(selector, options))?.map((i) => i.id) ?? [];
|
|
150
|
-
if (idsInQuery.some((id) => itemIds.has(id)))
|
|
151
|
-
return true;
|
|
152
|
-
return flatItems.some((item) => match(item, selector));
|
|
153
|
-
});
|
|
154
|
-
queries.forEach(({ selector, options }) => {
|
|
155
|
-
this.executeAndCacheQuery(collection, selector, options);
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
executeAndCacheQuery(collection, selector, options) {
|
|
159
|
-
const result = this.executeQuery(collection, selector, options);
|
|
160
|
-
this.cachedQueryResults.set(collection.name, this.cachedQueryResults.get(collection.name) || /* @__PURE__ */ new Map());
|
|
161
|
-
this.cachedQueryResults.get(collection.name)?.set(queryId(selector, options), result);
|
|
162
|
-
const emitter = this.queryEmitters.get(collection.name);
|
|
163
|
-
if (!emitter)
|
|
164
|
-
return;
|
|
165
|
-
emitter.emit("change", selector, options, "complete");
|
|
166
|
-
}
|
|
167
|
-
updateQueries(collection, changes) {
|
|
168
|
-
this.queuedQueryUpdates.set(collection.name, this.queuedQueryUpdates.get(collection.name) || { added: [], modified: [], removed: [] });
|
|
169
|
-
this.queuedQueryUpdates.get(collection.name)?.added.push(...changes.added);
|
|
170
|
-
this.queuedQueryUpdates.get(collection.name)?.modified.push(...changes.modified);
|
|
171
|
-
this.queuedQueryUpdates.get(collection.name)?.removed.push(...changes.removed);
|
|
172
|
-
this.flushQueuedQueryUpdates(collection);
|
|
173
|
-
}
|
|
174
|
-
createCollectionBackend(collection, indices) {
|
|
175
|
-
this.ensureStorageAdapter(collection.name);
|
|
176
|
-
this.items.set(collection.name, this.items.get(collection.name) ?? /* @__PURE__ */ new Map());
|
|
177
|
-
this.queryEmitters.set(collection.name, this.queryEmitters.get(collection.name) ?? new EventEmitter());
|
|
178
|
-
this.queryEmitters.get(collection.name)?.setMaxListeners(Infinity);
|
|
179
|
-
this.activeQueries.set(collection.name, this.activeQueries.get(collection.name) || /* @__PURE__ */ new Map());
|
|
180
|
-
this.indices.set(collection.name, indices.map((field) => createIndex(field)));
|
|
181
|
-
this.rebuildIndices(collection);
|
|
182
|
-
const persistenceReadyPromise = this.setupStorageAdapter(collection);
|
|
183
|
-
const backend = {
|
|
184
|
-
// CRUD operations
|
|
185
|
-
insert: async (newItem) => {
|
|
186
|
-
const items = this.items.get(collection.name);
|
|
187
|
-
if (!items)
|
|
188
|
-
throw new Error(`Items not found for collection ${collection.name}`);
|
|
189
|
-
if (items.has(serializeValue(newItem.id))) {
|
|
190
|
-
throw new Error(`Item with id '${newItem.id}' already exists`);
|
|
191
|
-
}
|
|
192
|
-
this.items.get(collection.name)?.set(serializeValue(newItem.id), newItem);
|
|
193
|
-
await this.storageAdapters.get(collection.name)?.insert([newItem]);
|
|
194
|
-
this.applyIndexDeltas(collection, { added: [newItem] });
|
|
195
|
-
this.updateQueries(collection, {
|
|
196
|
-
added: [],
|
|
197
|
-
modified: [newItem],
|
|
198
|
-
removed: []
|
|
199
|
-
});
|
|
200
|
-
return newItem;
|
|
201
|
-
},
|
|
202
|
-
updateOne: async (selector, modifier) => {
|
|
203
|
-
const { $setOnInsert, ...restModifier } = modifier;
|
|
204
|
-
const item = this.getItem(collection, selector);
|
|
205
|
-
if (item == null)
|
|
206
|
-
return [];
|
|
207
|
-
const modifiedItem = modify(deepClone(item), restModifier);
|
|
208
|
-
const hasItemWithSameId = item.id !== modifiedItem.id && this.getItem(collection, { id: modifiedItem.id }) != null;
|
|
209
|
-
if (hasItemWithSameId) {
|
|
210
|
-
throw new Error(`Item with id '${modifiedItem.id}' already exists`);
|
|
211
|
-
}
|
|
212
|
-
this.items.get(collection.name)?.set(serializeValue(modifiedItem.id), modifiedItem);
|
|
213
|
-
await this.storageAdapters.get(collection.name)?.replace([modifiedItem]);
|
|
214
|
-
this.applyIndexDeltas(collection, { modified: [{ oldItem: item, newItem: modifiedItem }] });
|
|
215
|
-
this.updateQueries(collection, {
|
|
216
|
-
added: [],
|
|
217
|
-
modified: [modifiedItem],
|
|
218
|
-
removed: []
|
|
219
|
-
});
|
|
220
|
-
return [modifiedItem];
|
|
221
|
-
},
|
|
222
|
-
updateMany: async (selector, modifier) => {
|
|
223
|
-
const { $setOnInsert, ...restModifier } = modifier;
|
|
224
|
-
const items = this.executeQuery(collection, selector, {});
|
|
225
|
-
const changedItems = items.map((item) => {
|
|
226
|
-
const modifiedItem = modify(deepClone(item), restModifier);
|
|
227
|
-
const hasItemWithSameId = item.id !== modifiedItem.id && this.getItem(collection, { id: modifiedItem.id }) != null;
|
|
228
|
-
if (hasItemWithSameId) {
|
|
229
|
-
throw new Error(`Item with id '${modifiedItem.id}' already exists`);
|
|
230
|
-
}
|
|
231
|
-
return modifiedItem;
|
|
232
|
-
});
|
|
233
|
-
changedItems.forEach((item) => {
|
|
234
|
-
this.items.get(collection.name)?.set(serializeValue(item.id), item);
|
|
235
|
-
});
|
|
236
|
-
await this.storageAdapters.get(collection.name)?.replace(changedItems);
|
|
237
|
-
const pairs = items.map((oldItem, index) => ({ oldItem, newItem: changedItems[index] }));
|
|
238
|
-
this.applyIndexDeltas(collection, { modified: pairs });
|
|
239
|
-
this.updateQueries(collection, {
|
|
240
|
-
added: [],
|
|
241
|
-
modified: changedItems,
|
|
242
|
-
removed: []
|
|
243
|
-
});
|
|
244
|
-
return changedItems;
|
|
245
|
-
},
|
|
246
|
-
replaceOne: async (selector, replacement) => {
|
|
247
|
-
const item = this.getItem(collection, selector);
|
|
248
|
-
if (item == null)
|
|
249
|
-
return [];
|
|
250
|
-
const hasItemWithSameId = item.id !== replacement.id && replacement.id != null && this.getItem(collection, { id: replacement.id }) != null;
|
|
251
|
-
if (hasItemWithSameId) {
|
|
252
|
-
throw new Error(`Item with id '${replacement.id}' already exists`);
|
|
253
|
-
}
|
|
254
|
-
const modifiedItem = { id: item.id, ...replacement };
|
|
255
|
-
this.items.get(collection.name)?.set(serializeValue(modifiedItem.id), modifiedItem);
|
|
256
|
-
await this.storageAdapters.get(collection.name)?.replace([modifiedItem]);
|
|
257
|
-
this.applyIndexDeltas(collection, { modified: [{ oldItem: item, newItem: modifiedItem }] });
|
|
258
|
-
this.updateQueries(collection, {
|
|
259
|
-
added: [],
|
|
260
|
-
modified: [modifiedItem],
|
|
261
|
-
removed: []
|
|
262
|
-
});
|
|
263
|
-
return [modifiedItem];
|
|
264
|
-
},
|
|
265
|
-
removeOne: async (selector) => {
|
|
266
|
-
const item = this.getItem(collection, selector);
|
|
267
|
-
if (item == null)
|
|
268
|
-
return [];
|
|
269
|
-
this.items.get(collection.name)?.delete(serializeValue(item.id));
|
|
270
|
-
await this.storageAdapters.get(collection.name)?.remove([item]);
|
|
271
|
-
this.applyIndexDeltas(collection, { removed: [item] });
|
|
272
|
-
this.updateQueries(collection, {
|
|
273
|
-
added: [],
|
|
274
|
-
modified: [],
|
|
275
|
-
removed: [item]
|
|
276
|
-
});
|
|
277
|
-
return [item];
|
|
278
|
-
},
|
|
279
|
-
removeMany: async (selector) => {
|
|
280
|
-
const items = backend.getQueryResult(selector, {});
|
|
281
|
-
items.forEach((item) => {
|
|
282
|
-
this.items.get(collection.name)?.delete(serializeValue(item.id));
|
|
283
|
-
});
|
|
284
|
-
await this.storageAdapters.get(collection.name)?.remove(items);
|
|
285
|
-
this.applyIndexDeltas(collection, { removed: items });
|
|
286
|
-
this.updateQueries(collection, {
|
|
287
|
-
added: [],
|
|
288
|
-
modified: [],
|
|
289
|
-
removed: items
|
|
290
|
-
});
|
|
291
|
-
return items;
|
|
292
|
-
},
|
|
293
|
-
// methods for registering and unregistering queries that will be called from the collection during find/findOne
|
|
294
|
-
registerQuery: (selector, options) => {
|
|
295
|
-
this.activeQueries.set(collection.name, this.activeQueries.get(collection.name) || /* @__PURE__ */ new Map());
|
|
296
|
-
this.activeQueries.get(collection.name)?.set(queryId(selector, options), {
|
|
297
|
-
selector,
|
|
298
|
-
options
|
|
299
|
-
});
|
|
300
|
-
this.executeAndCacheQuery(collection, selector, options);
|
|
301
|
-
},
|
|
302
|
-
unregisterQuery: (selector, options) => {
|
|
303
|
-
if (!this.activeQueries.get(collection.name))
|
|
304
|
-
return;
|
|
305
|
-
this.activeQueries.get(collection.name)?.delete(queryId(selector, options));
|
|
306
|
-
},
|
|
307
|
-
getQueryState: () => "complete",
|
|
308
|
-
onQueryStateChange: (selector, options, callback) => {
|
|
309
|
-
const emitter = this.queryEmitters.get(collection.name);
|
|
310
|
-
if (!emitter)
|
|
311
|
-
throw new Error(`Query emitter not found for collection ${collection.name}`);
|
|
312
|
-
const handler = (querySelector, queryOptions, state) => {
|
|
313
|
-
if (queryId(querySelector, queryOptions) !== queryId(selector, options))
|
|
314
|
-
return;
|
|
315
|
-
callback(state);
|
|
316
|
-
};
|
|
317
|
-
emitter.on("change", handler);
|
|
318
|
-
return () => {
|
|
319
|
-
emitter.off("change", handler);
|
|
320
|
-
};
|
|
321
|
-
},
|
|
322
|
-
getQueryError: () => null,
|
|
323
|
-
getQueryResult: (selector, options) => {
|
|
324
|
-
const isQueryActive = this.activeQueries.get(collection.name)?.has(queryId(selector, options));
|
|
325
|
-
if (isQueryActive) {
|
|
326
|
-
const results = this.cachedQueryResults.get(collection.name)?.get(queryId(selector, options));
|
|
327
|
-
if (!results)
|
|
328
|
-
throw new Error("Cached query results are not defined!");
|
|
329
|
-
return results;
|
|
330
|
-
}
|
|
331
|
-
return this.executeQuery(collection, selector, options);
|
|
332
|
-
},
|
|
333
|
-
executeQuery: (selector, options) => Promise.resolve(this.executeQuery(collection, selector, options)),
|
|
334
|
-
// lifecycle methods
|
|
335
|
-
dispose: async () => {
|
|
336
|
-
const adapter = this.storageAdapters.get(collection.name);
|
|
337
|
-
if (adapter?.teardown)
|
|
338
|
-
await adapter.teardown();
|
|
339
|
-
this.storageAdapters.delete(collection.name);
|
|
340
|
-
this.items.delete(collection.name);
|
|
341
|
-
this.indices.delete(collection.name);
|
|
342
|
-
this.activeQueries.delete(collection.name);
|
|
343
|
-
this.queryEmitters.delete(collection.name);
|
|
344
|
-
this.queuedQueryUpdates.delete(collection.name);
|
|
345
|
-
this.cachedQueryResults.delete(collection.name);
|
|
346
|
-
},
|
|
347
|
-
isReady: () => persistenceReadyPromise
|
|
348
|
-
};
|
|
349
|
-
return backend;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
export {
|
|
353
|
-
DefaultDataAdapter as default
|
|
354
|
-
};
|
|
44
|
+
//#endregion
|
|
45
|
+
export { isFieldExpression as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/utils/serializeValue.ts
|
|
2
|
+
/**
|
|
3
|
+
* Serializes a value into a string representation.
|
|
4
|
+
* Handles various types, including strings, numbers, booleans, dates, and objects.
|
|
5
|
+
* Falls back to JSON stringification for unsupported types.
|
|
6
|
+
* @param value - The value to serialize.
|
|
7
|
+
* - Strings are returned as-is.
|
|
8
|
+
* - Numbers and booleans are converted to their string representation.
|
|
9
|
+
* - Dates are converted to ISO string format.
|
|
10
|
+
* - Other values are stringified using `JSON.stringify`.
|
|
11
|
+
* @returns A string representation of the value.
|
|
12
|
+
*/
|
|
13
|
+
function serializeValue(value) {
|
|
14
|
+
if (value == null) return null;
|
|
15
|
+
if (typeof value === "string") return value;
|
|
16
|
+
if (typeof value === "number") return value.toString();
|
|
17
|
+
if (typeof value === "boolean") return value.toString();
|
|
18
|
+
if (value instanceof Date) return value.toISOString();
|
|
19
|
+
return JSON.stringify(value);
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
exports.default = serializeValue;
|