@tldraw/store 5.4.0-next.ef99ab47e5ce → 5.5.0-next.6d9e51e9f3f7
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/DOCS.md +50 -50
- package/dist-cjs/index.d.ts +38 -8
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/AtomMap.js +45 -3
- package/dist-cjs/lib/AtomMap.js.map +3 -3
- package/dist-cjs/lib/ImmutableMap.js +11 -8
- package/dist-cjs/lib/ImmutableMap.js.map +2 -2
- package/dist-cjs/lib/IncrementalSetConstructor.js +2 -0
- package/dist-cjs/lib/IncrementalSetConstructor.js.map +2 -2
- package/dist-cjs/lib/RecordsDiff.js +11 -1
- package/dist-cjs/lib/RecordsDiff.js.map +2 -2
- package/dist-cjs/lib/Store.js +6 -2
- package/dist-cjs/lib/Store.js.map +2 -2
- package/dist-cjs/lib/StoreQueries.js +1 -1
- package/dist-cjs/lib/StoreQueries.js.map +2 -2
- package/dist-cjs/lib/StoreSchema.js +5 -1
- package/dist-cjs/lib/StoreSchema.js.map +2 -2
- package/dist-cjs/lib/migrate.js +6 -5
- package/dist-cjs/lib/migrate.js.map +2 -2
- package/dist-esm/index.d.mts +38 -8
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/AtomMap.mjs +45 -3
- package/dist-esm/lib/AtomMap.mjs.map +3 -3
- package/dist-esm/lib/ImmutableMap.mjs +11 -8
- package/dist-esm/lib/ImmutableMap.mjs.map +2 -2
- package/dist-esm/lib/IncrementalSetConstructor.mjs +2 -0
- package/dist-esm/lib/IncrementalSetConstructor.mjs.map +2 -2
- package/dist-esm/lib/RecordsDiff.mjs +11 -1
- package/dist-esm/lib/RecordsDiff.mjs.map +2 -2
- package/dist-esm/lib/Store.mjs +6 -2
- package/dist-esm/lib/Store.mjs.map +2 -2
- package/dist-esm/lib/StoreQueries.mjs +1 -1
- package/dist-esm/lib/StoreQueries.mjs.map +2 -2
- package/dist-esm/lib/StoreSchema.mjs +5 -1
- package/dist-esm/lib/StoreSchema.mjs.map +2 -2
- package/dist-esm/lib/migrate.mjs +6 -5
- package/dist-esm/lib/migrate.mjs.map +2 -2
- package/package.json +9 -3
- package/src/lib/AtomMap.test.ts +69 -0
- package/src/lib/AtomMap.ts +52 -3
- package/src/lib/ImmutableMap.test.ts +33 -0
- package/src/lib/ImmutableMap.ts +16 -8
- package/src/lib/IncrementalSetConstructor.test.ts +10 -0
- package/src/lib/IncrementalSetConstructor.ts +4 -0
- package/src/lib/RecordsDiff.test.ts +27 -0
- package/src/lib/RecordsDiff.ts +19 -1
- package/src/lib/Store.ts +9 -4
- package/src/lib/StoreListeners.test.ts +22 -0
- package/src/lib/StoreQueries.test.ts +14 -0
- package/src/lib/StoreQueries.ts +4 -1
- package/src/lib/StoreSchema.test.ts +45 -0
- package/src/lib/StoreSchema.ts +6 -1
- package/src/lib/StoreSideEffects.test.ts +31 -0
- package/src/lib/migrate.test.ts +15 -0
- package/src/lib/migrate.ts +9 -5
package/DOCS.md
CHANGED
|
@@ -17,9 +17,9 @@ The store provides:
|
|
|
17
17
|
- **Side effects** - Lifecycle hooks for implementing business logic
|
|
18
18
|
- **Queries** - Reactive indexes and filtering for efficient data access
|
|
19
19
|
|
|
20
|
-
## 2. Core
|
|
20
|
+
## 2. Core concepts
|
|
21
21
|
|
|
22
|
-
### Records:
|
|
22
|
+
### Records: the foundation
|
|
23
23
|
|
|
24
24
|
**Records** are immutable data objects that extend the `BaseRecord` interface. Every record has an `id` and a `typeName` that identifies its type:
|
|
25
25
|
|
|
@@ -34,7 +34,7 @@ interface Book extends BaseRecord<'book', RecordId<Book>> {
|
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
### Record
|
|
37
|
+
### Record types: factories for records
|
|
38
38
|
|
|
39
39
|
A **RecordType** is a factory that creates and manages records of a specific type. You define how records are created, validated, and what their default properties are:
|
|
40
40
|
|
|
@@ -52,9 +52,9 @@ const Book = createRecordType<Book>('book', {
|
|
|
52
52
|
|
|
53
53
|
// Create a new book
|
|
54
54
|
|
|
55
|
-
## 2. Core
|
|
55
|
+
## 2. Core concepts
|
|
56
56
|
|
|
57
|
-
### Records:
|
|
57
|
+
### Records: the foundation
|
|
58
58
|
|
|
59
59
|
**Records** are immutable data objects that extend the `BaseRecord` interface. Every record has an `id` and a `typeName` that identifies its type:
|
|
60
60
|
|
|
@@ -73,7 +73,7 @@ interface Book extends BaseRecord<'book', RecordId<Book>> {
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
### Record
|
|
76
|
+
### Record types: factories for records
|
|
77
77
|
|
|
78
78
|
A **RecordType** is a factory that creates and manages records of a specific type. You define how records are created, validated, and what their default properties are:
|
|
79
79
|
|
|
@@ -100,9 +100,9 @@ const book = Book.create({
|
|
|
100
100
|
// Results in: { id: 'book:abc123', typeName: 'book', title: '1984', authorId: 'author:xyz789', publishedYear: 2025, inStock: true }
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
## 3. Basic
|
|
103
|
+
## 3. Basic usage
|
|
104
104
|
|
|
105
|
-
### Creating and
|
|
105
|
+
### Creating and storing records
|
|
106
106
|
|
|
107
107
|
You add records to the store using the `put` method:
|
|
108
108
|
|
|
@@ -123,7 +123,7 @@ store.put([orwell, huxley, ...books])
|
|
|
123
123
|
|
|
124
124
|
> Tip: The `put` method handles both creating new records and updating existing ones. If a record with the same ID already exists, it will be updated.
|
|
125
125
|
|
|
126
|
-
### Reading
|
|
126
|
+
### Reading records
|
|
127
127
|
|
|
128
128
|
You can read individual records or access all records of a type:
|
|
129
129
|
|
|
@@ -139,7 +139,7 @@ const allRecords = store.allRecords()
|
|
|
139
139
|
const hasBook = store.has(books[0].id) // true
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
### Updating
|
|
142
|
+
### Updating records
|
|
143
143
|
|
|
144
144
|
Use the `update` method to modify existing records:
|
|
145
145
|
|
|
@@ -153,7 +153,7 @@ store.update(book.id, (currentBook) => ({
|
|
|
153
153
|
|
|
154
154
|
The update function receives the current record and returns a new record with your changes applied.
|
|
155
155
|
|
|
156
|
-
### Removing
|
|
156
|
+
### Removing records
|
|
157
157
|
|
|
158
158
|
Remove records using their IDs:
|
|
159
159
|
|
|
@@ -165,9 +165,9 @@ store.remove([book.id])
|
|
|
165
165
|
store.remove([book1.id, book2.id, book3.id])
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
## 4. Reactive
|
|
168
|
+
## 4. Reactive queries and indexing
|
|
169
169
|
|
|
170
|
-
### Understanding
|
|
170
|
+
### Understanding reactive indexes
|
|
171
171
|
|
|
172
172
|
The store automatically maintains **reactive indexes** that allow efficient querying of your data. These indexes update automatically when records change:
|
|
173
173
|
|
|
@@ -183,7 +183,7 @@ console.log(orwellBooks) // Set<RecordId<Book>>
|
|
|
183
183
|
|
|
184
184
|
The index returns a `Map` where keys are property values and values are `Set`s of record IDs that have that property value.
|
|
185
185
|
|
|
186
|
-
### Reactive
|
|
186
|
+
### Reactive queries with computed values
|
|
187
187
|
|
|
188
188
|
Combine indexes with computed values to create reactive queries:
|
|
189
189
|
|
|
@@ -210,7 +210,7 @@ const inStockBooksByAuthor = computed('inStockBooksByAuthor', () => {
|
|
|
210
210
|
console.log(inStockBooksByAuthor.get()) // Map<RecordId<Author>, Book[]>
|
|
211
211
|
```
|
|
212
212
|
|
|
213
|
-
### The
|
|
213
|
+
### The store: your reactive database
|
|
214
214
|
|
|
215
215
|
The **Store** is the central container that manages all your records. It provides reactive access to data and automatically tracks changes:
|
|
216
216
|
|
|
@@ -230,9 +230,9 @@ const store = new Store({
|
|
|
230
230
|
})
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
## 3. Basic
|
|
233
|
+
## 3. Basic usage
|
|
234
234
|
|
|
235
|
-
### Creating and
|
|
235
|
+
### Creating and storing records
|
|
236
236
|
|
|
237
237
|
You add records to the store using the `put` method:
|
|
238
238
|
|
|
@@ -250,7 +250,7 @@ store.put(books)
|
|
|
250
250
|
|
|
251
251
|
> Tip: The `put` method handles both creating new records and updating existing ones. If a record with the same ID already exists, it will be updated.
|
|
252
252
|
|
|
253
|
-
### Reading
|
|
253
|
+
### Reading records
|
|
254
254
|
|
|
255
255
|
You can read individual records or access all records of a type:
|
|
256
256
|
|
|
@@ -266,7 +266,7 @@ const allRecords = store.allRecords()
|
|
|
266
266
|
const hasBook = store.has(books[0].id) // true
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
-
### Updating
|
|
269
|
+
### Updating records
|
|
270
270
|
|
|
271
271
|
Use the `update` method to modify existing records:
|
|
272
272
|
|
|
@@ -280,7 +280,7 @@ store.update(book.id, (currentBook) => ({
|
|
|
280
280
|
|
|
281
281
|
The update function receives the current record and returns a new record with your changes applied.
|
|
282
282
|
|
|
283
|
-
### Removing
|
|
283
|
+
### Removing records
|
|
284
284
|
|
|
285
285
|
Remove records using their IDs:
|
|
286
286
|
|
|
@@ -292,9 +292,9 @@ store.remove([book.id])
|
|
|
292
292
|
store.remove([book1.id, book2.id, book3.id])
|
|
293
293
|
```
|
|
294
294
|
|
|
295
|
-
## 4. Reactive
|
|
295
|
+
## 4. Reactive queries and indexing
|
|
296
296
|
|
|
297
|
-
### Understanding
|
|
297
|
+
### Understanding reactive indexes
|
|
298
298
|
|
|
299
299
|
The store automatically maintains **reactive indexes** that allow efficient querying of your data. These indexes update automatically when records change:
|
|
300
300
|
|
|
@@ -309,7 +309,7 @@ console.log(orwellBooks) // Set<RecordId<Book>>
|
|
|
309
309
|
|
|
310
310
|
The index returns a `Map` where keys are property values and values are `Set`s of record IDs that have that property value.
|
|
311
311
|
|
|
312
|
-
### Reactive
|
|
312
|
+
### Reactive queries with computed values
|
|
313
313
|
|
|
314
314
|
Combine indexes with computed values to create reactive queries:
|
|
315
315
|
|
|
@@ -336,7 +336,7 @@ const inStockBooksByAuthor = computed('inStockBooksByAuthor', () => {
|
|
|
336
336
|
console.log(inStockBooksByAuthor.get()) // Map<string, Book[]>
|
|
337
337
|
```
|
|
338
338
|
|
|
339
|
-
### Filtering
|
|
339
|
+
### Filtering history for specific record types
|
|
340
340
|
|
|
341
341
|
You can create reactive computations that track changes to specific record types:
|
|
342
342
|
|
|
@@ -358,9 +358,9 @@ const dispose = react('book-changes', () => {
|
|
|
358
358
|
|
|
359
359
|
> Tip: The `filterHistory` method returns a `Computed` that tracks changes to records of a specific type. Use it with `react()` from `@tldraw/state` to respond to changes.
|
|
360
360
|
|
|
361
|
-
## 5. Record
|
|
361
|
+
## 5. Record scopes and persistence
|
|
362
362
|
|
|
363
|
-
### Understanding
|
|
363
|
+
### Understanding record scopes
|
|
364
364
|
|
|
365
365
|
Records have different **scopes** that determine how they're persisted and synchronized:
|
|
366
366
|
|
|
@@ -382,7 +382,7 @@ const PresenceRecord = createRecordType<PresenceData>('presence', {
|
|
|
382
382
|
- **`session`** - Per-instance data that might be saved locally
|
|
383
383
|
- **`presence`** - Temporary data that's shared but not saved
|
|
384
384
|
|
|
385
|
-
### Serialization and
|
|
385
|
+
### Serialization and snapshots
|
|
386
386
|
|
|
387
387
|
You can serialize the store's data for persistence:
|
|
388
388
|
|
|
@@ -400,9 +400,9 @@ store.loadStoreSnapshot(saved)
|
|
|
400
400
|
|
|
401
401
|
> Note: The store automatically handles migrations when loading snapshots from older versions of your schema.
|
|
402
402
|
|
|
403
|
-
## 6. Side
|
|
403
|
+
## 6. Side effects and business logic
|
|
404
404
|
|
|
405
|
-
### Understanding
|
|
405
|
+
### Understanding side effects
|
|
406
406
|
|
|
407
407
|
**Side effects** are hooks that let you implement business logic in response to record changes. They run automatically when records are created, updated, or deleted:
|
|
408
408
|
|
|
@@ -431,7 +431,7 @@ store.sideEffects.registerAfterDeleteHandler('book', (book, source) => {
|
|
|
431
431
|
})
|
|
432
432
|
```
|
|
433
433
|
|
|
434
|
-
### Change
|
|
434
|
+
### Change sources
|
|
435
435
|
|
|
436
436
|
Side effects receive a `source` parameter that tells you where the change originated:
|
|
437
437
|
|
|
@@ -447,7 +447,7 @@ store.sideEffects.registerAfterCreateHandler('book', (book, source) => {
|
|
|
447
447
|
})
|
|
448
448
|
```
|
|
449
449
|
|
|
450
|
-
### Before
|
|
450
|
+
### Before handlers: validation and transformation
|
|
451
451
|
|
|
452
452
|
**Before handlers** run before changes are applied and can validate or transform the data:
|
|
453
453
|
|
|
@@ -470,9 +470,9 @@ store.sideEffects.registerBeforeCreateHandler('book', (book, source) => {
|
|
|
470
470
|
})
|
|
471
471
|
```
|
|
472
472
|
|
|
473
|
-
## 7. Schema
|
|
473
|
+
## 7. Schema evolution with migrations
|
|
474
474
|
|
|
475
|
-
### Creating
|
|
475
|
+
### Creating migration sequences
|
|
476
476
|
|
|
477
477
|
As your application evolves, you'll need to update your data structure. **Migrations** handle this automatically:
|
|
478
478
|
|
|
@@ -527,7 +527,7 @@ const schema = StoreSchema.create(
|
|
|
527
527
|
)
|
|
528
528
|
```
|
|
529
529
|
|
|
530
|
-
### Migration
|
|
530
|
+
### Migration safety
|
|
531
531
|
|
|
532
532
|
The store automatically applies migrations when loading data from older versions:
|
|
533
533
|
|
|
@@ -542,13 +542,13 @@ store.loadStoreSnapshot(oldSnapshot)
|
|
|
542
542
|
|
|
543
543
|
> Tip: Always test your migrations thoroughly with real data before deploying to production.
|
|
544
544
|
|
|
545
|
-
## 8. Advanced
|
|
545
|
+
## 8. Advanced topics
|
|
546
546
|
|
|
547
|
-
### Transactional
|
|
547
|
+
### Transactional operations
|
|
548
548
|
|
|
549
549
|
The store automatically ensures that related operations happen atomically. When you perform multiple operations in response to user actions or side effects, they are automatically grouped together for consistency and performance.
|
|
550
550
|
|
|
551
|
-
### Custom
|
|
551
|
+
### Custom computed caches
|
|
552
552
|
|
|
553
553
|
Create **computed caches** for expensive derivations that should be memoized per record:
|
|
554
554
|
|
|
@@ -564,7 +564,7 @@ const analysis = expensiveBookData.get(book.id)
|
|
|
564
564
|
|
|
565
565
|
The cache automatically updates when the underlying record changes and cleans up when records are deleted.
|
|
566
566
|
|
|
567
|
-
### Extracting
|
|
567
|
+
### Extracting changes
|
|
568
568
|
|
|
569
569
|
You can capture changes that occur within a function:
|
|
570
570
|
|
|
@@ -585,7 +585,7 @@ This is useful for implementing undo/redo systems or understanding what changed
|
|
|
585
585
|
|
|
586
586
|
The store provides several tools for understanding what's happening in your application.
|
|
587
587
|
|
|
588
|
-
### Store
|
|
588
|
+
### Store listeners
|
|
589
589
|
|
|
590
590
|
Add listeners to react to changes in your store:
|
|
591
591
|
|
|
@@ -608,7 +608,7 @@ const removeDocumentListener = store.listen(
|
|
|
608
608
|
)
|
|
609
609
|
```
|
|
610
610
|
|
|
611
|
-
### Understanding
|
|
611
|
+
### Understanding record validation
|
|
612
612
|
|
|
613
613
|
The store validates all records when they're created or updated. Validation errors provide detailed information:
|
|
614
614
|
|
|
@@ -625,7 +625,7 @@ try {
|
|
|
625
625
|
|
|
626
626
|
## 10. Integration
|
|
627
627
|
|
|
628
|
-
### Framework
|
|
628
|
+
### Framework integration
|
|
629
629
|
|
|
630
630
|
The store is framework-agnostic but integrates well with React through `@tldraw/state-react`:
|
|
631
631
|
|
|
@@ -647,7 +647,7 @@ const BookList = track(() => {
|
|
|
647
647
|
|
|
648
648
|
The `track` function automatically subscribes the component to relevant store changes.
|
|
649
649
|
|
|
650
|
-
### Persistence
|
|
650
|
+
### Persistence strategies
|
|
651
651
|
|
|
652
652
|
Implement different persistence strategies based on your needs:
|
|
653
653
|
|
|
@@ -685,9 +685,9 @@ store.mergeRemoteChanges(() => {
|
|
|
685
685
|
|
|
686
686
|
Changes merged this way are marked with `source: 'remote'` so your side effects can handle them appropriately.
|
|
687
687
|
|
|
688
|
-
## 11. Performance
|
|
688
|
+
## 11. Performance considerations
|
|
689
689
|
|
|
690
|
-
### Memory
|
|
690
|
+
### Memory management
|
|
691
691
|
|
|
692
692
|
The store uses several strategies to maintain good performance:
|
|
693
693
|
|
|
@@ -696,7 +696,7 @@ The store uses several strategies to maintain good performance:
|
|
|
696
696
|
- **Efficient indexes** - Reactive indexes use incremental updates rather than full rebuilds
|
|
697
697
|
- **Change batching** - Multiple changes are batched together before notifying listeners
|
|
698
698
|
|
|
699
|
-
### Query
|
|
699
|
+
### Query optimization
|
|
700
700
|
|
|
701
701
|
For best performance with large datasets:
|
|
702
702
|
|
|
@@ -712,7 +712,7 @@ const book = store.unsafeGetWithoutCapture(bookId) // No reactive subscription
|
|
|
712
712
|
const expensiveData = store.createComputedCache('expensive', computeExpensiveData)
|
|
713
713
|
```
|
|
714
714
|
|
|
715
|
-
### Side
|
|
715
|
+
### Side effect performance
|
|
716
716
|
|
|
717
717
|
Keep side effects fast since they run synchronously:
|
|
718
718
|
|
|
@@ -728,9 +728,9 @@ store.sideEffects.registerAfterCreateHandler('book', (book) => {
|
|
|
728
728
|
})
|
|
729
729
|
```
|
|
730
730
|
|
|
731
|
-
## 12. Common
|
|
731
|
+
## 12. Common patterns
|
|
732
732
|
|
|
733
|
-
### Repository
|
|
733
|
+
### Repository pattern
|
|
734
734
|
|
|
735
735
|
Create typed repositories for cleaner APIs:
|
|
736
736
|
|
|
@@ -754,7 +754,7 @@ class BookRepository {
|
|
|
754
754
|
}
|
|
755
755
|
```
|
|
756
756
|
|
|
757
|
-
### State
|
|
757
|
+
### State machines with records
|
|
758
758
|
|
|
759
759
|
Use records to represent state machine states:
|
|
760
760
|
|
|
@@ -775,7 +775,7 @@ store.sideEffects.registerAfterChangeHandler('orderState', (prev, next) => {
|
|
|
775
775
|
})
|
|
776
776
|
```
|
|
777
777
|
|
|
778
|
-
### Computed
|
|
778
|
+
### Computed relationships
|
|
779
779
|
|
|
780
780
|
Model relationships between records using efficient queries:
|
|
781
781
|
|
package/dist-cjs/index.d.ts
CHANGED
|
@@ -116,6 +116,36 @@ export declare class AtomMap<K, V> implements Map<K, V> {
|
|
|
116
116
|
* ```
|
|
117
117
|
*/
|
|
118
118
|
set(key: K, value: V): this;
|
|
119
|
+
/**
|
|
120
|
+
* Gets the value associated with a key, inserting `defaultValue` first if the key doesn't exist.
|
|
121
|
+
* This method is reactive and will cause reactive contexts to update when the value changes.
|
|
122
|
+
*
|
|
123
|
+
* @param key - The key to retrieve the value for
|
|
124
|
+
* @param defaultValue - The value to insert if the key doesn't exist
|
|
125
|
+
* @returns The existing value, or `defaultValue` if the key was missing
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* const map = new AtomMap('myMap')
|
|
129
|
+
* console.log(map.getOrInsert('count', 0)) // 0, and 'count' is now set
|
|
130
|
+
* console.log(map.getOrInsert('count', 10)) // 0
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
getOrInsert(key: K, defaultValue: V): V;
|
|
134
|
+
/**
|
|
135
|
+
* Gets the value associated with a key, inserting the result of `callback` first if the key
|
|
136
|
+
* doesn't exist. The callback only runs when the key is missing.
|
|
137
|
+
* This method is reactive and will cause reactive contexts to update when the value changes.
|
|
138
|
+
*
|
|
139
|
+
* @param key - The key to retrieve the value for
|
|
140
|
+
* @param callback - Called with the key to produce the value to insert
|
|
141
|
+
* @returns The existing value, or the newly computed value if the key was missing
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* const map = new AtomMap<string, string[]>('myMap')
|
|
145
|
+
* map.getOrInsertComputed('tags', () => []).push('new')
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
getOrInsertComputed(key: K, callback: (key: K) => V): V;
|
|
119
149
|
/**
|
|
120
150
|
* Updates an existing value using an updater function.
|
|
121
151
|
*
|
|
@@ -503,7 +533,7 @@ export declare function createMigrationIds<const ID extends string, const Versio
|
|
|
503
533
|
* ```
|
|
504
534
|
* @public
|
|
505
535
|
*/
|
|
506
|
-
export declare function createMigrationSequence({ sequence, sequenceId, retroactive }: {
|
|
536
|
+
export declare function createMigrationSequence({ sequence, sequenceId, retroactive, }: {
|
|
507
537
|
retroactive?: boolean;
|
|
508
538
|
sequence: Array<Migration | StandaloneDependsOn>;
|
|
509
539
|
sequenceId: string;
|
|
@@ -709,12 +739,12 @@ export declare type Migration = {
|
|
|
709
739
|
|
|
710
740
|
/** @public */
|
|
711
741
|
export declare const MigrationFailureReason: {
|
|
712
|
-
readonly IncompatibleSubtype:
|
|
713
|
-
readonly MigrationError:
|
|
714
|
-
readonly TargetVersionTooNew:
|
|
715
|
-
readonly TargetVersionTooOld:
|
|
716
|
-
readonly UnknownType:
|
|
717
|
-
readonly UnrecognizedSubtype:
|
|
742
|
+
readonly IncompatibleSubtype: 'incompatible-subtype';
|
|
743
|
+
readonly MigrationError: 'migration-error';
|
|
744
|
+
readonly TargetVersionTooNew: 'target-version-too-new';
|
|
745
|
+
readonly TargetVersionTooOld: 'target-version-too-old';
|
|
746
|
+
readonly UnknownType: 'unknown-type';
|
|
747
|
+
readonly UnrecognizedSubtype: 'unrecognized-subtype';
|
|
718
748
|
};
|
|
719
749
|
|
|
720
750
|
/** @public */
|
|
@@ -1769,7 +1799,7 @@ export declare class Store<R extends UnknownRecord = UnknownRecord, Props = unkn
|
|
|
1769
1799
|
* Run `fn` and return a {@link RecordsDiff} of the changes that occurred as a result.
|
|
1770
1800
|
*/
|
|
1771
1801
|
extractingChanges(fn: () => void): RecordsDiff<R>;
|
|
1772
|
-
applyDiff(diff: RecordsDiff<R>, { runCallbacks, ignoreEphemeralKeys }?: {
|
|
1802
|
+
applyDiff(diff: RecordsDiff<R>, { runCallbacks, ignoreEphemeralKeys, }?: {
|
|
1773
1803
|
ignoreEphemeralKeys?: boolean;
|
|
1774
1804
|
runCallbacks?: boolean;
|
|
1775
1805
|
}): void;
|
package/dist-cjs/index.js
CHANGED
|
@@ -56,7 +56,7 @@ var import_StoreSchema = require("./lib/StoreSchema");
|
|
|
56
56
|
var import_StoreSideEffects = require("./lib/StoreSideEffects");
|
|
57
57
|
(0, import_utils.registerTldrawLibraryVersion)(
|
|
58
58
|
"@tldraw/store",
|
|
59
|
-
"5.
|
|
59
|
+
"5.5.0-next.6d9e51e9f3f7",
|
|
60
60
|
"cjs"
|
|
61
61
|
);
|
|
62
62
|
//# sourceMappingURL=index.js.map
|
package/dist-cjs/lib/AtomMap.js
CHANGED
|
@@ -172,6 +172,47 @@ class AtomMap {
|
|
|
172
172
|
}
|
|
173
173
|
return this;
|
|
174
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Gets the value associated with a key, inserting `defaultValue` first if the key doesn't exist.
|
|
177
|
+
* This method is reactive and will cause reactive contexts to update when the value changes.
|
|
178
|
+
*
|
|
179
|
+
* @param key - The key to retrieve the value for
|
|
180
|
+
* @param defaultValue - The value to insert if the key doesn't exist
|
|
181
|
+
* @returns The existing value, or `defaultValue` if the key was missing
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* const map = new AtomMap('myMap')
|
|
185
|
+
* console.log(map.getOrInsert('count', 0)) // 0, and 'count' is now set
|
|
186
|
+
* console.log(map.getOrInsert('count', 10)) // 0
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
getOrInsert(key, defaultValue) {
|
|
190
|
+
return this.getOrInsertComputed(key, () => defaultValue);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Gets the value associated with a key, inserting the result of `callback` first if the key
|
|
194
|
+
* doesn't exist. The callback only runs when the key is missing.
|
|
195
|
+
* This method is reactive and will cause reactive contexts to update when the value changes.
|
|
196
|
+
*
|
|
197
|
+
* @param key - The key to retrieve the value for
|
|
198
|
+
* @param callback - Called with the key to produce the value to insert
|
|
199
|
+
* @returns The existing value, or the newly computed value if the key was missing
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* const map = new AtomMap<string, string[]>('myMap')
|
|
203
|
+
* map.getOrInsertComputed('tags', () => []).push('new')
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
getOrInsertComputed(key, callback) {
|
|
207
|
+
const valueAtom = this.getAtom(key);
|
|
208
|
+
if (valueAtom) {
|
|
209
|
+
const value2 = valueAtom.get();
|
|
210
|
+
if (value2 !== import_state.UNINITIALIZED) return value2;
|
|
211
|
+
}
|
|
212
|
+
const value = callback(key);
|
|
213
|
+
this.set(key, value);
|
|
214
|
+
return value;
|
|
215
|
+
}
|
|
175
216
|
/**
|
|
176
217
|
* Updates an existing value using an updater function.
|
|
177
218
|
*
|
|
@@ -289,7 +330,7 @@ class AtomMap {
|
|
|
289
330
|
*entries() {
|
|
290
331
|
for (const [key, valueAtom] of this.atoms.get()) {
|
|
291
332
|
const value = valueAtom.get();
|
|
292
|
-
|
|
333
|
+
if (value === import_state.UNINITIALIZED) continue;
|
|
293
334
|
yield [key, value];
|
|
294
335
|
}
|
|
295
336
|
}
|
|
@@ -308,7 +349,8 @@ class AtomMap {
|
|
|
308
349
|
* ```
|
|
309
350
|
*/
|
|
310
351
|
*keys() {
|
|
311
|
-
for (const key of this.atoms.get()
|
|
352
|
+
for (const [key, valueAtom] of this.atoms.get()) {
|
|
353
|
+
if (valueAtom.__unsafe__getWithoutCapture() === import_state.UNINITIALIZED) continue;
|
|
312
354
|
yield key;
|
|
313
355
|
}
|
|
314
356
|
}
|
|
@@ -329,7 +371,7 @@ class AtomMap {
|
|
|
329
371
|
*values() {
|
|
330
372
|
for (const valueAtom of this.atoms.get().values()) {
|
|
331
373
|
const value = valueAtom.get();
|
|
332
|
-
|
|
374
|
+
if (value === import_state.UNINITIALIZED) continue;
|
|
333
375
|
yield value;
|
|
334
376
|
}
|
|
335
377
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/AtomMap.ts"],
|
|
4
|
-
"sourcesContent": ["import { atom, Atom, transact, UNINITIALIZED } from '@tldraw/state'\nimport { assert } from '@tldraw/utils'\nimport { emptyMap, ImmutableMap } from './ImmutableMap'\n\n/**\n * A drop-in replacement for Map that stores values in atoms and can be used in reactive contexts.\n * @public\n */\nexport class AtomMap<K, V> implements Map<K, V> {\n\tprivate atoms: Atom<ImmutableMap<K, Atom<V | UNINITIALIZED>>>\n\n\t/**\n\t * Creates a new AtomMap instance.\n\t *\n\t * name - A unique name for this map, used for atom identification\n\t * entries - Optional initial entries to populate the map with\n\t * @example\n\t * ```ts\n\t * // Create an empty map\n\t * const map = new AtomMap('userMap')\n\t *\n\t * // Create a map with initial data\n\t * const initialData: [string, number][] = [['a', 1], ['b', 2]]\n\t * const mapWithData = new AtomMap('numbersMap', initialData)\n\t * ```\n\t */\n\tconstructor(\n\t\tprivate readonly name: string,\n\t\tentries?: Iterable<readonly [K, V]>\n\t) {\n\t\tlet atoms = emptyMap<K, Atom<V>>()\n\t\tif (entries) {\n\t\t\tatoms = atoms.withMutations((atoms) => {\n\t\t\t\tfor (const [k, v] of entries) {\n\t\t\t\t\tatoms.set(k, atom(`${name}:${String(k)}`, v))\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tthis.atoms = atom(`${name}:atoms`, atoms)\n\t}\n\n\t/**\n\t * Retrieves the underlying atom for a given key.\n\t *\n\t * @param key - The key to retrieve the atom for\n\t * @returns The atom containing the value, or undefined if the key doesn't exist\n\t * @internal\n\t */\n\tgetAtom(key: K): Atom<V | UNINITIALIZED> | undefined {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) {\n\t\t\t// if the value is missing, we want to track whether it's in the present keys set\n\t\t\tthis.atoms.get()\n\t\t\treturn undefined\n\t\t}\n\t\treturn valueAtom\n\t}\n\n\t/**\n\t * Gets the value associated with a key. Returns undefined if the key doesn't exist.\n\t * This method is reactive and will cause reactive contexts to update when the value changes.\n\t *\n\t * @param key - The key to retrieve the value for\n\t * @returns The value associated with the key, or undefined if not found\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice')\n\t * console.log(map.get('name')) // 'Alice'\n\t * console.log(map.get('missing')) // undefined\n\t * ```\n\t */\n\tget(key: K): V | undefined {\n\t\tconst value = this.getAtom(key)?.get()\n\t\tassert(value !== UNINITIALIZED)\n\t\treturn value\n\t}\n\n\t/**\n\t * Gets the value associated with a key without creating reactive dependencies.\n\t * This method will not cause reactive contexts to update when the value changes.\n\t *\n\t * @param key - The key to retrieve the value for\n\t * @returns The value associated with the key, or undefined if not found\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('count', 42)\n\t * const value = map.__unsafe__getWithoutCapture('count') // No reactive subscription\n\t * ```\n\t */\n\t__unsafe__getWithoutCapture(key: K): V | undefined {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) return undefined\n\t\tconst value = valueAtom.__unsafe__getWithoutCapture()\n\t\tassert(value !== UNINITIALIZED)\n\t\treturn value\n\t}\n\n\t/**\n\t * Checks whether a key exists in the map.\n\t * This method is reactive and will cause reactive contexts to update when keys are added or removed.\n\t *\n\t * @param key - The key to check for\n\t * @returns True if the key exists in the map, false otherwise\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * console.log(map.has('name')) // false\n\t * map.set('name', 'Alice')\n\t * console.log(map.has('name')) // true\n\t * ```\n\t */\n\thas(key: K): boolean {\n\t\tconst valueAtom = this.getAtom(key)\n\t\tif (!valueAtom) {\n\t\t\treturn false\n\t\t}\n\t\treturn valueAtom.get() !== UNINITIALIZED\n\t}\n\n\t/**\n\t * Checks whether a key exists in the map without creating reactive dependencies.\n\t * This method will not cause reactive contexts to update when keys are added or removed.\n\t *\n\t * @param key - The key to check for\n\t * @returns True if the key exists in the map, false otherwise\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('active', true)\n\t * const exists = map.__unsafe__hasWithoutCapture('active') // No reactive subscription\n\t * ```\n\t */\n\t__unsafe__hasWithoutCapture(key: K): boolean {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) return false\n\t\tassert(valueAtom.__unsafe__getWithoutCapture() !== UNINITIALIZED)\n\t\treturn true\n\t}\n\n\t/**\n\t * Sets a value for the given key. If the key already exists, its value is updated.\n\t * If the key doesn't exist, a new entry is created.\n\t *\n\t * @param key - The key to set the value for\n\t * @param value - The value to associate with the key\n\t * @returns This AtomMap instance for method chaining\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice').set('age', 30)\n\t * ```\n\t */\n\tset(key: K, value: V) {\n\t\tconst existingAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (existingAtom) {\n\t\t\texistingAtom.set(value)\n\t\t} else {\n\t\t\tthis.atoms.update((atoms) => {\n\t\t\t\treturn atoms.set(key, atom(`${this.name}:${String(key)}`, value))\n\t\t\t})\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Updates an existing value using an updater function.\n\t *\n\t * @param key - The key of the value to update\n\t * @param updater - A function that receives the current value and returns the new value\n\t * @throws Error if the key doesn't exist in the map\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('count', 5)\n\t * map.update('count', count => count + 1) // count is now 6\n\t * ```\n\t */\n\tupdate(key: K, updater: (value: V) => V) {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) {\n\t\t\tthrow new Error(`AtomMap: key ${key} not found`)\n\t\t}\n\t\tconst value = valueAtom.__unsafe__getWithoutCapture()\n\t\tassert(value !== UNINITIALIZED)\n\t\tvalueAtom.set(updater(value))\n\t}\n\n\t/**\n\t * Removes a key-value pair from the map.\n\t *\n\t * @param key - The key to remove\n\t * @returns True if the key existed and was removed, false if it didn't exist\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('temp', 'value')\n\t * console.log(map.delete('temp')) // true\n\t * console.log(map.delete('missing')) // false\n\t * ```\n\t */\n\tdelete(key: K) {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) {\n\t\t\treturn false\n\t\t}\n\n\t\ttransact(() => {\n\t\t\tvalueAtom.set(UNINITIALIZED)\n\t\t\tthis.atoms.update((atoms) => {\n\t\t\t\treturn atoms.delete(key)\n\t\t\t})\n\t\t})\n\t\treturn true\n\t}\n\n\t/**\n\t * Removes multiple key-value pairs from the map in a single transaction.\n\t *\n\t * @param keys - An iterable of keys to remove\n\t * @returns An array of [key, value] pairs that were actually deleted\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2).set('c', 3)\n\t * const deleted = map.deleteMany(['a', 'c', 'missing'])\n\t * console.log(deleted) // [['a', 1], ['c', 3]]\n\t * ```\n\t */\n\tdeleteMany(keys: Iterable<K>): [K, V][] {\n\t\treturn transact(() => {\n\t\t\tconst deleted: [K, V][] = []\n\t\t\tconst newAtoms = this.atoms.get().withMutations((atoms) => {\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\tconst valueAtom = atoms.get(key)\n\t\t\t\t\tif (!valueAtom) continue\n\t\t\t\t\tconst oldValue = valueAtom.get()\n\t\t\t\t\tassert(oldValue !== UNINITIALIZED)\n\n\t\t\t\t\tdeleted.push([key, oldValue])\n\n\t\t\t\t\tatoms.delete(key)\n\t\t\t\t\tvalueAtom.set(UNINITIALIZED)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tif (deleted.length) {\n\t\t\t\tthis.atoms.set(newAtoms)\n\t\t\t}\n\n\t\t\treturn deleted\n\t\t})\n\t}\n\n\t/**\n\t * Removes all key-value pairs from the map.\n\t *\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t * map.clear()\n\t * console.log(map.size) // 0\n\t * ```\n\t */\n\tclear() {\n\t\treturn transact(() => {\n\t\t\tfor (const valueAtom of this.atoms.__unsafe__getWithoutCapture().values()) {\n\t\t\t\tvalueAtom.set(UNINITIALIZED)\n\t\t\t}\n\t\t\tthis.atoms.set(emptyMap())\n\t\t})\n\t}\n\n\t/**\n\t * Returns an iterator that yields [key, value] pairs for each entry in the map.\n\t * This method is reactive and will cause reactive contexts to update when entries change.\n\t *\n\t * @returns A generator that yields [key, value] tuples\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t * for (const [key, value] of map.entries()) {\n\t * console.log(`${key}: ${value}`)\n\t * }\n\t * ```\n\t */\n\t*entries(): Generator<[K, V], undefined, unknown> {\n\t\tfor (const [key, valueAtom] of this.atoms.get()) {\n\t\t\tconst value = valueAtom.get()\n\t\t\tassert(value !== UNINITIALIZED)\n\t\t\tyield [key, value]\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that yields all keys in the map.\n\t * This method is reactive and will cause reactive contexts to update when keys change.\n\t *\n\t * @returns A generator that yields keys\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice').set('age', 30)\n\t * for (const key of map.keys()) {\n\t * console.log(key) // 'name', 'age'\n\t * }\n\t * ```\n\t */\n\t*keys(): Generator<K, undefined, unknown> {\n\t\tfor (const key of this.atoms.get().keys()) {\n\t\t\tyield key\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that yields all values in the map.\n\t * This method is reactive and will cause reactive contexts to update when values change.\n\t *\n\t * @returns A generator that yields values\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice').set('age', 30)\n\t * for (const value of map.values()) {\n\t * console.log(value) // 'Alice', 30\n\t * }\n\t * ```\n\t */\n\t*values(): Generator<V, undefined, unknown> {\n\t\tfor (const valueAtom of this.atoms.get().values()) {\n\t\t\tconst value = valueAtom.get()\n\t\t\tassert(value !== UNINITIALIZED)\n\t\t\tyield value\n\t\t}\n\t}\n\n\t/**\n\t * The number of key-value pairs in the map.\n\t * This property is reactive and will cause reactive contexts to update when the size changes.\n\t *\n\t * @returns The number of entries in the map\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * console.log(map.size) // 0\n\t * map.set('a', 1)\n\t * console.log(map.size) // 1\n\t * ```\n\t */\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget size() {\n\t\treturn this.atoms.get().size\n\t}\n\n\t/**\n\t * Executes a provided function once for each key-value pair in the map.\n\t * This method is reactive and will cause reactive contexts to update when entries change.\n\t *\n\t * @param callbackfn - Function to execute for each entry\n\t * - value - The value of the current entry\n\t * - key - The key of the current entry\n\t * - map - The AtomMap being traversed\n\t * @param thisArg - Value to use as `this` when executing the callback\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t * map.forEach((value, key) => {\n\t * console.log(`${key} = ${value}`)\n\t * })\n\t * ```\n\t */\n\tforEach(callbackfn: (value: V, key: K, map: AtomMap<K, V>) => void, thisArg?: any): void {\n\t\tfor (const [key, value] of this.entries()) {\n\t\t\tcallbackfn.call(thisArg, value, key, this)\n\t\t}\n\t}\n\n\t/**\n\t * Returns the default iterator for the map, which is the same as entries().\n\t * This allows the map to be used in for...of loops and other iterable contexts.\n\t *\n\t * @returns The same iterator as entries()\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t *\n\t * // These are equivalent:\n\t * for (const [key, value] of map) {\n\t * console.log(`${key}: ${value}`)\n\t * }\n\t *\n\t * for (const [key, value] of map.entries()) {\n\t * console.log(`${key}: ${value}`)\n\t * }\n\t * ```\n\t */\n\t[Symbol.iterator]() {\n\t\treturn this.entries()\n\t}\n\n\t/**\n\t * The string tag used by Object.prototype.toString for this class.\n\t *\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * console.log(Object.prototype.toString.call(map)) // '[object AtomMap]'\n\t * ```\n\t */\n\t[Symbol.toStringTag] = 'AtomMap'\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
6
|
-
"names": ["atoms"]
|
|
4
|
+
"sourcesContent": ["import { atom, Atom, transact, UNINITIALIZED } from '@tldraw/state'\nimport { assert } from '@tldraw/utils'\nimport { emptyMap, ImmutableMap } from './ImmutableMap'\n\n/**\n * A drop-in replacement for Map that stores values in atoms and can be used in reactive contexts.\n * @public\n */\nexport class AtomMap<K, V> implements Map<K, V> {\n\tprivate atoms: Atom<ImmutableMap<K, Atom<V | UNINITIALIZED>>>\n\n\t/**\n\t * Creates a new AtomMap instance.\n\t *\n\t * name - A unique name for this map, used for atom identification\n\t * entries - Optional initial entries to populate the map with\n\t * @example\n\t * ```ts\n\t * // Create an empty map\n\t * const map = new AtomMap('userMap')\n\t *\n\t * // Create a map with initial data\n\t * const initialData: [string, number][] = [['a', 1], ['b', 2]]\n\t * const mapWithData = new AtomMap('numbersMap', initialData)\n\t * ```\n\t */\n\tconstructor(\n\t\tprivate readonly name: string,\n\t\tentries?: Iterable<readonly [K, V]>\n\t) {\n\t\tlet atoms = emptyMap<K, Atom<V>>()\n\t\tif (entries) {\n\t\t\tatoms = atoms.withMutations((atoms) => {\n\t\t\t\tfor (const [k, v] of entries) {\n\t\t\t\t\tatoms.set(k, atom(`${name}:${String(k)}`, v))\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tthis.atoms = atom(`${name}:atoms`, atoms)\n\t}\n\n\t/**\n\t * Retrieves the underlying atom for a given key.\n\t *\n\t * @param key - The key to retrieve the atom for\n\t * @returns The atom containing the value, or undefined if the key doesn't exist\n\t * @internal\n\t */\n\tgetAtom(key: K): Atom<V | UNINITIALIZED> | undefined {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) {\n\t\t\t// if the value is missing, we want to track whether it's in the present keys set\n\t\t\tthis.atoms.get()\n\t\t\treturn undefined\n\t\t}\n\t\treturn valueAtom\n\t}\n\n\t/**\n\t * Gets the value associated with a key. Returns undefined if the key doesn't exist.\n\t * This method is reactive and will cause reactive contexts to update when the value changes.\n\t *\n\t * @param key - The key to retrieve the value for\n\t * @returns The value associated with the key, or undefined if not found\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice')\n\t * console.log(map.get('name')) // 'Alice'\n\t * console.log(map.get('missing')) // undefined\n\t * ```\n\t */\n\tget(key: K): V | undefined {\n\t\tconst value = this.getAtom(key)?.get()\n\t\tassert(value !== UNINITIALIZED)\n\t\treturn value\n\t}\n\n\t/**\n\t * Gets the value associated with a key without creating reactive dependencies.\n\t * This method will not cause reactive contexts to update when the value changes.\n\t *\n\t * @param key - The key to retrieve the value for\n\t * @returns The value associated with the key, or undefined if not found\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('count', 42)\n\t * const value = map.__unsafe__getWithoutCapture('count') // No reactive subscription\n\t * ```\n\t */\n\t__unsafe__getWithoutCapture(key: K): V | undefined {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) return undefined\n\t\tconst value = valueAtom.__unsafe__getWithoutCapture()\n\t\tassert(value !== UNINITIALIZED)\n\t\treturn value\n\t}\n\n\t/**\n\t * Checks whether a key exists in the map.\n\t * This method is reactive and will cause reactive contexts to update when keys are added or removed.\n\t *\n\t * @param key - The key to check for\n\t * @returns True if the key exists in the map, false otherwise\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * console.log(map.has('name')) // false\n\t * map.set('name', 'Alice')\n\t * console.log(map.has('name')) // true\n\t * ```\n\t */\n\thas(key: K): boolean {\n\t\tconst valueAtom = this.getAtom(key)\n\t\tif (!valueAtom) {\n\t\t\treturn false\n\t\t}\n\t\treturn valueAtom.get() !== UNINITIALIZED\n\t}\n\n\t/**\n\t * Checks whether a key exists in the map without creating reactive dependencies.\n\t * This method will not cause reactive contexts to update when keys are added or removed.\n\t *\n\t * @param key - The key to check for\n\t * @returns True if the key exists in the map, false otherwise\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('active', true)\n\t * const exists = map.__unsafe__hasWithoutCapture('active') // No reactive subscription\n\t * ```\n\t */\n\t__unsafe__hasWithoutCapture(key: K): boolean {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) return false\n\t\tassert(valueAtom.__unsafe__getWithoutCapture() !== UNINITIALIZED)\n\t\treturn true\n\t}\n\n\t/**\n\t * Sets a value for the given key. If the key already exists, its value is updated.\n\t * If the key doesn't exist, a new entry is created.\n\t *\n\t * @param key - The key to set the value for\n\t * @param value - The value to associate with the key\n\t * @returns This AtomMap instance for method chaining\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice').set('age', 30)\n\t * ```\n\t */\n\tset(key: K, value: V) {\n\t\tconst existingAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (existingAtom) {\n\t\t\texistingAtom.set(value)\n\t\t} else {\n\t\t\tthis.atoms.update((atoms) => {\n\t\t\t\treturn atoms.set(key, atom(`${this.name}:${String(key)}`, value))\n\t\t\t})\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Gets the value associated with a key, inserting `defaultValue` first if the key doesn't exist.\n\t * This method is reactive and will cause reactive contexts to update when the value changes.\n\t *\n\t * @param key - The key to retrieve the value for\n\t * @param defaultValue - The value to insert if the key doesn't exist\n\t * @returns The existing value, or `defaultValue` if the key was missing\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * console.log(map.getOrInsert('count', 0)) // 0, and 'count' is now set\n\t * console.log(map.getOrInsert('count', 10)) // 0\n\t * ```\n\t */\n\tgetOrInsert(key: K, defaultValue: V): V {\n\t\treturn this.getOrInsertComputed(key, () => defaultValue)\n\t}\n\n\t/**\n\t * Gets the value associated with a key, inserting the result of `callback` first if the key\n\t * doesn't exist. The callback only runs when the key is missing.\n\t * This method is reactive and will cause reactive contexts to update when the value changes.\n\t *\n\t * @param key - The key to retrieve the value for\n\t * @param callback - Called with the key to produce the value to insert\n\t * @returns The existing value, or the newly computed value if the key was missing\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap<string, string[]>('myMap')\n\t * map.getOrInsertComputed('tags', () => []).push('new')\n\t * ```\n\t */\n\tgetOrInsertComputed(key: K, callback: (key: K) => V): V {\n\t\tconst valueAtom = this.getAtom(key)\n\t\tif (valueAtom) {\n\t\t\tconst value = valueAtom.get()\n\t\t\tif (value !== UNINITIALIZED) return value\n\t\t}\n\n\t\tconst value = callback(key)\n\t\tthis.set(key, value)\n\t\treturn value\n\t}\n\n\t/**\n\t * Updates an existing value using an updater function.\n\t *\n\t * @param key - The key of the value to update\n\t * @param updater - A function that receives the current value and returns the new value\n\t * @throws Error if the key doesn't exist in the map\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('count', 5)\n\t * map.update('count', count => count + 1) // count is now 6\n\t * ```\n\t */\n\tupdate(key: K, updater: (value: V) => V) {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) {\n\t\t\tthrow new Error(`AtomMap: key ${key} not found`)\n\t\t}\n\t\tconst value = valueAtom.__unsafe__getWithoutCapture()\n\t\tassert(value !== UNINITIALIZED)\n\t\tvalueAtom.set(updater(value))\n\t}\n\n\t/**\n\t * Removes a key-value pair from the map.\n\t *\n\t * @param key - The key to remove\n\t * @returns True if the key existed and was removed, false if it didn't exist\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('temp', 'value')\n\t * console.log(map.delete('temp')) // true\n\t * console.log(map.delete('missing')) // false\n\t * ```\n\t */\n\tdelete(key: K) {\n\t\tconst valueAtom = this.atoms.__unsafe__getWithoutCapture().get(key)\n\t\tif (!valueAtom) {\n\t\t\treturn false\n\t\t}\n\n\t\ttransact(() => {\n\t\t\tvalueAtom.set(UNINITIALIZED)\n\t\t\tthis.atoms.update((atoms) => {\n\t\t\t\treturn atoms.delete(key)\n\t\t\t})\n\t\t})\n\t\treturn true\n\t}\n\n\t/**\n\t * Removes multiple key-value pairs from the map in a single transaction.\n\t *\n\t * @param keys - An iterable of keys to remove\n\t * @returns An array of [key, value] pairs that were actually deleted\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2).set('c', 3)\n\t * const deleted = map.deleteMany(['a', 'c', 'missing'])\n\t * console.log(deleted) // [['a', 1], ['c', 3]]\n\t * ```\n\t */\n\tdeleteMany(keys: Iterable<K>): [K, V][] {\n\t\treturn transact(() => {\n\t\t\tconst deleted: [K, V][] = []\n\t\t\tconst newAtoms = this.atoms.get().withMutations((atoms) => {\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\tconst valueAtom = atoms.get(key)\n\t\t\t\t\tif (!valueAtom) continue\n\t\t\t\t\tconst oldValue = valueAtom.get()\n\t\t\t\t\tassert(oldValue !== UNINITIALIZED)\n\n\t\t\t\t\tdeleted.push([key, oldValue])\n\n\t\t\t\t\tatoms.delete(key)\n\t\t\t\t\tvalueAtom.set(UNINITIALIZED)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tif (deleted.length) {\n\t\t\t\tthis.atoms.set(newAtoms)\n\t\t\t}\n\n\t\t\treturn deleted\n\t\t})\n\t}\n\n\t/**\n\t * Removes all key-value pairs from the map.\n\t *\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t * map.clear()\n\t * console.log(map.size) // 0\n\t * ```\n\t */\n\tclear() {\n\t\treturn transact(() => {\n\t\t\tfor (const valueAtom of this.atoms.__unsafe__getWithoutCapture().values()) {\n\t\t\t\tvalueAtom.set(UNINITIALIZED)\n\t\t\t}\n\t\t\tthis.atoms.set(emptyMap())\n\t\t})\n\t}\n\n\t/**\n\t * Returns an iterator that yields [key, value] pairs for each entry in the map.\n\t * This method is reactive and will cause reactive contexts to update when entries change.\n\t *\n\t * @returns A generator that yields [key, value] tuples\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t * for (const [key, value] of map.entries()) {\n\t * console.log(`${key}: ${value}`)\n\t * }\n\t * ```\n\t */\n\t*entries(): Generator<[K, V], undefined, unknown> {\n\t\tfor (const [key, valueAtom] of this.atoms.get()) {\n\t\t\tconst value = valueAtom.get()\n\t\t\t// The key set is a snapshot taken when iteration started, so a key deleted mid-iteration\n\t\t\t// still appears in it; skip it, as `Map` skips entries deleted before they are visited.\n\t\t\tif (value === UNINITIALIZED) continue\n\t\t\tyield [key, value]\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that yields all keys in the map.\n\t * This method is reactive and will cause reactive contexts to update when keys change.\n\t *\n\t * @returns A generator that yields keys\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice').set('age', 30)\n\t * for (const key of map.keys()) {\n\t * console.log(key) // 'name', 'age'\n\t * }\n\t * ```\n\t */\n\t*keys(): Generator<K, undefined, unknown> {\n\t\tfor (const [key, valueAtom] of this.atoms.get()) {\n\t\t\t// see entries(): skip keys deleted mid-iteration\n\t\t\tif (valueAtom.__unsafe__getWithoutCapture() === UNINITIALIZED) continue\n\t\t\tyield key\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that yields all values in the map.\n\t * This method is reactive and will cause reactive contexts to update when values change.\n\t *\n\t * @returns A generator that yields values\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('name', 'Alice').set('age', 30)\n\t * for (const value of map.values()) {\n\t * console.log(value) // 'Alice', 30\n\t * }\n\t * ```\n\t */\n\t*values(): Generator<V, undefined, unknown> {\n\t\tfor (const valueAtom of this.atoms.get().values()) {\n\t\t\tconst value = valueAtom.get()\n\t\t\t// see entries(): skip keys deleted mid-iteration\n\t\t\tif (value === UNINITIALIZED) continue\n\t\t\tyield value\n\t\t}\n\t}\n\n\t/**\n\t * The number of key-value pairs in the map.\n\t * This property is reactive and will cause reactive contexts to update when the size changes.\n\t *\n\t * @returns The number of entries in the map\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * console.log(map.size) // 0\n\t * map.set('a', 1)\n\t * console.log(map.size) // 1\n\t * ```\n\t */\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget size() {\n\t\treturn this.atoms.get().size\n\t}\n\n\t/**\n\t * Executes a provided function once for each key-value pair in the map.\n\t * This method is reactive and will cause reactive contexts to update when entries change.\n\t *\n\t * @param callbackfn - Function to execute for each entry\n\t * - value - The value of the current entry\n\t * - key - The key of the current entry\n\t * - map - The AtomMap being traversed\n\t * @param thisArg - Value to use as `this` when executing the callback\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t * map.forEach((value, key) => {\n\t * console.log(`${key} = ${value}`)\n\t * })\n\t * ```\n\t */\n\tforEach(callbackfn: (value: V, key: K, map: AtomMap<K, V>) => void, thisArg?: any): void {\n\t\tfor (const [key, value] of this.entries()) {\n\t\t\tcallbackfn.call(thisArg, value, key, this)\n\t\t}\n\t}\n\n\t/**\n\t * Returns the default iterator for the map, which is the same as entries().\n\t * This allows the map to be used in for...of loops and other iterable contexts.\n\t *\n\t * @returns The same iterator as entries()\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * map.set('a', 1).set('b', 2)\n\t *\n\t * // These are equivalent:\n\t * for (const [key, value] of map) {\n\t * console.log(`${key}: ${value}`)\n\t * }\n\t *\n\t * for (const [key, value] of map.entries()) {\n\t * console.log(`${key}: ${value}`)\n\t * }\n\t * ```\n\t */\n\t[Symbol.iterator]() {\n\t\treturn this.entries()\n\t}\n\n\t/**\n\t * The string tag used by Object.prototype.toString for this class.\n\t *\n\t * @example\n\t * ```ts\n\t * const map = new AtomMap('myMap')\n\t * console.log(Object.prototype.toString.call(map)) // '[object AtomMap]'\n\t * ```\n\t */\n\t[Symbol.toStringTag] = 'AtomMap'\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["atoms", "value"]
|
|
7
7
|
}
|