@tanstack/db 0.0.11 → 0.0.13
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/SortedMap.cjs +38 -11
- package/dist/cjs/SortedMap.cjs.map +1 -1
- package/dist/cjs/SortedMap.d.cts +10 -0
- package/dist/cjs/collection.cjs +476 -144
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +107 -32
- package/dist/cjs/index.cjs +2 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/optimistic-action.cjs +21 -0
- package/dist/cjs/optimistic-action.cjs.map +1 -0
- package/dist/cjs/optimistic-action.d.cts +39 -0
- package/dist/cjs/query/compiled-query.cjs +38 -16
- package/dist/cjs/query/compiled-query.cjs.map +1 -1
- package/dist/cjs/query/query-builder.cjs +2 -2
- package/dist/cjs/query/query-builder.cjs.map +1 -1
- package/dist/cjs/transactions.cjs +3 -1
- package/dist/cjs/transactions.cjs.map +1 -1
- package/dist/cjs/types.d.cts +83 -10
- package/dist/esm/SortedMap.d.ts +10 -0
- package/dist/esm/SortedMap.js +38 -11
- package/dist/esm/SortedMap.js.map +1 -1
- package/dist/esm/collection.d.ts +107 -32
- package/dist/esm/collection.js +477 -145
- package/dist/esm/collection.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/optimistic-action.d.ts +39 -0
- package/dist/esm/optimistic-action.js +21 -0
- package/dist/esm/optimistic-action.js.map +1 -0
- package/dist/esm/query/compiled-query.js +38 -16
- package/dist/esm/query/compiled-query.js.map +1 -1
- package/dist/esm/query/query-builder.js +2 -2
- package/dist/esm/query/query-builder.js.map +1 -1
- package/dist/esm/transactions.js +3 -1
- package/dist/esm/transactions.js.map +1 -1
- package/dist/esm/types.d.ts +83 -10
- package/package.json +1 -1
- package/src/SortedMap.ts +46 -13
- package/src/collection.ts +689 -239
- package/src/index.ts +1 -0
- package/src/optimistic-action.ts +65 -0
- package/src/query/compiled-query.ts +79 -21
- package/src/query/query-builder.ts +2 -2
- package/src/transactions.ts +6 -1
- package/src/types.ts +124 -8
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./errors"
|
|
|
7
7
|
export * from "./utils"
|
|
8
8
|
export * from "./proxy"
|
|
9
9
|
export * from "./query/index.js"
|
|
10
|
+
export * from "./optimistic-action"
|
|
10
11
|
|
|
11
12
|
// Re-export some stuff explicitly to ensure the type & value is exported
|
|
12
13
|
export type { Collection } from "./collection"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createTransaction } from "./transactions"
|
|
2
|
+
import type { CreateOptimisticActionsOptions, Transaction } from "./types"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates an optimistic action function that applies local optimistic updates immediately
|
|
6
|
+
* before executing the actual mutation on the server.
|
|
7
|
+
*
|
|
8
|
+
* This pattern allows for responsive UI updates while the actual mutation is in progress.
|
|
9
|
+
* The optimistic update is applied via the `onMutate` callback, and the server mutation
|
|
10
|
+
* is executed via the `mutationFn`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const addTodo = createOptimisticAction<string>({
|
|
15
|
+
* onMutate: (text) => {
|
|
16
|
+
* // Instantly applies local optimistic state
|
|
17
|
+
* todoCollection.insert({
|
|
18
|
+
* id: uuid(),
|
|
19
|
+
* text,
|
|
20
|
+
* completed: false
|
|
21
|
+
* })
|
|
22
|
+
* },
|
|
23
|
+
* mutationFn: async (text, params) => {
|
|
24
|
+
* // Persist the todo to your backend
|
|
25
|
+
* const response = await fetch('/api/todos', {
|
|
26
|
+
* method: 'POST',
|
|
27
|
+
* body: JSON.stringify({ text, completed: false }),
|
|
28
|
+
* })
|
|
29
|
+
* return response.json()
|
|
30
|
+
* }
|
|
31
|
+
* })
|
|
32
|
+
*
|
|
33
|
+
* // Usage
|
|
34
|
+
* const transaction = addTodo('New Todo Item')
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @template TVariables - The type of variables that will be passed to the action function
|
|
38
|
+
* @param options - Configuration options for the optimistic action
|
|
39
|
+
* @returns A function that accepts variables of type TVariables and returns a Transaction
|
|
40
|
+
*/
|
|
41
|
+
export function createOptimisticAction<TVariables = unknown>(
|
|
42
|
+
options: CreateOptimisticActionsOptions<TVariables>
|
|
43
|
+
) {
|
|
44
|
+
const { mutationFn, onMutate, ...config } = options
|
|
45
|
+
|
|
46
|
+
return (variables: TVariables): Transaction => {
|
|
47
|
+
// Create transaction with the original config
|
|
48
|
+
const transaction = createTransaction({
|
|
49
|
+
...config,
|
|
50
|
+
// Wire the mutationFn to use the provided variables
|
|
51
|
+
mutationFn: async (params) => {
|
|
52
|
+
return await mutationFn(variables, params)
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// Execute the transaction. The mutationFn is called once mutate()
|
|
57
|
+
// is finished.
|
|
58
|
+
transaction.mutate(() => {
|
|
59
|
+
// Call onMutate with variables to apply optimistic updates
|
|
60
|
+
onMutate(variables)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return transaction
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { D2, MultiSet, output } from "@electric-sql/d2mini"
|
|
2
2
|
import { createCollection } from "../collection.js"
|
|
3
3
|
import { compileQueryPipeline } from "./pipeline-compiler.js"
|
|
4
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec"
|
|
4
5
|
import type { Collection } from "../collection.js"
|
|
5
|
-
import type { ChangeMessage, SyncConfig } from "../types.js"
|
|
6
|
+
import type { ChangeMessage, ResolveType, SyncConfig } from "../types.js"
|
|
6
7
|
import type {
|
|
7
8
|
IStreamBuilder,
|
|
8
9
|
MultiSetArray,
|
|
@@ -42,7 +43,13 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
|
|
|
42
43
|
Object.entries(collections).map(([key]) => [key, graph.newInput<any>()])
|
|
43
44
|
)
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
// Use TResults directly to ensure type compatibility
|
|
47
|
+
const sync: SyncConfig<TResults>[`sync`] = ({
|
|
48
|
+
begin,
|
|
49
|
+
write,
|
|
50
|
+
commit,
|
|
51
|
+
collection,
|
|
52
|
+
}) => {
|
|
46
53
|
compileQueryPipeline<IStreamBuilder<[unknown, TResults]>>(
|
|
47
54
|
query,
|
|
48
55
|
inputs
|
|
@@ -69,21 +76,35 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
|
|
|
69
76
|
.forEach((changes, rawKey) => {
|
|
70
77
|
const { deletes, inserts, value } = changes
|
|
71
78
|
const valueWithKey = { ...value, _key: rawKey }
|
|
72
|
-
|
|
79
|
+
|
|
80
|
+
// Simple singular insert.
|
|
81
|
+
if (inserts && deletes === 0) {
|
|
73
82
|
write({
|
|
74
83
|
value: valueWithKey,
|
|
75
84
|
type: `insert`,
|
|
76
85
|
})
|
|
77
|
-
} else if (
|
|
86
|
+
} else if (
|
|
87
|
+
// Insert & update(s) (updates are a delete & insert)
|
|
88
|
+
inserts > deletes ||
|
|
89
|
+
// Just update(s) but the item is already in the collection (so
|
|
90
|
+
// was inserted previously).
|
|
91
|
+
(inserts === deletes &&
|
|
92
|
+
collection.has(valueWithKey._key as string | number))
|
|
93
|
+
) {
|
|
78
94
|
write({
|
|
79
95
|
value: valueWithKey,
|
|
80
96
|
type: `update`,
|
|
81
97
|
})
|
|
98
|
+
// Only delete is left as an option
|
|
82
99
|
} else if (deletes > 0) {
|
|
83
100
|
write({
|
|
84
101
|
value: valueWithKey,
|
|
85
102
|
type: `delete`,
|
|
86
103
|
})
|
|
104
|
+
} else {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`This should never happen ${JSON.stringify(changes)}`
|
|
107
|
+
)
|
|
87
108
|
}
|
|
88
109
|
})
|
|
89
110
|
commit()
|
|
@@ -94,15 +115,57 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
|
|
|
94
115
|
|
|
95
116
|
this.graph = graph
|
|
96
117
|
this.inputs = inputs
|
|
118
|
+
|
|
119
|
+
const compare = query.orderBy
|
|
120
|
+
? (
|
|
121
|
+
val1: ResolveType<
|
|
122
|
+
TResults,
|
|
123
|
+
StandardSchemaV1,
|
|
124
|
+
Record<string, unknown>
|
|
125
|
+
>,
|
|
126
|
+
val2: ResolveType<TResults, StandardSchemaV1, Record<string, unknown>>
|
|
127
|
+
): number => {
|
|
128
|
+
// The query builder always adds an _orderByIndex property if the results are ordered
|
|
129
|
+
const x = val1 as TResults & { _orderByIndex: number }
|
|
130
|
+
const y = val2 as TResults & { _orderByIndex: number }
|
|
131
|
+
if (x._orderByIndex < y._orderByIndex) {
|
|
132
|
+
return -1
|
|
133
|
+
} else if (x._orderByIndex > y._orderByIndex) {
|
|
134
|
+
return 1
|
|
135
|
+
} else {
|
|
136
|
+
return 0
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
: undefined
|
|
140
|
+
|
|
97
141
|
this.resultCollection = createCollection<TResults>({
|
|
98
|
-
id: crypto.randomUUID(), // TODO: remove when we don't require any more
|
|
99
142
|
getKey: (val: unknown) => {
|
|
100
143
|
return (val as any)._key
|
|
101
144
|
},
|
|
145
|
+
gcTime: 0,
|
|
146
|
+
startSync: true,
|
|
147
|
+
compare,
|
|
102
148
|
sync: {
|
|
103
|
-
sync
|
|
149
|
+
sync: sync as unknown as (params: {
|
|
150
|
+
collection: Collection<
|
|
151
|
+
ResolveType<TResults, never, Record<string, unknown>>,
|
|
152
|
+
string | number,
|
|
153
|
+
{}
|
|
154
|
+
>
|
|
155
|
+
begin: () => void
|
|
156
|
+
write: (
|
|
157
|
+
message: Omit<
|
|
158
|
+
ChangeMessage<
|
|
159
|
+
ResolveType<TResults, never, Record<string, unknown>>,
|
|
160
|
+
string | number
|
|
161
|
+
>,
|
|
162
|
+
`key`
|
|
163
|
+
>
|
|
164
|
+
) => void
|
|
165
|
+
commit: () => void
|
|
166
|
+
}) => void,
|
|
104
167
|
},
|
|
105
|
-
})
|
|
168
|
+
}) as unknown as Collection<TResults, string | number, {}>
|
|
106
169
|
}
|
|
107
170
|
|
|
108
171
|
get results() {
|
|
@@ -142,26 +205,21 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
|
|
|
142
205
|
throw new Error(`Query is stopped`)
|
|
143
206
|
}
|
|
144
207
|
|
|
145
|
-
// Send initial state
|
|
146
|
-
Object.entries(this.inputCollections).forEach(([key, collection]) => {
|
|
147
|
-
this.sendChangesToInput(
|
|
148
|
-
key,
|
|
149
|
-
collection.currentStateAsChanges(),
|
|
150
|
-
collection.config.getKey
|
|
151
|
-
)
|
|
152
|
-
})
|
|
153
|
-
this.runGraph()
|
|
154
|
-
|
|
155
208
|
// Subscribe to changes
|
|
156
209
|
Object.entries(this.inputCollections).forEach(([key, collection]) => {
|
|
157
|
-
const unsubscribe = collection.subscribeChanges(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
210
|
+
const unsubscribe = collection.subscribeChanges(
|
|
211
|
+
(changes) => {
|
|
212
|
+
this.sendChangesToInput(key, changes, collection.config.getKey)
|
|
213
|
+
this.runGraph()
|
|
214
|
+
},
|
|
215
|
+
{ includeInitialState: true }
|
|
216
|
+
)
|
|
161
217
|
|
|
162
218
|
this.unsubscribeCallbacks.push(unsubscribe)
|
|
163
219
|
})
|
|
164
220
|
|
|
221
|
+
this.runGraph()
|
|
222
|
+
|
|
165
223
|
this.state = `running`
|
|
166
224
|
return () => {
|
|
167
225
|
this.stop()
|
|
@@ -268,7 +268,7 @@ export class BaseQueryBuilder<TContext extends Context<Schema>> {
|
|
|
268
268
|
// Ensure we have an orderByIndex in the select if we have an orderBy
|
|
269
269
|
// This is required if select is called after orderBy
|
|
270
270
|
if (this._query.orderBy) {
|
|
271
|
-
validatedSelects.push({ _orderByIndex: { ORDER_INDEX: `
|
|
271
|
+
validatedSelects.push({ _orderByIndex: { ORDER_INDEX: `fractional` } })
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
const newBuilder = new BaseQueryBuilder<TContext>(
|
|
@@ -735,7 +735,7 @@ export class BaseQueryBuilder<TContext extends Context<Schema>> {
|
|
|
735
735
|
// This is required if select is called before orderBy
|
|
736
736
|
newBuilder.query.select = [
|
|
737
737
|
...(newBuilder.query.select ?? []),
|
|
738
|
-
{ _orderByIndex: { ORDER_INDEX: `
|
|
738
|
+
{ _orderByIndex: { ORDER_INDEX: `fractional` } },
|
|
739
739
|
]
|
|
740
740
|
|
|
741
741
|
return newBuilder as QueryBuilder<TContext>
|
package/src/transactions.ts
CHANGED
|
@@ -156,7 +156,12 @@ export class Transaction<T extends object = Record<string, unknown>> {
|
|
|
156
156
|
for (const mutation of this.mutations) {
|
|
157
157
|
if (!hasCalled.has(mutation.collection.id)) {
|
|
158
158
|
mutation.collection.onTransactionStateChange()
|
|
159
|
-
|
|
159
|
+
|
|
160
|
+
// Only call commitPendingTransactions if there are pending sync transactions
|
|
161
|
+
if (mutation.collection.pendingSyncedTransactions.length > 0) {
|
|
162
|
+
mutation.collection.commitPendingTransactions()
|
|
163
|
+
}
|
|
164
|
+
|
|
160
165
|
hasCalled.add(mutation.collection.id)
|
|
161
166
|
}
|
|
162
167
|
}
|
package/src/types.ts
CHANGED
|
@@ -3,6 +3,39 @@ import type { Collection } from "./collection"
|
|
|
3
3
|
import type { StandardSchemaV1 } from "@standard-schema/spec"
|
|
4
4
|
import type { Transaction } from "./transactions"
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Helper type to extract the output type from a standard schema
|
|
8
|
+
*
|
|
9
|
+
* @internal This is used by the type resolution system
|
|
10
|
+
*/
|
|
11
|
+
export type InferSchemaOutput<T> = T extends StandardSchemaV1
|
|
12
|
+
? StandardSchemaV1.InferOutput<T> extends object
|
|
13
|
+
? StandardSchemaV1.InferOutput<T>
|
|
14
|
+
: Record<string, unknown>
|
|
15
|
+
: Record<string, unknown>
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Helper type to determine the final type based on priority:
|
|
19
|
+
* 1. Explicit generic TExplicit (if not 'unknown')
|
|
20
|
+
* 2. Schema output type (if schema provided)
|
|
21
|
+
* 3. Fallback type TFallback
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* This type is used internally to resolve the collection item type based on the provided generics and schema.
|
|
25
|
+
* Users should not need to use this type directly, but understanding the priority order helps when defining collections.
|
|
26
|
+
*/
|
|
27
|
+
export type ResolveType<
|
|
28
|
+
TExplicit,
|
|
29
|
+
TSchema extends StandardSchemaV1 = never,
|
|
30
|
+
TFallback extends object = Record<string, unknown>,
|
|
31
|
+
> = unknown extends TExplicit
|
|
32
|
+
? [TSchema] extends [never]
|
|
33
|
+
? TFallback
|
|
34
|
+
: InferSchemaOutput<TSchema>
|
|
35
|
+
: TExplicit extends object
|
|
36
|
+
? TExplicit
|
|
37
|
+
: Record<string, unknown>
|
|
38
|
+
|
|
6
39
|
export type TransactionState = `pending` | `persisting` | `completed` | `failed`
|
|
7
40
|
|
|
8
41
|
/**
|
|
@@ -19,11 +52,18 @@ export type UtilsRecord = Record<string, Fn>
|
|
|
19
52
|
* Represents a pending mutation within a transaction
|
|
20
53
|
* Contains information about the original and modified data, as well as metadata
|
|
21
54
|
*/
|
|
22
|
-
export interface PendingMutation<
|
|
55
|
+
export interface PendingMutation<
|
|
56
|
+
T extends object = Record<string, unknown>,
|
|
57
|
+
TOperation extends OperationType = OperationType,
|
|
58
|
+
> {
|
|
23
59
|
mutationId: string
|
|
24
|
-
original:
|
|
60
|
+
original: TOperation extends `insert` ? {} : T
|
|
25
61
|
modified: T
|
|
26
|
-
changes:
|
|
62
|
+
changes: TOperation extends `insert`
|
|
63
|
+
? T
|
|
64
|
+
: TOperation extends `delete`
|
|
65
|
+
? T
|
|
66
|
+
: Partial<T>
|
|
27
67
|
globalKey: string
|
|
28
68
|
key: any
|
|
29
69
|
type: OperationType
|
|
@@ -56,8 +96,9 @@ export type NonEmptyArray<T> = [T, ...Array<T>]
|
|
|
56
96
|
*/
|
|
57
97
|
export type TransactionWithMutations<
|
|
58
98
|
T extends object = Record<string, unknown>,
|
|
99
|
+
TOperation extends OperationType = OperationType,
|
|
59
100
|
> = Transaction<T> & {
|
|
60
|
-
mutations: NonEmptyArray<PendingMutation<T>>
|
|
101
|
+
mutations: NonEmptyArray<PendingMutation<T, TOperation>>
|
|
61
102
|
}
|
|
62
103
|
|
|
63
104
|
export interface TransactionConfig<T extends object = Record<string, unknown>> {
|
|
@@ -70,6 +111,17 @@ export interface TransactionConfig<T extends object = Record<string, unknown>> {
|
|
|
70
111
|
metadata?: Record<string, unknown>
|
|
71
112
|
}
|
|
72
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Options for the createOptimisticAction helper
|
|
116
|
+
*/
|
|
117
|
+
export interface CreateOptimisticActionsOptions<TVars = unknown>
|
|
118
|
+
extends Omit<TransactionConfig, `mutationFn`> {
|
|
119
|
+
/** Function to apply optimistic updates locally before the mutation completes */
|
|
120
|
+
onMutate: (vars: TVars) => void
|
|
121
|
+
/** Function to execute the mutation on the server */
|
|
122
|
+
mutationFn: (vars: TVars, params: MutationFnParams) => Promise<any>
|
|
123
|
+
}
|
|
124
|
+
|
|
73
125
|
export type { Transaction }
|
|
74
126
|
|
|
75
127
|
type Value<TExtensions = never> =
|
|
@@ -148,15 +200,58 @@ export interface InsertConfig {
|
|
|
148
200
|
metadata?: Record<string, unknown>
|
|
149
201
|
}
|
|
150
202
|
|
|
203
|
+
export type UpdateMutationFnParams<T extends object = Record<string, unknown>> =
|
|
204
|
+
{
|
|
205
|
+
transaction: TransactionWithMutations<T, `update`>
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export type InsertMutationFnParams<T extends object = Record<string, unknown>> =
|
|
209
|
+
{
|
|
210
|
+
transaction: TransactionWithMutations<T, `insert`>
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export type DeleteMutationFnParams<T extends object = Record<string, unknown>> =
|
|
214
|
+
{
|
|
215
|
+
transaction: TransactionWithMutations<T, `delete`>
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export type InsertMutationFn<T extends object = Record<string, unknown>> = (
|
|
219
|
+
params: InsertMutationFnParams<T>
|
|
220
|
+
) => Promise<any>
|
|
221
|
+
|
|
222
|
+
export type UpdateMutationFn<T extends object = Record<string, unknown>> = (
|
|
223
|
+
params: UpdateMutationFnParams<T>
|
|
224
|
+
) => Promise<any>
|
|
225
|
+
|
|
226
|
+
export type DeleteMutationFn<T extends object = Record<string, unknown>> = (
|
|
227
|
+
params: DeleteMutationFnParams<T>
|
|
228
|
+
) => Promise<any>
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Collection status values for lifecycle management
|
|
232
|
+
*/
|
|
233
|
+
export type CollectionStatus =
|
|
234
|
+
/** Collection is created but sync hasn't started yet (when startSync config is false) */
|
|
235
|
+
| `idle`
|
|
236
|
+
/** Sync has started but hasn't received the first commit yet */
|
|
237
|
+
| `loading`
|
|
238
|
+
/** Collection has received at least one commit and is ready for use */
|
|
239
|
+
| `ready`
|
|
240
|
+
/** An error occurred during sync initialization */
|
|
241
|
+
| `error`
|
|
242
|
+
/** Collection has been cleaned up and resources freed */
|
|
243
|
+
| `cleaned-up`
|
|
244
|
+
|
|
151
245
|
export interface CollectionConfig<
|
|
152
246
|
T extends object = Record<string, unknown>,
|
|
153
247
|
TKey extends string | number = string | number,
|
|
248
|
+
TSchema extends StandardSchemaV1 = StandardSchemaV1,
|
|
154
249
|
> {
|
|
155
250
|
// If an id isn't passed in, a UUID will be
|
|
156
251
|
// generated for it.
|
|
157
252
|
id?: string
|
|
158
253
|
sync: SyncConfig<T, TKey>
|
|
159
|
-
schema?:
|
|
254
|
+
schema?: TSchema
|
|
160
255
|
/**
|
|
161
256
|
* Function to extract the ID from an object
|
|
162
257
|
* This is required for update/delete operations which now only accept IDs
|
|
@@ -167,24 +262,45 @@ export interface CollectionConfig<
|
|
|
167
262
|
* getKey: (item) => item.uuid
|
|
168
263
|
*/
|
|
169
264
|
getKey: (item: T) => TKey
|
|
265
|
+
/**
|
|
266
|
+
* Time in milliseconds after which the collection will be garbage collected
|
|
267
|
+
* when it has no active subscribers. Defaults to 5 minutes (300000ms).
|
|
268
|
+
*/
|
|
269
|
+
gcTime?: number
|
|
270
|
+
/**
|
|
271
|
+
* Whether to start syncing immediately when the collection is created.
|
|
272
|
+
* Defaults to false for lazy loading. Set to true to immediately sync.
|
|
273
|
+
*/
|
|
274
|
+
startSync?: boolean
|
|
275
|
+
/**
|
|
276
|
+
* Optional function to compare two items.
|
|
277
|
+
* This is used to order the items in the collection.
|
|
278
|
+
* @param x The first item to compare
|
|
279
|
+
* @param y The second item to compare
|
|
280
|
+
* @returns A number indicating the order of the items
|
|
281
|
+
* @example
|
|
282
|
+
* // For a collection with a 'createdAt' field
|
|
283
|
+
* compare: (x, y) => x.createdAt.getTime() - y.createdAt.getTime()
|
|
284
|
+
*/
|
|
285
|
+
compare?: (x: T, y: T) => number
|
|
170
286
|
/**
|
|
171
287
|
* Optional asynchronous handler function called before an insert operation
|
|
172
288
|
* @param params Object containing transaction and mutation information
|
|
173
289
|
* @returns Promise resolving to any value
|
|
174
290
|
*/
|
|
175
|
-
onInsert?:
|
|
291
|
+
onInsert?: InsertMutationFn<T>
|
|
176
292
|
/**
|
|
177
293
|
* Optional asynchronous handler function called before an update operation
|
|
178
294
|
* @param params Object containing transaction and mutation information
|
|
179
295
|
* @returns Promise resolving to any value
|
|
180
296
|
*/
|
|
181
|
-
onUpdate?:
|
|
297
|
+
onUpdate?: UpdateMutationFn<T>
|
|
182
298
|
/**
|
|
183
299
|
* Optional asynchronous handler function called before a delete operation
|
|
184
300
|
* @param params Object containing transaction and mutation information
|
|
185
301
|
* @returns Promise resolving to any value
|
|
186
302
|
*/
|
|
187
|
-
onDelete?:
|
|
303
|
+
onDelete?: DeleteMutationFn<T>
|
|
188
304
|
}
|
|
189
305
|
|
|
190
306
|
export type ChangesPayload<T extends object = Record<string, unknown>> = Array<
|