@signaldb/core 2.0.0-beta.0 → 2.0.0-beta.2
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 +24 -11
- package/dist/AsyncDataAdapter.d.ts +1 -1
- package/dist/AutoFetchDataAdapter.d.ts +1 -2
- package/dist/Collection/Cursor.d.ts +3 -2
- package/dist/Collection/index.d.ts +17 -12
- package/dist/Collection/types.d.ts +1 -0
- package/dist/DataAdapter.d.ts +9 -7
- package/dist/DefaultDataAdapter.d.ts +2 -1
- package/dist/WorkerDataAdapter.d.ts +5 -2
- package/dist/WorkerDataAdapterHost.d.ts +9 -6
- package/dist/index.cjs12.js +35 -21
- package/dist/index.cjs13.js +27 -15
- package/dist/index.cjs14.js +72 -56
- package/dist/index.cjs15.js +122 -75
- package/dist/index.cjs16.js +45 -36
- package/dist/index.cjs17.js +4 -2
- package/dist/index.cjs19.js +0 -1
- package/dist/index.cjs2.js +6 -2
- package/dist/index.cjs20.js +14 -102
- package/dist/index.cjs21.js +93 -118
- package/dist/index.cjs22.js +127 -5
- package/dist/index.cjs23.js +5 -25
- package/dist/index.cjs24.js +25 -5
- package/dist/index.cjs27.js +44 -3
- package/dist/index.cjs28.js +6 -5
- package/dist/index.cjs29.js +5 -27
- package/dist/index.cjs3.js +41 -22
- package/dist/index.cjs31.js +27 -7
- package/dist/index.cjs32.js +9 -0
- package/dist/index.cjs33.js +5 -0
- package/dist/index.d.ts +2 -1
- package/dist/index12.mjs +35 -21
- package/dist/index13.mjs +27 -15
- package/dist/index14.mjs +72 -56
- package/dist/index15.mjs +122 -75
- package/dist/index16.mjs +45 -36
- package/dist/index17.mjs +4 -2
- package/dist/index19.mjs +0 -1
- package/dist/index2.mjs +6 -2
- package/dist/index20.mjs +14 -102
- package/dist/index21.mjs +93 -117
- package/dist/index22.mjs +126 -5
- package/dist/index23.mjs +5 -25
- package/dist/index24.mjs +25 -5
- package/dist/index27.mjs +44 -3
- package/dist/index28.mjs +6 -5
- package/dist/index29.mjs +5 -27
- package/dist/index3.mjs +41 -22
- package/dist/index31.mjs +27 -7
- package/dist/index32.mjs +10 -0
- package/dist/index33.mjs +6 -0
- package/dist/utils/batchOnNextTick.d.ts +16 -0
- package/dist/utils/deepClone.d.ts +1 -1
- package/package.json +3 -3
package/dist/.vite/manifest.json
CHANGED
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"src/DefaultDataAdapter.ts",
|
|
60
60
|
"src/utils/modify.ts",
|
|
61
61
|
"src/utils/deepClone.ts",
|
|
62
|
+
"src/utils/queryId.ts",
|
|
62
63
|
"src/Collection/Cursor.ts"
|
|
63
64
|
]
|
|
64
65
|
},
|
|
@@ -86,7 +87,8 @@
|
|
|
86
87
|
"src": "src/WorkerDataAdapter.ts",
|
|
87
88
|
"imports": [
|
|
88
89
|
"src/utils/queryId.ts",
|
|
89
|
-
"src/utils/randomId.ts"
|
|
90
|
+
"src/utils/randomId.ts",
|
|
91
|
+
"src/utils/batchOnNextTick.ts"
|
|
90
92
|
]
|
|
91
93
|
},
|
|
92
94
|
"src/WorkerDataAdapterHost.ts": {
|
|
@@ -102,11 +104,12 @@
|
|
|
102
104
|
"src/getIndexInfo.ts",
|
|
103
105
|
"src/utils/getMatchingKeys.ts",
|
|
104
106
|
"src/utils/sortItems.ts",
|
|
105
|
-
"src/utils/project.ts"
|
|
107
|
+
"src/utils/project.ts",
|
|
108
|
+
"src/utils/compact.ts"
|
|
106
109
|
]
|
|
107
110
|
},
|
|
108
111
|
"src/createIndex.ts": {
|
|
109
|
-
"file": "index.
|
|
112
|
+
"file": "index.cjs21.js",
|
|
110
113
|
"name": "createIndex",
|
|
111
114
|
"src": "src/createIndex.ts",
|
|
112
115
|
"imports": [
|
|
@@ -117,7 +120,7 @@
|
|
|
117
120
|
]
|
|
118
121
|
},
|
|
119
122
|
"src/createIndexProvider.ts": {
|
|
120
|
-
"file": "index.
|
|
123
|
+
"file": "index.cjs33.js",
|
|
121
124
|
"name": "createIndexProvider",
|
|
122
125
|
"src": "src/createIndexProvider.ts"
|
|
123
126
|
},
|
|
@@ -132,7 +135,7 @@
|
|
|
132
135
|
"src": "src/createStorageAdapter.ts"
|
|
133
136
|
},
|
|
134
137
|
"src/getIndexInfo.ts": {
|
|
135
|
-
"file": "index.
|
|
138
|
+
"file": "index.cjs22.js",
|
|
136
139
|
"name": "getIndexInfo",
|
|
137
140
|
"src": "src/getIndexInfo.ts",
|
|
138
141
|
"imports": [
|
|
@@ -167,6 +170,16 @@
|
|
|
167
170
|
"name": "utils/EventEmitter",
|
|
168
171
|
"src": "src/utils/EventEmitter.ts"
|
|
169
172
|
},
|
|
173
|
+
"src/utils/batchOnNextTick.ts": {
|
|
174
|
+
"file": "index.cjs27.js",
|
|
175
|
+
"name": "utils/batchOnNextTick",
|
|
176
|
+
"src": "src/utils/batchOnNextTick.ts"
|
|
177
|
+
},
|
|
178
|
+
"src/utils/compact.ts": {
|
|
179
|
+
"file": "index.cjs28.js",
|
|
180
|
+
"name": "utils/compact",
|
|
181
|
+
"src": "src/utils/compact.ts"
|
|
182
|
+
},
|
|
170
183
|
"src/utils/createSignal.ts": {
|
|
171
184
|
"file": "index.cjs18.js",
|
|
172
185
|
"name": "utils/createSignal",
|
|
@@ -192,7 +205,7 @@
|
|
|
192
205
|
]
|
|
193
206
|
},
|
|
194
207
|
"src/utils/intersection.ts": {
|
|
195
|
-
"file": "index.
|
|
208
|
+
"file": "index.cjs29.js",
|
|
196
209
|
"name": "utils/intersection",
|
|
197
210
|
"src": "src/utils/intersection.ts"
|
|
198
211
|
},
|
|
@@ -207,7 +220,7 @@
|
|
|
207
220
|
"src": "src/utils/isFieldExpression.ts"
|
|
208
221
|
},
|
|
209
222
|
"src/utils/match.ts": {
|
|
210
|
-
"file": "index.
|
|
223
|
+
"file": "index.cjs23.js",
|
|
211
224
|
"name": "utils/match",
|
|
212
225
|
"src": "src/utils/match.ts"
|
|
213
226
|
},
|
|
@@ -220,7 +233,7 @@
|
|
|
220
233
|
]
|
|
221
234
|
},
|
|
222
235
|
"src/utils/project.ts": {
|
|
223
|
-
"file": "index.
|
|
236
|
+
"file": "index.cjs24.js",
|
|
224
237
|
"name": "utils/project",
|
|
225
238
|
"src": "src/utils/project.ts",
|
|
226
239
|
"imports": [
|
|
@@ -229,7 +242,7 @@
|
|
|
229
242
|
]
|
|
230
243
|
},
|
|
231
244
|
"src/utils/queryId.ts": {
|
|
232
|
-
"file": "index.
|
|
245
|
+
"file": "index.cjs20.js",
|
|
233
246
|
"name": "utils/queryId",
|
|
234
247
|
"src": "src/utils/queryId.ts"
|
|
235
248
|
},
|
|
@@ -244,7 +257,7 @@
|
|
|
244
257
|
"src": "src/utils/serializeValue.ts"
|
|
245
258
|
},
|
|
246
259
|
"src/utils/set.ts": {
|
|
247
|
-
"file": "index.
|
|
260
|
+
"file": "index.cjs31.js",
|
|
248
261
|
"name": "utils/set",
|
|
249
262
|
"src": "src/utils/set.ts"
|
|
250
263
|
},
|
|
@@ -257,7 +270,7 @@
|
|
|
257
270
|
]
|
|
258
271
|
},
|
|
259
272
|
"src/utils/uniqueBy.ts": {
|
|
260
|
-
"file": "index.
|
|
273
|
+
"file": "index.cjs32.js",
|
|
261
274
|
"name": "utils/uniqueBy",
|
|
262
275
|
"src": "src/utils/uniqueBy.ts"
|
|
263
276
|
}
|
|
@@ -27,7 +27,7 @@ export default class AsyncDataAdapter implements DataAdapter {
|
|
|
27
27
|
private collectionIndices;
|
|
28
28
|
private queries;
|
|
29
29
|
constructor(options: AsyncDataAdapterOptions);
|
|
30
|
-
createCollectionBackend<T extends BaseItem<I>, I = any, U =
|
|
30
|
+
createCollectionBackend<T extends BaseItem<I>, I = any, E extends BaseItem = T, U = E>(collection: Collection<T, I, E, U>, indices: string[]): CollectionBackend<T, I>;
|
|
31
31
|
private setupStorage;
|
|
32
32
|
private ensureStorageAdapter;
|
|
33
33
|
/**
|
|
@@ -71,8 +71,7 @@ export default class AutoFetchDataAdapter implements DataAdapter {
|
|
|
71
71
|
private idRefCounts;
|
|
72
72
|
private autoloadIds;
|
|
73
73
|
constructor(options: AutoFetchDataAdapterOptions);
|
|
74
|
-
createCollectionBackend<T extends BaseItem<I>, I = any, U =
|
|
75
|
-
private selectorKey;
|
|
74
|
+
createCollectionBackend<T extends BaseItem<I>, I = any, E extends BaseItem = T, U = E>(collection: Collection<T, I, E, U>, indices: string[]): CollectionBackend<T, I>;
|
|
76
75
|
private forceRefetchAll;
|
|
77
76
|
private fetchAndIngest;
|
|
78
77
|
private purgeSelector;
|
|
@@ -15,7 +15,7 @@ export interface CursorOptions<T extends BaseItem, U = T, Async extends boolean
|
|
|
15
15
|
* Represents a cursor for querying and observing a filtered, sorted, and transformed
|
|
16
16
|
* subset of items from a collection. Supports reactivity and field tracking.
|
|
17
17
|
* @template T - The type of the items in the collection.
|
|
18
|
-
* @template U - The transformed item type after applying
|
|
18
|
+
* @template U - The transformed item type after applying transform (default is T).
|
|
19
19
|
*/
|
|
20
20
|
export default class Cursor<T extends BaseItem, U = T, Async extends boolean = false> {
|
|
21
21
|
private observer;
|
|
@@ -37,6 +37,7 @@ export default class Cursor<T extends BaseItem, U = T, Async extends boolean = f
|
|
|
37
37
|
* @param options.limit - The maximum number of items to return in the result set.
|
|
38
38
|
* @param options.reactive - A reactivity adapter to enable observing changes in the cursor's result set.
|
|
39
39
|
* @param options.fieldTracking - A boolean to enable fine-grained field tracking for reactivity.
|
|
40
|
+
* @param options.transformAll - A function that will be able to solve the n+1 problem
|
|
40
41
|
*/
|
|
41
42
|
constructor(getItems: Async extends true ? () => Promise<T[]> : () => T[], options?: CursorOptions<T, U, Async>);
|
|
42
43
|
private addGetters;
|
|
@@ -102,7 +103,7 @@ export default class Cursor<T extends BaseItem, U = T, Async extends boolean = f
|
|
|
102
103
|
* @param skipInitial - A boolean indicating whether to skip the initial notification of the current result set.
|
|
103
104
|
* @returns A function to stop observing changes.
|
|
104
105
|
*/
|
|
105
|
-
observeChanges(callbacks: ObserveCallbacks<
|
|
106
|
+
observeChanges(callbacks: ObserveCallbacks<T>, skipInitial?: boolean): () => void;
|
|
106
107
|
/**
|
|
107
108
|
* Forces the cursor to re-evaluate its result set by re-fetching items
|
|
108
109
|
* from the collection. This is useful when the underlying data or query
|
|
@@ -6,12 +6,12 @@ import type DataAdapter from '../DataAdapter';
|
|
|
6
6
|
import type { QueryOptions } from '../DataAdapter';
|
|
7
7
|
import type StorageAdapter from '../types/StorageAdapter';
|
|
8
8
|
import Cursor from './Cursor';
|
|
9
|
-
import type { BaseItem, FindOptions, Transform } from './types';
|
|
10
|
-
export type { BaseItem, Transform, SortSpecifier, FieldSpecifier, FindOptions } from './types';
|
|
9
|
+
import type { BaseItem, FindOptions, Transform, TransformAll } from './types';
|
|
10
|
+
export type { BaseItem, Transform, TransformAll, SortSpecifier, FieldSpecifier, FindOptions } from './types';
|
|
11
11
|
export type { CursorOptions } from './Cursor';
|
|
12
12
|
export type { ObserveCallbacks } from './Observer';
|
|
13
13
|
export { default as createIndex } from '../createIndex';
|
|
14
|
-
export interface CollectionOptions<T extends BaseItem<I>, I, U =
|
|
14
|
+
export interface CollectionOptions<T extends BaseItem<I>, I, E extends BaseItem = T, U = E> {
|
|
15
15
|
/**
|
|
16
16
|
* @deprecated Use new constructor parameters instead.
|
|
17
17
|
*/
|
|
@@ -22,19 +22,20 @@ export interface CollectionOptions<T extends BaseItem<I>, I, U = T> {
|
|
|
22
22
|
persistence?: StorageAdapter<T, I>;
|
|
23
23
|
primaryKeyGenerator?: (item: Omit<T, 'id'>) => I;
|
|
24
24
|
reactivity?: ReactivityAdapter;
|
|
25
|
-
transform?: Transform<
|
|
25
|
+
transform?: Transform<E, U>;
|
|
26
|
+
transformAll?: TransformAll<T, E>;
|
|
26
27
|
indices?: string[];
|
|
27
28
|
enableDebugMode?: boolean;
|
|
28
29
|
fieldTracking?: boolean;
|
|
29
30
|
}
|
|
30
|
-
interface CollectionEvents<T extends BaseItem, U =
|
|
31
|
+
interface CollectionEvents<T extends BaseItem, E extends BaseItem = T, U = E> {
|
|
31
32
|
'added': (item: T) => void;
|
|
32
33
|
'changed': (item: T, modifier: Modifier<T>) => void;
|
|
33
34
|
'removed': (item: T) => void;
|
|
34
35
|
'observer.created': <O extends QueryOptions<T>>(selector?: Selector<T>, options?: O) => void;
|
|
35
36
|
'observer.disposed': <O extends QueryOptions<T>>(selector?: Selector<T>, options?: O) => void;
|
|
36
37
|
'getItems': (selector: Selector<T> | undefined) => void;
|
|
37
|
-
'find': <O extends FindOptions<T, Async>, Async extends boolean>(selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<
|
|
38
|
+
'find': <O extends FindOptions<T, Async>, Async extends boolean>(selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<E, U, Async>) => void;
|
|
38
39
|
'findOne': <O extends QueryOptions<T>>(selector: Selector<T>, options: O | undefined, item: U | undefined) => void;
|
|
39
40
|
'insert': (item: Omit<T, 'id'> & Partial<Pick<T, 'id'>>) => void;
|
|
40
41
|
'updateOne': (selector: Selector<T>, modifier: Modifier<T>) => void;
|
|
@@ -44,7 +45,7 @@ interface CollectionEvents<T extends BaseItem, U = T> {
|
|
|
44
45
|
'removeMany': (selector: Selector<T>) => void;
|
|
45
46
|
'validate': (item: T) => void;
|
|
46
47
|
'_debug.getItems': (callstack: string, selector: Selector<T> | undefined, measuredTime: number) => void;
|
|
47
|
-
'_debug.find': <O extends FindOptions<T, Async>, Async extends boolean>(callstack: string, selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<
|
|
48
|
+
'_debug.find': <O extends FindOptions<T, Async>, Async extends boolean>(callstack: string, selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<E, U, Async>) => void;
|
|
48
49
|
'_debug.findOne': <O extends FindOptions<T, Async>, Async extends boolean>(callstack: string, selector: Selector<T>, options: O | undefined, item: U | undefined) => void;
|
|
49
50
|
'_debug.insert': (callstack: string, item: Omit<T, 'id'> & Partial<Pick<T, 'id'>>) => void;
|
|
50
51
|
'_debug.updateOne': (callstack: string, selector: Selector<T>, modifier: Modifier<T>) => void;
|
|
@@ -61,14 +62,14 @@ interface CollectionEvents<T extends BaseItem, U = T> {
|
|
|
61
62
|
* @template I - The type of the unique identifier for the items.
|
|
62
63
|
* @template U - The transformed item type after applying transformations (default is T).
|
|
63
64
|
*/
|
|
64
|
-
export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U =
|
|
65
|
+
export default class Collection<T extends BaseItem<I> = BaseItem, I = any, E extends BaseItem = T, U = E> extends EventEmitter<CollectionEvents<T, E, U>> {
|
|
65
66
|
private static collections;
|
|
66
67
|
private static debugMode;
|
|
67
68
|
private static batchOperationInProgress;
|
|
68
69
|
private static fieldTracking;
|
|
69
70
|
private static onCreationCallbacks;
|
|
70
71
|
private static onDisposeCallbacks;
|
|
71
|
-
static getCollections(): Collection<any, any, any>[];
|
|
72
|
+
static getCollections(): Collection<any, any, any, any>[];
|
|
72
73
|
static onCreation(callback: (collection: Collection<any>) => void): void;
|
|
73
74
|
static onDispose(callback: (collection: Collection<any>) => void): void;
|
|
74
75
|
/**
|
|
@@ -102,6 +103,7 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
102
103
|
private isDisposed;
|
|
103
104
|
private postBatchCallbacks;
|
|
104
105
|
private fieldTracking;
|
|
106
|
+
private queryListenersMap;
|
|
105
107
|
/**
|
|
106
108
|
* Initializes a new instance of the `Collection` class with optional configuration.
|
|
107
109
|
* Sets up memory, persistence, reactivity, and indices as specified in the options.
|
|
@@ -119,9 +121,10 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
119
121
|
* @param options.indices - An array of index providers for optimized querying.
|
|
120
122
|
* @param options.enableDebugMode - A boolean to enable or disable debug mode.
|
|
121
123
|
* @param options.fieldTracking - A boolean to enable or disable field tracking by default.
|
|
124
|
+
* @param options.transformAll - A function that will be able to solve the n+1 problem
|
|
122
125
|
*/
|
|
123
|
-
constructor(options?: CollectionOptions<T, I, U>);
|
|
124
|
-
constructor(name: string, dataAdapter: DataAdapter, options?: CollectionOptions<T, I, U>);
|
|
126
|
+
constructor(options?: CollectionOptions<T, I, E, U>);
|
|
127
|
+
constructor(name: string, dataAdapter: DataAdapter, options?: CollectionOptions<T, I, E, U>);
|
|
125
128
|
isBatchOperationInProgress(): boolean;
|
|
126
129
|
/**
|
|
127
130
|
* Checks whether the collection is currently performing a pull operation
|
|
@@ -183,9 +186,11 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
183
186
|
private profile;
|
|
184
187
|
private executeInDebugMode;
|
|
185
188
|
private transform;
|
|
189
|
+
private transformAll;
|
|
186
190
|
private getItem;
|
|
187
191
|
private getItems;
|
|
188
192
|
private withPushState;
|
|
193
|
+
private queryListeners;
|
|
189
194
|
/**
|
|
190
195
|
* Disposes the collection, unregisters persistence adapters, clears memory, and
|
|
191
196
|
* cleans up all resources used by the collection.
|
|
@@ -200,7 +205,7 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
200
205
|
* @param [options] - Options for the find operation, such as limit and sort.
|
|
201
206
|
* @returns A cursor to fetch and observe the matching items.
|
|
202
207
|
*/
|
|
203
|
-
find<Async extends boolean = false, O extends FindOptions<T, Async> = FindOptions<T, Async>>(selector?: Selector<T>, options?: O): Cursor<
|
|
208
|
+
find<Async extends boolean = false, O extends FindOptions<T, Async> = FindOptions<T, Async>>(selector?: Selector<T>, options?: O): Cursor<E, U, Async>;
|
|
204
209
|
/**
|
|
205
210
|
* Finds a single item in the collection based on a selector and optional options.
|
|
206
211
|
* ⚡️ this function is reactive!
|
|
@@ -4,6 +4,7 @@ export type BaseItem<I = any> = {
|
|
|
4
4
|
id: I;
|
|
5
5
|
} & Record<string, any>;
|
|
6
6
|
export type Transform<T, U = T> = ((document: T) => U) | null | undefined;
|
|
7
|
+
export type TransformAll<T extends BaseItem, O extends BaseItem = T> = ((items: T[], fields: FieldSpecifier<O> | undefined) => O[]) | null | undefined;
|
|
7
8
|
export type SortSpecifier<T> = {
|
|
8
9
|
[P in keyof T]?: -1 | 1;
|
|
9
10
|
} & Record<string, -1 | 1>;
|
package/dist/DataAdapter.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface QueryOptions<T extends BaseItem> {
|
|
|
12
12
|
/** Dictionary of fields to return or exclude. */
|
|
13
13
|
fields?: FieldSpecifier<T> | undefined;
|
|
14
14
|
}
|
|
15
|
+
export type StateChangeCallback = (state: 'active' | 'complete' | 'error') => void;
|
|
15
16
|
export interface CollectionBackend<T extends BaseItem<I>, I> {
|
|
16
17
|
insert(item: T): Promise<T>;
|
|
17
18
|
updateOne(selector: Selector<T>, modifier: Modifier<T>): Promise<T[]>;
|
|
@@ -19,15 +20,16 @@ export interface CollectionBackend<T extends BaseItem<I>, I> {
|
|
|
19
20
|
replaceOne(selector: Selector<T>, replacement: Omit<T, 'id'> & Partial<Pick<T, 'id'>>): Promise<T[]>;
|
|
20
21
|
removeOne(selector: Selector<T>): Promise<T[]>;
|
|
21
22
|
removeMany(selector: Selector<T>): Promise<T[]>;
|
|
22
|
-
registerQuery<O extends QueryOptions<T>>(selector: Selector<T>, options
|
|
23
|
-
unregisterQuery<O extends QueryOptions<T>>(selector: Selector<T>, options
|
|
24
|
-
getQueryState<O extends QueryOptions<T>>(selector: Selector<T>, options
|
|
25
|
-
getQueryError<O extends QueryOptions<T>>(selector: Selector<T>, options
|
|
26
|
-
getQueryResult<O extends QueryOptions<T>>(selector: Selector<T>, options
|
|
27
|
-
|
|
23
|
+
registerQuery<O extends QueryOptions<T>>(selector: Selector<T>, options: O): void;
|
|
24
|
+
unregisterQuery<O extends QueryOptions<T>>(selector: Selector<T>, options: O): void;
|
|
25
|
+
getQueryState<O extends QueryOptions<T>>(selector: Selector<T>, options: O): 'active' | 'complete' | 'error';
|
|
26
|
+
getQueryError<O extends QueryOptions<T>>(selector: Selector<T>, options: O): Error | null;
|
|
27
|
+
getQueryResult<O extends QueryOptions<T>>(selector: Selector<T>, options: O): T[];
|
|
28
|
+
executeQuery<O extends QueryOptions<T>>(selector: Selector<T>, options: O): Promise<T[]>;
|
|
29
|
+
onQueryStateChange<O extends QueryOptions<T>>(selector: Selector<T>, options: O, callback: StateChangeCallback): () => void;
|
|
28
30
|
dispose(): Promise<void>;
|
|
29
31
|
isReady(): Promise<void>;
|
|
30
32
|
}
|
|
31
33
|
export default interface DataAdapter {
|
|
32
|
-
createCollectionBackend<T extends BaseItem<I>, I = any, U =
|
|
34
|
+
createCollectionBackend<T extends BaseItem<I>, I = any, E extends BaseItem = T, U = E>(collection: Collection<T, I, E, U>, indices: string[]): CollectionBackend<T, I>;
|
|
33
35
|
}
|
|
@@ -26,7 +26,8 @@ export default class DefaultDataAdapter implements DataAdapter {
|
|
|
26
26
|
private queryItems;
|
|
27
27
|
private executeQuery;
|
|
28
28
|
private flushQueuedQueryUpdates;
|
|
29
|
+
private executeAndCacheQuery;
|
|
29
30
|
private updateQueries;
|
|
30
|
-
createCollectionBackend<T extends BaseItem<I>, I = any, U =
|
|
31
|
+
createCollectionBackend<T extends BaseItem<I>, I = any, E extends BaseItem = T, U = E>(collection: Collection<T, I, E, U>, indices: string[]): CollectionBackend<T, I>;
|
|
31
32
|
}
|
|
32
33
|
export {};
|
|
@@ -4,6 +4,7 @@ import type DataAdapter from './DataAdapter';
|
|
|
4
4
|
import type { CollectionBackend } from './DataAdapter';
|
|
5
5
|
interface WorkerDataAdapterOptions {
|
|
6
6
|
id?: string;
|
|
7
|
+
log?: (message: string, ...args: any[]) => void;
|
|
7
8
|
}
|
|
8
9
|
export default class WorkerDataAdapter implements DataAdapter {
|
|
9
10
|
private worker;
|
|
@@ -11,12 +12,14 @@ export default class WorkerDataAdapter implements DataAdapter {
|
|
|
11
12
|
private id;
|
|
12
13
|
private isDisposed;
|
|
13
14
|
private workerReady;
|
|
15
|
+
private log;
|
|
14
16
|
private collectionReady;
|
|
17
|
+
private batchExecutionHelpers;
|
|
15
18
|
private queries;
|
|
16
19
|
constructor(worker: Worker, options: WorkerDataAdapterOptions);
|
|
17
20
|
private exec;
|
|
18
|
-
private
|
|
21
|
+
private enqueueBatched;
|
|
19
22
|
private updateQuery;
|
|
20
|
-
createCollectionBackend<T extends BaseItem<I>, I = any, U =
|
|
23
|
+
createCollectionBackend<T extends BaseItem<I>, I = any, E extends BaseItem = T, U = E>(collection: Collection<T, I, E, U>, indices: string[]): CollectionBackend<T, I>;
|
|
21
24
|
}
|
|
22
25
|
export {};
|
|
@@ -11,24 +11,27 @@ interface WorkerDataAdapterHostOptions {
|
|
|
11
11
|
id?: string;
|
|
12
12
|
storage: (name: string) => StorageAdapter<any, any>;
|
|
13
13
|
onError?: (error: Error) => void;
|
|
14
|
+
log?: (message: string, ...args: any[]) => void;
|
|
14
15
|
}
|
|
15
16
|
type CollectionMethods<T extends BaseItem<I>, I = any> = {
|
|
16
17
|
registerCollection: (collectionName: string, indices: string[]) => Promise<void>;
|
|
17
18
|
unregisterCollection: (collectionName: string) => Promise<void>;
|
|
18
19
|
registerQuery: <O extends QueryOptions<T>>(collectionName: string, selector: Selector<T>, options?: O) => Promise<void>;
|
|
19
20
|
unregisterQuery: <O extends QueryOptions<T>>(collectionName: string, selector: Selector<T>, options?: O) => Promise<void>;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
executeQuery: <O extends QueryOptions<T>>(collectionName: string, selector: Selector<T>, options?: O) => Promise<T[]>;
|
|
22
|
+
insert: (collectionName: string, items: [T][]) => Promise<(T | Error)[]>;
|
|
23
|
+
updateOne: (collectionName: string, args: [Selector<T>, Modifier<T>][]) => Promise<(T[] | Error)[]>;
|
|
24
|
+
updateMany: (collectionName: string, args: [Selector<T>, Modifier<T>][]) => Promise<(T[] | Error)[]>;
|
|
25
|
+
replaceOne: (collectionName: string, args: [Selector<T>, Omit<T, 'id'> & Partial<Pick<T, 'id'>>][]) => Promise<(T[] | Error)[]>;
|
|
26
|
+
removeOne: (collectionName: string, selectors: [Selector<T>][]) => Promise<(T[] | Error)[]>;
|
|
27
|
+
removeMany: (collectionName: string, selectors: [Selector<T>][]) => Promise<(T[] | Error)[]>;
|
|
26
28
|
isReady: (collectionName: string) => Promise<void>;
|
|
27
29
|
};
|
|
28
30
|
export default class WorkerDataAdapterHost<T extends BaseItem<I>, I = any> {
|
|
29
31
|
private workerContext;
|
|
30
32
|
private options;
|
|
31
33
|
private id;
|
|
34
|
+
private log;
|
|
32
35
|
private storageAdapters;
|
|
33
36
|
private storageAdapterReady;
|
|
34
37
|
private collectionIndices;
|
package/dist/index.cjs12.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const createIndex = require("./index.
|
|
3
|
-
const getIndexInfo = require("./index.
|
|
2
|
+
const createIndex = require("./index.cjs21.js");
|
|
3
|
+
const getIndexInfo = require("./index.cjs22.js");
|
|
4
4
|
const deepClone = require("./index.cjs19.js");
|
|
5
5
|
const EventEmitter = require("./index.cjs9.js");
|
|
6
6
|
const isEqual = require("./index.cjs6.js");
|
|
7
|
-
const match = require("./index.
|
|
7
|
+
const match = require("./index.cjs23.js");
|
|
8
8
|
const modify = require("./index.cjs7.js");
|
|
9
|
-
const project = require("./index.
|
|
10
|
-
const queryId = require("./index.
|
|
9
|
+
const project = require("./index.cjs24.js");
|
|
10
|
+
const queryId = require("./index.cjs20.js");
|
|
11
11
|
const serializeValue = require("./index.cjs11.js");
|
|
12
12
|
const sortItems = require("./index.cjs25.js");
|
|
13
13
|
function hasPendingUpdates(pendingUpdates) {
|
|
@@ -143,14 +143,28 @@ class DefaultDataAdapter {
|
|
|
143
143
|
return;
|
|
144
144
|
this.queuedQueryUpdates.set(collection.name, { added: [], modified: [], removed: [] });
|
|
145
145
|
const flatItems = [...changes.added, ...changes.modified, ...changes.removed];
|
|
146
|
-
const
|
|
146
|
+
const itemIds = new Set(flatItems.map((i) => i.id));
|
|
147
|
+
const queries = [
|
|
148
|
+
...this.activeQueries.get(collection.name)?.values() ?? []
|
|
149
|
+
].filter(({ selector, options }) => {
|
|
150
|
+
const idsInQuery = this.cachedQueryResults.get(collection.name)?.get(queryId(selector, options))?.map((i) => i.id) ?? [];
|
|
151
|
+
if (idsInQuery.some((id) => itemIds.has(id)))
|
|
152
|
+
return true;
|
|
153
|
+
return flatItems.some((item) => match(item, selector));
|
|
154
|
+
});
|
|
147
155
|
queries.forEach(({ selector, options }) => {
|
|
148
|
-
|
|
149
|
-
if (!emitter)
|
|
150
|
-
return;
|
|
151
|
-
emitter.emit("change", selector, options, "complete");
|
|
156
|
+
this.executeAndCacheQuery(collection, selector, options);
|
|
152
157
|
});
|
|
153
158
|
}
|
|
159
|
+
executeAndCacheQuery(collection, selector, options) {
|
|
160
|
+
const result = this.executeQuery(collection, selector, options);
|
|
161
|
+
this.cachedQueryResults.set(collection.name, this.cachedQueryResults.get(collection.name) || /* @__PURE__ */ new Map());
|
|
162
|
+
this.cachedQueryResults.get(collection.name)?.set(queryId(selector, options), result);
|
|
163
|
+
const emitter = this.queryEmitters.get(collection.name);
|
|
164
|
+
if (!emitter)
|
|
165
|
+
return;
|
|
166
|
+
emitter.emit("change", selector, options, "complete");
|
|
167
|
+
}
|
|
154
168
|
updateQueries(collection, changes) {
|
|
155
169
|
this.queuedQueryUpdates.set(collection.name, this.queuedQueryUpdates.get(collection.name) || { added: [], modified: [], removed: [] });
|
|
156
170
|
this.queuedQueryUpdates.get(collection.name)?.added.push(...changes.added);
|
|
@@ -162,6 +176,7 @@ class DefaultDataAdapter {
|
|
|
162
176
|
this.ensureStorageAdapter(collection.name);
|
|
163
177
|
this.items.set(collection.name, this.items.get(collection.name) ?? /* @__PURE__ */ new Map());
|
|
164
178
|
this.queryEmitters.set(collection.name, this.queryEmitters.get(collection.name) ?? new EventEmitter());
|
|
179
|
+
this.queryEmitters.get(collection.name)?.setMaxListeners(Infinity);
|
|
165
180
|
this.activeQueries.set(collection.name, this.activeQueries.get(collection.name) || /* @__PURE__ */ new Map());
|
|
166
181
|
this.indices.set(collection.name, indices.map((field) => createIndex(field)));
|
|
167
182
|
this.rebuildIndices(collection);
|
|
@@ -207,7 +222,7 @@ class DefaultDataAdapter {
|
|
|
207
222
|
},
|
|
208
223
|
updateMany: async (selector, modifier) => {
|
|
209
224
|
const { $setOnInsert, ...restModifier } = modifier;
|
|
210
|
-
const items =
|
|
225
|
+
const items = this.executeQuery(collection, selector, {});
|
|
211
226
|
const changedItems = items.map((item) => {
|
|
212
227
|
const modifiedItem = modify(deepClone.default(item), restModifier);
|
|
213
228
|
const hasItemWithSameId = item.id !== modifiedItem.id && this.getItem(collection, { id: modifiedItem.id }) != null;
|
|
@@ -263,7 +278,7 @@ class DefaultDataAdapter {
|
|
|
263
278
|
return [item];
|
|
264
279
|
},
|
|
265
280
|
removeMany: async (selector) => {
|
|
266
|
-
const items = backend.getQueryResult(selector);
|
|
281
|
+
const items = backend.getQueryResult(selector, {});
|
|
267
282
|
items.forEach((item) => {
|
|
268
283
|
this.items.get(collection.name)?.delete(serializeValue(item.id));
|
|
269
284
|
});
|
|
@@ -283,10 +298,7 @@ class DefaultDataAdapter {
|
|
|
283
298
|
selector,
|
|
284
299
|
options
|
|
285
300
|
});
|
|
286
|
-
|
|
287
|
-
if (!emitter)
|
|
288
|
-
throw new Error(`Query emitter not found for collection ${collection.name}`);
|
|
289
|
-
emitter.emit("change", selector, options, "complete");
|
|
301
|
+
this.executeAndCacheQuery(collection, selector, options);
|
|
290
302
|
},
|
|
291
303
|
unregisterQuery: (selector, options) => {
|
|
292
304
|
if (!this.activeQueries.get(collection.name))
|
|
@@ -299,7 +311,7 @@ class DefaultDataAdapter {
|
|
|
299
311
|
if (!emitter)
|
|
300
312
|
throw new Error(`Query emitter not found for collection ${collection.name}`);
|
|
301
313
|
const handler = (querySelector, queryOptions, state) => {
|
|
302
|
-
if (querySelector !== selector
|
|
314
|
+
if (queryId(querySelector, queryOptions) !== queryId(selector, options))
|
|
303
315
|
return;
|
|
304
316
|
callback(state);
|
|
305
317
|
};
|
|
@@ -310,14 +322,16 @@ class DefaultDataAdapter {
|
|
|
310
322
|
},
|
|
311
323
|
getQueryError: () => null,
|
|
312
324
|
getQueryResult: (selector, options) => {
|
|
313
|
-
const result = this.executeQuery(collection, selector, options);
|
|
314
325
|
const isQueryActive = this.activeQueries.get(collection.name)?.has(queryId(selector, options));
|
|
315
326
|
if (isQueryActive) {
|
|
316
|
-
|
|
317
|
-
|
|
327
|
+
const results = this.cachedQueryResults.get(collection.name)?.get(queryId(selector, options));
|
|
328
|
+
if (!results)
|
|
329
|
+
throw new Error("Cached query results are not defined!");
|
|
330
|
+
return results;
|
|
318
331
|
}
|
|
319
|
-
return
|
|
332
|
+
return this.executeQuery(collection, selector, options);
|
|
320
333
|
},
|
|
334
|
+
executeQuery: (selector, options) => Promise.resolve(this.executeQuery(collection, selector, options)),
|
|
321
335
|
// lifecycle methods
|
|
322
336
|
dispose: async () => {
|
|
323
337
|
const adapter = this.storageAdapters.get(collection.name);
|
package/dist/index.cjs13.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const deepClone = require("./index.cjs19.js");
|
|
3
|
-
const match = require("./index.
|
|
3
|
+
const match = require("./index.cjs23.js");
|
|
4
4
|
const modify = require("./index.cjs7.js");
|
|
5
|
-
const queryId = require("./index.
|
|
5
|
+
const queryId = require("./index.cjs20.js");
|
|
6
6
|
const isEqual = require("./index.cjs6.js");
|
|
7
|
-
const getIndexInfo = require("./index.
|
|
7
|
+
const getIndexInfo = require("./index.cjs22.js");
|
|
8
8
|
const getMatchingKeys = require("./index.cjs26.js");
|
|
9
9
|
const sortItems = require("./index.cjs25.js");
|
|
10
|
-
const project = require("./index.
|
|
10
|
+
const project = require("./index.cjs24.js");
|
|
11
11
|
class AsyncDataAdapter {
|
|
12
12
|
options;
|
|
13
13
|
id;
|
|
@@ -120,6 +120,13 @@ class AsyncDataAdapter {
|
|
|
120
120
|
getQueryError,
|
|
121
121
|
getQueryResult,
|
|
122
122
|
onQueryStateChange,
|
|
123
|
+
executeQuery: async (selector, options) => {
|
|
124
|
+
await ready;
|
|
125
|
+
registerQuery(selector, options);
|
|
126
|
+
const result = getQueryResult(selector, options);
|
|
127
|
+
unregisterQuery(selector, options);
|
|
128
|
+
return result;
|
|
129
|
+
},
|
|
123
130
|
dispose: async () => {
|
|
124
131
|
this.storageAdapters.delete(collection.name);
|
|
125
132
|
this.queries.delete(collection.name);
|
|
@@ -135,11 +142,8 @@ class AsyncDataAdapter {
|
|
|
135
142
|
const storage = this.storageAdapters.get(collectionName);
|
|
136
143
|
if (!storage)
|
|
137
144
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
138
|
-
await Promise.all([
|
|
139
|
-
storage.createIndex("id"),
|
|
140
|
-
...indices.map((index) => storage.createIndex(index))
|
|
141
|
-
]);
|
|
142
145
|
await storage.setup();
|
|
146
|
+
await Promise.all(indices.map((index) => storage.createIndex(index)));
|
|
143
147
|
}
|
|
144
148
|
ensureStorageAdapter(name) {
|
|
145
149
|
if (this.storageAdapters.has(name))
|
|
@@ -200,20 +204,28 @@ class AsyncDataAdapter {
|
|
|
200
204
|
rec.items = items;
|
|
201
205
|
}
|
|
202
206
|
async getIndexInfo(collectionName, selector) {
|
|
203
|
-
const
|
|
204
|
-
if (!
|
|
207
|
+
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
208
|
+
if (!storageAdapter)
|
|
205
209
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
206
210
|
if (selector != null && Object.keys(selector).length === 1 && "id" in selector && typeof selector.id !== "object") {
|
|
207
|
-
return {
|
|
211
|
+
return {
|
|
212
|
+
matched: true,
|
|
213
|
+
ids: [selector.id].filter(Boolean),
|
|
214
|
+
optimizedSelector: {}
|
|
215
|
+
};
|
|
208
216
|
}
|
|
209
217
|
if (selector == null) {
|
|
210
|
-
return {
|
|
218
|
+
return {
|
|
219
|
+
matched: false,
|
|
220
|
+
ids: [],
|
|
221
|
+
optimizedSelector: {}
|
|
222
|
+
};
|
|
211
223
|
}
|
|
212
224
|
const indices = this.collectionIndices.get(collectionName) ?? [];
|
|
213
225
|
return getIndexInfo.default(indices.map((field) => async (flatSelector) => {
|
|
214
226
|
if (!Object.hasOwnProperty.call(flatSelector, field))
|
|
215
227
|
return { matched: false };
|
|
216
|
-
const index = await
|
|
228
|
+
const index = await storageAdapter.readIndex(field);
|
|
217
229
|
const fieldSelector = flatSelector[field];
|
|
218
230
|
const filtersForNull = fieldSelector == null || fieldSelector.$exists === false;
|
|
219
231
|
const keys = filtersForNull ? { include: null, exclude: [...index.keys()].filter((key) => key != null) } : getMatchingKeys(field, flatSelector);
|
|
@@ -315,8 +327,8 @@ class AsyncDataAdapter {
|
|
|
315
327
|
const storage = this.storageAdapters.get(collectionName);
|
|
316
328
|
if (!storage)
|
|
317
329
|
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
318
|
-
const
|
|
319
|
-
if (
|
|
330
|
+
const existingItems = await storage.readIds([newItem.id]);
|
|
331
|
+
if (existingItems.length > 0)
|
|
320
332
|
throw new Error(`Item with id ${String(newItem.id)} already exists`);
|
|
321
333
|
await storage.insert([newItem]);
|
|
322
334
|
await this.checkQueryUpdates(collectionName, [newItem]);
|