@signaldb/svelte 2.0.0-beta.21 → 2.0.0-beta.22
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/package.json +3 -3
- package/dist/base/core/src/AsyncDataAdapter.d.ts +0 -112
- package/dist/base/core/src/AsyncDataAdapter.js +0 -549
- package/dist/base/core/src/AutoFetchDataAdapter.d.ts +0 -112
- package/dist/base/core/src/AutoFetchDataAdapter.js +0 -612
- package/dist/base/core/src/Collection/Cursor.d.ts +0 -165
- package/dist/base/core/src/Collection/Cursor.js +0 -352
- package/dist/base/core/src/Collection/Observer.d.ts +0 -95
- package/dist/base/core/src/Collection/Observer.js +0 -227
- package/dist/base/core/src/Collection/index.d.ts +0 -341
- package/dist/base/core/src/Collection/index.js +0 -761
- package/dist/base/core/src/Collection/types.d.ts +0 -28
- package/dist/base/core/src/Collection/types.js +0 -2
- package/dist/base/core/src/DataAdapter.d.ts +0 -54
- package/dist/base/core/src/DataAdapter.js +0 -2
- package/dist/base/core/src/DefaultDataAdapter.d.ts +0 -35
- package/dist/base/core/src/DefaultDataAdapter.js +0 -408
- package/dist/base/core/src/WorkerDataAdapter.d.ts +0 -79
- package/dist/base/core/src/WorkerDataAdapter.js +0 -749
- package/dist/base/core/src/WorkerDataAdapterHost.d.ts +0 -64
- package/dist/base/core/src/WorkerDataAdapterHost.js +0 -430
- package/dist/base/core/src/createIndex.d.ts +0 -7
- package/dist/base/core/src/createIndex.js +0 -120
- package/dist/base/core/src/createIndexProvider.d.ts +0 -8
- package/dist/base/core/src/createIndexProvider.js +0 -11
- package/dist/base/core/src/createReactivityAdapter.d.ts +0 -8
- package/dist/base/core/src/createReactivityAdapter.js +0 -11
- package/dist/base/core/src/createStorageAdapter.d.ts +0 -9
- package/dist/base/core/src/createStorageAdapter.js +0 -11
- package/dist/base/core/src/getIndexInfo.d.ts +0 -39
- package/dist/base/core/src/getIndexInfo.js +0 -188
- package/dist/base/core/src/index.d.ts +0 -26
- package/dist/base/core/src/index.js +0 -39
- package/dist/base/core/src/types/Dependency.d.ts +0 -4
- package/dist/base/core/src/types/Dependency.js +0 -2
- package/dist/base/core/src/types/IndexProvider.d.ts +0 -26
- package/dist/base/core/src/types/IndexProvider.js +0 -2
- package/dist/base/core/src/types/Modifier.d.ts +0 -46
- package/dist/base/core/src/types/Modifier.js +0 -3
- package/dist/base/core/src/types/ReactivityAdapter.d.ts +0 -6
- package/dist/base/core/src/types/ReactivityAdapter.js +0 -2
- package/dist/base/core/src/types/Selector.d.ts +0 -46
- package/dist/base/core/src/types/Selector.js +0 -3
- package/dist/base/core/src/types/Signal.d.ts +0 -4
- package/dist/base/core/src/types/Signal.js +0 -2
- package/dist/base/core/src/types/StorageAdapter.d.ts +0 -28
- package/dist/base/core/src/types/StorageAdapter.js +0 -2
- package/dist/base/core/src/utils/EventEmitter.d.ts +0 -71
- package/dist/base/core/src/utils/EventEmitter.js +0 -144
- package/dist/base/core/src/utils/applyQueryOptions.d.ts +0 -15
- package/dist/base/core/src/utils/applyQueryOptions.js +0 -36
- package/dist/base/core/src/utils/batchOnNextTick.d.ts +0 -16
- package/dist/base/core/src/utils/batchOnNextTick.js +0 -72
- package/dist/base/core/src/utils/compact.d.ts +0 -9
- package/dist/base/core/src/utils/compact.js +0 -21
- package/dist/base/core/src/utils/createSignal.d.ts +0 -14
- package/dist/base/core/src/utils/createSignal.js +0 -38
- package/dist/base/core/src/utils/deepClone.d.ts +0 -17
- package/dist/base/core/src/utils/deepClone.js +0 -68
- package/dist/base/core/src/utils/get.d.ts +0 -9
- package/dist/base/core/src/utils/get.js +0 -27
- package/dist/base/core/src/utils/getMatchingKeys.d.ts +0 -19
- package/dist/base/core/src/utils/getMatchingKeys.js +0 -49
- package/dist/base/core/src/utils/idIndexQuery.d.ts +0 -20
- package/dist/base/core/src/utils/idIndexQuery.js +0 -49
- package/dist/base/core/src/utils/incrementalQueryUpdate.d.ts +0 -62
- package/dist/base/core/src/utils/incrementalQueryUpdate.js +0 -197
- package/dist/base/core/src/utils/intersection.d.ts +0 -9
- package/dist/base/core/src/utils/intersection.js +0 -16
- package/dist/base/core/src/utils/isEqual.d.ts +0 -14
- package/dist/base/core/src/utils/isEqual.js +0 -43
- package/dist/base/core/src/utils/isFieldExpression.d.ts +0 -11
- package/dist/base/core/src/utils/isFieldExpression.js +0 -52
- package/dist/base/core/src/utils/match.d.ts +0 -12
- package/dist/base/core/src/utils/match.js +0 -16
- package/dist/base/core/src/utils/modify.d.ts +0 -14
- package/dist/base/core/src/utils/modify.js +0 -29
- package/dist/base/core/src/utils/project.d.ts +0 -15
- package/dist/base/core/src/utils/project.js +0 -43
- package/dist/base/core/src/utils/projectItems.d.ts +0 -12
- package/dist/base/core/src/utils/projectItems.js +0 -25
- package/dist/base/core/src/utils/queryDelta.d.ts +0 -83
- package/dist/base/core/src/utils/queryDelta.js +0 -231
- package/dist/base/core/src/utils/queryId.d.ts +0 -9
- package/dist/base/core/src/utils/queryId.js +0 -61
- package/dist/base/core/src/utils/randomId.d.ts +0 -7
- package/dist/base/core/src/utils/randomId.js +0 -12
- package/dist/base/core/src/utils/reactiveOrAsync.d.ts +0 -59
- package/dist/base/core/src/utils/reactiveOrAsync.js +0 -93
- package/dist/base/core/src/utils/serializeValue.d.ts +0 -12
- package/dist/base/core/src/utils/serializeValue.js +0 -27
- package/dist/base/core/src/utils/set.d.ts +0 -13
- package/dist/base/core/src/utils/set.js +0 -43
- package/dist/base/core/src/utils/sortItems.d.ts +0 -12
- package/dist/base/core/src/utils/sortItems.js +0 -23
- package/dist/base/core/src/utils/storageIndexQuery.d.ts +0 -20
- package/dist/base/core/src/utils/storageIndexQuery.js +0 -75
- package/dist/base/core/src/utils/uniqueBy.d.ts +0 -10
- package/dist/base/core/src/utils/uniqueBy.js +0 -19
- package/dist/index.cjs +0 -38
- package/dist/index.cjs.map +0 -1
- package/dist/index.mjs +0 -38
- package/dist/index.mjs.map +0 -1
- package/dist/reactivity-adapters/svelte/index.svelte.d.ts +0 -10
- package/dist/reactivity-adapters/svelte/index.svelte.js +0 -36
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import type { BaseItem } from './Collection';
|
|
2
|
-
import type { QueryOptions } from './DataAdapter';
|
|
3
|
-
import type Modifier from './types/Modifier';
|
|
4
|
-
import type StorageAdapter from './types/StorageAdapter';
|
|
5
|
-
import type Selector from './types/Selector';
|
|
6
|
-
export interface WorkerDataAdapterHostEndpoint {
|
|
7
|
-
addEventListener: (type: 'message', listener: (event: MessageEvent) => any) => void;
|
|
8
|
-
postMessage: (message: any) => void;
|
|
9
|
-
}
|
|
10
|
-
interface WorkerDataAdapterHostOptions {
|
|
11
|
-
id?: string;
|
|
12
|
-
storage: (name: string) => StorageAdapter<any, any>;
|
|
13
|
-
onError?: (error: Error) => void;
|
|
14
|
-
log?: (message: string, ...args: any[]) => void;
|
|
15
|
-
}
|
|
16
|
-
type CollectionMethods<T extends BaseItem<I>, I = any> = {
|
|
17
|
-
registerCollection: (collectionName: string, indices: string[]) => Promise<void>;
|
|
18
|
-
unregisterCollection: (collectionName: string) => Promise<void>;
|
|
19
|
-
registerQuery: <O extends QueryOptions<T>>(collectionName: string, selector: Selector<T>, options?: O) => Promise<void>;
|
|
20
|
-
unregisterQuery: <O extends QueryOptions<T>>(collectionName: string, selector: Selector<T>, options?: O) => Promise<void>;
|
|
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)[]>;
|
|
28
|
-
isReady: (collectionName: string) => Promise<void>;
|
|
29
|
-
};
|
|
30
|
-
export default class WorkerDataAdapterHost<T extends BaseItem<I>, I = any> {
|
|
31
|
-
private workerContext;
|
|
32
|
-
private options;
|
|
33
|
-
private id;
|
|
34
|
-
private log;
|
|
35
|
-
private storageAdapters;
|
|
36
|
-
private storageAdapterReady;
|
|
37
|
-
private collectionIndices;
|
|
38
|
-
private queries;
|
|
39
|
-
private onError;
|
|
40
|
-
constructor(workerContext: WorkerDataAdapterHostEndpoint, options: WorkerDataAdapterHostOptions);
|
|
41
|
-
private respond;
|
|
42
|
-
private handleMessage;
|
|
43
|
-
private getIndexInfo;
|
|
44
|
-
private queryItems;
|
|
45
|
-
private executeQuery;
|
|
46
|
-
private ensureQuery;
|
|
47
|
-
private setQueryItems;
|
|
48
|
-
private queryItemIds;
|
|
49
|
-
private emitQueryUpdate;
|
|
50
|
-
private ensureStorageAdapter;
|
|
51
|
-
private checkQueryUpdates;
|
|
52
|
-
protected registerCollection: CollectionMethods<T, I>['registerCollection'];
|
|
53
|
-
protected unregisterCollection: CollectionMethods<T, I>['unregisterCollection'];
|
|
54
|
-
protected registerQuery: CollectionMethods<T, I>['registerQuery'];
|
|
55
|
-
protected unregisterQuery: CollectionMethods<T, I>['unregisterQuery'];
|
|
56
|
-
protected insert: CollectionMethods<T, I>['insert'];
|
|
57
|
-
protected updateOne: CollectionMethods<T, I>['updateOne'];
|
|
58
|
-
protected updateMany: CollectionMethods<T, I>['updateMany'];
|
|
59
|
-
protected replaceOne: CollectionMethods<T, I>['replaceOne'];
|
|
60
|
-
protected removeOne: CollectionMethods<T, I>['removeOne'];
|
|
61
|
-
protected removeMany: CollectionMethods<T, I>['removeMany'];
|
|
62
|
-
protected isReady: CollectionMethods<T, I>['isReady'];
|
|
63
|
-
}
|
|
64
|
-
export {};
|
|
@@ -1,430 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const deepClone_1 = __importDefault(require("./utils/deepClone"));
|
|
7
|
-
const match_1 = __importDefault(require("./utils/match"));
|
|
8
|
-
const modify_1 = __importDefault(require("./utils/modify"));
|
|
9
|
-
const queryId_1 = __importDefault(require("./utils/queryId"));
|
|
10
|
-
const isEqual_1 = __importDefault(require("./utils/isEqual"));
|
|
11
|
-
const getIndexInfo_1 = __importDefault(require("./getIndexInfo"));
|
|
12
|
-
const idIndexQuery_1 = __importDefault(require("./utils/idIndexQuery"));
|
|
13
|
-
const storageIndexQuery_1 = __importDefault(require("./utils/storageIndexQuery"));
|
|
14
|
-
const sortItems_1 = __importDefault(require("./utils/sortItems"));
|
|
15
|
-
const projectItems_1 = __importDefault(require("./utils/projectItems"));
|
|
16
|
-
const compact_1 = __importDefault(require("./utils/compact"));
|
|
17
|
-
const incrementalQueryUpdate_1 = __importDefault(require("./utils/incrementalQueryUpdate"));
|
|
18
|
-
const queryDelta_1 = require("./utils/queryDelta");
|
|
19
|
-
/**
|
|
20
|
-
* Turns the item states a write produced into the upsert/delete split a query update needs.
|
|
21
|
-
*
|
|
22
|
-
* The two lists are not symmetric: an item that is still there after the write is described by
|
|
23
|
-
* its new state, while an item that is gone — removed, or given a new id — is described by the id
|
|
24
|
-
* it used to have and nothing else. Mixing the states from before and after a write into one list
|
|
25
|
-
* loses exactly that distinction.
|
|
26
|
-
* @template T - The type of the items.
|
|
27
|
-
* @param previousItems - The items as they were before the write.
|
|
28
|
-
* @param modifiedItems - The items as they are after it.
|
|
29
|
-
* @returns The changeset describing the write.
|
|
30
|
-
*/
|
|
31
|
-
function toChangeset(previousItems, modifiedItems) {
|
|
32
|
-
const modifiedIds = new Set(modifiedItems.map(item => item.id));
|
|
33
|
-
return {
|
|
34
|
-
upserts: modifiedItems,
|
|
35
|
-
deletes: previousItems
|
|
36
|
-
.map(item => item.id)
|
|
37
|
-
.filter(id => !modifiedIds.has(id)),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
class WorkerDataAdapterHost {
|
|
41
|
-
workerContext;
|
|
42
|
-
options;
|
|
43
|
-
id;
|
|
44
|
-
log = () => { };
|
|
45
|
-
storageAdapters = new Map();
|
|
46
|
-
storageAdapterReady = new Map();
|
|
47
|
-
collectionIndices = new Map();
|
|
48
|
-
queries = new Map();
|
|
49
|
-
onError = (error) => {
|
|
50
|
-
// eslint-disable-next-line no-console
|
|
51
|
-
console.error(error);
|
|
52
|
-
};
|
|
53
|
-
constructor(workerContext, options) {
|
|
54
|
-
this.workerContext = workerContext;
|
|
55
|
-
this.options = options;
|
|
56
|
-
this.id = this.options.id || 'default-worker-data-adapter';
|
|
57
|
-
if (this.options.onError) {
|
|
58
|
-
this.onError = this.options.onError;
|
|
59
|
-
}
|
|
60
|
-
if (this.options.log)
|
|
61
|
-
this.log = this.options.log;
|
|
62
|
-
this.workerContext.addEventListener('message', async (event) => {
|
|
63
|
-
try {
|
|
64
|
-
const { workerId, id, method, args } = event.data;
|
|
65
|
-
await this.handleMessage(workerId, id, method, args);
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
this.onError(error);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
this.respond('ready', null, null, 'ready');
|
|
72
|
-
}
|
|
73
|
-
respond(id, data, error = null, type = 'response') {
|
|
74
|
-
this.workerContext.postMessage({ id, workerId: this.id, type, data, error });
|
|
75
|
-
}
|
|
76
|
-
async handleMessage(workerId, id, method, args) {
|
|
77
|
-
if (workerId !== this.id)
|
|
78
|
-
return;
|
|
79
|
-
const fn = this[method];
|
|
80
|
-
if (typeof fn !== 'function') {
|
|
81
|
-
this.respond(id, null, new Error(`Method ${method} not found`));
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
85
|
-
this.log(method, ...args);
|
|
86
|
-
// wait for the storage adapter to be ready
|
|
87
|
-
await this.isReady(args[0]);
|
|
88
|
-
try {
|
|
89
|
-
const result = await fn.apply(this, args);
|
|
90
|
-
this.respond(id, result);
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
this.respond(id, null, error);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
async getIndexInfo(collectionName, selector) {
|
|
97
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
98
|
-
if (!storageAdapter)
|
|
99
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
100
|
-
// `id` needs no declared index: `readIds` is exactly the lookup it
|
|
101
|
-
// describes, so every inclusive form of it is answered here rather than by
|
|
102
|
-
// reading the whole collection (utils/idIndexQuery.ts).
|
|
103
|
-
if (selector != null && Object.keys(selector).length === 1 && 'id' in selector) {
|
|
104
|
-
const idResult = (0, idIndexQuery_1.default)(selector);
|
|
105
|
-
if (idResult.matched) {
|
|
106
|
-
return {
|
|
107
|
-
matched: true,
|
|
108
|
-
ids: (0, compact_1.default)(idResult.ids),
|
|
109
|
-
optimizedSelector: {},
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (selector == null) {
|
|
114
|
-
return {
|
|
115
|
-
matched: false,
|
|
116
|
-
ids: [],
|
|
117
|
-
optimizedSelector: {},
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
const indices = this.collectionIndices.get(collectionName) ?? [];
|
|
121
|
-
// `id` first, and always present: it needs no declared index, because
|
|
122
|
-
// `readIds` is exactly the lookup it describes (utils/idIndexQuery.ts).
|
|
123
|
-
return (0, getIndexInfo_1.default)(indices.map(field => (0, storageIndexQuery_1.default)(storageAdapter, field)), selector);
|
|
124
|
-
}
|
|
125
|
-
async queryItems(collectionName, selector) {
|
|
126
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
127
|
-
if (!storageAdapter)
|
|
128
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
129
|
-
const indexInfo = await this.getIndexInfo(collectionName, selector);
|
|
130
|
-
const matchItems = (item) => {
|
|
131
|
-
if (indexInfo.optimizedSelector == null)
|
|
132
|
-
return true; // if no selector is given, return all items
|
|
133
|
-
if (Object.keys(indexInfo.optimizedSelector).length <= 0)
|
|
134
|
-
return true; // if selector is empty, return all items
|
|
135
|
-
const matches = (0, match_1.default)(item, indexInfo.optimizedSelector);
|
|
136
|
-
return matches;
|
|
137
|
-
};
|
|
138
|
-
if (indexInfo.matched) {
|
|
139
|
-
const items = await storageAdapter.readIds(indexInfo.ids);
|
|
140
|
-
if ((0, isEqual_1.default)(indexInfo.optimizedSelector, {}))
|
|
141
|
-
return items;
|
|
142
|
-
return items.filter(matchItems);
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
const allItems = await storageAdapter.readAll();
|
|
146
|
-
if ((0, isEqual_1.default)(selector, {}))
|
|
147
|
-
return allItems;
|
|
148
|
-
return allItems.filter(matchItems);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
async executeQuery(collectionName, selector, options) {
|
|
152
|
-
// null selector means no matches
|
|
153
|
-
if (selector === null)
|
|
154
|
-
return [];
|
|
155
|
-
const items = await this.queryItems(collectionName, selector || {});
|
|
156
|
-
const { sort, skip, limit, fields } = options || {};
|
|
157
|
-
const sorted = sort ? (0, sortItems_1.default)(items, sort) : items;
|
|
158
|
-
const skipped = skip ? sorted.slice(skip) : sorted;
|
|
159
|
-
const limited = limit ? skipped.slice(0, limit) : skipped;
|
|
160
|
-
return (0, projectItems_1.default)(limited, fields);
|
|
161
|
-
}
|
|
162
|
-
ensureQuery(collectionName, selector, options) {
|
|
163
|
-
const id = (0, queryId_1.default)(selector, options);
|
|
164
|
-
if (!this.queries.get(collectionName)) {
|
|
165
|
-
throw new Error(`Collection ${collectionName} not initialized!`);
|
|
166
|
-
}
|
|
167
|
-
let query = this.queries.get(collectionName)?.get(id);
|
|
168
|
-
if (!query) {
|
|
169
|
-
query = { selector, options, items: null };
|
|
170
|
-
this.queries.get(collectionName)?.set(id, query);
|
|
171
|
-
}
|
|
172
|
-
return query;
|
|
173
|
-
}
|
|
174
|
-
setQueryItems(query, items) {
|
|
175
|
-
query.items = items;
|
|
176
|
-
query.itemIds = undefined;
|
|
177
|
-
}
|
|
178
|
-
queryItemIds(query) {
|
|
179
|
-
if (!query.itemIds)
|
|
180
|
-
query.itemIds = new Set((query.items ?? []).map(item => item.id));
|
|
181
|
-
return query.itemIds;
|
|
182
|
-
}
|
|
183
|
-
emitQueryUpdate(collectionName, selector, options, state, error, items, delta) {
|
|
184
|
-
const id = (0, queryId_1.default)(selector, options);
|
|
185
|
-
const collectionQueries = this.queries.get(collectionName);
|
|
186
|
-
if (!collectionQueries)
|
|
187
|
-
throw new Error(`Collection ${collectionName} not initialized!`);
|
|
188
|
-
// `qid` is what the adapter routes on. It is derived from the same selector/options pair the
|
|
189
|
-
// adapter registered the query with, so sending it saves every recipient from re-deriving it.
|
|
190
|
-
//
|
|
191
|
-
// `items` and `delta` are alternatives: the first answer to a query carries the whole result
|
|
192
|
-
// because the recipient holds nothing yet, every answer after it carries only what changed.
|
|
193
|
-
// Everything in this message is structurally cloned on its way out of the worker, which is why
|
|
194
|
-
// it matters that editing one field of one row no longer costs a copy of the entire result.
|
|
195
|
-
this.respond(id, { collectionName, qid: id, selector, options, state, error, items, delta }, null, 'queryUpdate');
|
|
196
|
-
}
|
|
197
|
-
ensureStorageAdapter(name) {
|
|
198
|
-
if (this.storageAdapters.has(name))
|
|
199
|
-
return; // already created
|
|
200
|
-
const adapter = this.options.storage(name);
|
|
201
|
-
if (!adapter)
|
|
202
|
-
return; // no adapter returned
|
|
203
|
-
this.storageAdapters.set(name, adapter);
|
|
204
|
-
}
|
|
205
|
-
async checkQueryUpdates(collectionName, changes) {
|
|
206
|
-
const queries = this.queries.get(collectionName);
|
|
207
|
-
if (!queries)
|
|
208
|
-
throw new Error(`Collection ${collectionName} not initialized!`);
|
|
209
|
-
if (changes.upserts.length === 0 && changes.deletes.length === 0)
|
|
210
|
-
return;
|
|
211
|
-
// A query is affected when the write produces something it should hold, or takes away
|
|
212
|
-
// something it already holds. The second half is what the write itself cannot tell us: an
|
|
213
|
-
// item that no longer matches, or that was removed outright, is invisible to the matcher.
|
|
214
|
-
const affectedQueries = [...queries.values()].filter((query) => {
|
|
215
|
-
const ids = this.queryItemIds(query);
|
|
216
|
-
if (changes.deletes.some(id => ids.has(id)))
|
|
217
|
-
return true;
|
|
218
|
-
return changes.upserts.some(item => ids.has(item.id) || (0, match_1.default)(item, query.selector));
|
|
219
|
-
});
|
|
220
|
-
if (affectedQueries.length === 0)
|
|
221
|
-
return; // no active queries affected
|
|
222
|
-
await Promise.all(affectedQueries.map(async (query) => {
|
|
223
|
-
const { selector, options } = query;
|
|
224
|
-
const previous = query.items;
|
|
225
|
-
const incremental = previous == null
|
|
226
|
-
? null
|
|
227
|
-
: (0, incrementalQueryUpdate_1.default)(previous, selector, options, changes);
|
|
228
|
-
if (incremental != null) {
|
|
229
|
-
// Answered from the previous result, without touching the store — so there is no window in
|
|
230
|
-
// which the query is stale, and nothing to announce with an `'active'` state either.
|
|
231
|
-
const delta = (0, queryDelta_1.diffQueryResults)(previous, incremental);
|
|
232
|
-
if ((0, queryDelta_1.isEmptyQueryDelta)(delta))
|
|
233
|
-
return;
|
|
234
|
-
this.setQueryItems(query, incremental);
|
|
235
|
-
this.emitQueryUpdate(collectionName, selector, options, 'complete', null, undefined, delta);
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
this.emitQueryUpdate(collectionName, selector, options, 'active', null);
|
|
239
|
-
const queryItems = await this.executeQuery(collectionName, selector, options);
|
|
240
|
-
if (previous == null) {
|
|
241
|
-
this.setQueryItems(query, queryItems);
|
|
242
|
-
this.emitQueryUpdate(collectionName, selector, options, 'complete', null, queryItems);
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
const delta = (0, queryDelta_1.diffQueryResults)(previous, queryItems);
|
|
246
|
-
this.setQueryItems(query, queryItems);
|
|
247
|
-
this.emitQueryUpdate(collectionName, selector, options, 'complete', null, undefined, delta);
|
|
248
|
-
}));
|
|
249
|
-
}
|
|
250
|
-
registerCollection = async (collectionName, indices) => {
|
|
251
|
-
this.collectionIndices.set(collectionName, indices);
|
|
252
|
-
this.queries.set(collectionName, new Map());
|
|
253
|
-
this.ensureStorageAdapter(collectionName);
|
|
254
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
255
|
-
if (!storageAdapter)
|
|
256
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
257
|
-
const setupPromise = (async () => {
|
|
258
|
-
await storageAdapter.setup();
|
|
259
|
-
await Promise.all(indices.map(index => storageAdapter.createIndex(index)));
|
|
260
|
-
})();
|
|
261
|
-
this.storageAdapterReady.set(collectionName, setupPromise);
|
|
262
|
-
await setupPromise;
|
|
263
|
-
};
|
|
264
|
-
unregisterCollection = async (collectionName) => {
|
|
265
|
-
this.storageAdapters.delete(collectionName);
|
|
266
|
-
this.queries.delete(collectionName);
|
|
267
|
-
};
|
|
268
|
-
registerQuery = async (collectionName, selector, options) => {
|
|
269
|
-
const query = this.ensureQuery(collectionName, selector, options);
|
|
270
|
-
const queryItems = await this.executeQuery(collectionName, selector, options);
|
|
271
|
-
// Always the full result, even for a query that is already registered: whoever is registering
|
|
272
|
-
// holds nothing for it yet, and a delta would be relative to a result only the host has seen.
|
|
273
|
-
this.setQueryItems(query, queryItems);
|
|
274
|
-
this.emitQueryUpdate(collectionName, selector, options, 'complete', null, queryItems);
|
|
275
|
-
};
|
|
276
|
-
unregisterQuery = async (collectionName, selector, options) => {
|
|
277
|
-
const id = (0, queryId_1.default)(selector, options);
|
|
278
|
-
if (!this.queries.get(collectionName))
|
|
279
|
-
throw new Error(`Collection ${collectionName} not initialized!`);
|
|
280
|
-
this.queries.get(collectionName)?.delete(id);
|
|
281
|
-
};
|
|
282
|
-
insert = async (collectionName, input) => {
|
|
283
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
284
|
-
if (!storageAdapter)
|
|
285
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
286
|
-
const existingItems = await this.executeQuery(collectionName, { id: { $in: input.map(i => i[0].id) } });
|
|
287
|
-
const result = input.map(([item]) => {
|
|
288
|
-
if (item.id == null)
|
|
289
|
-
return new Error('Item must have an id');
|
|
290
|
-
if (existingItems.some(existing => existing.id === item.id)) {
|
|
291
|
-
return new Error(`Item with id ${item.id} already exists`);
|
|
292
|
-
}
|
|
293
|
-
return item;
|
|
294
|
-
});
|
|
295
|
-
const newItems = result.filter(item => !(item instanceof Error));
|
|
296
|
-
await storageAdapter.insert(newItems);
|
|
297
|
-
await this.checkQueryUpdates(collectionName, { upserts: newItems, deletes: [] });
|
|
298
|
-
return result;
|
|
299
|
-
};
|
|
300
|
-
updateOne = async (collectionName, parameters) => {
|
|
301
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
302
|
-
if (!storageAdapter)
|
|
303
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
304
|
-
const previousItems = [];
|
|
305
|
-
const result = await Promise.all(parameters.map(async ([selector, modifier]) => {
|
|
306
|
-
const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then(items => items[0] ?? null);
|
|
307
|
-
const { $setOnInsert, ...restModifier } = modifier;
|
|
308
|
-
if (item == null)
|
|
309
|
-
return [];
|
|
310
|
-
previousItems.push(item);
|
|
311
|
-
const modifiedItem = (0, modify_1.default)((0, deepClone_1.default)(item), restModifier);
|
|
312
|
-
if (item.id !== modifiedItem.id) {
|
|
313
|
-
const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
|
|
314
|
-
if (existingItems.length > 0) {
|
|
315
|
-
return new Error(`Item with id ${modifiedItem.id} already exists`);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return [modifiedItem];
|
|
319
|
-
}));
|
|
320
|
-
const modifiedItems = (0, compact_1.default)(result.filter(item => !(item instanceof Error)).flat());
|
|
321
|
-
if (modifiedItems.length > 0) {
|
|
322
|
-
await storageAdapter.replace(modifiedItems);
|
|
323
|
-
await this.checkQueryUpdates(collectionName, toChangeset(previousItems, modifiedItems));
|
|
324
|
-
}
|
|
325
|
-
return result;
|
|
326
|
-
};
|
|
327
|
-
updateMany = async (collectionName, parameters) => {
|
|
328
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
329
|
-
if (!storageAdapter)
|
|
330
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
331
|
-
const previousItems = [];
|
|
332
|
-
const result = await Promise.all(parameters.map(async ([selector, modifier]) => {
|
|
333
|
-
const items = await this.executeQuery(collectionName, selector);
|
|
334
|
-
if (items.length === 0)
|
|
335
|
-
return []; // no items found, nothing to update
|
|
336
|
-
const { $setOnInsert, ...restModifier } = modifier;
|
|
337
|
-
try {
|
|
338
|
-
const changedItems = await Promise.all(items.map(async (item) => {
|
|
339
|
-
const modifiedItem = (0, modify_1.default)((0, deepClone_1.default)(item), restModifier);
|
|
340
|
-
if (item.id !== modifiedItem.id) {
|
|
341
|
-
const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
|
|
342
|
-
if (existingItems.length > 0) {
|
|
343
|
-
throw new Error(`Item with id ${modifiedItem.id} already exists`);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
previousItems.push(item);
|
|
347
|
-
return modifiedItem;
|
|
348
|
-
}));
|
|
349
|
-
return changedItems;
|
|
350
|
-
}
|
|
351
|
-
catch (error) {
|
|
352
|
-
return error;
|
|
353
|
-
}
|
|
354
|
-
}));
|
|
355
|
-
const modifiedItems = (0, compact_1.default)(result.filter(item => !(item instanceof Error)).flat());
|
|
356
|
-
if (modifiedItems.length > 0) {
|
|
357
|
-
await storageAdapter.replace(modifiedItems);
|
|
358
|
-
await this.checkQueryUpdates(collectionName, toChangeset(previousItems, modifiedItems));
|
|
359
|
-
}
|
|
360
|
-
return result;
|
|
361
|
-
};
|
|
362
|
-
replaceOne = async (collectionName, parameters) => {
|
|
363
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
364
|
-
if (!storageAdapter)
|
|
365
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
366
|
-
const previousItems = [];
|
|
367
|
-
const result = await Promise.all(parameters.map(async ([selector, replacement,]) => {
|
|
368
|
-
const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then(items => items[0] ?? null);
|
|
369
|
-
if (item == null)
|
|
370
|
-
return []; // no item found, nothing to update
|
|
371
|
-
previousItems.push(item);
|
|
372
|
-
const modifiedItem = {
|
|
373
|
-
...replacement,
|
|
374
|
-
id: replacement.id ?? item.id,
|
|
375
|
-
};
|
|
376
|
-
if (item.id !== modifiedItem.id) {
|
|
377
|
-
const existingItems = await this.executeQuery(collectionName, { id: modifiedItem.id }, { limit: 1 });
|
|
378
|
-
if (existingItems.length > 0) {
|
|
379
|
-
return new Error(`Item with id ${modifiedItem.id} already exists`);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
return [modifiedItem];
|
|
383
|
-
}));
|
|
384
|
-
const modifiedItems = (0, compact_1.default)(result.filter(item => !(item instanceof Error)).flat());
|
|
385
|
-
if (modifiedItems.length > 0) {
|
|
386
|
-
await storageAdapter.replace(modifiedItems);
|
|
387
|
-
await this.checkQueryUpdates(collectionName, toChangeset(previousItems, modifiedItems));
|
|
388
|
-
}
|
|
389
|
-
return result;
|
|
390
|
-
};
|
|
391
|
-
removeOne = async (collectionName, selectors) => {
|
|
392
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
393
|
-
if (!storageAdapter)
|
|
394
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
395
|
-
const result = await Promise.all(selectors.map(async ([selector]) => {
|
|
396
|
-
const item = await this.executeQuery(collectionName, selector, { limit: 1 }).then(items => items[0] ?? null);
|
|
397
|
-
if (item == null)
|
|
398
|
-
return []; // no item found, nothing to remove
|
|
399
|
-
return [item];
|
|
400
|
-
}));
|
|
401
|
-
const items = result.flat();
|
|
402
|
-
if (items.length > 0) {
|
|
403
|
-
await storageAdapter.remove(items);
|
|
404
|
-
await this.checkQueryUpdates(collectionName, {
|
|
405
|
-
upserts: [],
|
|
406
|
-
deletes: items.map(item => item.id),
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
return result;
|
|
410
|
-
};
|
|
411
|
-
removeMany = async (collectionName, selectors) => {
|
|
412
|
-
const storageAdapter = this.storageAdapters.get(collectionName);
|
|
413
|
-
if (!storageAdapter)
|
|
414
|
-
throw new Error(`No persistence adapter for collection ${collectionName}`);
|
|
415
|
-
const result = await Promise.all(selectors.map(async ([selector]) => this.executeQuery(collectionName, selector)));
|
|
416
|
-
const items = result.flat();
|
|
417
|
-
if (items.length > 0) {
|
|
418
|
-
await storageAdapter.remove(items);
|
|
419
|
-
await this.checkQueryUpdates(collectionName, {
|
|
420
|
-
upserts: [],
|
|
421
|
-
deletes: items.map(item => item.id),
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
return result;
|
|
425
|
-
};
|
|
426
|
-
isReady = async (collectionName) => {
|
|
427
|
-
return this.storageAdapterReady.get(collectionName);
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
exports.default = WorkerDataAdapterHost;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { BaseItem } from './Collection/types';
|
|
2
|
-
/**
|
|
3
|
-
* creates an index for a specific field
|
|
4
|
-
* @param field name of the field
|
|
5
|
-
* @returns an index provider to pass to the `indices` option of the collection constructor
|
|
6
|
-
*/
|
|
7
|
-
export default function createIndex<T extends BaseItem<I> = BaseItem, I = any>(field: string): import("./types/IndexProvider").default<T, I>;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.default = createIndex;
|
|
7
|
-
const createIndexProvider_1 = __importDefault(require("./createIndexProvider"));
|
|
8
|
-
const get_1 = __importDefault(require("./utils/get"));
|
|
9
|
-
const getMatchingKeys_1 = __importDefault(require("./utils/getMatchingKeys"));
|
|
10
|
-
const serializeValue_1 = __importDefault(require("./utils/serializeValue"));
|
|
11
|
-
/**
|
|
12
|
-
* creates an index for a specific field
|
|
13
|
-
* @param field name of the field
|
|
14
|
-
* @returns an index provider to pass to the `indices` option of the collection constructor
|
|
15
|
-
*/
|
|
16
|
-
function createIndex(field) {
|
|
17
|
-
const index = new Map();
|
|
18
|
-
const ensureSet = (key) => {
|
|
19
|
-
let set = index.get(key);
|
|
20
|
-
if (!set) {
|
|
21
|
-
set = new Set();
|
|
22
|
-
index.set(key, set);
|
|
23
|
-
}
|
|
24
|
-
return set;
|
|
25
|
-
};
|
|
26
|
-
return (0, createIndexProvider_1.default)({
|
|
27
|
-
query(selector) {
|
|
28
|
-
if (!Object.hasOwnProperty.call(selector, field)) {
|
|
29
|
-
// If the field is not present in the selector, we can't optimize
|
|
30
|
-
return { matched: false };
|
|
31
|
-
}
|
|
32
|
-
const fieldSelector = selector[field];
|
|
33
|
-
const filteresForNull = fieldSelector == null || fieldSelector.$exists === false;
|
|
34
|
-
const keys = filteresForNull
|
|
35
|
-
? { include: null, exclude: [...index.keys()].filter(key => key != null) }
|
|
36
|
-
: (0, getMatchingKeys_1.default)(field, selector);
|
|
37
|
-
if (keys.include == null && keys.exclude == null)
|
|
38
|
-
return { matched: false };
|
|
39
|
-
// Accumulate included positions
|
|
40
|
-
let includedIds = [];
|
|
41
|
-
if (keys.include == null) {
|
|
42
|
-
for (const set of index.values()) {
|
|
43
|
-
for (const pos of set) {
|
|
44
|
-
includedIds.push(pos);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
for (const key of keys.include) {
|
|
50
|
-
const posSet = index.get(key);
|
|
51
|
-
if (posSet) {
|
|
52
|
-
for (const pos of posSet) {
|
|
53
|
-
includedIds.push(pos);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// If exclusion is specified, build a single set of all positions to exclude.
|
|
59
|
-
if (keys.exclude != null) {
|
|
60
|
-
const excludeIds = new Set();
|
|
61
|
-
for (const key of keys.exclude) {
|
|
62
|
-
const posSet = index.get(key);
|
|
63
|
-
if (posSet) {
|
|
64
|
-
for (const pos of posSet) {
|
|
65
|
-
excludeIds.add(pos);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
// Filter out any position that exists in the exclude set.
|
|
70
|
-
includedIds = includedIds.filter(pos => !excludeIds.has(pos));
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
matched: true,
|
|
74
|
-
ids: includedIds,
|
|
75
|
-
fields: [field],
|
|
76
|
-
keepSelector: filteresForNull,
|
|
77
|
-
};
|
|
78
|
-
},
|
|
79
|
-
rebuild(items) {
|
|
80
|
-
index.clear();
|
|
81
|
-
items.forEach((item) => {
|
|
82
|
-
const value = (0, serializeValue_1.default)((0, get_1.default)(item, field));
|
|
83
|
-
ensureSet(value).add(item.id);
|
|
84
|
-
});
|
|
85
|
-
},
|
|
86
|
-
// NEW: delta methods
|
|
87
|
-
insert(items) {
|
|
88
|
-
for (const item of items) {
|
|
89
|
-
const value = (0, serializeValue_1.default)((0, get_1.default)(item, field));
|
|
90
|
-
ensureSet(value).add(item.id);
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
remove(items) {
|
|
94
|
-
for (const item of items) {
|
|
95
|
-
const value = (0, serializeValue_1.default)((0, get_1.default)(item, field));
|
|
96
|
-
const set = index.get(value);
|
|
97
|
-
if (!set)
|
|
98
|
-
continue;
|
|
99
|
-
set.delete(item.id);
|
|
100
|
-
if (set.size === 0)
|
|
101
|
-
index.delete(value);
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
update(pairs) {
|
|
105
|
-
for (const { oldItem, newItem } of pairs) {
|
|
106
|
-
const oldValue = (0, serializeValue_1.default)((0, get_1.default)(oldItem, field));
|
|
107
|
-
const newValue = (0, serializeValue_1.default)((0, get_1.default)(newItem, field));
|
|
108
|
-
if (oldValue === newValue)
|
|
109
|
-
continue;
|
|
110
|
-
const oldSet = index.get(oldValue);
|
|
111
|
-
if (oldSet) {
|
|
112
|
-
oldSet.delete(oldItem.id);
|
|
113
|
-
if (oldSet.size === 0)
|
|
114
|
-
index.delete(oldValue);
|
|
115
|
-
}
|
|
116
|
-
ensureSet(newValue).add(newItem.id);
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { BaseItem } from './Collection';
|
|
2
|
-
import type IndexProvider from './types/IndexProvider';
|
|
3
|
-
/**
|
|
4
|
-
* Creates an IndexProvider based on the given definition.
|
|
5
|
-
* @param definition - The definition of the IndexProvider.
|
|
6
|
-
* @returns The created IndexProvider.
|
|
7
|
-
*/
|
|
8
|
-
export default function createIndexProvider<T extends BaseItem<I> = BaseItem, I = any>(definition: IndexProvider<T, I>): IndexProvider<T, I>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = createIndexProvider;
|
|
4
|
-
/**
|
|
5
|
-
* Creates an IndexProvider based on the given definition.
|
|
6
|
-
* @param definition - The definition of the IndexProvider.
|
|
7
|
-
* @returns The created IndexProvider.
|
|
8
|
-
*/
|
|
9
|
-
function createIndexProvider(definition) {
|
|
10
|
-
return definition;
|
|
11
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type Dependency from './types/Dependency';
|
|
2
|
-
import type ReactivityAdapter from './types/ReactivityAdapter';
|
|
3
|
-
/**
|
|
4
|
-
* Creates an ReactivityAdapter based on the given definition.
|
|
5
|
-
* @param definition - The definition of the ReactivityAdapter.
|
|
6
|
-
* @returns The created ReactivityAdapter.
|
|
7
|
-
*/
|
|
8
|
-
export default function createReactivityAdapter<T extends Dependency = Dependency>(definition: ReactivityAdapter<T>): ReactivityAdapter<T>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = createReactivityAdapter;
|
|
4
|
-
/**
|
|
5
|
-
* Creates an ReactivityAdapter based on the given definition.
|
|
6
|
-
* @param definition - The definition of the ReactivityAdapter.
|
|
7
|
-
* @returns The created ReactivityAdapter.
|
|
8
|
-
*/
|
|
9
|
-
function createReactivityAdapter(definition) {
|
|
10
|
-
return definition;
|
|
11
|
-
}
|