@tanstack/db 0.5.9 → 0.5.10

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.
@@ -127,32 +127,85 @@ export interface Collection<
127
127
  *
128
128
  */
129
129
 
130
- // Overload for when schema is provided
130
+ // Overload for when schema is provided and utils is required (not optional)
131
+ // We can't infer the Utils type from the CollectionConfig because it will always be optional
132
+ // So we omit it from that type and instead infer it from the extension `& { utils: TUtils }`
133
+ // such that we have the real, non-optional Utils type
131
134
  export function createCollection<
132
135
  T extends StandardSchemaV1,
133
- TKey extends string | number = string | number,
134
- TUtils extends UtilsRecord = UtilsRecord,
136
+ TKey extends string | number,
137
+ TUtils extends UtilsRecord,
135
138
  >(
136
- options: CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils> & {
139
+ options: Omit<
140
+ CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils>,
141
+ `utils`
142
+ > & {
137
143
  schema: T
138
- utils?: TUtils
144
+ utils: TUtils // Required utils
139
145
  } & NonSingleResult
140
146
  ): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> &
141
147
  NonSingleResult
142
148
 
149
+ // Overload for when schema is provided and utils is optional
150
+ // In this case we can simply infer the Utils type from the CollectionConfig type
151
+ export function createCollection<
152
+ T extends StandardSchemaV1,
153
+ TKey extends string | number,
154
+ TUtils extends UtilsRecord,
155
+ >(
156
+ options: CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils> & {
157
+ schema: T
158
+ } & NonSingleResult
159
+ ): Collection<
160
+ InferSchemaOutput<T>,
161
+ TKey,
162
+ Exclude<TUtils, undefined>,
163
+ T,
164
+ InferSchemaInput<T>
165
+ > &
166
+ NonSingleResult
167
+
168
+ // Overload for when schema is provided, singleResult is true, and utils is required
169
+ export function createCollection<
170
+ T extends StandardSchemaV1,
171
+ TKey extends string | number,
172
+ TUtils extends UtilsRecord,
173
+ >(
174
+ options: Omit<
175
+ CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils>,
176
+ `utils`
177
+ > & {
178
+ schema: T
179
+ utils: TUtils // Required utils
180
+ } & SingleResult
181
+ ): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> &
182
+ SingleResult
183
+
143
184
  // Overload for when schema is provided and singleResult is true
144
185
  export function createCollection<
145
186
  T extends StandardSchemaV1,
146
- TKey extends string | number = string | number,
147
- TUtils extends UtilsRecord = UtilsRecord,
187
+ TKey extends string | number,
188
+ TUtils extends UtilsRecord,
148
189
  >(
149
190
  options: CollectionConfig<InferSchemaOutput<T>, TKey, T, TUtils> & {
150
191
  schema: T
151
- utils?: TUtils
152
192
  } & SingleResult
153
193
  ): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> &
154
194
  SingleResult
155
195
 
196
+ // Overload for when no schema is provided and utils is required
197
+ // the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config
198
+ export function createCollection<
199
+ T extends object,
200
+ TKey extends string | number,
201
+ TUtils extends UtilsRecord,
202
+ >(
203
+ options: Omit<CollectionConfig<T, TKey, never, TUtils>, `utils`> & {
204
+ schema?: never // prohibit schema if an explicit type is provided
205
+ utils: TUtils // Required utils
206
+ } & NonSingleResult
207
+ ): Collection<T, TKey, TUtils, never, T> & NonSingleResult
208
+
156
209
  // Overload for when no schema is provided
157
210
  // the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config
158
211
  export function createCollection<
@@ -162,10 +215,22 @@ export function createCollection<
162
215
  >(
163
216
  options: CollectionConfig<T, TKey, never, TUtils> & {
164
217
  schema?: never // prohibit schema if an explicit type is provided
165
- utils?: TUtils
166
218
  } & NonSingleResult
167
219
  ): Collection<T, TKey, TUtils, never, T> & NonSingleResult
168
220
 
221
+ // Overload for when no schema is provided, singleResult is true, and utils is required
222
+ // the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config
223
+ export function createCollection<
224
+ T extends object,
225
+ TKey extends string | number = string | number,
226
+ TUtils extends UtilsRecord = UtilsRecord,
227
+ >(
228
+ options: Omit<CollectionConfig<T, TKey, never, TUtils>, `utils`> & {
229
+ schema?: never // prohibit schema if an explicit type is provided
230
+ utils: TUtils // Required utils
231
+ } & SingleResult
232
+ ): Collection<T, TKey, TUtils, never, T> & SingleResult
233
+
169
234
  // Overload for when no schema is provided and singleResult is true
170
235
  // the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config
171
236
  export function createCollection<
@@ -175,15 +240,13 @@ export function createCollection<
175
240
  >(
176
241
  options: CollectionConfig<T, TKey, never, TUtils> & {
177
242
  schema?: never // prohibit schema if an explicit type is provided
178
- utils?: TUtils
179
243
  } & SingleResult
180
244
  ): Collection<T, TKey, TUtils, never, T> & SingleResult
181
245
 
182
246
  // Implementation
183
247
  export function createCollection(
184
- options: CollectionConfig<any, string | number, any> & {
248
+ options: CollectionConfig<any, string | number, any, UtilsRecord> & {
185
249
  schema?: StandardSchemaV1
186
- utils?: UtilsRecord
187
250
  }
188
251
  ): Collection<any, string | number, UtilsRecord, any, any> {
189
252
  const collection = new CollectionImpl<any, string | number, any, any, any>(
package/src/proxy.ts CHANGED
@@ -994,21 +994,31 @@ export function createChangeProxy<
994
994
  return true
995
995
  },
996
996
 
997
- defineProperty(_ptarget, prop, descriptor) {
998
- // const result = Reflect.defineProperty(
999
- // changeTracker.copy_,
1000
- // prop,
1001
- // descriptor
1002
- // )
1003
- // if (result) {
1004
- if (`value` in descriptor) {
997
+ defineProperty(ptarget, prop, descriptor) {
998
+ // Forward the defineProperty to the target to maintain Proxy invariants
999
+ // This allows Object.seal() and Object.freeze() to work on the proxy
1000
+ const result = Reflect.defineProperty(ptarget, prop, descriptor)
1001
+ if (result && `value` in descriptor) {
1005
1002
  changeTracker.copy_[prop as keyof T] = deepClone(descriptor.value)
1006
1003
  changeTracker.assigned_[prop.toString()] = true
1007
1004
  markChanged(changeTracker)
1008
1005
  }
1009
- // }
1010
- // return result
1011
- return true
1006
+ return result
1007
+ },
1008
+
1009
+ getOwnPropertyDescriptor(ptarget, prop) {
1010
+ // Forward to target to maintain Proxy invariants for seal/freeze
1011
+ return Reflect.getOwnPropertyDescriptor(ptarget, prop)
1012
+ },
1013
+
1014
+ preventExtensions(ptarget) {
1015
+ // Forward to target to allow Object.seal() and Object.preventExtensions()
1016
+ return Reflect.preventExtensions(ptarget)
1017
+ },
1018
+
1019
+ isExtensible(ptarget) {
1020
+ // Forward to target to maintain consistency
1021
+ return Reflect.isExtensible(ptarget)
1012
1022
  },
1013
1023
 
1014
1024
  deleteProperty(dobj, prop) {
@@ -1020,33 +1030,36 @@ export function createChangeProxy<
1020
1030
  const hadPropertyInOriginal =
1021
1031
  stringProp in changeTracker.originalObject
1022
1032
 
1023
- // Delete the property from the copy
1024
- // Use type assertion to tell TypeScript this is allowed
1025
- delete (changeTracker.copy_ as Record<string | symbol, unknown>)[prop]
1033
+ // Forward the delete to the target using Reflect
1034
+ // This respects Object.seal/preventExtensions constraints
1035
+ const result = Reflect.deleteProperty(dobj, prop)
1026
1036
 
1027
- // If the property didn't exist in the original object, removing it
1028
- // should revert to the original state
1029
- if (!hadPropertyInOriginal) {
1030
- delete changeTracker.copy_[stringProp]
1031
- delete changeTracker.assigned_[stringProp]
1037
+ if (result) {
1038
+ // If the property didn't exist in the original object, removing it
1039
+ // should revert to the original state
1040
+ if (!hadPropertyInOriginal) {
1041
+ delete changeTracker.assigned_[stringProp]
1032
1042
 
1033
- // If this is the last change and we're not a nested object,
1034
- // mark the object as unmodified
1035
- if (
1036
- Object.keys(changeTracker.assigned_).length === 0 &&
1037
- Object.getOwnPropertySymbols(changeTracker.assigned_).length === 0
1038
- ) {
1039
- changeTracker.modified = false
1043
+ // If this is the last change and we're not a nested object,
1044
+ // mark the object as unmodified
1045
+ if (
1046
+ Object.keys(changeTracker.assigned_).length === 0 &&
1047
+ Object.getOwnPropertySymbols(changeTracker.assigned_).length ===
1048
+ 0
1049
+ ) {
1050
+ changeTracker.modified = false
1051
+ } else {
1052
+ // We still have changes, keep as modified
1053
+ changeTracker.modified = true
1054
+ }
1040
1055
  } else {
1041
- // We still have changes, keep as modified
1042
- changeTracker.modified = true
1056
+ // Mark this property as deleted
1057
+ changeTracker.assigned_[stringProp] = false
1058
+ markChanged(changeTracker)
1043
1059
  }
1044
- } else {
1045
- // Mark this property as deleted
1046
- changeTracker.assigned_[stringProp] = false
1047
- changeTracker.copy_[stringProp as keyof T] = undefined as T[keyof T]
1048
- markChanged(changeTracker)
1049
1060
  }
1061
+
1062
+ return result
1050
1063
  }
1051
1064
 
1052
1065
  return true
@@ -1060,7 +1073,9 @@ export function createChangeProxy<
1060
1073
  }
1061
1074
 
1062
1075
  // Create a proxy for the target object
1063
- const proxy = createObjectProxy(target)
1076
+ // Use the unfrozen copy_ as the proxy target to avoid Proxy invariant violations
1077
+ // when the original target is frozen (e.g., from Immer)
1078
+ const proxy = createObjectProxy(changeTracker.copy_ as unknown as T)
1064
1079
 
1065
1080
  // Return the proxy and a function to get the changes
1066
1081
  return {