@signaldb/core 2.0.0-beta.11 → 2.0.0-beta.12
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 +19 -4
- package/dist/Collection/Cursor.d.ts +42 -0
- package/dist/Collection/index.d.ts +2 -1
- package/dist/WorkerDataAdapter.d.ts +20 -0
- package/dist/index.cjs.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index25.cjs.js +17 -1
- package/dist/index25.mjs +17 -1
- package/dist/index29.cjs.js +2 -1
- package/dist/index29.mjs +2 -1
- package/dist/index31.cjs.js +29 -188
- package/dist/index31.mjs +29 -188
- package/dist/index32.cjs.js +310 -20
- package/dist/index32.mjs +310 -20
- package/dist/index33.cjs.js +20 -334
- package/dist/index33.mjs +20 -334
- package/dist/index34.cjs.js +237 -441
- package/dist/index34.mjs +237 -441
- package/dist/index35.cjs.js +539 -0
- package/dist/index35.mjs +539 -0
- package/dist/index5.cjs.js +35 -1
- package/dist/index5.mjs +35 -1
- package/dist/utils/applyQueryOptions.d.ts +15 -0
- package/package.json +1 -1
package/dist/.vite/manifest.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
]
|
|
18
18
|
},
|
|
19
19
|
"src/AutoFetchDataAdapter.ts": {
|
|
20
|
-
"file": "
|
|
20
|
+
"file": "index35.cjs.js",
|
|
21
21
|
"name": "AutoFetchDataAdapter",
|
|
22
22
|
"src": "src/AutoFetchDataAdapter.ts",
|
|
23
23
|
"isDynamicEntry": true,
|
|
@@ -89,18 +89,22 @@
|
|
|
89
89
|
]
|
|
90
90
|
},
|
|
91
91
|
"src/WorkerDataAdapter.ts": {
|
|
92
|
-
"file": "
|
|
92
|
+
"file": "index32.cjs.js",
|
|
93
93
|
"name": "WorkerDataAdapter",
|
|
94
94
|
"src": "src/WorkerDataAdapter.ts",
|
|
95
95
|
"isDynamicEntry": true,
|
|
96
96
|
"imports": [
|
|
97
|
+
"src/utils/applyQueryOptions.ts",
|
|
97
98
|
"src/utils/batchOnNextTick.ts",
|
|
99
|
+
"src/utils/deepClone.ts",
|
|
100
|
+
"src/utils/match.ts",
|
|
101
|
+
"src/utils/modify.ts",
|
|
98
102
|
"src/utils/queryId.ts",
|
|
99
103
|
"src/utils/randomId.ts"
|
|
100
104
|
]
|
|
101
105
|
},
|
|
102
106
|
"src/WorkerDataAdapterHost.ts": {
|
|
103
|
-
"file": "
|
|
107
|
+
"file": "index34.cjs.js",
|
|
104
108
|
"name": "WorkerDataAdapterHost",
|
|
105
109
|
"src": "src/WorkerDataAdapterHost.ts",
|
|
106
110
|
"isDynamicEntry": true,
|
|
@@ -186,6 +190,17 @@
|
|
|
186
190
|
"src": "src/utils/EventEmitter.ts",
|
|
187
191
|
"isDynamicEntry": true
|
|
188
192
|
},
|
|
193
|
+
"src/utils/applyQueryOptions.ts": {
|
|
194
|
+
"file": "index31.cjs.js",
|
|
195
|
+
"name": "utils/applyQueryOptions",
|
|
196
|
+
"src": "src/utils/applyQueryOptions.ts",
|
|
197
|
+
"isDynamicEntry": true,
|
|
198
|
+
"imports": [
|
|
199
|
+
"src/utils/match.ts",
|
|
200
|
+
"src/utils/project.ts",
|
|
201
|
+
"src/utils/sortItems.ts"
|
|
202
|
+
]
|
|
203
|
+
},
|
|
189
204
|
"src/utils/batchOnNextTick.ts": {
|
|
190
205
|
"file": "index30.cjs.js",
|
|
191
206
|
"name": "utils/batchOnNextTick",
|
|
@@ -193,7 +208,7 @@
|
|
|
193
208
|
"isDynamicEntry": true
|
|
194
209
|
},
|
|
195
210
|
"src/utils/compact.ts": {
|
|
196
|
-
"file": "
|
|
211
|
+
"file": "index33.cjs.js",
|
|
197
212
|
"name": "utils/compact",
|
|
198
213
|
"src": "src/utils/compact.ts",
|
|
199
214
|
"isDynamicEntry": true
|
|
@@ -7,9 +7,26 @@ import { ObserveCallbacks } from './Observer';
|
|
|
7
7
|
* @returns A boolean indicating if the current scope is reactive.
|
|
8
8
|
*/
|
|
9
9
|
export declare function isInReactiveScope(reactivity: ReactivityAdapter | undefined | false): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Reports whether the query a cursor stands for has produced an outcome yet.
|
|
12
|
+
* Supplied by the collection, which owns the query registration; a cursor
|
|
13
|
+
* built without one simply never reports itself as loading.
|
|
14
|
+
*/
|
|
15
|
+
export interface QueryStateAccessor {
|
|
16
|
+
/**
|
|
17
|
+
* Whether the query has settled — completed or failed — at least once
|
|
18
|
+
* since it was registered.
|
|
19
|
+
*/
|
|
20
|
+
hasSettled: () => boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Subscribes to the query settling. Returns a cleanup function.
|
|
23
|
+
*/
|
|
24
|
+
onSettled: (callback: () => void) => () => void;
|
|
25
|
+
}
|
|
10
26
|
export interface CursorOptions<T extends BaseItem, U = T, Async extends boolean = false> extends FindOptions<T, Async> {
|
|
11
27
|
transform?: Transform<T, U>;
|
|
12
28
|
bindEvents?: (requery: () => void) => () => void;
|
|
29
|
+
queryState?: QueryStateAccessor;
|
|
13
30
|
}
|
|
14
31
|
/**
|
|
15
32
|
* Represents a cursor for querying and observing a filtered, sorted, and transformed
|
|
@@ -90,6 +107,31 @@ export default class Cursor<T extends BaseItem, U = T, Async extends boolean = f
|
|
|
90
107
|
* @returns The total number of items in the result set.
|
|
91
108
|
*/
|
|
92
109
|
count(): Async extends true ? Promise<number> : number;
|
|
110
|
+
/**
|
|
111
|
+
* Whether this cursor's query has yet to deliver a first result.
|
|
112
|
+
* ⚡️ this function is reactive!
|
|
113
|
+
*
|
|
114
|
+
* An asynchronous data adapter answers a newly registered query only after a
|
|
115
|
+
* round trip, and serves a neutral empty result until it does — which a
|
|
116
|
+
* consumer cannot otherwise tell apart from "there is nothing to show". This
|
|
117
|
+
* is that distinction, per query rather than per collection, so one screen
|
|
118
|
+
* waiting on its own data says nothing about any other query.
|
|
119
|
+
*
|
|
120
|
+
* Follows the usual `isLoading`/`isFetching` split: it reports "no result
|
|
121
|
+
* yet", not "an execution is in flight". A write that re-runs an
|
|
122
|
+
* already-settled query drives it through `'active'` again while this stays
|
|
123
|
+
* `false`, so a list does not fall back to a loading state every time one of
|
|
124
|
+
* its rows changes.
|
|
125
|
+
*
|
|
126
|
+
* A query that fails counts as settled — the `query.error` event on the
|
|
127
|
+
* collection is what surfaces the failure, and a loading state that never
|
|
128
|
+
* ends is the worse answer. Reading this registers the query if nothing else
|
|
129
|
+
* has, so it cannot wait on something nobody asked for. It is always `false`
|
|
130
|
+
* for an `{ async: true }` cursor, whose `fetch()` awaits the real result
|
|
131
|
+
* anyway, and for a data adapter that answers synchronously.
|
|
132
|
+
* @returns A boolean indicating whether the first result is still pending.
|
|
133
|
+
*/
|
|
134
|
+
isLoading(): boolean;
|
|
93
135
|
/**
|
|
94
136
|
* Observes changes to the cursor's result set and triggers the specified callbacks
|
|
95
137
|
* when items are added, removed, or updated. Supports reactivity and transformation.
|
|
@@ -7,7 +7,7 @@ import { default as StorageAdapter } from '../types/StorageAdapter';
|
|
|
7
7
|
import { default as Cursor } from './Cursor';
|
|
8
8
|
import { AsyncFindOptions, BaseItem, FindOptions, SyncFindOptions, Transform, TransformAll } from './types';
|
|
9
9
|
export type { AnyFindOptions, AsyncFindOptions, BaseItem, Transform, TransformAll, SortSpecifier, FieldSpecifier, FindOptions, SyncFindOptions, } from './types';
|
|
10
|
-
export type { CursorOptions } from './Cursor';
|
|
10
|
+
export type { CursorOptions, QueryStateAccessor } from './Cursor';
|
|
11
11
|
export type { ObserveCallbacks } from './Observer';
|
|
12
12
|
export { default as createIndex } from '../createIndex';
|
|
13
13
|
export interface CollectionOptions<T extends BaseItem<I>, I, E extends BaseItem = T, U = E> {
|
|
@@ -109,6 +109,7 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, E ext
|
|
|
109
109
|
private postBatchCallbacks;
|
|
110
110
|
private fieldTracking;
|
|
111
111
|
private queryListenersMap;
|
|
112
|
+
private settledQueriesSet;
|
|
112
113
|
/**
|
|
113
114
|
* Initializes a new instance of the `Collection` class with optional configuration.
|
|
114
115
|
* Sets up memory, persistence, reactivity, and indices as specified in the options.
|
|
@@ -20,8 +20,28 @@ export default class WorkerDataAdapter implements DataAdapter {
|
|
|
20
20
|
private collectionReady;
|
|
21
21
|
private batchExecutionHelpers;
|
|
22
22
|
private queries;
|
|
23
|
+
private pendingWrites;
|
|
24
|
+
private pendingWriteSeq;
|
|
23
25
|
constructor(worker: WorkerDataAdapterEndpoint, options: WorkerDataAdapterOptions);
|
|
24
26
|
private exec;
|
|
27
|
+
private observableItems;
|
|
28
|
+
private mergePendingWrites;
|
|
29
|
+
/**
|
|
30
|
+
* Registers a write's effect locally and notifies every active query it
|
|
31
|
+
* touches, then returns a function that drops it again once the write
|
|
32
|
+
* settles.
|
|
33
|
+
* @param collectionName - The collection the write targets.
|
|
34
|
+
* @param upserts - Items inserted or updated by the write.
|
|
35
|
+
* @param deletes - Ids removed by the write.
|
|
36
|
+
* @returns A function that drops the pending write and re-notifies.
|
|
37
|
+
*/
|
|
38
|
+
private applyPendingWrite;
|
|
39
|
+
private notifyAffectedQueries;
|
|
40
|
+
private matchObservableItems;
|
|
41
|
+
private resolveUpdate;
|
|
42
|
+
private resolveRemoval;
|
|
43
|
+
private resolveReplacement;
|
|
44
|
+
private withPendingWrite;
|
|
25
45
|
private enqueueBatched;
|
|
26
46
|
private updateQuery;
|
|
27
47
|
createCollectionBackend<T extends BaseItem<I>, I = any, E extends BaseItem = T, U = E>(collection: Collection<T, I, E, U>, indices: string[]): CollectionBackend<T, I>;
|
package/dist/index.cjs.js
CHANGED
|
@@ -12,9 +12,9 @@ const require_createStorageAdapter = require("./index26.cjs.js");
|
|
|
12
12
|
const require_createReactivityAdapter = require("./index27.cjs.js");
|
|
13
13
|
const require_reactiveOrAsync = require("./index28.cjs.js");
|
|
14
14
|
const require_AsyncDataAdapter = require("./index29.cjs.js");
|
|
15
|
-
const require_WorkerDataAdapter = require("./
|
|
16
|
-
const require_WorkerDataAdapterHost = require("./
|
|
17
|
-
const require_AutoFetchDataAdapter = require("./
|
|
15
|
+
const require_WorkerDataAdapter = require("./index32.cjs.js");
|
|
16
|
+
const require_WorkerDataAdapterHost = require("./index34.cjs.js");
|
|
17
|
+
const require_AutoFetchDataAdapter = require("./index35.cjs.js");
|
|
18
18
|
exports.AsyncDataAdapter = require_AsyncDataAdapter.default;
|
|
19
19
|
exports.AutoFetchDataAdapter = require_AutoFetchDataAdapter.default;
|
|
20
20
|
exports.Collection = require_index.default;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type { default as ReactivityAdapter } from './types/ReactivityAdapter';
|
|
|
2
2
|
export type { default as StorageAdapter, Changeset, } from './types/StorageAdapter';
|
|
3
3
|
export type { default as Selector } from './types/Selector';
|
|
4
4
|
export type { default as Modifier } from './types/Modifier';
|
|
5
|
-
export type { BaseItem, ObserveCallbacks, CursorOptions, Transform, TransformAll, SortSpecifier, FieldSpecifier, AnyFindOptions, AsyncFindOptions, FindOptions, SyncFindOptions, CollectionOptions, } from './Collection';
|
|
5
|
+
export type { BaseItem, ObserveCallbacks, CursorOptions, Transform, TransformAll, SortSpecifier, FieldSpecifier, AnyFindOptions, AsyncFindOptions, FindOptions, SyncFindOptions, CollectionOptions, QueryStateAccessor, } from './Collection';
|
|
6
6
|
export type { default as DataAdapter } from './DataAdapter';
|
|
7
7
|
export { default as Cursor } from './Collection/Cursor';
|
|
8
8
|
export { default as Collection } from './Collection';
|
package/dist/index.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import createStorageAdapter from "./index26.mjs";
|
|
|
11
11
|
import createReactivityAdapter from "./index27.mjs";
|
|
12
12
|
import reactiveOrAsync, { unwrap } from "./index28.mjs";
|
|
13
13
|
import AsyncDataAdapter from "./index29.mjs";
|
|
14
|
-
import WorkerDataAdapter from "./
|
|
15
|
-
import WorkerDataAdapterHost from "./
|
|
16
|
-
import AutoFetchDataAdapter from "./
|
|
14
|
+
import WorkerDataAdapter from "./index32.mjs";
|
|
15
|
+
import WorkerDataAdapterHost from "./index34.mjs";
|
|
16
|
+
import AutoFetchDataAdapter from "./index35.mjs";
|
|
17
17
|
export { AsyncDataAdapter, AutoFetchDataAdapter, Collection, Cursor, DefaultDataAdapter, EventEmitter, WorkerDataAdapter, WorkerDataAdapterHost, createReactivityAdapter, createStorageAdapter, get, isEqual, modify, randomId, reactiveOrAsync, serializeValue, unwrap };
|
package/dist/index25.cjs.js
CHANGED
|
@@ -84,6 +84,7 @@ var Collection = class Collection extends require_EventEmitter.default {
|
|
|
84
84
|
postBatchCallbacks = /* @__PURE__ */ new Set();
|
|
85
85
|
fieldTracking = false;
|
|
86
86
|
queryListenersMap = /* @__PURE__ */ new Map();
|
|
87
|
+
settledQueriesSet = /* @__PURE__ */ new Set();
|
|
87
88
|
constructor(nameOrOptions, maybeDataAdapter, maybeOptions) {
|
|
88
89
|
super();
|
|
89
90
|
const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions?.name || `${this.constructor.name}-${require_randomId.default()}`;
|
|
@@ -265,6 +266,18 @@ var Collection = class Collection extends require_EventEmitter.default {
|
|
|
265
266
|
fieldTracking: this.fieldTracking,
|
|
266
267
|
...options,
|
|
267
268
|
transform: this.transform.bind(this),
|
|
269
|
+
queryState: {
|
|
270
|
+
hasSettled: () => {
|
|
271
|
+
if (this.settledQueriesSet.has(require_queryId.default(selector, options))) return true;
|
|
272
|
+
const state = this.backend.getQueryState(selector, options || {});
|
|
273
|
+
return state === "complete" || state === "error";
|
|
274
|
+
},
|
|
275
|
+
onSettled: (callback) => this.backend.onQueryStateChange(selector, options || {}, (state) => {
|
|
276
|
+
if (state !== "complete" && state !== "error") return;
|
|
277
|
+
this.settledQueriesSet.add(require_queryId.default(selector, options));
|
|
278
|
+
callback();
|
|
279
|
+
})
|
|
280
|
+
},
|
|
268
281
|
bindEvents: (requery) => {
|
|
269
282
|
const handleRequery = () => {
|
|
270
283
|
if (this.batchOperationInProgress) {
|
|
@@ -299,7 +312,10 @@ var Collection = class Collection extends require_EventEmitter.default {
|
|
|
299
312
|
selector,
|
|
300
313
|
options
|
|
301
314
|
}) - 1);
|
|
302
|
-
if (newListeners === 0 && didRegister)
|
|
315
|
+
if (newListeners === 0 && didRegister) {
|
|
316
|
+
this.backend.unregisterQuery(selector, options || {});
|
|
317
|
+
this.settledQueriesSet.delete(require_queryId.default(selector, options));
|
|
318
|
+
}
|
|
303
319
|
this.queryListeners({
|
|
304
320
|
selector,
|
|
305
321
|
options
|
package/dist/index25.mjs
CHANGED
|
@@ -84,6 +84,7 @@ var Collection = class Collection extends EventEmitter {
|
|
|
84
84
|
postBatchCallbacks = /* @__PURE__ */ new Set();
|
|
85
85
|
fieldTracking = false;
|
|
86
86
|
queryListenersMap = /* @__PURE__ */ new Map();
|
|
87
|
+
settledQueriesSet = /* @__PURE__ */ new Set();
|
|
87
88
|
constructor(nameOrOptions, maybeDataAdapter, maybeOptions) {
|
|
88
89
|
super();
|
|
89
90
|
const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions?.name || `${this.constructor.name}-${randomId()}`;
|
|
@@ -265,6 +266,18 @@ var Collection = class Collection extends EventEmitter {
|
|
|
265
266
|
fieldTracking: this.fieldTracking,
|
|
266
267
|
...options,
|
|
267
268
|
transform: this.transform.bind(this),
|
|
269
|
+
queryState: {
|
|
270
|
+
hasSettled: () => {
|
|
271
|
+
if (this.settledQueriesSet.has(queryId(selector, options))) return true;
|
|
272
|
+
const state = this.backend.getQueryState(selector, options || {});
|
|
273
|
+
return state === "complete" || state === "error";
|
|
274
|
+
},
|
|
275
|
+
onSettled: (callback) => this.backend.onQueryStateChange(selector, options || {}, (state) => {
|
|
276
|
+
if (state !== "complete" && state !== "error") return;
|
|
277
|
+
this.settledQueriesSet.add(queryId(selector, options));
|
|
278
|
+
callback();
|
|
279
|
+
})
|
|
280
|
+
},
|
|
268
281
|
bindEvents: (requery) => {
|
|
269
282
|
const handleRequery = () => {
|
|
270
283
|
if (this.batchOperationInProgress) {
|
|
@@ -299,7 +312,10 @@ var Collection = class Collection extends EventEmitter {
|
|
|
299
312
|
selector,
|
|
300
313
|
options
|
|
301
314
|
}) - 1);
|
|
302
|
-
if (newListeners === 0 && didRegister)
|
|
315
|
+
if (newListeners === 0 && didRegister) {
|
|
316
|
+
this.backend.unregisterQuery(selector, options || {});
|
|
317
|
+
this.settledQueriesSet.delete(queryId(selector, options));
|
|
318
|
+
}
|
|
303
319
|
this.queryListeners({
|
|
304
320
|
selector,
|
|
305
321
|
options
|
package/dist/index29.cjs.js
CHANGED
|
@@ -239,7 +239,8 @@ var AsyncDataAdapter = class {
|
|
|
239
239
|
if (!rec) return;
|
|
240
240
|
rec.state = state;
|
|
241
241
|
rec.error = error;
|
|
242
|
-
|
|
242
|
+
const subscribers = [...rec.listeners];
|
|
243
|
+
for (const callback of subscribers) try {
|
|
243
244
|
callback(state);
|
|
244
245
|
} catch (error_) {
|
|
245
246
|
this.onError(error_);
|
package/dist/index29.mjs
CHANGED
|
@@ -239,7 +239,8 @@ var AsyncDataAdapter = class {
|
|
|
239
239
|
if (!rec) return;
|
|
240
240
|
rec.state = state;
|
|
241
241
|
rec.error = error;
|
|
242
|
-
|
|
242
|
+
const subscribers = [...rec.listeners];
|
|
243
|
+
for (const callback of subscribers) try {
|
|
243
244
|
callback(state);
|
|
244
245
|
} catch (error_) {
|
|
245
246
|
this.onError(error_);
|
package/dist/index31.cjs.js
CHANGED
|
@@ -1,191 +1,32 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
//#region src/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const { type, workerId } = event.data;
|
|
26
|
-
if (workerId !== this.id) return;
|
|
27
|
-
if (type === "ready") {
|
|
28
|
-
resolve();
|
|
29
|
-
clearTimeout(timeoutId);
|
|
30
|
-
this.worker.removeEventListener("message", handleMessage);
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
this.worker.addEventListener("message", handleMessage);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
async exec(method, collectionName, ...args) {
|
|
37
|
-
await this.workerReady;
|
|
38
|
-
if (method !== "isReady") {
|
|
39
|
-
const collectionReady = this.collectionReady.get(collectionName);
|
|
40
|
-
if (!collectionReady) throw new Error(`Collection "${collectionName}" is not registered in WorkerDataAdapter`);
|
|
41
|
-
await collectionReady;
|
|
42
|
-
}
|
|
43
|
-
if (this.isDisposed) throw new Error("WorkerDataAdapter is disposed");
|
|
44
|
-
return new Promise((resolve, reject) => {
|
|
45
|
-
const messageId = require_randomId.default();
|
|
46
|
-
const handleMessage = (event) => {
|
|
47
|
-
const { id, workerId, type, data, error } = event.data;
|
|
48
|
-
if (workerId !== this.id) return;
|
|
49
|
-
if (type !== "response") return;
|
|
50
|
-
if (id !== messageId) return;
|
|
51
|
-
this.log(method, "result", data ?? error);
|
|
52
|
-
if (error) reject(error);
|
|
53
|
-
else resolve(data);
|
|
54
|
-
this.worker.removeEventListener("message", handleMessage);
|
|
55
|
-
};
|
|
56
|
-
this.worker.addEventListener("message", handleMessage);
|
|
57
|
-
this.worker.postMessage({
|
|
58
|
-
id: messageId,
|
|
59
|
-
workerId: this.id,
|
|
60
|
-
method,
|
|
61
|
-
args: [collectionName, ...args]
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
enqueueBatched(collectionName, method, args) {
|
|
66
|
-
const helper = this.batchExecutionHelpers.get(collectionName);
|
|
67
|
-
if (!helper) throw new Error(`Collection "${collectionName}" is not registered in WorkerDataAdapter`);
|
|
68
|
-
return helper.enqueue(method, args);
|
|
69
|
-
}
|
|
70
|
-
updateQuery(collectionName, query, update) {
|
|
71
|
-
const id = require_queryId.default(query.selector, query.options);
|
|
72
|
-
const collectionQueries = this.queries[collectionName];
|
|
73
|
-
if (!collectionQueries) return;
|
|
74
|
-
const existing = collectionQueries.get(id);
|
|
75
|
-
const newState = {
|
|
76
|
-
state: "active",
|
|
77
|
-
error: null,
|
|
78
|
-
items: [],
|
|
79
|
-
stateChangeCallbacks: [],
|
|
80
|
-
eventHandler: existing?.eventHandler,
|
|
81
|
-
...existing,
|
|
82
|
-
...update
|
|
83
|
-
};
|
|
84
|
-
collectionQueries.set(id, newState);
|
|
85
|
-
this.queries[collectionName] = collectionQueries;
|
|
86
|
-
}
|
|
87
|
-
createCollectionBackend(collection, indices) {
|
|
88
|
-
this.queries[collection.name] = /* @__PURE__ */ new Map();
|
|
89
|
-
this.exec("registerCollection", collection.name, indices);
|
|
90
|
-
this.collectionReady.set(collection.name, this.exec("isReady", collection.name));
|
|
91
|
-
this.batchExecutionHelpers.set(collection.name, require_batchOnNextTick.default(async (method, args) => this.exec(method, collection.name, args)));
|
|
1
|
+
const require_match = require("./index18.cjs.js");
|
|
2
|
+
const require_project = require("./index21.cjs.js");
|
|
3
|
+
const require_sortItems = require("./index23.cjs.js");
|
|
4
|
+
//#region src/utils/applyQueryOptions.ts
|
|
5
|
+
/**
|
|
6
|
+
* Filters, sorts, paginates and projects a plain in-memory array the same way
|
|
7
|
+
* DefaultDataAdapter and WorkerDataAdapterHost apply a selector/QueryOptions
|
|
8
|
+
* pair to their stored items. Used to re-derive a query's result locally after
|
|
9
|
+
* a write, without asking the backing store again.
|
|
10
|
+
* @template T - The type of the items.
|
|
11
|
+
* @param items - The items to filter, sort, paginate and project.
|
|
12
|
+
* @param selector - The selector to match items against.
|
|
13
|
+
* @param options - Sort, skip, limit and field projection options.
|
|
14
|
+
* @returns The resulting items.
|
|
15
|
+
*/
|
|
16
|
+
function applyQueryOptions(items, selector, options) {
|
|
17
|
+
const matched = selector == null ? [] : items.filter((item) => require_match.default(item, selector));
|
|
18
|
+
const { sort, skip, limit, fields } = options || {};
|
|
19
|
+
const sorted = sort ? require_sortItems.default(matched, sort) : matched;
|
|
20
|
+
const skipped = skip ? sorted.slice(skip) : sorted;
|
|
21
|
+
const limited = limit ? skipped.slice(0, limit) : skipped;
|
|
22
|
+
const idExcluded = fields && fields.id === 0;
|
|
23
|
+
return limited.map((item) => {
|
|
24
|
+
if (!fields) return item;
|
|
92
25
|
return {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
},
|
|
96
|
-
updateOne: async (selector, modifier) => {
|
|
97
|
-
return this.enqueueBatched(collection.name, "updateOne", [selector, modifier]);
|
|
98
|
-
},
|
|
99
|
-
updateMany: async (selector, modifier) => {
|
|
100
|
-
return this.enqueueBatched(collection.name, "updateMany", [selector, modifier]);
|
|
101
|
-
},
|
|
102
|
-
replaceOne: async (selector, replacement) => {
|
|
103
|
-
return this.enqueueBatched(collection.name, "replaceOne", [selector, replacement]);
|
|
104
|
-
},
|
|
105
|
-
removeOne: async (selector) => {
|
|
106
|
-
return this.enqueueBatched(collection.name, "removeOne", [selector]);
|
|
107
|
-
},
|
|
108
|
-
removeMany: async (selector) => {
|
|
109
|
-
return this.enqueueBatched(collection.name, "removeMany", [selector]);
|
|
110
|
-
},
|
|
111
|
-
registerQuery: (selector, options) => {
|
|
112
|
-
this.updateQuery(collection.name, {
|
|
113
|
-
selector,
|
|
114
|
-
options
|
|
115
|
-
}, {
|
|
116
|
-
state: "active",
|
|
117
|
-
error: null,
|
|
118
|
-
items: []
|
|
119
|
-
});
|
|
120
|
-
this.exec("registerQuery", collection.name, selector, options);
|
|
121
|
-
const handler = (event) => {
|
|
122
|
-
const { type, data, workerId, error } = event.data;
|
|
123
|
-
if (type !== "queryUpdate") return;
|
|
124
|
-
if (data == null) return;
|
|
125
|
-
const { collectionName, selector: responseSelector, options: responseOptions, state, items } = data;
|
|
126
|
-
if (workerId !== this.id) return;
|
|
127
|
-
if (collectionName !== collection.name) return;
|
|
128
|
-
if (require_queryId.default(responseSelector, responseOptions) !== require_queryId.default(selector, options)) return;
|
|
129
|
-
this.log("queryUpdate", responseSelector, responseOptions, state, data ?? error);
|
|
130
|
-
this.updateQuery(collection.name, {
|
|
131
|
-
selector: responseSelector,
|
|
132
|
-
options: responseOptions
|
|
133
|
-
}, {
|
|
134
|
-
state,
|
|
135
|
-
error,
|
|
136
|
-
items
|
|
137
|
-
});
|
|
138
|
-
const query = this.queries[collection.name]?.get(require_queryId.default(selector, options));
|
|
139
|
-
if (!query) return;
|
|
140
|
-
query.stateChangeCallbacks.forEach((callback) => callback(state));
|
|
141
|
-
};
|
|
142
|
-
this.worker.addEventListener("message", handler);
|
|
143
|
-
this.updateQuery(collection.name, {
|
|
144
|
-
selector,
|
|
145
|
-
options
|
|
146
|
-
}, { eventHandler: handler });
|
|
147
|
-
},
|
|
148
|
-
unregisterQuery: (selector, options) => {
|
|
149
|
-
const qid = require_queryId.default(selector, options);
|
|
150
|
-
const query = this.queries[collection.name]?.get(qid);
|
|
151
|
-
if (query?.eventHandler) this.worker.removeEventListener("message", query.eventHandler);
|
|
152
|
-
this.queries[collection.name]?.delete(qid);
|
|
153
|
-
this.exec("unregisterQuery", collection.name, selector, options);
|
|
154
|
-
},
|
|
155
|
-
getQueryState: (selector, options) => {
|
|
156
|
-
return (this.queries[collection.name]?.get(require_queryId.default(selector, options)))?.state || "active";
|
|
157
|
-
},
|
|
158
|
-
getQueryError: (selector, options) => {
|
|
159
|
-
return (this.queries[collection.name]?.get(require_queryId.default(selector, options)))?.error || null;
|
|
160
|
-
},
|
|
161
|
-
getQueryResult: (selector, options) => {
|
|
162
|
-
return (this.queries[collection.name]?.get(require_queryId.default(selector, options)))?.items || [];
|
|
163
|
-
},
|
|
164
|
-
onQueryStateChange: (selector, options, callback) => {
|
|
165
|
-
this.updateQuery(collection.name, {
|
|
166
|
-
selector,
|
|
167
|
-
options
|
|
168
|
-
}, { stateChangeCallbacks: [...this.queries[collection.name]?.get(require_queryId.default(selector, options))?.stateChangeCallbacks || [], callback] });
|
|
169
|
-
return () => {
|
|
170
|
-
const currentCallbacks = this.queries[collection.name]?.get(require_queryId.default(selector, options))?.stateChangeCallbacks;
|
|
171
|
-
if (!currentCallbacks) return;
|
|
172
|
-
this.updateQuery(collection.name, {
|
|
173
|
-
selector,
|
|
174
|
-
options
|
|
175
|
-
}, { stateChangeCallbacks: currentCallbacks.filter((existingCallback) => existingCallback !== callback) });
|
|
176
|
-
};
|
|
177
|
-
},
|
|
178
|
-
executeQuery: (selector, options) => this.exec("executeQuery", collection.name, selector, options),
|
|
179
|
-
dispose: async () => {
|
|
180
|
-
await this.exec("unregisterCollection", collection.name);
|
|
181
|
-
this.isDisposed = true;
|
|
182
|
-
this.worker.terminate?.();
|
|
183
|
-
},
|
|
184
|
-
isReady: async () => {
|
|
185
|
-
await this.exec("isReady", collection.name);
|
|
186
|
-
}
|
|
26
|
+
...idExcluded ? {} : { id: item.id },
|
|
27
|
+
...require_project.default(item, fields)
|
|
187
28
|
};
|
|
188
|
-
}
|
|
189
|
-
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
190
31
|
//#endregion
|
|
191
|
-
exports.default =
|
|
32
|
+
exports.default = applyQueryOptions;
|