@tanstack/db 0.0.21 → 0.0.23

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.
Files changed (38) hide show
  1. package/dist/cjs/collection.cjs +14 -6
  2. package/dist/cjs/collection.cjs.map +1 -1
  3. package/dist/cjs/collection.d.cts +10 -9
  4. package/dist/cjs/local-storage.cjs +1 -1
  5. package/dist/cjs/local-storage.cjs.map +1 -1
  6. package/dist/cjs/query/builder/index.cjs +20 -0
  7. package/dist/cjs/query/builder/index.cjs.map +1 -1
  8. package/dist/cjs/query/builder/index.d.cts +15 -0
  9. package/dist/cjs/query/compiler/index.cjs +6 -0
  10. package/dist/cjs/query/compiler/index.cjs.map +1 -1
  11. package/dist/cjs/query/ir.cjs.map +1 -1
  12. package/dist/cjs/query/ir.d.cts +1 -0
  13. package/dist/cjs/transactions.cjs.map +1 -1
  14. package/dist/cjs/transactions.d.cts +5 -5
  15. package/dist/cjs/types.d.cts +35 -10
  16. package/dist/esm/collection.d.ts +10 -9
  17. package/dist/esm/collection.js +14 -6
  18. package/dist/esm/collection.js.map +1 -1
  19. package/dist/esm/local-storage.js +1 -1
  20. package/dist/esm/local-storage.js.map +1 -1
  21. package/dist/esm/query/builder/index.d.ts +15 -0
  22. package/dist/esm/query/builder/index.js +20 -0
  23. package/dist/esm/query/builder/index.js.map +1 -1
  24. package/dist/esm/query/compiler/index.js +7 -1
  25. package/dist/esm/query/compiler/index.js.map +1 -1
  26. package/dist/esm/query/ir.d.ts +1 -0
  27. package/dist/esm/query/ir.js.map +1 -1
  28. package/dist/esm/transactions.d.ts +5 -5
  29. package/dist/esm/transactions.js.map +1 -1
  30. package/dist/esm/types.d.ts +35 -10
  31. package/package.json +2 -2
  32. package/src/collection.ts +62 -21
  33. package/src/local-storage.ts +2 -2
  34. package/src/query/builder/index.ts +21 -0
  35. package/src/query/compiler/index.ts +11 -2
  36. package/src/query/ir.ts +1 -0
  37. package/src/transactions.ts +8 -12
  38. package/src/types.ts +69 -14
@@ -8,6 +8,24 @@ import { Transaction } from './transactions.cjs';
8
8
  * @internal This is used by the type resolution system
9
9
  */
10
10
  export type InferSchemaOutput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<T> extends object ? StandardSchemaV1.InferOutput<T> : Record<string, unknown> : Record<string, unknown>;
11
+ /**
12
+ * Helper type to extract the input type from a standard schema
13
+ *
14
+ * @internal This is used for collection insert type inference
15
+ */
16
+ export type InferSchemaInput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferInput<T> extends object ? StandardSchemaV1.InferInput<T> : Record<string, unknown> : Record<string, unknown>;
17
+ /**
18
+ * Helper type to determine the insert input type
19
+ * This takes the raw generics (TExplicit, TSchema, TFallback) instead of the resolved T.
20
+ *
21
+ * Priority:
22
+ * 1. Explicit generic TExplicit (if not 'unknown')
23
+ * 2. Schema input type (if schema provided)
24
+ * 3. Fallback type TFallback
25
+ *
26
+ * @internal This is used for collection insert type inference
27
+ */
28
+ export type ResolveInsertInput<TExplicit = unknown, TSchema extends StandardSchemaV1 = never, TFallback extends object = Record<string, unknown>> = unknown extends TExplicit ? [TSchema] extends [never] ? TFallback : InferSchemaInput<TSchema> : TExplicit extends object ? TExplicit : Record<string, unknown>;
11
29
  /**
12
30
  * Helper type to determine the final type based on priority:
13
31
  * 1. Explicit generic TExplicit (if not 'unknown')
@@ -28,25 +46,32 @@ export type Fn = (...args: Array<any>) => any;
28
46
  * A record of utility functions that can be attached to a collection
29
47
  */
30
48
  export type UtilsRecord = Record<string, Fn>;
49
+ /**
50
+ *
51
+ * @remarks `update` and `insert` are both represented as `Partial<T>`, but changes for `insert` could me made more precise by inferring the schema input type. In practice, this has almost 0 real world impact so it's not worth the added type complexity.
52
+ *
53
+ * @see https://github.com/TanStack/db/pull/209#issuecomment-3053001206
54
+ */
55
+ export type ResolveTransactionChanges<T extends object = Record<string, unknown>, TOperation extends OperationType = OperationType> = TOperation extends `delete` ? T : Partial<T>;
31
56
  /**
32
57
  * Represents a pending mutation within a transaction
33
58
  * Contains information about the original and modified data, as well as metadata
34
59
  */
35
- export interface PendingMutation<T extends object = Record<string, unknown>, TOperation extends OperationType = OperationType> {
60
+ export interface PendingMutation<T extends object = Record<string, unknown>, TOperation extends OperationType = OperationType, TCollection extends Collection<T, any, any, any, any> = Collection<T, any, any, any, any>> {
36
61
  mutationId: string;
37
62
  original: TOperation extends `insert` ? {} : T;
38
63
  modified: T;
39
- changes: TOperation extends `insert` ? T : TOperation extends `delete` ? T : Partial<T>;
64
+ changes: ResolveTransactionChanges<T, TOperation>;
40
65
  globalKey: string;
41
66
  key: any;
42
- type: OperationType;
67
+ type: TOperation;
43
68
  metadata: unknown;
44
69
  syncMetadata: Record<string, unknown>;
45
70
  /** Whether this mutation should be applied optimistically (defaults to true) */
46
71
  optimistic: boolean;
47
72
  createdAt: Date;
48
73
  updatedAt: Date;
49
- collection: Collection<T, any, any>;
74
+ collection: TCollection;
50
75
  }
51
76
  /**
52
77
  * Configuration options for creating a new transaction
@@ -63,7 +88,7 @@ export type NonEmptyArray<T> = [T, ...Array<T>];
63
88
  * Utility type for a Transaction with at least one mutation
64
89
  * This is used internally by the Transaction.commit method
65
90
  */
66
- export type TransactionWithMutations<T extends object = Record<string, unknown>, TOperation extends OperationType = OperationType> = Transaction<T, TOperation> & {
91
+ export type TransactionWithMutations<T extends object = Record<string, unknown>, TOperation extends OperationType = OperationType> = Transaction<T> & {
67
92
  mutations: NonEmptyArray<PendingMutation<T, TOperation>>;
68
93
  };
69
94
  export interface TransactionConfig<T extends object = Record<string, unknown>> {
@@ -77,11 +102,11 @@ export interface TransactionConfig<T extends object = Record<string, unknown>> {
77
102
  /**
78
103
  * Options for the createOptimisticAction helper
79
104
  */
80
- export interface CreateOptimisticActionsOptions<TVars = unknown> extends Omit<TransactionConfig, `mutationFn`> {
105
+ export interface CreateOptimisticActionsOptions<TVars = unknown, T extends object = Record<string, unknown>> extends Omit<TransactionConfig<T>, `mutationFn`> {
81
106
  /** Function to apply optimistic updates locally before the mutation completes */
82
107
  onMutate: (vars: TVars) => void;
83
108
  /** Function to execute the mutation on the server */
84
- mutationFn: (vars: TVars, params: MutationFnParams) => Promise<any>;
109
+ mutationFn: (vars: TVars, params: MutationFnParams<T>) => Promise<any>;
85
110
  }
86
111
  export type { Transaction };
87
112
  type Value<TExtensions = never> = string | number | boolean | bigint | null | TExtensions | Array<Value<TExtensions>> | {
@@ -91,7 +116,7 @@ export type Row<TExtensions = never> = Record<string, Value<TExtensions>>;
91
116
  export type OperationType = `insert` | `update` | `delete`;
92
117
  export interface SyncConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number> {
93
118
  sync: (params: {
94
- collection: Collection<T, TKey>;
119
+ collection: Collection<T, TKey, any, any, any>;
95
120
  begin: () => void;
96
121
  write: (message: Omit<ChangeMessage<T>, `key`>) => void;
97
122
  commit: () => void;
@@ -189,7 +214,7 @@ export type CollectionStatus =
189
214
  | `error`
190
215
  /** Collection has been cleaned up and resources freed */
191
216
  | `cleaned-up`;
192
- export interface CollectionConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = StandardSchemaV1> {
217
+ export interface CollectionConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = StandardSchemaV1, TInsertInput extends object = T> {
193
218
  id?: string;
194
219
  sync: SyncConfig<T, TKey>;
195
220
  schema?: TSchema;
@@ -265,7 +290,7 @@ export interface CollectionConfig<T extends object = Record<string, unknown>, TK
265
290
  * })
266
291
  * }
267
292
  */
268
- onInsert?: InsertMutationFn<T, TKey>;
293
+ onInsert?: InsertMutationFn<TInsertInput, TKey>;
269
294
  /**
270
295
  * Optional asynchronous handler function called before an update operation
271
296
  * @param params Object containing transaction and collection information
@@ -1,8 +1,8 @@
1
1
  import { SortedMap } from './SortedMap.js';
2
2
  import { Transaction } from './transactions.js';
3
- import { ChangeListener, ChangeMessage, CollectionConfig, CollectionStatus, Fn, InsertConfig, OperationConfig, OptimisticChangeMessage, ResolveType, Transaction as TransactionType, UtilsRecord } from './types.js';
3
+ import { ChangeListener, ChangeMessage, CollectionConfig, CollectionStatus, Fn, InsertConfig, OperationConfig, OptimisticChangeMessage, ResolveInsertInput, ResolveType, Transaction as TransactionType, UtilsRecord } from './types.js';
4
4
  import { StandardSchemaV1 } from '@standard-schema/spec';
5
- export declare const collectionsStore: Map<string, CollectionImpl<any, any, {}>>;
5
+ export declare const collectionsStore: Map<string, CollectionImpl<any, any, any, StandardSchemaV1<unknown, unknown>, any>>;
6
6
  interface PendingSyncedTransaction<T extends object = Record<string, unknown>> {
7
7
  committed: boolean;
8
8
  operations: Array<OptimisticChangeMessage<T>>;
@@ -12,8 +12,9 @@ interface PendingSyncedTransaction<T extends object = Record<string, unknown>> {
12
12
  * @template T - The type of items in the collection
13
13
  * @template TKey - The type of the key for the collection
14
14
  * @template TUtils - The utilities record type
15
+ * @template TInsertInput - The type for insert operations (can be different from T for schemas with defaults)
15
16
  */
16
- export interface Collection<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}> extends CollectionImpl<T, TKey> {
17
+ export interface Collection<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}, TSchema extends StandardSchemaV1 = StandardSchemaV1, TInsertInput extends object = T> extends CollectionImpl<T, TKey, TUtils, TSchema, TInsertInput> {
17
18
  readonly utils: TUtils;
18
19
  }
19
20
  /**
@@ -89,9 +90,9 @@ export interface Collection<T extends object = Record<string, unknown>, TKey ext
89
90
  *
90
91
  * // Note: You must provide either an explicit type or a schema, but not both.
91
92
  */
92
- export declare function createCollection<TExplicit = unknown, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}, TSchema extends StandardSchemaV1 = StandardSchemaV1, TFallback extends object = Record<string, unknown>>(options: CollectionConfig<ResolveType<TExplicit, TSchema, TFallback>, TKey, TSchema> & {
93
+ export declare function createCollection<TExplicit = unknown, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}, TSchema extends StandardSchemaV1 = StandardSchemaV1, TFallback extends object = Record<string, unknown>>(options: CollectionConfig<ResolveType<TExplicit, TSchema, TFallback>, TKey, TSchema, ResolveInsertInput<TExplicit, TSchema, TFallback>> & {
93
94
  utils?: TUtils;
94
- }): Collection<ResolveType<TExplicit, TSchema, TFallback>, TKey, TUtils>;
95
+ }): Collection<ResolveType<TExplicit, TSchema, TFallback>, TKey, TUtils, TSchema, ResolveInsertInput<TExplicit, TSchema, TFallback>>;
95
96
  /**
96
97
  * Custom error class for schema validation errors
97
98
  */
@@ -106,8 +107,8 @@ export declare class SchemaValidationError extends Error {
106
107
  path?: ReadonlyArray<string | number | symbol>;
107
108
  }>, message?: string);
108
109
  }
109
- export declare class CollectionImpl<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}> {
110
- config: CollectionConfig<T, TKey, any>;
110
+ export declare class CollectionImpl<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}, TSchema extends StandardSchemaV1 = StandardSchemaV1, TInsertInput extends object = T> {
111
+ config: CollectionConfig<T, TKey, TSchema, TInsertInput>;
111
112
  transactions: SortedMap<string, Transaction<any>>;
112
113
  pendingSyncedTransactions: Array<PendingSyncedTransaction<T>>;
113
114
  syncedData: Map<TKey, T> | SortedMap<TKey, T>;
@@ -168,7 +169,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
168
169
  * @param config - Configuration object for the collection
169
170
  * @throws Error if sync config is missing
170
171
  */
171
- constructor(config: CollectionConfig<T, TKey, any>);
172
+ constructor(config: CollectionConfig<T, TKey, TSchema, TInsertInput>);
172
173
  /**
173
174
  * Start sync immediately - internal method for compiled queries
174
175
  * This bypasses lazy loading for special cases like live query results
@@ -309,7 +310,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
309
310
  * console.log('Insert failed:', error)
310
311
  * }
311
312
  */
312
- insert: (data: T | Array<T>, config?: InsertConfig) => Transaction<Record<string, unknown>, import('./types.js').OperationType>;
313
+ insert: (data: TInsertInput | Array<TInsertInput>, config?: InsertConfig) => Transaction<Record<string, unknown>> | Transaction<T>;
313
314
  /**
314
315
  * Updates one or more items in the collection using a callback function
315
316
  * @param keys - Single key or array of keys to update
@@ -218,7 +218,7 @@ class CollectionImpl {
218
218
  items.forEach((item) => {
219
219
  var _a, _b;
220
220
  const validatedData = this.validateData(item, `insert`);
221
- const key = this.getKeyFromItem(item);
221
+ const key = this.getKeyFromItem(validatedData);
222
222
  if (this.has(key)) {
223
223
  throw `Cannot insert document with ID "${key}" because it already exists in the collection`;
224
224
  }
@@ -227,7 +227,15 @@ class CollectionImpl {
227
227
  mutationId: crypto.randomUUID(),
228
228
  original: {},
229
229
  modified: validatedData,
230
- changes: validatedData,
230
+ // Pick the values from validatedData based on what's passed in - this is for cases
231
+ // where a schema has default values. The validated data has the extra default
232
+ // values but for changes, we just want to show the data that was actually passed in.
233
+ changes: Object.fromEntries(
234
+ Object.keys(item).map((k) => [
235
+ k,
236
+ validatedData[k]
237
+ ])
238
+ ),
231
239
  globalKey,
232
240
  key,
233
241
  metadata: config2 == null ? void 0 : config2.metadata,
@@ -248,8 +256,8 @@ class CollectionImpl {
248
256
  } else {
249
257
  const directOpTransaction = createTransaction({
250
258
  mutationFn: async (params) => {
251
- return this.config.onInsert({
252
- ...params,
259
+ return await this.config.onInsert({
260
+ transaction: params.transaction,
253
261
  collection: this
254
262
  });
255
263
  }
@@ -308,7 +316,7 @@ class CollectionImpl {
308
316
  autoCommit: true,
309
317
  mutationFn: async (params) => {
310
318
  return this.config.onDelete({
311
- ...params,
319
+ transaction: params.transaction,
312
320
  collection: this
313
321
  });
314
322
  }
@@ -1050,7 +1058,7 @@ class CollectionImpl {
1050
1058
  const directOpTransaction = createTransaction({
1051
1059
  mutationFn: async (params) => {
1052
1060
  return this.config.onUpdate({
1053
- ...params,
1061
+ transaction: params.transaction,
1054
1062
  collection: this
1055
1063
  });
1056
1064
  }