@signaldb/core 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.vite/manifest.json +4 -3
- package/dist/AutoFetchCollection.d.ts +3 -3
- package/dist/Collection/Cursor.d.ts +10 -7
- package/dist/Collection/index.d.ts +27 -11
- package/dist/Collection/types.d.ts +1 -0
- package/dist/ReplicatedCollection.d.ts +3 -3
- package/dist/index.cjs11.js +1 -1
- package/dist/index.cjs17.js +36 -136
- package/dist/index.cjs18.js +140 -5
- package/dist/index.cjs19.js +5 -40
- package/dist/index.cjs2.js +9 -3
- package/dist/index.cjs3.js +80 -54
- package/dist/index.d.ts +1 -1
- package/dist/index11.mjs +1 -1
- package/dist/index17.mjs +35 -136
- package/dist/index18.mjs +140 -5
- package/dist/index19.mjs +5 -39
- package/dist/index2.mjs +9 -3
- package/dist/index3.mjs +80 -54
- package/dist/utils/deepClone.d.ts +1 -1
- package/package.json +3 -3
package/dist/.vite/manifest.json
CHANGED
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
"imports": [
|
|
16
16
|
"src/utils/sortItems.ts",
|
|
17
17
|
"src/utils/project.ts",
|
|
18
|
+
"src/utils/deepClone.ts",
|
|
18
19
|
"src/Collection/Observer.ts"
|
|
19
20
|
]
|
|
20
21
|
},
|
|
21
22
|
"src/Collection/Observer.ts": {
|
|
22
|
-
"file": "index.
|
|
23
|
+
"file": "index.cjs18.js",
|
|
23
24
|
"name": "Collection/Observer",
|
|
24
25
|
"src": "src/Collection/Observer.ts",
|
|
25
26
|
"imports": [
|
|
@@ -135,7 +136,7 @@
|
|
|
135
136
|
"src": "src/utils/createSignal.ts"
|
|
136
137
|
},
|
|
137
138
|
"src/utils/deepClone.ts": {
|
|
138
|
-
"file": "index.
|
|
139
|
+
"file": "index.cjs17.js",
|
|
139
140
|
"name": "utils/deepClone",
|
|
140
141
|
"src": "src/utils/deepClone.ts"
|
|
141
142
|
},
|
|
@@ -169,7 +170,7 @@
|
|
|
169
170
|
"src": "src/utils/isFieldExpression.ts"
|
|
170
171
|
},
|
|
171
172
|
"src/utils/match.ts": {
|
|
172
|
-
"file": "index.
|
|
173
|
+
"file": "index.cjs19.js",
|
|
173
174
|
"name": "utils/match",
|
|
174
175
|
"src": "src/utils/match.ts"
|
|
175
176
|
},
|
|
@@ -10,11 +10,11 @@ interface AutoFetchOptions<T extends {
|
|
|
10
10
|
registerRemoteChange?: (onChange: () => Promise<void>) => Promise<void>;
|
|
11
11
|
mergeItems?: (itemA: T, itemB: T) => T;
|
|
12
12
|
}
|
|
13
|
-
export type AutoFetchCollectionOptions<T extends BaseItem<I>, I, U =
|
|
13
|
+
export type AutoFetchCollectionOptions<T extends BaseItem<I>, I, E extends BaseItem = T, U = E> = Omit<ReplicatedCollectionOptions<T, I, E, U>, 'pull' | 'registerRemoteChange'> & AutoFetchOptions<T, I>;
|
|
14
14
|
/**
|
|
15
15
|
* A special collection that automatically fetches items when they are needed.
|
|
16
16
|
*/
|
|
17
|
-
export default class AutoFetchCollection<T extends BaseItem<I> = BaseItem, I = any, U =
|
|
17
|
+
export default class AutoFetchCollection<T extends BaseItem<I> = BaseItem, I = any, E extends BaseItem = T, U = E> extends ReplicatedCollection<T, I, E, U> {
|
|
18
18
|
private activeObservers;
|
|
19
19
|
private observerTimeouts;
|
|
20
20
|
private purgeDelay;
|
|
@@ -31,7 +31,7 @@ export default class AutoFetchCollection<T extends BaseItem<I> = BaseItem, I = a
|
|
|
31
31
|
* @param options.fetchQueryItems {Function} - A function that fetches items from the server. It takes the selector as an argument and returns a promise that resolves to an object with an `items` property.
|
|
32
32
|
* @param options.purgeDelay {Number} - The delay in milliseconds before purging an item from the cache.
|
|
33
33
|
*/
|
|
34
|
-
constructor(options: AutoFetchCollectionOptions<T, I, U>);
|
|
34
|
+
constructor(options: AutoFetchCollectionOptions<T, I, E, U>);
|
|
35
35
|
/**
|
|
36
36
|
* Registers a query manually that items should be fetched for it
|
|
37
37
|
* @param selector {Object} Selector of the query
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type ReactivityAdapter from '../types/ReactivityAdapter';
|
|
2
|
-
import type { BaseItem, FindOptions, Transform } from './types';
|
|
2
|
+
import type { BaseItem, FindOptions, Transform, TransformAll } from './types';
|
|
3
3
|
import type { ObserveCallbacks } from './Observer';
|
|
4
4
|
/**
|
|
5
5
|
* Checks if the current scope is reactive, considering the provided reactivity adapter.
|
|
@@ -7,17 +7,19 @@ import type { 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
|
-
export interface CursorOptions<T extends BaseItem, U =
|
|
11
|
-
|
|
10
|
+
export interface CursorOptions<T extends BaseItem, E extends BaseItem = T, U = E> extends FindOptions<T> {
|
|
11
|
+
transformAll?: TransformAll<T, E>;
|
|
12
|
+
transform?: Transform<E, U>;
|
|
12
13
|
bindEvents?: (requery: () => void) => () => void;
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
16
|
* Represents a cursor for querying and observing a filtered, sorted, and transformed
|
|
16
17
|
* subset of items from a collection. Supports reactivity and field tracking.
|
|
17
18
|
* @template T - The type of the items in the collection.
|
|
18
|
-
* @template
|
|
19
|
+
* @template E - The transformed item type after applying transformAll (default is T).
|
|
20
|
+
* @template U - The transformed item type after applying transform (default is E).
|
|
19
21
|
*/
|
|
20
|
-
export default class Cursor<T extends BaseItem, U =
|
|
22
|
+
export default class Cursor<T extends BaseItem, E extends BaseItem = T, U = E> {
|
|
21
23
|
private observer;
|
|
22
24
|
private getFilteredItems;
|
|
23
25
|
private options;
|
|
@@ -37,8 +39,9 @@ export default class Cursor<T extends BaseItem, U = T> {
|
|
|
37
39
|
* @param options.limit - The maximum number of items to return in the result set.
|
|
38
40
|
* @param options.reactive - A reactivity adapter to enable observing changes in the cursor's result set.
|
|
39
41
|
* @param options.fieldTracking - A boolean to enable fine-grained field tracking for reactivity.
|
|
42
|
+
* @param options.transformAll - A function that will be able to solve the n+1 problem
|
|
40
43
|
*/
|
|
41
|
-
constructor(getItems: () => T[], options?: CursorOptions<T, U>);
|
|
44
|
+
constructor(getItems: () => T[], options?: CursorOptions<T, E, U>);
|
|
42
45
|
private addGetters;
|
|
43
46
|
private transform;
|
|
44
47
|
private getItems;
|
|
@@ -102,7 +105,7 @@ export default class Cursor<T extends BaseItem, U = T> {
|
|
|
102
105
|
* @param skipInitial - A boolean indicating whether to skip the initial notification of the current result set.
|
|
103
106
|
* @returns A function to stop observing changes.
|
|
104
107
|
*/
|
|
105
|
-
observeChanges(callbacks: ObserveCallbacks<
|
|
108
|
+
observeChanges(callbacks: ObserveCallbacks<E>, skipInitial?: boolean): () => void;
|
|
106
109
|
/**
|
|
107
110
|
* Forces the cursor to re-evaluate its result set by re-fetching items
|
|
108
111
|
* from the collection. This is useful when the underlying data or query
|
|
@@ -6,23 +6,24 @@ import type Selector from '../types/Selector';
|
|
|
6
6
|
import type Modifier from '../types/Modifier';
|
|
7
7
|
import type IndexProvider from '../types/IndexProvider';
|
|
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
|
name?: string;
|
|
16
16
|
memory?: MemoryAdapter;
|
|
17
17
|
reactivity?: ReactivityAdapter;
|
|
18
|
-
transform?: Transform<
|
|
18
|
+
transform?: Transform<E, U>;
|
|
19
19
|
persistence?: PersistenceAdapter<T, I>;
|
|
20
20
|
indices?: IndexProvider<T, I>[];
|
|
21
21
|
enableDebugMode?: boolean;
|
|
22
22
|
fieldTracking?: boolean;
|
|
23
|
+
transformAll?: TransformAll<T, E>;
|
|
23
24
|
primaryKeyGenerator?: (item: Omit<T, 'id'>) => I;
|
|
24
25
|
}
|
|
25
|
-
interface CollectionEvents<T extends BaseItem, U =
|
|
26
|
+
interface CollectionEvents<T extends BaseItem, E extends BaseItem = T, U = E> {
|
|
26
27
|
'added': (item: T) => void;
|
|
27
28
|
'changed': (item: T, modifier: Modifier<T>) => void;
|
|
28
29
|
'removed': (item: T) => void;
|
|
@@ -37,7 +38,7 @@ interface CollectionEvents<T extends BaseItem, U = T> {
|
|
|
37
38
|
'observer.created': <O extends FindOptions<T>>(selector?: Selector<T>, options?: O) => void;
|
|
38
39
|
'observer.disposed': <O extends FindOptions<T>>(selector?: Selector<T>, options?: O) => void;
|
|
39
40
|
'getItems': (selector: Selector<T> | undefined) => void;
|
|
40
|
-
'find': <O extends FindOptions<T>>(selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<T, U>) => void;
|
|
41
|
+
'find': <O extends FindOptions<T>>(selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<T, E, U>) => void;
|
|
41
42
|
'findOne': <O extends FindOptions<T>>(selector: Selector<T>, options: O | undefined, item: U | undefined) => void;
|
|
42
43
|
'insert': (item: Omit<T, 'id'> & Partial<Pick<T, 'id'>>) => void;
|
|
43
44
|
'updateOne': (selector: Selector<T>, modifier: Modifier<T>) => void;
|
|
@@ -47,7 +48,7 @@ interface CollectionEvents<T extends BaseItem, U = T> {
|
|
|
47
48
|
'removeMany': (selector: Selector<T>) => void;
|
|
48
49
|
'validate': (item: T) => void;
|
|
49
50
|
'_debug.getItems': (callstack: string, selector: Selector<T> | undefined, measuredTime: number) => void;
|
|
50
|
-
'_debug.find': <O extends FindOptions<T>>(callstack: string, selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<T, U>) => void;
|
|
51
|
+
'_debug.find': <O extends FindOptions<T>>(callstack: string, selector: Selector<T> | undefined, options: O | undefined, cursor: Cursor<T, E, U>) => void;
|
|
51
52
|
'_debug.findOne': <O extends FindOptions<T>>(callstack: string, selector: Selector<T>, options: O | undefined, item: U | undefined) => void;
|
|
52
53
|
'_debug.insert': (callstack: string, item: Omit<T, 'id'> & Partial<Pick<T, 'id'>>) => void;
|
|
53
54
|
'_debug.updateOne': (callstack: string, selector: Selector<T>, modifier: Modifier<T>) => void;
|
|
@@ -64,14 +65,14 @@ interface CollectionEvents<T extends BaseItem, U = T> {
|
|
|
64
65
|
* @template I - The type of the unique identifier for the items.
|
|
65
66
|
* @template U - The transformed item type after applying transformations (default is T).
|
|
66
67
|
*/
|
|
67
|
-
export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U =
|
|
68
|
+
export default class Collection<T extends BaseItem<I> = BaseItem, I = any, E extends BaseItem = T, U = E> extends EventEmitter<CollectionEvents<T, E, U>> {
|
|
68
69
|
private static collections;
|
|
69
70
|
private static debugMode;
|
|
70
71
|
private static batchOperationInProgress;
|
|
71
72
|
private static fieldTracking;
|
|
72
73
|
private static onCreationCallbacks;
|
|
73
74
|
private static onDisposeCallbacks;
|
|
74
|
-
static getCollections(): Collection<any, any, any>[];
|
|
75
|
+
static getCollections(): Collection<any, any, any, any>[];
|
|
75
76
|
static onCreation(callback: (collection: Collection<any>) => void): void;
|
|
76
77
|
static onDispose(callback: (collection: Collection<any>) => void): void;
|
|
77
78
|
/**
|
|
@@ -105,6 +106,7 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
105
106
|
private postBatchCallbacks;
|
|
106
107
|
private fieldTracking;
|
|
107
108
|
private persistenceReadyPromise;
|
|
109
|
+
private pendingUpdates;
|
|
108
110
|
/**
|
|
109
111
|
* Initializes a new instance of the `Collection` class with optional configuration.
|
|
110
112
|
* Sets up memory, persistence, reactivity, and indices as specified in the options.
|
|
@@ -120,8 +122,21 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
120
122
|
* @param options.indices - An array of index providers for optimized querying.
|
|
121
123
|
* @param options.enableDebugMode - A boolean to enable or disable debug mode.
|
|
122
124
|
* @param options.fieldTracking - A boolean to enable or disable field tracking by default.
|
|
125
|
+
* @param options.transformAll - A function that will be able to solve the n+1 problem
|
|
123
126
|
*/
|
|
124
|
-
constructor(options?: CollectionOptions<T, I, U>);
|
|
127
|
+
constructor(options?: CollectionOptions<T, I, E, U>);
|
|
128
|
+
/**
|
|
129
|
+
* Resets the collection's data by clearing the in-memory items and reloading from the persistence adapter.
|
|
130
|
+
* @returns A promise that resolves when the data has been reset and reloaded.
|
|
131
|
+
*/
|
|
132
|
+
resetData(): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Loads data from the persistence adapter and updates the in-memory collection accordingly.
|
|
135
|
+
* @param data - Optional data to load, containing either a full list of items or a set of changes. If not provided, data will be loaded from the persistence adapter.
|
|
136
|
+
* @param hasOngoingSaves - A boolean indicating whether there are ongoing save operations. If `true`, the method will skip loading data to avoid conflicts with pending updates.
|
|
137
|
+
* @returns A promise that resolves when the data has been loaded and the in-memory collection has been updated.
|
|
138
|
+
*/
|
|
139
|
+
private loadPersistentData;
|
|
125
140
|
/**
|
|
126
141
|
* Checks whether the collection is currently performing a pull operation
|
|
127
142
|
* ⚡️ this function is reactive!
|
|
@@ -183,6 +198,7 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
183
198
|
private memory;
|
|
184
199
|
private memoryArray;
|
|
185
200
|
private transform;
|
|
201
|
+
private transformAll;
|
|
186
202
|
private getItems;
|
|
187
203
|
/**
|
|
188
204
|
* Disposes the collection, unregisters persistence adapters, clears memory, and
|
|
@@ -198,7 +214,7 @@ export default class Collection<T extends BaseItem<I> = BaseItem, I = any, U = T
|
|
|
198
214
|
* @param [options] - Options for the find operation, such as limit and sort.
|
|
199
215
|
* @returns A cursor to fetch and observe the matching items.
|
|
200
216
|
*/
|
|
201
|
-
find<O extends FindOptions<T>>(selector?: Selector<T>, options?: O): Cursor<T, U>;
|
|
217
|
+
find<O extends FindOptions<T>>(selector?: Selector<T>, options?: O): Cursor<T, E, U>;
|
|
202
218
|
/**
|
|
203
219
|
* Finds a single item in the collection based on a selector and optional options.
|
|
204
220
|
* ⚡️ this function is reactive!
|
|
@@ -3,6 +3,7 @@ export type BaseItem<I = any> = {
|
|
|
3
3
|
id: I;
|
|
4
4
|
} & Record<string, any>;
|
|
5
5
|
export type Transform<T, U = T> = ((document: T) => U) | null | undefined;
|
|
6
|
+
export type TransformAll<T extends BaseItem, O extends BaseItem = T> = ((items: T[], fields: FieldSpecifier<O> | undefined) => O[]) | null | undefined;
|
|
6
7
|
export type SortSpecifier<T> = {
|
|
7
8
|
[P in keyof T]?: -1 | 1;
|
|
8
9
|
} & Record<string, -1 | 1>;
|
|
@@ -22,7 +22,7 @@ interface ReplicationOptions<T extends {
|
|
|
22
22
|
export declare function createReplicationAdapter<T extends {
|
|
23
23
|
id: I;
|
|
24
24
|
} & Record<string, any>, I>(options: ReplicationOptions<T, I>): import("./types/PersistenceAdapter").default<T, unknown>;
|
|
25
|
-
export type ReplicatedCollectionOptions<T extends BaseItem<I>, I, U =
|
|
25
|
+
export type ReplicatedCollectionOptions<T extends BaseItem<I>, I, E extends BaseItem = T, U = E> = CollectionOptions<T, I, E, U> & ReplicationOptions<T, I>;
|
|
26
26
|
/**
|
|
27
27
|
* Extends the `Collection` class to support replication with remote sources.
|
|
28
28
|
* Handles pull and push operations, remote change registration, and enhanced loading states.
|
|
@@ -30,7 +30,7 @@ export type ReplicatedCollectionOptions<T extends BaseItem<I>, I, U = T> = Colle
|
|
|
30
30
|
* @template I - The type of the unique identifier for the items.
|
|
31
31
|
* @template U - The transformed item type after applying transformations (default is T).
|
|
32
32
|
*/
|
|
33
|
-
export default class ReplicatedCollection<T extends BaseItem<I> = BaseItem, I = any, U =
|
|
33
|
+
export default class ReplicatedCollection<T extends BaseItem<I> = BaseItem, I = any, E extends BaseItem = T, U = E> extends Collection<T, I, E, U> {
|
|
34
34
|
private isPullingRemoteSignal;
|
|
35
35
|
private isPushingRemoteSignal;
|
|
36
36
|
/**
|
|
@@ -47,7 +47,7 @@ export default class ReplicatedCollection<T extends BaseItem<I> = BaseItem, I =
|
|
|
47
47
|
* @param options.indices - An array of index providers for optimized querying.
|
|
48
48
|
* @param options.enableDebugMode - A boolean to enable or disable debug mode.
|
|
49
49
|
*/
|
|
50
|
-
constructor(options: ReplicatedCollectionOptions<T, I, U>);
|
|
50
|
+
constructor(options: ReplicatedCollectionOptions<T, I, E, U>);
|
|
51
51
|
/**
|
|
52
52
|
* Checks whether the collection is currently performing any loading operation,
|
|
53
53
|
* including pulling or pushing data from/to the remote source, or standard
|
package/dist/index.cjs11.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const mingo = require("mingo");
|
|
3
|
-
const deepClone = require("./index.
|
|
3
|
+
const deepClone = require("./index.cjs17.js");
|
|
4
4
|
function modify(item, modifier) {
|
|
5
5
|
const hasOperators = Object.keys(modifier).some((key) => key.startsWith("$"));
|
|
6
6
|
if (!hasOperators)
|
package/dist/index.cjs17.js
CHANGED
|
@@ -1,142 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
addedBefore: [],
|
|
17
|
-
changed: [],
|
|
18
|
-
changedField: [],
|
|
19
|
-
movedBefore: [],
|
|
20
|
-
removed: []
|
|
21
|
-
};
|
|
22
|
-
this.unbindEvents = bindEvents();
|
|
23
|
-
}
|
|
24
|
-
call(event, ...args) {
|
|
25
|
-
this.callbacks[event].forEach(({ callback, options }) => {
|
|
26
|
-
if (!options.skipInitial || !options.isInitial) {
|
|
27
|
-
callback(...args);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
hasCallbacks(events) {
|
|
32
|
-
return events.some((event) => this.callbacks[event].length > 0);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Determines if the observer has no active callbacks registered for any events.
|
|
36
|
-
* @returns A boolean indicating whether the observer is empty (i.e., no callbacks are registered).
|
|
37
|
-
*/
|
|
38
|
-
isEmpty() {
|
|
39
|
-
return !this.hasCallbacks([
|
|
40
|
-
"added",
|
|
41
|
-
"addedBefore",
|
|
42
|
-
"changed",
|
|
43
|
-
"changedField",
|
|
44
|
-
"movedBefore",
|
|
45
|
-
"removed"
|
|
46
|
-
]);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Compares the previous state of items with the new state and triggers the appropriate callbacks
|
|
50
|
-
* for events such as added, removed, changed, or moved items.
|
|
51
|
-
* @param newItems - The new list of items to compare against the previous state.
|
|
52
|
-
*/
|
|
53
|
-
runChecks(newItems) {
|
|
54
|
-
const oldItemsMap = new Map(this.previousItems.map((item, index) => [
|
|
55
|
-
item.id,
|
|
56
|
-
{ item, index, beforeItem: this.previousItems[index + 1] || null }
|
|
57
|
-
]));
|
|
58
|
-
const newItemsMap = new Map(newItems.map((item, index) => [
|
|
59
|
-
item.id,
|
|
60
|
-
{ item, index, beforeItem: newItems[index + 1] || null }
|
|
61
|
-
]));
|
|
62
|
-
if (this.hasCallbacks(["changed", "changedField", "movedBefore", "removed"])) {
|
|
63
|
-
oldItemsMap.forEach(({ item: oldItem, index, beforeItem: oldBeforeItem }) => {
|
|
64
|
-
const newItem = newItemsMap.get(oldItem.id);
|
|
65
|
-
if (newItem) {
|
|
66
|
-
if (this.hasCallbacks(["changed", "changedField"]) && !isEqual(newItem.item, oldItem)) {
|
|
67
|
-
this.call("changed", newItem.item);
|
|
68
|
-
if (this.hasCallbacks(["changedField"])) {
|
|
69
|
-
const keys = uniqueBy([
|
|
70
|
-
...Object.keys(newItem.item),
|
|
71
|
-
...Object.keys(oldItem)
|
|
72
|
-
], (value) => value);
|
|
73
|
-
keys.forEach((key) => {
|
|
74
|
-
if (isEqual(newItem.item[key], oldItem[key]))
|
|
75
|
-
return;
|
|
76
|
-
this.call("changedField", newItem.item, key, oldItem[key], newItem.item[key]);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (newItem.index !== index && newItem.beforeItem?.id !== oldBeforeItem?.id) {
|
|
81
|
-
this.call("movedBefore", newItem.item, newItem.beforeItem);
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
this.call("removed", oldItem);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
if (this.hasCallbacks(["added", "addedBefore"])) {
|
|
89
|
-
newItems.forEach((newItem, index) => {
|
|
90
|
-
const oldItem = oldItemsMap.get(newItem.id);
|
|
91
|
-
if (oldItem)
|
|
92
|
-
return;
|
|
93
|
-
this.call("added", newItem);
|
|
94
|
-
this.call("addedBefore", newItem, newItems[index + 1] || null);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
this.previousItems = newItems;
|
|
98
|
-
Object.keys(this.callbacks).forEach((key) => {
|
|
99
|
-
const event = key;
|
|
100
|
-
const callbacks = this.callbacks[event];
|
|
101
|
-
this.callbacks[event] = callbacks.map((callback) => ({
|
|
102
|
-
...callback,
|
|
103
|
-
options: {
|
|
104
|
-
...callback.options,
|
|
105
|
-
isInitial: false
|
|
106
|
-
}
|
|
107
|
-
}));
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Stops the observer by unbinding all events and cleaning up resources.
|
|
112
|
-
*/
|
|
113
|
-
stop() {
|
|
114
|
-
this.unbindEvents();
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Registers callbacks for specific events to observe changes in the collection.
|
|
118
|
-
* @param callbacks - An object containing the callbacks for various events (e.g., 'added', 'removed').
|
|
119
|
-
* @param skipInitial - A boolean indicating whether to skip invoking the callbacks for the initial state of the collection.
|
|
120
|
-
*/
|
|
121
|
-
addCallbacks(callbacks, skipInitial = false) {
|
|
122
|
-
Object.keys(callbacks).forEach((key) => {
|
|
123
|
-
const typedKey = key;
|
|
124
|
-
this.callbacks[typedKey].push({
|
|
125
|
-
callback: callbacks[typedKey],
|
|
126
|
-
options: { skipInitial, isInitial: true }
|
|
127
|
-
});
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
function clone(value) {
|
|
4
|
+
if (typeof value === "function")
|
|
5
|
+
throw new Error("Cloning functions is not supported");
|
|
6
|
+
if (value === null || typeof value !== "object")
|
|
7
|
+
return value;
|
|
8
|
+
if (value instanceof Date)
|
|
9
|
+
return new Date(value);
|
|
10
|
+
if (Array.isArray(value))
|
|
11
|
+
return value.map((item) => clone(item));
|
|
12
|
+
if (value instanceof Map) {
|
|
13
|
+
const result2 = /* @__PURE__ */ new Map();
|
|
14
|
+
value.forEach((currentValue, key) => {
|
|
15
|
+
result2.set(key, clone(currentValue));
|
|
128
16
|
});
|
|
17
|
+
return result2;
|
|
129
18
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
removeCallbacks(callbacks) {
|
|
135
|
-
Object.keys(callbacks).forEach((key) => {
|
|
136
|
-
const typedKey = key;
|
|
137
|
-
const index = this.callbacks[typedKey].findIndex(({ callback }) => callback === callbacks[typedKey]);
|
|
138
|
-
this.callbacks[typedKey].splice(index, 1);
|
|
19
|
+
if (value instanceof Set) {
|
|
20
|
+
const result2 = /* @__PURE__ */ new Set();
|
|
21
|
+
value.forEach((currentValue) => {
|
|
22
|
+
result2.add(clone(currentValue));
|
|
139
23
|
});
|
|
24
|
+
return result2;
|
|
25
|
+
}
|
|
26
|
+
if (value instanceof RegExp)
|
|
27
|
+
return new RegExp(value);
|
|
28
|
+
const result = {};
|
|
29
|
+
for (const key in value) {
|
|
30
|
+
if (Object.hasOwnProperty.call(value, key)) {
|
|
31
|
+
result[key] = clone(value[key]);
|
|
32
|
+
}
|
|
140
33
|
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
function deepClone(object) {
|
|
37
|
+
if (typeof structuredClone === "function")
|
|
38
|
+
return structuredClone(object);
|
|
39
|
+
return clone(object);
|
|
141
40
|
}
|
|
142
|
-
|
|
41
|
+
exports.clone = clone;
|
|
42
|
+
exports.default = deepClone;
|
package/dist/index.cjs18.js
CHANGED
|
@@ -1,7 +1,142 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
const isEqual = require("./index.cjs10.js");
|
|
3
|
+
const uniqueBy = require("./index.cjs26.js");
|
|
4
|
+
class Observer {
|
|
5
|
+
previousItems = [];
|
|
6
|
+
callbacks;
|
|
7
|
+
unbindEvents;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new instance of the `Observer` class.
|
|
10
|
+
* Sets up event bindings and initializes the callbacks for tracking changes in a collection.
|
|
11
|
+
* @param bindEvents - A function to bind external events to the observer. Must return a cleanup function to unbind those events.
|
|
12
|
+
*/
|
|
13
|
+
constructor(bindEvents) {
|
|
14
|
+
this.callbacks = {
|
|
15
|
+
added: [],
|
|
16
|
+
addedBefore: [],
|
|
17
|
+
changed: [],
|
|
18
|
+
changedField: [],
|
|
19
|
+
movedBefore: [],
|
|
20
|
+
removed: []
|
|
21
|
+
};
|
|
22
|
+
this.unbindEvents = bindEvents();
|
|
23
|
+
}
|
|
24
|
+
call(event, ...args) {
|
|
25
|
+
this.callbacks[event].forEach(({ callback, options }) => {
|
|
26
|
+
if (!options.skipInitial || !options.isInitial) {
|
|
27
|
+
callback(...args);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
hasCallbacks(events) {
|
|
32
|
+
return events.some((event) => this.callbacks[event].length > 0);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Determines if the observer has no active callbacks registered for any events.
|
|
36
|
+
* @returns A boolean indicating whether the observer is empty (i.e., no callbacks are registered).
|
|
37
|
+
*/
|
|
38
|
+
isEmpty() {
|
|
39
|
+
return !this.hasCallbacks([
|
|
40
|
+
"added",
|
|
41
|
+
"addedBefore",
|
|
42
|
+
"changed",
|
|
43
|
+
"changedField",
|
|
44
|
+
"movedBefore",
|
|
45
|
+
"removed"
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Compares the previous state of items with the new state and triggers the appropriate callbacks
|
|
50
|
+
* for events such as added, removed, changed, or moved items.
|
|
51
|
+
* @param newItems - The new list of items to compare against the previous state.
|
|
52
|
+
*/
|
|
53
|
+
runChecks(newItems) {
|
|
54
|
+
const oldItemsMap = new Map(this.previousItems.map((item, index) => [
|
|
55
|
+
item.id,
|
|
56
|
+
{ item, index, beforeItem: this.previousItems[index + 1] || null }
|
|
57
|
+
]));
|
|
58
|
+
const newItemsMap = new Map(newItems.map((item, index) => [
|
|
59
|
+
item.id,
|
|
60
|
+
{ item, index, beforeItem: newItems[index + 1] || null }
|
|
61
|
+
]));
|
|
62
|
+
if (this.hasCallbacks(["changed", "changedField", "movedBefore", "removed"])) {
|
|
63
|
+
oldItemsMap.forEach(({ item: oldItem, index, beforeItem: oldBeforeItem }) => {
|
|
64
|
+
const newItem = newItemsMap.get(oldItem.id);
|
|
65
|
+
if (newItem) {
|
|
66
|
+
if (this.hasCallbacks(["changed", "changedField"]) && !isEqual(newItem.item, oldItem)) {
|
|
67
|
+
this.call("changed", newItem.item);
|
|
68
|
+
if (this.hasCallbacks(["changedField"])) {
|
|
69
|
+
const keys = uniqueBy([
|
|
70
|
+
...Object.keys(newItem.item),
|
|
71
|
+
...Object.keys(oldItem)
|
|
72
|
+
], (value) => value);
|
|
73
|
+
keys.forEach((key) => {
|
|
74
|
+
if (isEqual(newItem.item[key], oldItem[key]))
|
|
75
|
+
return;
|
|
76
|
+
this.call("changedField", newItem.item, key, oldItem[key], newItem.item[key]);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (newItem.index !== index && newItem.beforeItem?.id !== oldBeforeItem?.id) {
|
|
81
|
+
this.call("movedBefore", newItem.item, newItem.beforeItem);
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
this.call("removed", oldItem);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (this.hasCallbacks(["added", "addedBefore"])) {
|
|
89
|
+
newItems.forEach((newItem, index) => {
|
|
90
|
+
const oldItem = oldItemsMap.get(newItem.id);
|
|
91
|
+
if (oldItem)
|
|
92
|
+
return;
|
|
93
|
+
this.call("added", newItem);
|
|
94
|
+
this.call("addedBefore", newItem, newItems[index + 1] || null);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
this.previousItems = newItems;
|
|
98
|
+
Object.keys(this.callbacks).forEach((key) => {
|
|
99
|
+
const event = key;
|
|
100
|
+
const callbacks = this.callbacks[event];
|
|
101
|
+
this.callbacks[event] = callbacks.map((callback) => ({
|
|
102
|
+
...callback,
|
|
103
|
+
options: {
|
|
104
|
+
...callback.options,
|
|
105
|
+
isInitial: false
|
|
106
|
+
}
|
|
107
|
+
}));
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Stops the observer by unbinding all events and cleaning up resources.
|
|
112
|
+
*/
|
|
113
|
+
stop() {
|
|
114
|
+
this.unbindEvents();
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Registers callbacks for specific events to observe changes in the collection.
|
|
118
|
+
* @param callbacks - An object containing the callbacks for various events (e.g., 'added', 'removed').
|
|
119
|
+
* @param skipInitial - A boolean indicating whether to skip invoking the callbacks for the initial state of the collection.
|
|
120
|
+
*/
|
|
121
|
+
addCallbacks(callbacks, skipInitial = false) {
|
|
122
|
+
Object.keys(callbacks).forEach((key) => {
|
|
123
|
+
const typedKey = key;
|
|
124
|
+
this.callbacks[typedKey].push({
|
|
125
|
+
callback: callbacks[typedKey],
|
|
126
|
+
options: { skipInitial, isInitial: true }
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Removes the specified callbacks for specific events, unregistering them from the observer.
|
|
132
|
+
* @param callbacks - An object containing the callbacks to be removed for various events.
|
|
133
|
+
*/
|
|
134
|
+
removeCallbacks(callbacks) {
|
|
135
|
+
Object.keys(callbacks).forEach((key) => {
|
|
136
|
+
const typedKey = key;
|
|
137
|
+
const index = this.callbacks[typedKey].findIndex(({ callback }) => callback === callbacks[typedKey]);
|
|
138
|
+
this.callbacks[typedKey].splice(index, 1);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
6
141
|
}
|
|
7
|
-
module.exports =
|
|
142
|
+
module.exports = Observer;
|
package/dist/index.cjs19.js
CHANGED
|
@@ -1,42 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (value === null || typeof value !== "object")
|
|
7
|
-
return value;
|
|
8
|
-
if (value instanceof Date)
|
|
9
|
-
return new Date(value);
|
|
10
|
-
if (Array.isArray(value))
|
|
11
|
-
return value.map((item) => clone(item));
|
|
12
|
-
if (value instanceof Map) {
|
|
13
|
-
const result2 = /* @__PURE__ */ new Map();
|
|
14
|
-
value.forEach((currentValue, key) => {
|
|
15
|
-
result2.set(key, clone(currentValue));
|
|
16
|
-
});
|
|
17
|
-
return result2;
|
|
18
|
-
}
|
|
19
|
-
if (value instanceof Set) {
|
|
20
|
-
const result2 = /* @__PURE__ */ new Set();
|
|
21
|
-
value.forEach((currentValue) => {
|
|
22
|
-
result2.add(clone(currentValue));
|
|
23
|
-
});
|
|
24
|
-
return result2;
|
|
25
|
-
}
|
|
26
|
-
if (value instanceof RegExp)
|
|
27
|
-
return new RegExp(value);
|
|
28
|
-
const result = {};
|
|
29
|
-
for (const key in value) {
|
|
30
|
-
if (Object.hasOwnProperty.call(value, key)) {
|
|
31
|
-
result[key] = clone(value[key]);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return result;
|
|
2
|
+
const mingo = require("mingo");
|
|
3
|
+
function match(item, selector) {
|
|
4
|
+
const query = new mingo.Query(selector);
|
|
5
|
+
return query.test(item);
|
|
35
6
|
}
|
|
36
|
-
|
|
37
|
-
if (typeof structuredClone === "function")
|
|
38
|
-
return structuredClone(object);
|
|
39
|
-
return clone(object);
|
|
40
|
-
}
|
|
41
|
-
exports.clone = clone;
|
|
42
|
-
exports.default = deepClone;
|
|
7
|
+
module.exports = match;
|