@tanstack/db-ivm 0.1.22 → 0.1.24

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/src/utils.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { isTemporal } from './hashing/temporal.js'
2
+
1
3
  /**
2
4
  * Simple assertion function for runtime checks.
3
5
  * Throws an error if the condition is false.
@@ -11,36 +13,6 @@ export function assert(
11
13
  }
12
14
  }
13
15
 
14
- /**
15
- * A map that returns a default value for keys that are not present.
16
- */
17
- export class DefaultMap<K, V> extends Map<K, V> {
18
- constructor(
19
- private defaultValue: () => V,
20
- entries?: Iterable<[K, V]>,
21
- ) {
22
- super(entries)
23
- }
24
-
25
- get(key: K): V {
26
- if (!this.has(key)) {
27
- // this.set(key, this.defaultValue())
28
- return this.defaultValue()
29
- }
30
- return super.get(key)!
31
- }
32
-
33
- /**
34
- * Update the value for a key using a function.
35
- */
36
- update(key: K, updater: (value: V) => V): V {
37
- const value = this.get(key)
38
- const newValue = updater(value)
39
- this.set(key, newValue)
40
- return newValue
41
- }
42
- }
43
-
44
16
  // JS engines have various limits on how many args can be passed to a function
45
17
  // with a spread operator, so we need to split the operation into chunks
46
18
  // 32767 is the max for Chrome 14, all others are higher
@@ -78,55 +50,21 @@ export function binarySearch<T>(
78
50
  return low
79
51
  }
80
52
 
81
- /**
82
- * Utility for generating unique IDs for objects and values.
83
- * Uses WeakMap for object reference tracking and consistent hashing for primitives.
84
- */
85
- export class ObjectIdGenerator {
86
- private objectIds = new WeakMap<object, number>()
87
- private nextId = 0
88
-
89
- /**
90
- * Get a unique identifier for any value.
91
- * - Objects: Uses WeakMap for reference-based identity
92
- * - Primitives: Uses consistent string-based hashing
93
- */
94
- getId(value: any): number {
95
- // For primitives, use a simple hash of their string representation
96
- if (typeof value !== `object` || value === null) {
97
- const str = String(value)
98
- let hashValue = 0
99
- for (let i = 0; i < str.length; i++) {
100
- const char = str.charCodeAt(i)
101
- hashValue = (hashValue << 5) - hashValue + char
102
- hashValue = hashValue & hashValue // Convert to 32-bit integer
103
- }
104
- return hashValue
105
- }
106
-
107
- // For objects, use WeakMap to assign unique IDs
108
- if (!this.objectIds.has(value)) {
109
- this.objectIds.set(value, this.nextId++)
110
- }
111
- return this.objectIds.get(value)!
112
- }
113
-
114
- /**
115
- * Get a string representation of the ID for use in composite keys.
116
- */
117
- getStringId(value: any): string {
118
- if (value === null) return `null`
119
- if (value === undefined) return `undefined`
120
- if (typeof value !== `object`) return `str_${String(value)}`
121
-
122
- return `obj_${this.getId(value)}`
123
- }
124
- }
53
+ const objectIds = new WeakMap<object, number>()
54
+ let nextObjectId = 0
125
55
 
126
56
  /**
127
- * Global instance for cases where a shared object ID space is needed.
57
+ * A string identity for composite keys: primitives by value, objects by
58
+ * reference.
128
59
  */
129
- export const globalObjectIdGenerator = new ObjectIdGenerator()
60
+ export function getStringId(value: unknown): string {
61
+ if (value === null) return `null`
62
+ if (value === undefined) return `undefined`
63
+ if (typeof value !== `object`) return `str_${String(value)}`
64
+ let id = objectIds.get(value)
65
+ if (id === undefined) objectIds.set(value, (id = nextObjectId++))
66
+ return `obj_${id}`
67
+ }
130
68
 
131
69
  export function* concatIterable<T>(
132
70
  ...iterables: Array<Iterable<T>>
@@ -209,6 +147,7 @@ type CanonicalValue =
209
147
  | readonly [`bigint`, string]
210
148
  | readonly [`string`, string]
211
149
  | readonly [`date`, number | `Invalid`]
150
+ | readonly [`temporal`, string, string]
212
151
  | readonly [`regexp`, string, string]
213
152
  | readonly [`bytes`, Array<number>]
214
153
  | readonly [`array`, Array<CanonicalValue>]
@@ -265,6 +204,7 @@ function isJsonSafeStructuralValue(
265
204
  value instanceof Date ||
266
205
  value instanceof RegExp ||
267
206
  value instanceof Uint8Array ||
207
+ isTemporal(value) ||
268
208
  value instanceof Map ||
269
209
  value instanceof Set
270
210
  ) {
@@ -348,6 +288,10 @@ function toCanonicalValue(
348
288
  return [`bytes`, Array.from(value)]
349
289
  }
350
290
 
291
+ if (isTemporal(value)) {
292
+ return [`temporal`, value[Symbol.toStringTag], value.toString()]
293
+ }
294
+
351
295
  if (Array.isArray(value)) {
352
296
  return [`array`, value.map((item) => toCanonicalValue(item, ancestors))]
353
297
  }