@signaldb/core 1.7.0 → 2.0.0-beta.0
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 +125 -82
- package/dist/AsyncDataAdapter.d.ts +64 -0
- package/dist/AutoFetchDataAdapter.d.ts +113 -0
- package/dist/Collection/Cursor.d.ts +9 -9
- package/dist/Collection/Observer.d.ts +3 -2
- package/dist/Collection/index.d.ts +52 -46
- package/dist/Collection/types.d.ts +4 -9
- package/dist/DataAdapter.d.ts +33 -0
- package/dist/DefaultDataAdapter.d.ts +32 -0
- package/dist/WorkerDataAdapter.d.ts +22 -0
- package/dist/WorkerDataAdapterHost.d.ts +59 -0
- package/dist/createIndex.d.ts +7 -0
- package/dist/createStorageAdapter.d.ts +9 -0
- package/dist/{Collection/getIndexInfo.d.ts → getIndexInfo.d.ts} +17 -19
- package/dist/index.cjs.js +21 -17
- package/dist/index.cjs10.js +15 -26
- package/dist/index.cjs11.js +13 -10
- package/dist/index.cjs12.js +337 -3
- package/dist/index.cjs13.js +384 -115
- package/dist/index.cjs14.js +183 -67
- package/dist/index.cjs15.js +339 -8
- package/dist/index.cjs16.js +563 -20
- package/dist/index.cjs17.js +16 -12
- package/dist/index.cjs18.js +24 -5
- package/dist/index.cjs2.js +27 -36
- package/dist/index.cjs20.js +102 -13
- package/dist/index.cjs21.js +124 -21
- package/dist/index.cjs22.js +5 -68
- package/dist/index.cjs23.js +22 -82
- package/dist/index.cjs24.js +5 -16
- package/dist/index.cjs25.js +8 -27
- package/dist/index.cjs26.js +27 -7
- package/dist/index.cjs27.js +3 -5
- package/dist/index.cjs28.js +5 -27
- package/dist/index.cjs29.js +27 -40
- package/dist/index.cjs3.js +242 -497
- package/dist/index.cjs30.js +42 -0
- package/dist/index.cjs31.js +9 -0
- package/dist/index.cjs4.js +3 -170
- package/dist/index.cjs5.js +3 -67
- package/dist/index.cjs6.js +27 -3
- package/dist/index.cjs7.js +10 -3
- package/dist/index.cjs8.js +3 -3
- package/dist/index.cjs9.js +131 -3
- package/dist/index.d.ts +10 -8
- package/dist/index.mjs +15 -11
- package/dist/index10.mjs +15 -26
- package/dist/index11.mjs +13 -10
- package/dist/index12.mjs +337 -3
- package/dist/index13.mjs +384 -115
- package/dist/index14.mjs +183 -66
- package/dist/index15.mjs +339 -8
- package/dist/index16.mjs +563 -20
- package/dist/index17.mjs +16 -12
- package/dist/index18.mjs +24 -5
- package/dist/index2.mjs +27 -36
- package/dist/index20.mjs +102 -13
- package/dist/index21.mjs +123 -21
- package/dist/index22.mjs +5 -67
- package/dist/index23.mjs +22 -81
- package/dist/index24.mjs +5 -16
- package/dist/index25.mjs +8 -27
- package/dist/index26.mjs +27 -7
- package/dist/index27.mjs +3 -5
- package/dist/index28.mjs +5 -27
- package/dist/index29.mjs +27 -40
- package/dist/index3.mjs +241 -497
- package/dist/index30.mjs +43 -0
- package/dist/index31.mjs +10 -0
- package/dist/index4.mjs +3 -170
- package/dist/index5.mjs +3 -66
- package/dist/index6.mjs +27 -3
- package/dist/index7.mjs +10 -3
- package/dist/index8.mjs +3 -3
- package/dist/index9.mjs +131 -3
- package/dist/types/IndexProvider.d.ts +12 -7
- package/dist/types/StorageAdapter.d.ts +20 -0
- package/dist/utils/objectId.d.ts +8 -0
- package/dist/utils/queryId.d.ts +9 -0
- package/package.json +2 -2
- package/dist/AutoFetchCollection.d.ts +0 -60
- package/dist/Collection/createIndex.d.ts +0 -15
- package/dist/ReplicatedCollection.d.ts +0 -60
- package/dist/createMemoryAdapter.d.ts +0 -7
- package/dist/persistence/combinePersistenceAdapters.d.ts +0 -32
- package/dist/persistence/createPersistenceAdapter.d.ts +0 -9
- package/dist/types/MemoryAdapter.d.ts +0 -15
- package/dist/types/PersistenceAdapter.d.ts +0 -20
package/dist/index3.mjs
CHANGED
|
@@ -1,253 +1,96 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import modify from "./index11.mjs";
|
|
7
|
-
import isEqual from "./index10.mjs";
|
|
8
|
-
import randomId from "./index12.mjs";
|
|
1
|
+
import EventEmitter from "./index9.mjs";
|
|
2
|
+
import createSignal from "./index18.mjs";
|
|
3
|
+
import randomId from "./index8.mjs";
|
|
4
|
+
import DefaultDataAdapter from "./index12.mjs";
|
|
5
|
+
import modify from "./index7.mjs";
|
|
9
6
|
import deepClone from "./index19.mjs";
|
|
10
|
-
import serializeValue from "./index20.mjs";
|
|
11
|
-
import createSignal from "./index21.mjs";
|
|
12
7
|
import Cursor from "./index2.mjs";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const items = [...currentItems];
|
|
21
|
-
added.forEach((item) => {
|
|
22
|
-
items.push(item);
|
|
23
|
-
});
|
|
24
|
-
modified.forEach((item) => {
|
|
25
|
-
const index = items.findIndex(({ id }) => id === item.id);
|
|
26
|
-
if (index === -1)
|
|
27
|
-
return;
|
|
28
|
-
items[index] = item;
|
|
29
|
-
});
|
|
30
|
-
removed.forEach((item) => {
|
|
31
|
-
const index = items.findIndex(({ id }) => id === item.id);
|
|
32
|
-
if (index === -1)
|
|
33
|
-
return;
|
|
34
|
-
items.splice(index, 1);
|
|
35
|
-
});
|
|
36
|
-
return items;
|
|
37
|
-
}
|
|
38
|
-
const _Collection = class _Collection extends EventEmitter {
|
|
39
|
-
/**
|
|
40
|
-
* Initializes a new instance of the `Collection` class with optional configuration.
|
|
41
|
-
* Sets up memory, persistence, reactivity, and indices as specified in the options.
|
|
42
|
-
* @template T - The type of the items stored in the collection.
|
|
43
|
-
* @template I - The type of the unique identifier for the items.
|
|
44
|
-
* @template U - The transformed item type after applying transformations (default is T).
|
|
45
|
-
* @param options - Optional configuration for the collection.
|
|
46
|
-
* @param options.name - An optional name for the collection.
|
|
47
|
-
* @param options.memory - The in-memory adapter for storing items.
|
|
48
|
-
* @param options.reactivity - The reactivity adapter for observing changes in the collection.
|
|
49
|
-
* @param options.transform - A transformation function to apply to items when retrieving them.
|
|
50
|
-
* @param options.persistence - The persistence adapter for saving and loading items.
|
|
51
|
-
* @param options.indices - An array of index providers for optimized querying.
|
|
52
|
-
* @param options.enableDebugMode - A boolean to enable or disable debug mode.
|
|
53
|
-
* @param options.fieldTracking - A boolean to enable or disable field tracking by default.
|
|
54
|
-
*/
|
|
55
|
-
constructor(options) {
|
|
56
|
-
super();
|
|
57
|
-
__publicField(this, "name");
|
|
58
|
-
__publicField(this, "options");
|
|
59
|
-
__publicField(this, "persistenceAdapter", null);
|
|
60
|
-
__publicField(this, "isPullingSignal");
|
|
61
|
-
__publicField(this, "isPushingSignal");
|
|
62
|
-
__publicField(this, "indexProviders", []);
|
|
63
|
-
__publicField(this, "indicesOutdated", false);
|
|
64
|
-
__publicField(this, "idIndex", /* @__PURE__ */ new Map());
|
|
65
|
-
__publicField(this, "debugMode");
|
|
66
|
-
__publicField(this, "batchOperationInProgress", false);
|
|
67
|
-
__publicField(this, "isDisposed", false);
|
|
68
|
-
__publicField(this, "postBatchCallbacks", /* @__PURE__ */ new Set());
|
|
69
|
-
__publicField(this, "fieldTracking", false);
|
|
70
|
-
__publicField(this, "persistenceReadyPromise");
|
|
71
|
-
_Collection.collections.push(this);
|
|
72
|
-
this.name = (options == null ? void 0 : options.name) ?? `${this.constructor.name}-${randomId()}`;
|
|
73
|
-
this.options = {
|
|
74
|
-
memory: [],
|
|
75
|
-
...options
|
|
76
|
-
};
|
|
77
|
-
this.fieldTracking = this.options.fieldTracking ?? _Collection.fieldTracking;
|
|
78
|
-
this.debugMode = this.options.enableDebugMode ?? _Collection.debugMode;
|
|
79
|
-
this.indexProviders = [
|
|
80
|
-
createExternalIndex("id", this.idIndex),
|
|
81
|
-
...this.options.indices || []
|
|
82
|
-
];
|
|
83
|
-
this.rebuildIndices();
|
|
84
|
-
this.isPullingSignal = createSignal(this.options.reactivity, !!(options == null ? void 0 : options.persistence));
|
|
85
|
-
this.isPushingSignal = createSignal(this.options.reactivity, false);
|
|
86
|
-
this.on("persistence.pullStarted", () => {
|
|
87
|
-
this.isPullingSignal.set(true);
|
|
88
|
-
});
|
|
89
|
-
this.on("persistence.pullCompleted", () => {
|
|
90
|
-
this.isPullingSignal.set(false);
|
|
91
|
-
});
|
|
92
|
-
this.on("persistence.pushStarted", () => {
|
|
93
|
-
this.isPushingSignal.set(true);
|
|
94
|
-
});
|
|
95
|
-
this.on("persistence.pushCompleted", () => {
|
|
96
|
-
this.isPushingSignal.set(false);
|
|
97
|
-
});
|
|
98
|
-
this.persistenceAdapter = this.options.persistence ?? null;
|
|
99
|
-
if (this.persistenceAdapter) {
|
|
100
|
-
let ongoingSaves = 0;
|
|
101
|
-
let isInitialized = false;
|
|
102
|
-
const pendingUpdates = { added: [], modified: [], removed: [] };
|
|
103
|
-
const loadPersistentData = async (data) => {
|
|
104
|
-
if (!this.persistenceAdapter)
|
|
105
|
-
throw new Error("Persistence adapter not found");
|
|
106
|
-
this.emit("persistence.pullStarted");
|
|
107
|
-
const { items, changes } = data ?? await this.persistenceAdapter.load();
|
|
108
|
-
if (items) {
|
|
109
|
-
if (ongoingSaves > 0)
|
|
110
|
-
return;
|
|
111
|
-
this.memory().splice(0, this.memoryArray().length, ...items);
|
|
112
|
-
this.idIndex.clear();
|
|
113
|
-
this.memory().map((item, index) => {
|
|
114
|
-
this.idIndex.set(serializeValue(item.id), /* @__PURE__ */ new Set([index]));
|
|
115
|
-
});
|
|
116
|
-
} else if (changes) {
|
|
117
|
-
changes.added.forEach((item) => {
|
|
118
|
-
const index = this.memory().findIndex((document) => document.id === item.id);
|
|
119
|
-
if (index !== -1) {
|
|
120
|
-
this.memory().splice(index, 1, item);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
this.memory().push(item);
|
|
124
|
-
const itemIndex = this.memory().findIndex((document) => document === item);
|
|
125
|
-
this.idIndex.set(serializeValue(item.id), /* @__PURE__ */ new Set([itemIndex]));
|
|
126
|
-
});
|
|
127
|
-
changes.modified.forEach((item) => {
|
|
128
|
-
const index = this.memory().findIndex((document) => document.id === item.id);
|
|
129
|
-
if (index === -1)
|
|
130
|
-
throw new Error("Cannot resolve index for item");
|
|
131
|
-
this.memory().splice(index, 1, item);
|
|
132
|
-
});
|
|
133
|
-
changes.removed.forEach((item) => {
|
|
134
|
-
const index = this.memory().findIndex((document) => document.id === item.id);
|
|
135
|
-
if (index === -1)
|
|
136
|
-
throw new Error("Cannot resolve index for item");
|
|
137
|
-
this.memory().splice(index, 1);
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
this.rebuildIndices();
|
|
141
|
-
this.emit("persistence.received");
|
|
142
|
-
setTimeout(() => this.emit("persistence.pullCompleted"), 0);
|
|
143
|
-
};
|
|
144
|
-
const saveQueue = {
|
|
145
|
-
added: [],
|
|
146
|
-
modified: [],
|
|
147
|
-
removed: []
|
|
148
|
-
};
|
|
149
|
-
let isFlushing = false;
|
|
150
|
-
const flushQueue = () => {
|
|
151
|
-
if (!this.persistenceAdapter)
|
|
152
|
-
throw new Error("Persistence adapter not found");
|
|
153
|
-
if (ongoingSaves <= 0)
|
|
154
|
-
this.emit("persistence.pushStarted");
|
|
155
|
-
if (isFlushing)
|
|
156
|
-
return;
|
|
157
|
-
if (!hasPendingUpdates(saveQueue))
|
|
158
|
-
return;
|
|
159
|
-
isFlushing = true;
|
|
160
|
-
ongoingSaves += 1;
|
|
161
|
-
const currentItems = this.memoryArray();
|
|
162
|
-
const changes = { ...saveQueue };
|
|
163
|
-
saveQueue.added = [];
|
|
164
|
-
saveQueue.modified = [];
|
|
165
|
-
saveQueue.removed = [];
|
|
166
|
-
this.persistenceAdapter.save(currentItems, changes).then(() => {
|
|
167
|
-
this.emit("persistence.transmitted");
|
|
168
|
-
}).catch((error) => {
|
|
169
|
-
this.emit("persistence.error", error instanceof Error ? error : new Error(error));
|
|
170
|
-
}).finally(() => {
|
|
171
|
-
ongoingSaves -= 1;
|
|
172
|
-
isFlushing = false;
|
|
173
|
-
flushQueue();
|
|
174
|
-
if (ongoingSaves <= 0)
|
|
175
|
-
this.emit("persistence.pushCompleted");
|
|
176
|
-
});
|
|
177
|
-
};
|
|
178
|
-
this.on("added", (item) => {
|
|
179
|
-
if (!isInitialized) {
|
|
180
|
-
pendingUpdates.added.push(item);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
saveQueue.added.push(item);
|
|
184
|
-
flushQueue();
|
|
185
|
-
});
|
|
186
|
-
this.on("changed", (item) => {
|
|
187
|
-
if (!isInitialized) {
|
|
188
|
-
pendingUpdates.modified.push(item);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
saveQueue.modified.push(item);
|
|
192
|
-
flushQueue();
|
|
193
|
-
});
|
|
194
|
-
this.on("removed", (item) => {
|
|
195
|
-
if (!isInitialized) {
|
|
196
|
-
pendingUpdates.removed.push(item);
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
saveQueue.removed.push(item);
|
|
200
|
-
flushQueue();
|
|
201
|
-
});
|
|
202
|
-
this.persistenceAdapter.register((data) => loadPersistentData(data)).then(async () => {
|
|
203
|
-
if (!this.persistenceAdapter)
|
|
204
|
-
throw new Error("Persistence adapter not found");
|
|
205
|
-
let currentItems = this.memoryArray();
|
|
206
|
-
await loadPersistentData();
|
|
207
|
-
while (hasPendingUpdates(pendingUpdates)) {
|
|
208
|
-
const added = pendingUpdates.added.splice(0);
|
|
209
|
-
const modified = pendingUpdates.modified.splice(0);
|
|
210
|
-
const removed = pendingUpdates.removed.splice(0);
|
|
211
|
-
currentItems = applyUpdates(this.memoryArray(), { added, modified, removed });
|
|
212
|
-
await this.persistenceAdapter.save(currentItems, { added, modified, removed }).then(() => {
|
|
213
|
-
this.emit("persistence.transmitted");
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
await loadPersistentData();
|
|
217
|
-
isInitialized = true;
|
|
218
|
-
setTimeout(() => this.emit("persistence.init"), 0);
|
|
219
|
-
}).catch((error) => {
|
|
220
|
-
this.emit("persistence.error", error instanceof Error ? error : new Error(error));
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
this.persistenceReadyPromise = new Promise((resolve, reject) => {
|
|
224
|
-
if (!this.persistenceAdapter)
|
|
225
|
-
return resolve();
|
|
226
|
-
this.once("persistence.init", resolve);
|
|
227
|
-
this.once("persistence.error", reject);
|
|
228
|
-
});
|
|
229
|
-
_Collection.onCreationCallbacks.forEach((callback) => callback(this));
|
|
230
|
-
}
|
|
8
|
+
class Collection extends EventEmitter {
|
|
9
|
+
static collections = [];
|
|
10
|
+
static debugMode = false;
|
|
11
|
+
static batchOperationInProgress = false;
|
|
12
|
+
static fieldTracking = false;
|
|
13
|
+
static onCreationCallbacks = [];
|
|
14
|
+
static onDisposeCallbacks = [];
|
|
231
15
|
static getCollections() {
|
|
232
|
-
return
|
|
16
|
+
return Collection.collections;
|
|
233
17
|
}
|
|
234
18
|
static onCreation(callback) {
|
|
235
|
-
|
|
19
|
+
Collection.onCreationCallbacks.push(callback);
|
|
236
20
|
}
|
|
237
21
|
static onDispose(callback) {
|
|
238
|
-
|
|
22
|
+
Collection.onDisposeCallbacks.push(callback);
|
|
239
23
|
}
|
|
240
24
|
/**
|
|
241
|
-
*
|
|
242
|
-
* while deferring index rebuilding until all operations in the batch are completed.
|
|
243
|
-
* This improves performance by avoiding repetitive index recalculations and
|
|
244
|
-
* provides atomicity for the batch of operations.
|
|
245
|
-
* @param callback - The batch operation to execute.
|
|
25
|
+
* Enables debug mode for all collections.
|
|
246
26
|
*/
|
|
27
|
+
static enableDebugMode = () => {
|
|
28
|
+
Collection.debugMode = true;
|
|
29
|
+
Collection.collections.forEach((collection) => {
|
|
30
|
+
collection.setDebugMode(true);
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Enables field tracking for all collections.
|
|
35
|
+
* @param enable - A boolean indicating whether to enable field tracking.
|
|
36
|
+
*/
|
|
37
|
+
static setFieldTracking = (enable) => {
|
|
38
|
+
Collection.fieldTracking = enable;
|
|
39
|
+
Collection.collections.forEach((collection) => {
|
|
40
|
+
collection.setFieldTracking(enable);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
247
43
|
static batch(callback) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
44
|
+
Collection.batchOperationInProgress = true;
|
|
45
|
+
const execute = () => Collection.collections.reduce((memo, collection) => () => {
|
|
46
|
+
return collection.batch(memo);
|
|
47
|
+
}, callback)();
|
|
48
|
+
const maybePromise = execute();
|
|
49
|
+
const afterBatch = () => {
|
|
50
|
+
Collection.batchOperationInProgress = false;
|
|
51
|
+
};
|
|
52
|
+
if (maybePromise && typeof maybePromise.then === "function") {
|
|
53
|
+
return maybePromise.then(() => afterBatch());
|
|
54
|
+
} else {
|
|
55
|
+
afterBatch();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
name;
|
|
59
|
+
backend;
|
|
60
|
+
options;
|
|
61
|
+
isPullingSignal;
|
|
62
|
+
isPushingSignal;
|
|
63
|
+
readySignal;
|
|
64
|
+
debugMode;
|
|
65
|
+
batchOperationInProgress = false;
|
|
66
|
+
isDisposed = false;
|
|
67
|
+
postBatchCallbacks = /* @__PURE__ */ new Set();
|
|
68
|
+
fieldTracking = false;
|
|
69
|
+
constructor(nameOrOptions, maybeDataAdapter, maybeOptions) {
|
|
70
|
+
super();
|
|
71
|
+
const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions?.name || `${this.constructor.name}-${randomId()}`;
|
|
72
|
+
const options = typeof nameOrOptions === "string" ? maybeOptions || {} : nameOrOptions || {};
|
|
73
|
+
const persistence = options.persistence;
|
|
74
|
+
const dataAdapter = maybeDataAdapter || new DefaultDataAdapter({
|
|
75
|
+
...persistence ? { storage: () => persistence } : {}
|
|
76
|
+
});
|
|
77
|
+
Collection.collections.push(this);
|
|
78
|
+
this.name = name;
|
|
79
|
+
this.options = { ...options };
|
|
80
|
+
this.fieldTracking = this.options.fieldTracking ?? Collection.fieldTracking;
|
|
81
|
+
this.debugMode = this.options.enableDebugMode ?? Collection.debugMode;
|
|
82
|
+
this.isPullingSignal = createSignal(this.options.reactivity, false);
|
|
83
|
+
this.isPushingSignal = createSignal(this.options.reactivity, false);
|
|
84
|
+
this.readySignal = createSignal(this.options.reactivity, false);
|
|
85
|
+
this.backend = dataAdapter.createCollectionBackend(this, this.options.indices ?? []);
|
|
86
|
+
void this.backend.isReady().then(() => {
|
|
87
|
+
this.readySignal.set(true);
|
|
88
|
+
}).catch(() => {
|
|
89
|
+
});
|
|
90
|
+
Collection.onCreationCallbacks.forEach((callback) => callback(this));
|
|
91
|
+
}
|
|
92
|
+
isBatchOperationInProgress() {
|
|
93
|
+
return Collection.batchOperationInProgress || this.batchOperationInProgress;
|
|
251
94
|
}
|
|
252
95
|
/**
|
|
253
96
|
* Checks whether the collection is currently performing a pull operation
|
|
@@ -313,17 +156,28 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
313
156
|
*
|
|
314
157
|
* collection.insert({ name: 'Item 1' })
|
|
315
158
|
*/
|
|
316
|
-
async
|
|
317
|
-
return this.
|
|
159
|
+
async ready() {
|
|
160
|
+
return this.backend.isReady();
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Checks if the collection is ready.
|
|
164
|
+
* ⚡️ this function is reactive!
|
|
165
|
+
* @returns A boolean indicating whether the collection is ready.
|
|
166
|
+
*/
|
|
167
|
+
isReady() {
|
|
168
|
+
return this.readySignal.get() ?? false;
|
|
318
169
|
}
|
|
319
170
|
profile(fn, measureFunction) {
|
|
320
171
|
if (!this.debugMode)
|
|
321
172
|
return fn();
|
|
322
173
|
const startTime = performance.now();
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
174
|
+
const handleProfileEnd = (result) => {
|
|
175
|
+
const endTime = performance.now();
|
|
176
|
+
measureFunction(endTime - startTime);
|
|
177
|
+
return result;
|
|
178
|
+
};
|
|
179
|
+
const maybePromise = fn();
|
|
180
|
+
return maybePromise instanceof Promise ? maybePromise.then(handleProfileEnd) : handleProfileEnd(maybePromise);
|
|
327
181
|
}
|
|
328
182
|
executeInDebugMode(fn) {
|
|
329
183
|
if (!this.debugMode)
|
|
@@ -331,119 +185,62 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
331
185
|
const callstack = new Error().stack || "";
|
|
332
186
|
fn(callstack);
|
|
333
187
|
}
|
|
334
|
-
rebuildIndices() {
|
|
335
|
-
this.indicesOutdated = true;
|
|
336
|
-
if (this.batchOperationInProgress)
|
|
337
|
-
return;
|
|
338
|
-
this.rebuildAllIndices();
|
|
339
|
-
}
|
|
340
|
-
rebuildAllIndices() {
|
|
341
|
-
this.idIndex.clear();
|
|
342
|
-
this.memory().map((item, index) => {
|
|
343
|
-
this.idIndex.set(serializeValue(item.id), /* @__PURE__ */ new Set([index]));
|
|
344
|
-
});
|
|
345
|
-
this.indexProviders.forEach((index) => index.rebuild(this.memoryArray()));
|
|
346
|
-
this.indicesOutdated = false;
|
|
347
|
-
}
|
|
348
|
-
getIndexInfo(selector) {
|
|
349
|
-
if (selector != null && Object.keys(selector).length === 1 && "id" in selector && typeof selector.id !== "object") {
|
|
350
|
-
return {
|
|
351
|
-
matched: true,
|
|
352
|
-
positions: [...this.idIndex.get(serializeValue(selector.id)) || []],
|
|
353
|
-
optimizedSelector: {}
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
if (selector == null) {
|
|
357
|
-
return {
|
|
358
|
-
matched: false,
|
|
359
|
-
positions: [],
|
|
360
|
-
optimizedSelector: {}
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
if (this.indicesOutdated) {
|
|
364
|
-
return {
|
|
365
|
-
matched: false,
|
|
366
|
-
positions: [],
|
|
367
|
-
optimizedSelector: selector
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
return getIndexInfo(this.indexProviders, selector);
|
|
371
|
-
}
|
|
372
|
-
getItemAndIndex(selector) {
|
|
373
|
-
const memory = this.memoryArray();
|
|
374
|
-
const indexInfo = this.getIndexInfo(selector);
|
|
375
|
-
const items = indexInfo.matched ? indexInfo.positions.map((index2) => memory[index2]) : memory;
|
|
376
|
-
const item = items.find((document) => match(document, selector));
|
|
377
|
-
const foundInIndex = indexInfo.matched && indexInfo.positions.find((itemIndex) => memory[itemIndex] === item);
|
|
378
|
-
const index = foundInIndex || memory.findIndex((document) => document === item);
|
|
379
|
-
if (item == null)
|
|
380
|
-
return { item: null, index: -1 };
|
|
381
|
-
if (index === -1)
|
|
382
|
-
throw new Error("Cannot resolve index for item");
|
|
383
|
-
return { item, index };
|
|
384
|
-
}
|
|
385
|
-
deleteFromIdIndex(id, index) {
|
|
386
|
-
this.idIndex.delete(serializeValue(id));
|
|
387
|
-
if (!this.batchOperationInProgress)
|
|
388
|
-
return;
|
|
389
|
-
this.idIndex.forEach(([currenIndex], key) => {
|
|
390
|
-
if (currenIndex > index) {
|
|
391
|
-
this.idIndex.set(key, /* @__PURE__ */ new Set([currenIndex - 1]));
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
memory() {
|
|
396
|
-
return this.options.memory;
|
|
397
|
-
}
|
|
398
|
-
memoryArray() {
|
|
399
|
-
return this.memory().map((item) => item);
|
|
400
|
-
}
|
|
401
188
|
transform(item) {
|
|
402
189
|
if (!this.options.transform)
|
|
403
190
|
return item;
|
|
404
191
|
return this.options.transform(item);
|
|
405
192
|
}
|
|
406
|
-
|
|
193
|
+
getItem(selector, options) {
|
|
194
|
+
const itemsOrPromise = this.getItems(selector, { ...options, limit: 1 });
|
|
195
|
+
if (itemsOrPromise instanceof Promise) {
|
|
196
|
+
return itemsOrPromise.then((items) => {
|
|
197
|
+
return items[0] || void 0;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return itemsOrPromise[0];
|
|
201
|
+
}
|
|
202
|
+
getItems(selector, options) {
|
|
203
|
+
this.emit("getItems", selector);
|
|
407
204
|
return this.profile(() => {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
return items;
|
|
427
|
-
return items.filter(matchItems);
|
|
205
|
+
if (!options?.async)
|
|
206
|
+
return this.backend.getQueryResult(selector, options);
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
this.isPullingSignal.set(true);
|
|
209
|
+
const cleanup = this.backend.onQueryStateChange(selector, options, (state) => {
|
|
210
|
+
if (state === "error") {
|
|
211
|
+
cleanup();
|
|
212
|
+
reject(this.backend.getQueryError(selector, options) || new Error("Unknown error"));
|
|
213
|
+
} else if (state === "complete") {
|
|
214
|
+
cleanup();
|
|
215
|
+
resolve(this.backend.getQueryResult(selector, options) || []);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
this.backend.registerQuery(selector, options);
|
|
219
|
+
}).finally(() => {
|
|
220
|
+
this.isPullingSignal.set(false);
|
|
221
|
+
this.backend.unregisterQuery(selector, options);
|
|
222
|
+
});
|
|
428
223
|
}, (measuredTime) => this.executeInDebugMode((callstack) => this.emit("_debug.getItems", callstack, selector, measuredTime)));
|
|
429
224
|
}
|
|
225
|
+
async withPushState(asyncFunction) {
|
|
226
|
+
this.isPushingSignal.set(true);
|
|
227
|
+
try {
|
|
228
|
+
return await asyncFunction();
|
|
229
|
+
} finally {
|
|
230
|
+
this.isPushingSignal.set(false);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
430
233
|
/**
|
|
431
234
|
* Disposes the collection, unregisters persistence adapters, clears memory, and
|
|
432
235
|
* cleans up all resources used by the collection.
|
|
433
236
|
* @returns A promise that resolves when the collection is disposed.
|
|
434
237
|
*/
|
|
435
238
|
async dispose() {
|
|
436
|
-
|
|
437
|
-
if ((_a = this.persistenceAdapter) == null ? void 0 : _a.unregister)
|
|
438
|
-
await this.persistenceAdapter.unregister();
|
|
439
|
-
this.persistenceAdapter = null;
|
|
440
|
-
this.memory().map(() => this.memory().pop());
|
|
441
|
-
this.idIndex.clear();
|
|
442
|
-
this.indexProviders = [];
|
|
239
|
+
await this.backend.dispose();
|
|
443
240
|
this.isDisposed = true;
|
|
444
241
|
this.removeAllListeners();
|
|
445
|
-
|
|
446
|
-
|
|
242
|
+
Collection.collections = Collection.collections.filter((collection) => collection !== this);
|
|
243
|
+
Collection.onDisposeCallbacks.forEach((callback) => callback(this));
|
|
447
244
|
}
|
|
448
245
|
/**
|
|
449
246
|
* Finds multiple items in the collection based on a selector and optional options.
|
|
@@ -453,12 +250,12 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
453
250
|
* @param [options] - Options for the find operation, such as limit and sort.
|
|
454
251
|
* @returns A cursor to fetch and observe the matching items.
|
|
455
252
|
*/
|
|
456
|
-
find(selector, options) {
|
|
253
|
+
find(selector = {}, options) {
|
|
457
254
|
if (this.isDisposed)
|
|
458
255
|
throw new Error("Collection is disposed");
|
|
459
256
|
if (selector !== void 0 && (!selector || typeof selector !== "object"))
|
|
460
257
|
throw new Error("Invalid selector");
|
|
461
|
-
const cursor = new Cursor(() => this.getItems(selector), {
|
|
258
|
+
const cursor = new Cursor((() => this.getItems(selector, options || {})), {
|
|
462
259
|
reactive: this.options.reactivity,
|
|
463
260
|
fieldTracking: this.fieldTracking,
|
|
464
261
|
...options,
|
|
@@ -471,16 +268,16 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
471
268
|
}
|
|
472
269
|
requery();
|
|
473
270
|
};
|
|
474
|
-
this.
|
|
475
|
-
this.
|
|
476
|
-
|
|
477
|
-
|
|
271
|
+
this.backend.registerQuery(selector, options);
|
|
272
|
+
const queryStateChangeCleanup = this.backend.onQueryStateChange(selector, options, (state) => {
|
|
273
|
+
if (state !== "complete")
|
|
274
|
+
return;
|
|
275
|
+
handleRequery();
|
|
276
|
+
});
|
|
478
277
|
this.emit("observer.created", selector, options);
|
|
479
278
|
return () => {
|
|
480
|
-
this.
|
|
481
|
-
|
|
482
|
-
this.removeListener("changed", handleRequery);
|
|
483
|
-
this.removeListener("removed", handleRequery);
|
|
279
|
+
this.backend.unregisterQuery(selector, options);
|
|
280
|
+
queryStateChangeCleanup();
|
|
484
281
|
this.emit("observer.disposed", selector, options);
|
|
485
282
|
};
|
|
486
283
|
}
|
|
@@ -493,6 +290,7 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
493
290
|
* Finds a single item in the collection based on a selector and optional options.
|
|
494
291
|
* ⚡️ this function is reactive!
|
|
495
292
|
* Returns the found item or undefined if no item matches.
|
|
293
|
+
* @template Async - Whether to perform the operation asynchronously.
|
|
496
294
|
* @template O - The options type for the find operation.
|
|
497
295
|
* @param selector - The criteria to select the item.
|
|
498
296
|
* @param [options] - Options for the find operation, such as projection.
|
|
@@ -505,23 +303,39 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
505
303
|
limit: 1,
|
|
506
304
|
...options
|
|
507
305
|
});
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
306
|
+
const handleItems = (items) => {
|
|
307
|
+
const returnValue = items[0] || void 0;
|
|
308
|
+
this.emit("findOne", selector, options, returnValue);
|
|
309
|
+
this.executeInDebugMode((callstack) => this.emit("_debug.findOne", callstack, selector, options, returnValue));
|
|
310
|
+
return returnValue;
|
|
311
|
+
};
|
|
312
|
+
const maybePromise = cursor.fetch();
|
|
313
|
+
return maybePromise instanceof Promise ? maybePromise.then(handleItems) : handleItems(maybePromise);
|
|
512
314
|
}
|
|
513
|
-
/**
|
|
514
|
-
* Performs a batch operation, deferring index rebuilds and allowing multiple
|
|
515
|
-
* modifications to be made atomically. Executes any post-batch callbacks afterwards.
|
|
516
|
-
* @param callback - The batch operation to execute.
|
|
517
|
-
*/
|
|
518
315
|
batch(callback) {
|
|
316
|
+
if (this.batchOperationInProgress)
|
|
317
|
+
return callback();
|
|
519
318
|
this.batchOperationInProgress = true;
|
|
520
|
-
callback();
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
319
|
+
const maybePromise = callback();
|
|
320
|
+
const afterBatch = () => {
|
|
321
|
+
this.batchOperationInProgress = false;
|
|
322
|
+
this.postBatchCallbacks.forEach((callback_) => callback_());
|
|
323
|
+
this.postBatchCallbacks.clear();
|
|
324
|
+
};
|
|
325
|
+
if (maybePromise && typeof maybePromise.then === "function") {
|
|
326
|
+
return maybePromise.then(() => afterBatch());
|
|
327
|
+
} else {
|
|
328
|
+
afterBatch();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
onPostBatch(callback) {
|
|
332
|
+
if (this.isDisposed)
|
|
333
|
+
throw new Error("Collection is disposed");
|
|
334
|
+
if (this.batchOperationInProgress) {
|
|
335
|
+
this.postBatchCallbacks.add(callback);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
return callback();
|
|
525
339
|
}
|
|
526
340
|
/**
|
|
527
341
|
* Inserts a single item into the collection. Generates a unique ID if not provided.
|
|
@@ -529,20 +343,18 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
529
343
|
* @returns The ID of the inserted item.
|
|
530
344
|
* @throws {Error} If the collection is disposed or the item has an invalid ID.
|
|
531
345
|
*/
|
|
532
|
-
insert(item) {
|
|
346
|
+
async insert(item) {
|
|
533
347
|
if (this.isDisposed)
|
|
534
348
|
throw new Error("Collection is disposed");
|
|
535
349
|
if (!item)
|
|
536
350
|
throw new Error("Invalid item");
|
|
537
351
|
const primaryKeyGenerator = this.options.primaryKeyGenerator ?? randomId;
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
this.
|
|
543
|
-
const
|
|
544
|
-
this.idIndex.set(serializeValue(newItem.id), /* @__PURE__ */ new Set([itemIndex]));
|
|
545
|
-
this.rebuildIndices();
|
|
352
|
+
const itemWithId = {
|
|
353
|
+
id: primaryKeyGenerator(item),
|
|
354
|
+
...item
|
|
355
|
+
};
|
|
356
|
+
this.emit("validate", itemWithId);
|
|
357
|
+
const newItem = await this.withPushState(() => this.backend.insert(itemWithId));
|
|
546
358
|
this.emit("added", newItem);
|
|
547
359
|
this.emit("insert", newItem);
|
|
548
360
|
this.executeInDebugMode((callstack) => this.emit("_debug.insert", callstack, newItem));
|
|
@@ -554,7 +366,7 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
554
366
|
* @returns An array of IDs of the inserted items.
|
|
555
367
|
* @throws {Error} If the collection is disposed or the items are invalid.
|
|
556
368
|
*/
|
|
557
|
-
insertMany(items) {
|
|
369
|
+
async insertMany(items) {
|
|
558
370
|
if (this.isDisposed)
|
|
559
371
|
throw new Error("Collection is disposed");
|
|
560
372
|
if (!items)
|
|
@@ -563,10 +375,10 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
563
375
|
return [];
|
|
564
376
|
}
|
|
565
377
|
const ids = [];
|
|
566
|
-
this.batch(() => {
|
|
567
|
-
items.
|
|
568
|
-
ids.push(this.insert(item));
|
|
569
|
-
});
|
|
378
|
+
await this.batch(async () => {
|
|
379
|
+
await Promise.all(items.map(async (item) => {
|
|
380
|
+
ids.push(await this.insert(item));
|
|
381
|
+
}));
|
|
570
382
|
});
|
|
571
383
|
return ids;
|
|
572
384
|
}
|
|
@@ -579,7 +391,7 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
579
391
|
* @returns The number of items updated (0 or 1).
|
|
580
392
|
* @throws {Error} If the collection is disposed or invalid arguments are provided.
|
|
581
393
|
*/
|
|
582
|
-
updateOne(selector, modifier, options) {
|
|
394
|
+
async updateOne(selector, modifier, options) {
|
|
583
395
|
if (this.isDisposed)
|
|
584
396
|
throw new Error("Collection is disposed");
|
|
585
397
|
if (!selector)
|
|
@@ -587,9 +399,9 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
587
399
|
if (!modifier)
|
|
588
400
|
throw new Error("Invalid modifier");
|
|
589
401
|
const { $setOnInsert, ...restModifier } = modifier;
|
|
590
|
-
const
|
|
402
|
+
const item = await this.getItem(selector, { async: true });
|
|
591
403
|
if (item == null) {
|
|
592
|
-
if (options
|
|
404
|
+
if (options?.upsert) {
|
|
593
405
|
const newItem = modify({}, {
|
|
594
406
|
...restModifier,
|
|
595
407
|
$set: {
|
|
@@ -597,26 +409,18 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
597
409
|
...restModifier.$set
|
|
598
410
|
}
|
|
599
411
|
});
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
this.insert(newItem);
|
|
604
|
-
}
|
|
605
|
-
} else {
|
|
606
|
-
const modifiedItem = modify(deepClone(item), restModifier);
|
|
607
|
-
if (item.id !== modifiedItem.id && this.getItemAndIndex({ id: modifiedItem.id }).item != null) {
|
|
608
|
-
throw new Error("Item with same id already exists");
|
|
412
|
+
await this.insert(newItem);
|
|
413
|
+
return 1;
|
|
609
414
|
}
|
|
610
|
-
|
|
611
|
-
this.memory().splice(index, 1, modifiedItem);
|
|
612
|
-
this.rebuildIndices();
|
|
613
|
-
this.emit("changed", modifiedItem, restModifier);
|
|
415
|
+
return 0;
|
|
614
416
|
}
|
|
417
|
+
const modifiedItem = modify(deepClone(item), restModifier);
|
|
418
|
+
this.emit("validate", modifiedItem);
|
|
419
|
+
const changes = await this.withPushState(() => this.backend.updateOne(selector, modifier));
|
|
420
|
+
this.emit("changed", modifiedItem, restModifier);
|
|
615
421
|
this.emit("updateOne", selector, modifier);
|
|
616
422
|
this.executeInDebugMode((callstack) => this.emit("_debug.updateOne", callstack, selector, modifier));
|
|
617
|
-
|
|
618
|
-
return 0;
|
|
619
|
-
return 1;
|
|
423
|
+
return changes.length;
|
|
620
424
|
}
|
|
621
425
|
/**
|
|
622
426
|
* Updates multiple items in the collection that match the given selector.
|
|
@@ -627,7 +431,7 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
627
431
|
* @returns The number of items updated.
|
|
628
432
|
* @throws {Error} If the collection is disposed or invalid arguments are provided.
|
|
629
433
|
*/
|
|
630
|
-
updateMany(selector, modifier, options) {
|
|
434
|
+
async updateMany(selector, modifier, options) {
|
|
631
435
|
if (this.isDisposed)
|
|
632
436
|
throw new Error("Collection is disposed");
|
|
633
437
|
if (!selector)
|
|
@@ -635,44 +439,32 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
635
439
|
if (!modifier)
|
|
636
440
|
throw new Error("Invalid modifier");
|
|
637
441
|
const { $setOnInsert, ...restModifier } = modifier;
|
|
638
|
-
const items = this.getItems(selector);
|
|
639
|
-
if (items.length === 0
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
442
|
+
const items = await this.getItems(selector, { async: true });
|
|
443
|
+
if (items.length === 0) {
|
|
444
|
+
if (options?.upsert) {
|
|
445
|
+
const newItem = modify({}, {
|
|
446
|
+
...restModifier,
|
|
447
|
+
$set: {
|
|
448
|
+
...$setOnInsert,
|
|
449
|
+
...restModifier.$set
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
await this.insert(newItem);
|
|
453
|
+
return 1;
|
|
649
454
|
}
|
|
650
|
-
|
|
455
|
+
return 0;
|
|
651
456
|
}
|
|
652
|
-
|
|
653
|
-
const { index } = this.getItemAndIndex({ id: item.id });
|
|
654
|
-
if (index === -1)
|
|
655
|
-
throw new Error(`Cannot resolve index for item with id '${item.id}'`);
|
|
457
|
+
items.forEach((item) => {
|
|
656
458
|
const modifiedItem = modify(deepClone(item), restModifier);
|
|
657
|
-
if (item.id !== modifiedItem.id && this.getItemAndIndex({ id: modifiedItem.id }).item != null) {
|
|
658
|
-
throw new Error(`Item with same id '${modifiedItem.id}' already exists`);
|
|
659
|
-
}
|
|
660
459
|
this.emit("validate", modifiedItem);
|
|
661
|
-
return {
|
|
662
|
-
item: modifiedItem,
|
|
663
|
-
index
|
|
664
|
-
};
|
|
665
|
-
});
|
|
666
|
-
changes.forEach(({ item, index }) => {
|
|
667
|
-
this.memory().splice(index, 1, item);
|
|
668
460
|
});
|
|
669
|
-
this.
|
|
670
|
-
changes.forEach((
|
|
461
|
+
const changes = await this.withPushState(() => this.backend.updateMany(selector, modifier));
|
|
462
|
+
changes.forEach((item) => {
|
|
671
463
|
this.emit("changed", item, restModifier);
|
|
672
464
|
});
|
|
673
465
|
this.emit("updateMany", selector, modifier);
|
|
674
466
|
this.executeInDebugMode((callstack) => this.emit("_debug.updateMany", callstack, selector, modifier));
|
|
675
|
-
return changes.length
|
|
467
|
+
return changes.length;
|
|
676
468
|
}
|
|
677
469
|
/**
|
|
678
470
|
* Replaces a single item in the collection that matches the given selector.
|
|
@@ -683,34 +475,26 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
683
475
|
* @returns The number of items replaced (0 or 1).
|
|
684
476
|
* @throws {Error} If the collection is disposed or invalid arguments are provided.
|
|
685
477
|
*/
|
|
686
|
-
replaceOne(selector, replacement, options) {
|
|
478
|
+
async replaceOne(selector, replacement, options) {
|
|
687
479
|
if (this.isDisposed)
|
|
688
480
|
throw new Error("Collection is disposed");
|
|
689
481
|
if (!selector)
|
|
690
482
|
throw new Error("Invalid selector");
|
|
691
|
-
const
|
|
483
|
+
const item = await this.getItem(selector, { async: true });
|
|
692
484
|
if (item == null) {
|
|
693
|
-
if (options
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
}
|
|
697
|
-
this.insert(replacement);
|
|
698
|
-
}
|
|
699
|
-
} else {
|
|
700
|
-
if (item.id !== replacement.id && this.getItemAndIndex({ id: replacement.id }).item != null) {
|
|
701
|
-
throw new Error("Item with same id already exists");
|
|
485
|
+
if (options?.upsert) {
|
|
486
|
+
await this.insert(replacement);
|
|
487
|
+
return 1;
|
|
702
488
|
}
|
|
703
|
-
|
|
704
|
-
this.emit("validate", modifiedItem);
|
|
705
|
-
this.memory().splice(index, 1, modifiedItem);
|
|
706
|
-
this.rebuildIndices();
|
|
707
|
-
this.emit("changed", modifiedItem, replacement);
|
|
489
|
+
return 0;
|
|
708
490
|
}
|
|
491
|
+
const modifiedItem = { id: item.id, ...replacement };
|
|
492
|
+
this.emit("validate", modifiedItem);
|
|
493
|
+
const changes = await this.withPushState(() => this.backend.replaceOne(selector, replacement));
|
|
494
|
+
this.emit("changed", modifiedItem, replacement);
|
|
709
495
|
this.emit("replaceOne", selector, replacement);
|
|
710
496
|
this.executeInDebugMode((callstack) => this.emit("_debug.replaceOne", callstack, selector, replacement));
|
|
711
|
-
|
|
712
|
-
return 0;
|
|
713
|
-
return 1;
|
|
497
|
+
return changes.length;
|
|
714
498
|
}
|
|
715
499
|
/**
|
|
716
500
|
* Removes a single item from the collection that matches the given selector.
|
|
@@ -718,21 +502,16 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
718
502
|
* @returns The number of items removed (0 or 1).
|
|
719
503
|
* @throws {Error} If the collection is disposed or invalid arguments are provided.
|
|
720
504
|
*/
|
|
721
|
-
removeOne(selector) {
|
|
505
|
+
async removeOne(selector) {
|
|
722
506
|
if (this.isDisposed)
|
|
723
507
|
throw new Error("Collection is disposed");
|
|
724
508
|
if (!selector)
|
|
725
509
|
throw new Error("Invalid selector");
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
this.memory().splice(index, 1);
|
|
729
|
-
this.deleteFromIdIndex(item.id, index);
|
|
730
|
-
this.rebuildIndices();
|
|
731
|
-
this.emit("removed", item);
|
|
732
|
-
}
|
|
510
|
+
const removedItems = await this.withPushState(() => this.backend.removeOne(selector));
|
|
511
|
+
this.emit("removed", removedItems[0]);
|
|
733
512
|
this.emit("removeOne", selector);
|
|
734
513
|
this.executeInDebugMode((callstack) => this.emit("_debug.removeOne", callstack, selector));
|
|
735
|
-
return
|
|
514
|
+
return removedItems.length;
|
|
736
515
|
}
|
|
737
516
|
/**
|
|
738
517
|
* Removes multiple items from the collection that match the given selector.
|
|
@@ -740,55 +519,20 @@ const _Collection = class _Collection extends EventEmitter {
|
|
|
740
519
|
* @returns The number of items removed.
|
|
741
520
|
* @throws {Error} If the collection is disposed or invalid arguments are provided.
|
|
742
521
|
*/
|
|
743
|
-
removeMany(selector) {
|
|
522
|
+
async removeMany(selector) {
|
|
744
523
|
if (this.isDisposed)
|
|
745
524
|
throw new Error("Collection is disposed");
|
|
746
525
|
if (!selector)
|
|
747
526
|
throw new Error("Invalid selector");
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
const index = this.memory().findIndex((document) => document === item);
|
|
751
|
-
if (index === -1)
|
|
752
|
-
throw new Error("Cannot resolve index for item");
|
|
753
|
-
this.memory().splice(index, 1);
|
|
754
|
-
this.deleteFromIdIndex(item.id, index);
|
|
755
|
-
this.rebuildIndices();
|
|
756
|
-
});
|
|
757
|
-
items.forEach((item) => {
|
|
527
|
+
const removedItems = await this.withPushState(() => this.backend.removeMany(selector));
|
|
528
|
+
removedItems.forEach((item) => {
|
|
758
529
|
this.emit("removed", item);
|
|
759
530
|
});
|
|
760
531
|
this.emit("removeMany", selector);
|
|
761
532
|
this.executeInDebugMode((callstack) => this.emit("_debug.removeMany", callstack, selector));
|
|
762
|
-
return
|
|
533
|
+
return removedItems.length;
|
|
763
534
|
}
|
|
764
|
-
}
|
|
765
|
-
__publicField(_Collection, "collections", []);
|
|
766
|
-
__publicField(_Collection, "debugMode", false);
|
|
767
|
-
__publicField(_Collection, "batchOperationInProgress", false);
|
|
768
|
-
__publicField(_Collection, "fieldTracking", false);
|
|
769
|
-
__publicField(_Collection, "onCreationCallbacks", []);
|
|
770
|
-
__publicField(_Collection, "onDisposeCallbacks", []);
|
|
771
|
-
/**
|
|
772
|
-
* Enables debug mode for all collections.
|
|
773
|
-
*/
|
|
774
|
-
__publicField(_Collection, "enableDebugMode", () => {
|
|
775
|
-
_Collection.debugMode = true;
|
|
776
|
-
_Collection.collections.forEach((collection) => {
|
|
777
|
-
collection.setDebugMode(true);
|
|
778
|
-
});
|
|
779
|
-
});
|
|
780
|
-
/**
|
|
781
|
-
* Enables field tracking for all collections.
|
|
782
|
-
* @param enable - A boolean indicating whether to enable field tracking.
|
|
783
|
-
*/
|
|
784
|
-
__publicField(_Collection, "setFieldTracking", (enable) => {
|
|
785
|
-
_Collection.fieldTracking = enable;
|
|
786
|
-
_Collection.collections.forEach((collection) => {
|
|
787
|
-
collection.setFieldTracking(enable);
|
|
788
|
-
});
|
|
789
|
-
});
|
|
790
|
-
let Collection = _Collection;
|
|
535
|
+
}
|
|
791
536
|
export {
|
|
792
|
-
default2 as createIndex,
|
|
793
537
|
Collection as default
|
|
794
538
|
};
|