@tanstack/db 0.2.4 → 0.3.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/cjs/collection.cjs +23 -4
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +35 -41
- package/dist/cjs/local-only.cjs.map +1 -1
- package/dist/cjs/local-only.d.cts +17 -43
- package/dist/cjs/local-storage.cjs +3 -12
- package/dist/cjs/local-storage.cjs.map +1 -1
- package/dist/cjs/local-storage.d.cts +16 -39
- package/dist/cjs/query/builder/types.d.cts +3 -10
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/transactions.cjs +76 -5
- package/dist/cjs/transactions.cjs.map +1 -1
- package/dist/cjs/transactions.d.cts +17 -0
- package/dist/cjs/types.d.cts +10 -31
- package/dist/esm/collection.d.ts +35 -41
- package/dist/esm/collection.js +23 -4
- package/dist/esm/collection.js.map +1 -1
- package/dist/esm/local-only.d.ts +17 -43
- package/dist/esm/local-only.js.map +1 -1
- package/dist/esm/local-storage.d.ts +16 -39
- package/dist/esm/local-storage.js +3 -12
- package/dist/esm/local-storage.js.map +1 -1
- package/dist/esm/query/builder/types.d.ts +3 -10
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/transactions.d.ts +17 -0
- package/dist/esm/transactions.js +76 -5
- package/dist/esm/transactions.js.map +1 -1
- package/dist/esm/types.d.ts +10 -31
- package/package.json +2 -2
- package/src/collection.ts +148 -196
- package/src/local-only.ts +57 -77
- package/src/local-storage.ts +53 -85
- package/src/query/builder/types.ts +3 -12
- package/src/query/live-query-collection.ts +1 -1
- package/src/transactions.ts +121 -6
- package/src/types.ts +25 -55
package/src/collection.ts
CHANGED
|
@@ -48,12 +48,12 @@ import type {
|
|
|
48
48
|
CollectionStatus,
|
|
49
49
|
CurrentStateAsChangesOptions,
|
|
50
50
|
Fn,
|
|
51
|
+
InferSchemaInput,
|
|
52
|
+
InferSchemaOutput,
|
|
51
53
|
InsertConfig,
|
|
52
54
|
OperationConfig,
|
|
53
55
|
OptimisticChangeMessage,
|
|
54
56
|
PendingMutation,
|
|
55
|
-
ResolveInsertInput,
|
|
56
|
-
ResolveType,
|
|
57
57
|
StandardSchema,
|
|
58
58
|
SubscribeChangesOptions,
|
|
59
59
|
Transaction as TransactionType,
|
|
@@ -91,11 +91,9 @@ export interface Collection<
|
|
|
91
91
|
/**
|
|
92
92
|
* Creates a new Collection instance with the given configuration
|
|
93
93
|
*
|
|
94
|
-
* @template
|
|
94
|
+
* @template T - The schema type if a schema is provided, otherwise the type of items in the collection
|
|
95
95
|
* @template TKey - The type of the key for the collection
|
|
96
96
|
* @template TUtils - The utilities record type
|
|
97
|
-
* @template TSchema - The schema type for validation and type inference (second priority)
|
|
98
|
-
* @template TFallback - The fallback type if no explicit or schema type is provided
|
|
99
97
|
* @param options - Collection options with optional utilities
|
|
100
98
|
* @returns A new Collection with utilities exposed both at top level and under .utils
|
|
101
99
|
*
|
|
@@ -159,142 +157,72 @@ export interface Collection<
|
|
|
159
157
|
* sync: { sync: () => {} }
|
|
160
158
|
* })
|
|
161
159
|
*
|
|
162
|
-
* // Note: You can provide an explicit type, a schema, or both. When both are provided, the explicit type takes precedence.
|
|
163
160
|
*/
|
|
164
161
|
|
|
165
|
-
// Overload for when schema is provided
|
|
162
|
+
// Overload for when schema is provided
|
|
166
163
|
export function createCollection<
|
|
167
|
-
|
|
164
|
+
T extends StandardSchemaV1,
|
|
168
165
|
TKey extends string | number = string | number,
|
|
169
166
|
TUtils extends UtilsRecord = {},
|
|
170
|
-
TFallback extends object = Record<string, unknown>,
|
|
171
167
|
>(
|
|
172
|
-
options: CollectionConfig<
|
|
173
|
-
|
|
174
|
-
TKey,
|
|
175
|
-
TSchema,
|
|
176
|
-
ResolveInsertInput<unknown, TSchema, TFallback>
|
|
177
|
-
> & {
|
|
178
|
-
schema: TSchema
|
|
168
|
+
options: CollectionConfig<InferSchemaOutput<T>, TKey, T> & {
|
|
169
|
+
schema: T
|
|
179
170
|
utils?: TUtils
|
|
180
171
|
}
|
|
181
|
-
): Collection<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
TSchema,
|
|
186
|
-
ResolveInsertInput<unknown, TSchema, TFallback>
|
|
187
|
-
>
|
|
188
|
-
|
|
189
|
-
// Overload for when explicit type is provided with schema - explicit type takes precedence
|
|
172
|
+
): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>>
|
|
173
|
+
|
|
174
|
+
// Overload for when no schema is provided
|
|
175
|
+
// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config
|
|
190
176
|
export function createCollection<
|
|
191
|
-
|
|
177
|
+
T extends object,
|
|
192
178
|
TKey extends string | number = string | number,
|
|
193
179
|
TUtils extends UtilsRecord = {},
|
|
194
|
-
TSchema extends StandardSchemaV1 = StandardSchemaV1,
|
|
195
|
-
TFallback extends object = Record<string, unknown>,
|
|
196
180
|
>(
|
|
197
|
-
options: CollectionConfig<
|
|
198
|
-
|
|
199
|
-
TKey,
|
|
200
|
-
TSchema,
|
|
201
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
202
|
-
> & {
|
|
203
|
-
schema: TSchema
|
|
181
|
+
options: CollectionConfig<T, TKey, never> & {
|
|
182
|
+
schema?: never // prohibit schema if an explicit type is provided
|
|
204
183
|
utils?: TUtils
|
|
205
184
|
}
|
|
206
|
-
): Collection<
|
|
207
|
-
ResolveType<TExplicit, TSchema, TFallback>,
|
|
208
|
-
TKey,
|
|
209
|
-
TUtils,
|
|
210
|
-
TSchema,
|
|
211
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
212
|
-
>
|
|
213
|
-
|
|
214
|
-
// Overload for when explicit type is provided or no schema
|
|
215
|
-
export function createCollection<
|
|
216
|
-
TExplicit = unknown,
|
|
217
|
-
TKey extends string | number = string | number,
|
|
218
|
-
TUtils extends UtilsRecord = {},
|
|
219
|
-
TSchema extends StandardSchemaV1 = StandardSchemaV1,
|
|
220
|
-
TFallback extends object = Record<string, unknown>,
|
|
221
|
-
>(
|
|
222
|
-
options: CollectionConfig<
|
|
223
|
-
ResolveType<TExplicit, TSchema, TFallback>,
|
|
224
|
-
TKey,
|
|
225
|
-
TSchema,
|
|
226
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
227
|
-
> & { utils?: TUtils }
|
|
228
|
-
): Collection<
|
|
229
|
-
ResolveType<TExplicit, TSchema, TFallback>,
|
|
230
|
-
TKey,
|
|
231
|
-
TUtils,
|
|
232
|
-
TSchema,
|
|
233
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
234
|
-
>
|
|
185
|
+
): Collection<T, TKey, TUtils, never, T>
|
|
235
186
|
|
|
236
187
|
// Implementation
|
|
237
|
-
export function createCollection
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
>(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
TKey,
|
|
247
|
-
TSchema,
|
|
248
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
249
|
-
> & { utils?: TUtils }
|
|
250
|
-
): Collection<
|
|
251
|
-
ResolveType<TExplicit, TSchema, TFallback>,
|
|
252
|
-
TKey,
|
|
253
|
-
TUtils,
|
|
254
|
-
TSchema,
|
|
255
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
256
|
-
> {
|
|
257
|
-
const collection = new CollectionImpl<
|
|
258
|
-
ResolveType<TExplicit, TSchema, TFallback>,
|
|
259
|
-
TKey,
|
|
260
|
-
TUtils,
|
|
261
|
-
TSchema,
|
|
262
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
263
|
-
>(options)
|
|
188
|
+
export function createCollection(
|
|
189
|
+
options: CollectionConfig<any, string | number, any> & {
|
|
190
|
+
schema?: StandardSchemaV1
|
|
191
|
+
utils?: UtilsRecord
|
|
192
|
+
}
|
|
193
|
+
): Collection<any, string | number, UtilsRecord, any, any> {
|
|
194
|
+
const collection = new CollectionImpl<any, string | number, any, any, any>(
|
|
195
|
+
options
|
|
196
|
+
)
|
|
264
197
|
|
|
265
198
|
// Copy utils to both top level and .utils namespace
|
|
266
199
|
if (options.utils) {
|
|
267
200
|
collection.utils = { ...options.utils }
|
|
268
201
|
} else {
|
|
269
|
-
collection.utils = {}
|
|
202
|
+
collection.utils = {}
|
|
270
203
|
}
|
|
271
204
|
|
|
272
|
-
return collection
|
|
273
|
-
ResolveType<TExplicit, TSchema, TFallback>,
|
|
274
|
-
TKey,
|
|
275
|
-
TUtils,
|
|
276
|
-
TSchema,
|
|
277
|
-
ResolveInsertInput<TExplicit, TSchema, TFallback>
|
|
278
|
-
>
|
|
205
|
+
return collection
|
|
279
206
|
}
|
|
280
207
|
|
|
281
208
|
export class CollectionImpl<
|
|
282
|
-
|
|
209
|
+
TOutput extends object = Record<string, unknown>,
|
|
283
210
|
TKey extends string | number = string | number,
|
|
284
211
|
TUtils extends UtilsRecord = {},
|
|
285
212
|
TSchema extends StandardSchemaV1 = StandardSchemaV1,
|
|
286
|
-
|
|
213
|
+
TInput extends object = TOutput,
|
|
287
214
|
> {
|
|
288
|
-
public config: CollectionConfig<
|
|
215
|
+
public config: CollectionConfig<TOutput, TKey, TSchema>
|
|
289
216
|
|
|
290
217
|
// Core state - make public for testing
|
|
291
218
|
public transactions: SortedMap<string, Transaction<any>>
|
|
292
|
-
public pendingSyncedTransactions: Array<PendingSyncedTransaction<
|
|
293
|
-
|
|
219
|
+
public pendingSyncedTransactions: Array<PendingSyncedTransaction<TOutput>> =
|
|
220
|
+
[]
|
|
221
|
+
public syncedData: Map<TKey, TOutput> | SortedMap<TKey, TOutput>
|
|
294
222
|
public syncedMetadata = new Map<TKey, unknown>()
|
|
295
223
|
|
|
296
224
|
// Optimistic state tracking - make public for testing
|
|
297
|
-
public optimisticUpserts = new Map<TKey,
|
|
225
|
+
public optimisticUpserts = new Map<TKey, TOutput>()
|
|
298
226
|
public optimisticDeletes = new Set<TKey>()
|
|
299
227
|
|
|
300
228
|
// Cached size for performance
|
|
@@ -307,8 +235,11 @@ export class CollectionImpl<
|
|
|
307
235
|
private indexCounter = 0
|
|
308
236
|
|
|
309
237
|
// Event system
|
|
310
|
-
private changeListeners = new Set<ChangeListener<
|
|
311
|
-
private changeKeyListeners = new Map<
|
|
238
|
+
private changeListeners = new Set<ChangeListener<TOutput, TKey>>()
|
|
239
|
+
private changeKeyListeners = new Map<
|
|
240
|
+
TKey,
|
|
241
|
+
Set<ChangeListener<TOutput, TKey>>
|
|
242
|
+
>()
|
|
312
243
|
|
|
313
244
|
// Utilities namespace
|
|
314
245
|
// This is populated by createCollection
|
|
@@ -316,7 +247,7 @@ export class CollectionImpl<
|
|
|
316
247
|
|
|
317
248
|
// State used for computing the change events
|
|
318
249
|
private syncedKeys = new Set<TKey>()
|
|
319
|
-
private preSyncVisibleState = new Map<TKey,
|
|
250
|
+
private preSyncVisibleState = new Map<TKey, TOutput>()
|
|
320
251
|
private recentlySyncedKeys = new Set<TKey>()
|
|
321
252
|
private hasReceivedFirstCommit = false
|
|
322
253
|
private isCommittingSyncTransactions = false
|
|
@@ -326,7 +257,7 @@ export class CollectionImpl<
|
|
|
326
257
|
private hasBeenReady = false
|
|
327
258
|
|
|
328
259
|
// Event batching for preventing duplicate emissions during transaction flows
|
|
329
|
-
private batchedEvents: Array<ChangeMessage<
|
|
260
|
+
private batchedEvents: Array<ChangeMessage<TOutput, TKey>> = []
|
|
330
261
|
private shouldBatchEvents = false
|
|
331
262
|
|
|
332
263
|
// Lifecycle management
|
|
@@ -481,7 +412,7 @@ export class CollectionImpl<
|
|
|
481
412
|
* @param config - Configuration object for the collection
|
|
482
413
|
* @throws Error if sync config is missing
|
|
483
414
|
*/
|
|
484
|
-
constructor(config: CollectionConfig<
|
|
415
|
+
constructor(config: CollectionConfig<TOutput, TKey, TSchema>) {
|
|
485
416
|
// eslint-disable-next-line
|
|
486
417
|
if (!config) {
|
|
487
418
|
throw new CollectionRequiresConfigError()
|
|
@@ -509,9 +440,9 @@ export class CollectionImpl<
|
|
|
509
440
|
|
|
510
441
|
// Set up data storage with optional comparison function
|
|
511
442
|
if (this.config.compare) {
|
|
512
|
-
this.syncedData = new SortedMap<TKey,
|
|
443
|
+
this.syncedData = new SortedMap<TKey, TOutput>(this.config.compare)
|
|
513
444
|
} else {
|
|
514
|
-
this.syncedData = new Map<TKey,
|
|
445
|
+
this.syncedData = new Map<TKey, TOutput>()
|
|
515
446
|
}
|
|
516
447
|
|
|
517
448
|
// Only start sync immediately if explicitly enabled
|
|
@@ -549,7 +480,7 @@ export class CollectionImpl<
|
|
|
549
480
|
deletedKeys: new Set(),
|
|
550
481
|
})
|
|
551
482
|
},
|
|
552
|
-
write: (messageWithoutKey: Omit<ChangeMessage<
|
|
483
|
+
write: (messageWithoutKey: Omit<ChangeMessage<TOutput>, `key`>) => {
|
|
553
484
|
const pendingTransaction =
|
|
554
485
|
this.pendingSyncedTransactions[
|
|
555
486
|
this.pendingSyncedTransactions.length - 1
|
|
@@ -578,7 +509,7 @@ export class CollectionImpl<
|
|
|
578
509
|
}
|
|
579
510
|
}
|
|
580
511
|
|
|
581
|
-
const message: ChangeMessage<
|
|
512
|
+
const message: ChangeMessage<TOutput> = {
|
|
582
513
|
...messageWithoutKey,
|
|
583
514
|
key,
|
|
584
515
|
}
|
|
@@ -831,7 +762,10 @@ export class CollectionImpl<
|
|
|
831
762
|
switch (mutation.type) {
|
|
832
763
|
case `insert`:
|
|
833
764
|
case `update`:
|
|
834
|
-
this.optimisticUpserts.set(
|
|
765
|
+
this.optimisticUpserts.set(
|
|
766
|
+
mutation.key,
|
|
767
|
+
mutation.modified as TOutput
|
|
768
|
+
)
|
|
835
769
|
this.optimisticDeletes.delete(mutation.key)
|
|
836
770
|
break
|
|
837
771
|
case `delete`:
|
|
@@ -847,7 +781,7 @@ export class CollectionImpl<
|
|
|
847
781
|
this._size = this.calculateSize()
|
|
848
782
|
|
|
849
783
|
// Collect events for changes
|
|
850
|
-
const events: Array<ChangeMessage<
|
|
784
|
+
const events: Array<ChangeMessage<TOutput, TKey>> = []
|
|
851
785
|
this.collectOptimisticChanges(previousState, previousDeletes, events)
|
|
852
786
|
|
|
853
787
|
// Filter out events for recently synced keys to prevent duplicates
|
|
@@ -934,9 +868,9 @@ export class CollectionImpl<
|
|
|
934
868
|
* Collect events for optimistic changes
|
|
935
869
|
*/
|
|
936
870
|
private collectOptimisticChanges(
|
|
937
|
-
previousUpserts: Map<TKey,
|
|
871
|
+
previousUpserts: Map<TKey, TOutput>,
|
|
938
872
|
previousDeletes: Set<TKey>,
|
|
939
|
-
events: Array<ChangeMessage<
|
|
873
|
+
events: Array<ChangeMessage<TOutput, TKey>>
|
|
940
874
|
): void {
|
|
941
875
|
const allKeys = new Set([
|
|
942
876
|
...previousUpserts.keys(),
|
|
@@ -977,9 +911,9 @@ export class CollectionImpl<
|
|
|
977
911
|
*/
|
|
978
912
|
private getPreviousValue(
|
|
979
913
|
key: TKey,
|
|
980
|
-
previousUpserts: Map<TKey,
|
|
914
|
+
previousUpserts: Map<TKey, TOutput>,
|
|
981
915
|
previousDeletes: Set<TKey>
|
|
982
|
-
):
|
|
916
|
+
): TOutput | undefined {
|
|
983
917
|
if (previousDeletes.has(key)) {
|
|
984
918
|
return undefined
|
|
985
919
|
}
|
|
@@ -1010,7 +944,7 @@ export class CollectionImpl<
|
|
|
1010
944
|
* Emit events either immediately or batch them for later emission
|
|
1011
945
|
*/
|
|
1012
946
|
private emitEvents(
|
|
1013
|
-
changes: Array<ChangeMessage<
|
|
947
|
+
changes: Array<ChangeMessage<TOutput, TKey>>,
|
|
1014
948
|
forceEmit = false
|
|
1015
949
|
): void {
|
|
1016
950
|
// Skip batching for user actions (forceEmit=true) to keep UI responsive
|
|
@@ -1040,7 +974,7 @@ export class CollectionImpl<
|
|
|
1040
974
|
// Emit to key-specific listeners
|
|
1041
975
|
if (this.changeKeyListeners.size > 0) {
|
|
1042
976
|
// Group changes by key, but only for keys that have listeners
|
|
1043
|
-
const changesByKey = new Map<TKey, Array<ChangeMessage<
|
|
977
|
+
const changesByKey = new Map<TKey, Array<ChangeMessage<TOutput, TKey>>>()
|
|
1044
978
|
for (const change of eventsToEmit) {
|
|
1045
979
|
if (this.changeKeyListeners.has(change.key)) {
|
|
1046
980
|
if (!changesByKey.has(change.key)) {
|
|
@@ -1063,7 +997,7 @@ export class CollectionImpl<
|
|
|
1063
997
|
/**
|
|
1064
998
|
* Get the current value for a key (virtual derived state)
|
|
1065
999
|
*/
|
|
1066
|
-
public get(key: TKey):
|
|
1000
|
+
public get(key: TKey): TOutput | undefined {
|
|
1067
1001
|
// Check if optimistically deleted
|
|
1068
1002
|
if (this.optimisticDeletes.has(key)) {
|
|
1069
1003
|
return undefined
|
|
@@ -1126,7 +1060,7 @@ export class CollectionImpl<
|
|
|
1126
1060
|
/**
|
|
1127
1061
|
* Get all values (virtual derived state)
|
|
1128
1062
|
*/
|
|
1129
|
-
public *values(): IterableIterator<
|
|
1063
|
+
public *values(): IterableIterator<TOutput> {
|
|
1130
1064
|
for (const key of this.keys()) {
|
|
1131
1065
|
const value = this.get(key)
|
|
1132
1066
|
if (value !== undefined) {
|
|
@@ -1138,7 +1072,7 @@ export class CollectionImpl<
|
|
|
1138
1072
|
/**
|
|
1139
1073
|
* Get all entries (virtual derived state)
|
|
1140
1074
|
*/
|
|
1141
|
-
public *entries(): IterableIterator<[TKey,
|
|
1075
|
+
public *entries(): IterableIterator<[TKey, TOutput]> {
|
|
1142
1076
|
for (const key of this.keys()) {
|
|
1143
1077
|
const value = this.get(key)
|
|
1144
1078
|
if (value !== undefined) {
|
|
@@ -1150,7 +1084,7 @@ export class CollectionImpl<
|
|
|
1150
1084
|
/**
|
|
1151
1085
|
* Get all entries (virtual derived state)
|
|
1152
1086
|
*/
|
|
1153
|
-
public *[Symbol.iterator](): IterableIterator<[TKey,
|
|
1087
|
+
public *[Symbol.iterator](): IterableIterator<[TKey, TOutput]> {
|
|
1154
1088
|
for (const [key, value] of this.entries()) {
|
|
1155
1089
|
yield [key, value]
|
|
1156
1090
|
}
|
|
@@ -1160,7 +1094,7 @@ export class CollectionImpl<
|
|
|
1160
1094
|
* Execute a callback for each entry in the collection
|
|
1161
1095
|
*/
|
|
1162
1096
|
public forEach(
|
|
1163
|
-
callbackfn: (value:
|
|
1097
|
+
callbackfn: (value: TOutput, key: TKey, index: number) => void
|
|
1164
1098
|
): void {
|
|
1165
1099
|
let index = 0
|
|
1166
1100
|
for (const [key, value] of this.entries()) {
|
|
@@ -1172,7 +1106,7 @@ export class CollectionImpl<
|
|
|
1172
1106
|
* Create a new array with the results of calling a function for each entry in the collection
|
|
1173
1107
|
*/
|
|
1174
1108
|
public map<U>(
|
|
1175
|
-
callbackfn: (value:
|
|
1109
|
+
callbackfn: (value: TOutput, key: TKey, index: number) => U
|
|
1176
1110
|
): Array<U> {
|
|
1177
1111
|
const result: Array<U> = []
|
|
1178
1112
|
let index = 0
|
|
@@ -1215,8 +1149,12 @@ export class CollectionImpl<
|
|
|
1215
1149
|
return acc
|
|
1216
1150
|
},
|
|
1217
1151
|
{
|
|
1218
|
-
committedSyncedTransactions: [] as Array<
|
|
1219
|
-
|
|
1152
|
+
committedSyncedTransactions: [] as Array<
|
|
1153
|
+
PendingSyncedTransaction<TOutput>
|
|
1154
|
+
>,
|
|
1155
|
+
uncommittedSyncedTransactions: [] as Array<
|
|
1156
|
+
PendingSyncedTransaction<TOutput>
|
|
1157
|
+
>,
|
|
1220
1158
|
hasTruncateSync: false,
|
|
1221
1159
|
}
|
|
1222
1160
|
)
|
|
@@ -1238,7 +1176,7 @@ export class CollectionImpl<
|
|
|
1238
1176
|
let currentVisibleState = this.preSyncVisibleState
|
|
1239
1177
|
if (currentVisibleState.size === 0) {
|
|
1240
1178
|
// No pre-captured state, capture it now for pure sync operations
|
|
1241
|
-
currentVisibleState = new Map<TKey,
|
|
1179
|
+
currentVisibleState = new Map<TKey, TOutput>()
|
|
1242
1180
|
for (const key of changedKeys) {
|
|
1243
1181
|
const currentValue = this.get(key)
|
|
1244
1182
|
if (currentValue !== undefined) {
|
|
@@ -1247,7 +1185,7 @@ export class CollectionImpl<
|
|
|
1247
1185
|
}
|
|
1248
1186
|
}
|
|
1249
1187
|
|
|
1250
|
-
const events: Array<ChangeMessage<
|
|
1188
|
+
const events: Array<ChangeMessage<TOutput, TKey>> = []
|
|
1251
1189
|
const rowUpdateMode = this.config.sync.rowUpdateMode || `partial`
|
|
1252
1190
|
|
|
1253
1191
|
for (const transaction of committedSyncedTransactions) {
|
|
@@ -1346,7 +1284,7 @@ export class CollectionImpl<
|
|
|
1346
1284
|
|
|
1347
1285
|
// Build re-apply sets from ACTIVE optimistic transactions against the new synced base
|
|
1348
1286
|
// We do not copy maps; we compute intent directly from transactions to avoid drift.
|
|
1349
|
-
const reapplyUpserts = new Map<TKey,
|
|
1287
|
+
const reapplyUpserts = new Map<TKey, TOutput>()
|
|
1350
1288
|
const reapplyDeletes = new Set<TKey>()
|
|
1351
1289
|
|
|
1352
1290
|
for (const tx of this.transactions.values()) {
|
|
@@ -1356,14 +1294,14 @@ export class CollectionImpl<
|
|
|
1356
1294
|
const key = mutation.key as TKey
|
|
1357
1295
|
switch (mutation.type) {
|
|
1358
1296
|
case `insert`:
|
|
1359
|
-
reapplyUpserts.set(key, mutation.modified as
|
|
1297
|
+
reapplyUpserts.set(key, mutation.modified as TOutput)
|
|
1360
1298
|
reapplyDeletes.delete(key)
|
|
1361
1299
|
break
|
|
1362
1300
|
case `update`: {
|
|
1363
1301
|
const base = this.syncedData.get(key)
|
|
1364
1302
|
const next = base
|
|
1365
|
-
? (Object.assign({}, base, mutation.changes) as
|
|
1366
|
-
: (mutation.modified as
|
|
1303
|
+
? (Object.assign({}, base, mutation.changes) as TOutput)
|
|
1304
|
+
: (mutation.modified as TOutput)
|
|
1367
1305
|
reapplyUpserts.set(key, next)
|
|
1368
1306
|
reapplyDeletes.delete(key)
|
|
1369
1307
|
break
|
|
@@ -1401,7 +1339,7 @@ export class CollectionImpl<
|
|
|
1401
1339
|
|
|
1402
1340
|
// Finally, ensure we do NOT insert keys that have an outstanding optimistic delete.
|
|
1403
1341
|
if (events.length > 0 && reapplyDeletes.size > 0) {
|
|
1404
|
-
const filtered: Array<ChangeMessage<
|
|
1342
|
+
const filtered: Array<ChangeMessage<TOutput, TKey>> = []
|
|
1405
1343
|
for (const evt of events) {
|
|
1406
1344
|
if (evt.type === `insert` && reapplyDeletes.has(evt.key)) {
|
|
1407
1345
|
continue
|
|
@@ -1435,7 +1373,7 @@ export class CollectionImpl<
|
|
|
1435
1373
|
case `update`:
|
|
1436
1374
|
this.optimisticUpserts.set(
|
|
1437
1375
|
mutation.key,
|
|
1438
|
-
mutation.modified as
|
|
1376
|
+
mutation.modified as TOutput
|
|
1439
1377
|
)
|
|
1440
1378
|
this.optimisticDeletes.delete(mutation.key)
|
|
1441
1379
|
break
|
|
@@ -1566,16 +1504,16 @@ export class CollectionImpl<
|
|
|
1566
1504
|
})
|
|
1567
1505
|
}
|
|
1568
1506
|
|
|
1569
|
-
private ensureStandardSchema(schema: unknown): StandardSchema<
|
|
1507
|
+
private ensureStandardSchema(schema: unknown): StandardSchema<TOutput> {
|
|
1570
1508
|
// If the schema already implements the standard-schema interface, return it
|
|
1571
1509
|
if (schema && `~standard` in (schema as {})) {
|
|
1572
|
-
return schema as StandardSchema<
|
|
1510
|
+
return schema as StandardSchema<TOutput>
|
|
1573
1511
|
}
|
|
1574
1512
|
|
|
1575
1513
|
throw new InvalidSchemaError()
|
|
1576
1514
|
}
|
|
1577
1515
|
|
|
1578
|
-
public getKeyFromItem(item:
|
|
1516
|
+
public getKeyFromItem(item: TOutput): TKey {
|
|
1579
1517
|
return this.config.getKey(item)
|
|
1580
1518
|
}
|
|
1581
1519
|
|
|
@@ -1618,13 +1556,13 @@ export class CollectionImpl<
|
|
|
1618
1556
|
* })
|
|
1619
1557
|
*/
|
|
1620
1558
|
public createIndex<TResolver extends IndexResolver<TKey> = typeof BTreeIndex>(
|
|
1621
|
-
indexCallback: (row: SingleRowRefProxy<
|
|
1559
|
+
indexCallback: (row: SingleRowRefProxy<TOutput>) => any,
|
|
1622
1560
|
config: IndexOptions<TResolver> = {}
|
|
1623
1561
|
): IndexProxy<TKey> {
|
|
1624
1562
|
this.validateCollectionUsable(`createIndex`)
|
|
1625
1563
|
|
|
1626
1564
|
const indexId = ++this.indexCounter
|
|
1627
|
-
const singleRowRefProxy = createSingleRowRefProxy<
|
|
1565
|
+
const singleRowRefProxy = createSingleRowRefProxy<TOutput>()
|
|
1628
1566
|
const indexExpression = indexCallback(singleRowRefProxy)
|
|
1629
1567
|
const expression = toExpression(indexExpression)
|
|
1630
1568
|
|
|
@@ -1720,7 +1658,7 @@ export class CollectionImpl<
|
|
|
1720
1658
|
* Updates all indexes when the collection changes
|
|
1721
1659
|
* @private
|
|
1722
1660
|
*/
|
|
1723
|
-
private updateIndexes(changes: Array<ChangeMessage<
|
|
1661
|
+
private updateIndexes(changes: Array<ChangeMessage<TOutput, TKey>>): void {
|
|
1724
1662
|
for (const index of this.resolvedIndexes.values()) {
|
|
1725
1663
|
for (const change of changes) {
|
|
1726
1664
|
switch (change.type) {
|
|
@@ -1746,8 +1684,8 @@ export class CollectionImpl<
|
|
|
1746
1684
|
data: unknown,
|
|
1747
1685
|
type: `insert` | `update`,
|
|
1748
1686
|
key?: TKey
|
|
1749
|
-
):
|
|
1750
|
-
if (!this.config.schema) return data as
|
|
1687
|
+
): TOutput | never {
|
|
1688
|
+
if (!this.config.schema) return data as TOutput
|
|
1751
1689
|
|
|
1752
1690
|
const standardSchema = this.ensureStandardSchema(this.config.schema)
|
|
1753
1691
|
|
|
@@ -1782,9 +1720,14 @@ export class CollectionImpl<
|
|
|
1782
1720
|
throw new SchemaValidationError(type, typedIssues)
|
|
1783
1721
|
}
|
|
1784
1722
|
|
|
1785
|
-
//
|
|
1786
|
-
|
|
1787
|
-
|
|
1723
|
+
// Extract only the modified keys from the validated result
|
|
1724
|
+
const validatedMergedData = result.value as TOutput
|
|
1725
|
+
const modifiedKeys = Object.keys(data)
|
|
1726
|
+
const extractedChanges = Object.fromEntries(
|
|
1727
|
+
modifiedKeys.map((k) => [k, validatedMergedData[k as keyof TOutput]])
|
|
1728
|
+
) as TOutput
|
|
1729
|
+
|
|
1730
|
+
return extractedChanges
|
|
1788
1731
|
}
|
|
1789
1732
|
}
|
|
1790
1733
|
|
|
@@ -1805,7 +1748,7 @@ export class CollectionImpl<
|
|
|
1805
1748
|
throw new SchemaValidationError(type, typedIssues)
|
|
1806
1749
|
}
|
|
1807
1750
|
|
|
1808
|
-
return result.value as
|
|
1751
|
+
return result.value as TOutput
|
|
1809
1752
|
}
|
|
1810
1753
|
|
|
1811
1754
|
/**
|
|
@@ -1844,10 +1787,7 @@ export class CollectionImpl<
|
|
|
1844
1787
|
* console.log('Insert failed:', error)
|
|
1845
1788
|
* }
|
|
1846
1789
|
*/
|
|
1847
|
-
insert = (
|
|
1848
|
-
data: TInsertInput | Array<TInsertInput>,
|
|
1849
|
-
config?: InsertConfig
|
|
1850
|
-
) => {
|
|
1790
|
+
insert = (data: TInput | Array<TInput>, config?: InsertConfig) => {
|
|
1851
1791
|
this.validateCollectionUsable(`insert`)
|
|
1852
1792
|
const ambientTransaction = getActiveTransaction()
|
|
1853
1793
|
|
|
@@ -1857,7 +1797,7 @@ export class CollectionImpl<
|
|
|
1857
1797
|
}
|
|
1858
1798
|
|
|
1859
1799
|
const items = Array.isArray(data) ? data : [data]
|
|
1860
|
-
const mutations: Array<PendingMutation<
|
|
1800
|
+
const mutations: Array<PendingMutation<TOutput>> = []
|
|
1861
1801
|
|
|
1862
1802
|
// Create mutations for each item
|
|
1863
1803
|
items.forEach((item) => {
|
|
@@ -1871,7 +1811,7 @@ export class CollectionImpl<
|
|
|
1871
1811
|
}
|
|
1872
1812
|
const globalKey = this.generateGlobalKey(key, item)
|
|
1873
1813
|
|
|
1874
|
-
const mutation: PendingMutation<
|
|
1814
|
+
const mutation: PendingMutation<TOutput, `insert`> = {
|
|
1875
1815
|
mutationId: crypto.randomUUID(),
|
|
1876
1816
|
original: {},
|
|
1877
1817
|
modified: validatedData,
|
|
@@ -1883,7 +1823,7 @@ export class CollectionImpl<
|
|
|
1883
1823
|
k,
|
|
1884
1824
|
validatedData[k as keyof typeof validatedData],
|
|
1885
1825
|
])
|
|
1886
|
-
) as
|
|
1826
|
+
) as TInput,
|
|
1887
1827
|
globalKey,
|
|
1888
1828
|
key,
|
|
1889
1829
|
metadata: config?.metadata as unknown,
|
|
@@ -1909,16 +1849,16 @@ export class CollectionImpl<
|
|
|
1909
1849
|
return ambientTransaction
|
|
1910
1850
|
} else {
|
|
1911
1851
|
// Create a new transaction with a mutation function that calls the onInsert handler
|
|
1912
|
-
const directOpTransaction = createTransaction<
|
|
1852
|
+
const directOpTransaction = createTransaction<TOutput>({
|
|
1913
1853
|
mutationFn: async (params) => {
|
|
1914
1854
|
// Call the onInsert handler with the transaction and collection
|
|
1915
1855
|
return await this.config.onInsert!({
|
|
1916
1856
|
transaction:
|
|
1917
1857
|
params.transaction as unknown as TransactionWithMutations<
|
|
1918
|
-
|
|
1858
|
+
TOutput,
|
|
1919
1859
|
`insert`
|
|
1920
1860
|
>,
|
|
1921
|
-
collection: this as unknown as Collection<
|
|
1861
|
+
collection: this as unknown as Collection<TOutput, TKey, TUtils>,
|
|
1922
1862
|
})
|
|
1923
1863
|
},
|
|
1924
1864
|
})
|
|
@@ -1977,37 +1917,40 @@ export class CollectionImpl<
|
|
|
1977
1917
|
*/
|
|
1978
1918
|
|
|
1979
1919
|
// Overload 1: Update multiple items with a callback
|
|
1980
|
-
update
|
|
1920
|
+
update(
|
|
1981
1921
|
key: Array<TKey | unknown>,
|
|
1982
|
-
callback: (drafts: Array<WritableDeep<
|
|
1922
|
+
callback: (drafts: Array<WritableDeep<TInput>>) => void
|
|
1983
1923
|
): TransactionType
|
|
1984
1924
|
|
|
1985
1925
|
// Overload 2: Update multiple items with config and a callback
|
|
1986
|
-
update
|
|
1926
|
+
update(
|
|
1987
1927
|
keys: Array<TKey | unknown>,
|
|
1988
1928
|
config: OperationConfig,
|
|
1989
|
-
callback: (drafts: Array<WritableDeep<
|
|
1929
|
+
callback: (drafts: Array<WritableDeep<TInput>>) => void
|
|
1990
1930
|
): TransactionType
|
|
1991
1931
|
|
|
1992
1932
|
// Overload 3: Update a single item with a callback
|
|
1993
|
-
update
|
|
1933
|
+
update(
|
|
1994
1934
|
id: TKey | unknown,
|
|
1995
|
-
callback: (draft: WritableDeep<
|
|
1935
|
+
callback: (draft: WritableDeep<TInput>) => void
|
|
1996
1936
|
): TransactionType
|
|
1997
1937
|
|
|
1998
1938
|
// Overload 4: Update a single item with config and a callback
|
|
1999
|
-
update
|
|
1939
|
+
update(
|
|
2000
1940
|
id: TKey | unknown,
|
|
2001
1941
|
config: OperationConfig,
|
|
2002
|
-
callback: (draft: WritableDeep<
|
|
1942
|
+
callback: (draft: WritableDeep<TInput>) => void
|
|
2003
1943
|
): TransactionType
|
|
2004
1944
|
|
|
2005
|
-
update
|
|
1945
|
+
update(
|
|
2006
1946
|
keys: (TKey | unknown) | Array<TKey | unknown>,
|
|
2007
1947
|
configOrCallback:
|
|
2008
|
-
| ((draft: WritableDeep<
|
|
1948
|
+
| ((draft: WritableDeep<TInput>) => void)
|
|
1949
|
+
| ((drafts: Array<WritableDeep<TInput>>) => void)
|
|
2009
1950
|
| OperationConfig,
|
|
2010
|
-
maybeCallback?:
|
|
1951
|
+
maybeCallback?:
|
|
1952
|
+
| ((draft: WritableDeep<TInput>) => void)
|
|
1953
|
+
| ((drafts: Array<WritableDeep<TInput>>) => void)
|
|
2011
1954
|
) {
|
|
2012
1955
|
if (typeof keys === `undefined`) {
|
|
2013
1956
|
throw new MissingUpdateArgumentError()
|
|
@@ -2042,25 +1985,25 @@ export class CollectionImpl<
|
|
|
2042
1985
|
}
|
|
2043
1986
|
|
|
2044
1987
|
return item
|
|
2045
|
-
}) as unknown as Array<
|
|
1988
|
+
}) as unknown as Array<TInput>
|
|
2046
1989
|
|
|
2047
1990
|
let changesArray
|
|
2048
1991
|
if (isArray) {
|
|
2049
1992
|
// Use the proxy to track changes for all objects
|
|
2050
1993
|
changesArray = withArrayChangeTracking(
|
|
2051
1994
|
currentObjects,
|
|
2052
|
-
callback as (draft: Array<
|
|
1995
|
+
callback as (draft: Array<TInput>) => void
|
|
2053
1996
|
)
|
|
2054
1997
|
} else {
|
|
2055
1998
|
const result = withChangeTracking(
|
|
2056
1999
|
currentObjects[0]!,
|
|
2057
|
-
callback as (draft:
|
|
2000
|
+
callback as (draft: TInput) => void
|
|
2058
2001
|
)
|
|
2059
2002
|
changesArray = [result]
|
|
2060
2003
|
}
|
|
2061
2004
|
|
|
2062
2005
|
// Create mutations for each object that has changes
|
|
2063
|
-
const mutations: Array<PendingMutation<
|
|
2006
|
+
const mutations: Array<PendingMutation<TOutput, `update`, this>> = keysArray
|
|
2064
2007
|
.map((key, index) => {
|
|
2065
2008
|
const itemChanges = changesArray[index] // User-provided changes for this specific item
|
|
2066
2009
|
|
|
@@ -2069,7 +2012,7 @@ export class CollectionImpl<
|
|
|
2069
2012
|
return null
|
|
2070
2013
|
}
|
|
2071
2014
|
|
|
2072
|
-
const originalItem = currentObjects[index] as unknown as
|
|
2015
|
+
const originalItem = currentObjects[index] as unknown as TOutput
|
|
2073
2016
|
// Validate the user-provided changes for this item
|
|
2074
2017
|
const validatedUpdatePayload = this.validateData(
|
|
2075
2018
|
itemChanges,
|
|
@@ -2098,7 +2041,16 @@ export class CollectionImpl<
|
|
|
2098
2041
|
mutationId: crypto.randomUUID(),
|
|
2099
2042
|
original: originalItem,
|
|
2100
2043
|
modified: modifiedItem,
|
|
2101
|
-
|
|
2044
|
+
// Pick the values from modifiedItem based on what's passed in - this is for cases
|
|
2045
|
+
// where a schema has default values or transforms. The modified data has the extra
|
|
2046
|
+
// default or transformed values but for changes, we just want to show the data that
|
|
2047
|
+
// was actually passed in.
|
|
2048
|
+
changes: Object.fromEntries(
|
|
2049
|
+
Object.keys(itemChanges).map((k) => [
|
|
2050
|
+
k,
|
|
2051
|
+
modifiedItem[k as keyof typeof modifiedItem],
|
|
2052
|
+
])
|
|
2053
|
+
) as TInput,
|
|
2102
2054
|
globalKey,
|
|
2103
2055
|
key,
|
|
2104
2056
|
metadata: config.metadata as unknown,
|
|
@@ -2113,7 +2065,7 @@ export class CollectionImpl<
|
|
|
2113
2065
|
collection: this,
|
|
2114
2066
|
}
|
|
2115
2067
|
})
|
|
2116
|
-
.filter(Boolean) as Array<PendingMutation<
|
|
2068
|
+
.filter(Boolean) as Array<PendingMutation<TOutput, `update`, this>>
|
|
2117
2069
|
|
|
2118
2070
|
// If no changes were made, return an empty transaction early
|
|
2119
2071
|
if (mutations.length === 0) {
|
|
@@ -2140,16 +2092,16 @@ export class CollectionImpl<
|
|
|
2140
2092
|
// No need to check for onUpdate handler here as we've already checked at the beginning
|
|
2141
2093
|
|
|
2142
2094
|
// Create a new transaction with a mutation function that calls the onUpdate handler
|
|
2143
|
-
const directOpTransaction = createTransaction<
|
|
2095
|
+
const directOpTransaction = createTransaction<TOutput>({
|
|
2144
2096
|
mutationFn: async (params) => {
|
|
2145
2097
|
// Call the onUpdate handler with the transaction and collection
|
|
2146
2098
|
return this.config.onUpdate!({
|
|
2147
2099
|
transaction:
|
|
2148
2100
|
params.transaction as unknown as TransactionWithMutations<
|
|
2149
|
-
|
|
2101
|
+
TOutput,
|
|
2150
2102
|
`update`
|
|
2151
2103
|
>,
|
|
2152
|
-
collection: this as unknown as Collection<
|
|
2104
|
+
collection: this as unknown as Collection<TOutput, TKey, TUtils>,
|
|
2153
2105
|
})
|
|
2154
2106
|
},
|
|
2155
2107
|
})
|
|
@@ -2215,14 +2167,14 @@ export class CollectionImpl<
|
|
|
2215
2167
|
}
|
|
2216
2168
|
|
|
2217
2169
|
const keysArray = Array.isArray(keys) ? keys : [keys]
|
|
2218
|
-
const mutations: Array<PendingMutation<
|
|
2170
|
+
const mutations: Array<PendingMutation<TOutput, `delete`, this>> = []
|
|
2219
2171
|
|
|
2220
2172
|
for (const key of keysArray) {
|
|
2221
2173
|
if (!this.has(key)) {
|
|
2222
2174
|
throw new DeleteKeyNotFoundError(key)
|
|
2223
2175
|
}
|
|
2224
2176
|
const globalKey = this.generateGlobalKey(key, this.get(key)!)
|
|
2225
|
-
const mutation: PendingMutation<
|
|
2177
|
+
const mutation: PendingMutation<TOutput, `delete`, this> = {
|
|
2226
2178
|
mutationId: crypto.randomUUID(),
|
|
2227
2179
|
original: this.get(key)!,
|
|
2228
2180
|
modified: this.get(key)!,
|
|
@@ -2256,17 +2208,17 @@ export class CollectionImpl<
|
|
|
2256
2208
|
}
|
|
2257
2209
|
|
|
2258
2210
|
// Create a new transaction with a mutation function that calls the onDelete handler
|
|
2259
|
-
const directOpTransaction = createTransaction<
|
|
2211
|
+
const directOpTransaction = createTransaction<TOutput>({
|
|
2260
2212
|
autoCommit: true,
|
|
2261
2213
|
mutationFn: async (params) => {
|
|
2262
2214
|
// Call the onDelete handler with the transaction and collection
|
|
2263
2215
|
return this.config.onDelete!({
|
|
2264
2216
|
transaction:
|
|
2265
2217
|
params.transaction as unknown as TransactionWithMutations<
|
|
2266
|
-
|
|
2218
|
+
TOutput,
|
|
2267
2219
|
`delete`
|
|
2268
2220
|
>,
|
|
2269
|
-
collection: this as unknown as Collection<
|
|
2221
|
+
collection: this as unknown as Collection<TOutput, TKey, TUtils>,
|
|
2270
2222
|
})
|
|
2271
2223
|
},
|
|
2272
2224
|
})
|
|
@@ -2299,7 +2251,7 @@ export class CollectionImpl<
|
|
|
2299
2251
|
* }
|
|
2300
2252
|
*/
|
|
2301
2253
|
get state() {
|
|
2302
|
-
const result = new Map<TKey,
|
|
2254
|
+
const result = new Map<TKey, TOutput>()
|
|
2303
2255
|
for (const [key, value] of this.entries()) {
|
|
2304
2256
|
result.set(key, value)
|
|
2305
2257
|
}
|
|
@@ -2312,14 +2264,14 @@ export class CollectionImpl<
|
|
|
2312
2264
|
*
|
|
2313
2265
|
* @returns Promise that resolves to a Map containing all items in the collection
|
|
2314
2266
|
*/
|
|
2315
|
-
stateWhenReady(): Promise<Map<TKey,
|
|
2267
|
+
stateWhenReady(): Promise<Map<TKey, TOutput>> {
|
|
2316
2268
|
// If we already have data or collection is ready, resolve immediately
|
|
2317
2269
|
if (this.size > 0 || this.isReady()) {
|
|
2318
2270
|
return Promise.resolve(this.state)
|
|
2319
2271
|
}
|
|
2320
2272
|
|
|
2321
2273
|
// Otherwise, wait for the collection to be ready
|
|
2322
|
-
return new Promise<Map<TKey,
|
|
2274
|
+
return new Promise<Map<TKey, TOutput>>((resolve) => {
|
|
2323
2275
|
this.onFirstReady(() => {
|
|
2324
2276
|
resolve(this.state)
|
|
2325
2277
|
})
|
|
@@ -2341,14 +2293,14 @@ export class CollectionImpl<
|
|
|
2341
2293
|
*
|
|
2342
2294
|
* @returns Promise that resolves to an Array containing all items in the collection
|
|
2343
2295
|
*/
|
|
2344
|
-
toArrayWhenReady(): Promise<Array<
|
|
2296
|
+
toArrayWhenReady(): Promise<Array<TOutput>> {
|
|
2345
2297
|
// If we already have data or collection is ready, resolve immediately
|
|
2346
2298
|
if (this.size > 0 || this.isReady()) {
|
|
2347
2299
|
return Promise.resolve(this.toArray)
|
|
2348
2300
|
}
|
|
2349
2301
|
|
|
2350
2302
|
// Otherwise, wait for the collection to be ready
|
|
2351
|
-
return new Promise<Array<
|
|
2303
|
+
return new Promise<Array<TOutput>>((resolve) => {
|
|
2352
2304
|
this.onFirstReady(() => {
|
|
2353
2305
|
resolve(this.toArray)
|
|
2354
2306
|
})
|
|
@@ -2374,8 +2326,8 @@ export class CollectionImpl<
|
|
|
2374
2326
|
* })
|
|
2375
2327
|
*/
|
|
2376
2328
|
public currentStateAsChanges(
|
|
2377
|
-
options: CurrentStateAsChangesOptions<
|
|
2378
|
-
): Array<ChangeMessage<
|
|
2329
|
+
options: CurrentStateAsChangesOptions<TOutput> = {}
|
|
2330
|
+
): Array<ChangeMessage<TOutput>> {
|
|
2379
2331
|
return currentStateAsChanges(this, options)
|
|
2380
2332
|
}
|
|
2381
2333
|
|
|
@@ -2419,8 +2371,8 @@ export class CollectionImpl<
|
|
|
2419
2371
|
* })
|
|
2420
2372
|
*/
|
|
2421
2373
|
public subscribeChanges(
|
|
2422
|
-
callback: (changes: Array<ChangeMessage<
|
|
2423
|
-
options: SubscribeChangesOptions<
|
|
2374
|
+
callback: (changes: Array<ChangeMessage<TOutput>>) => void,
|
|
2375
|
+
options: SubscribeChangesOptions<TOutput> = {}
|
|
2424
2376
|
): () => void {
|
|
2425
2377
|
// Start sync and track subscriber
|
|
2426
2378
|
this.addSubscriber()
|
|
@@ -2459,7 +2411,7 @@ export class CollectionImpl<
|
|
|
2459
2411
|
*/
|
|
2460
2412
|
public subscribeChangesKey(
|
|
2461
2413
|
key: TKey,
|
|
2462
|
-
listener: ChangeListener<
|
|
2414
|
+
listener: ChangeListener<TOutput, TKey>,
|
|
2463
2415
|
{ includeInitialState = false }: { includeInitialState?: boolean } = {}
|
|
2464
2416
|
): () => void {
|
|
2465
2417
|
// Start sync and track subscriber
|