@tldraw/store 3.16.0-internal.a478398270c6 → 3.16.0-internal.f8b97f0c414f

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 (41) hide show
  1. package/README.md +13 -13
  2. package/dist-cjs/index.d.ts +10 -42
  3. package/dist-cjs/index.js +1 -2
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/RecordType.js +0 -16
  6. package/dist-cjs/lib/RecordType.js.map +2 -2
  7. package/dist-cjs/lib/RecordsDiff.js +3 -3
  8. package/dist-cjs/lib/RecordsDiff.js.map +2 -2
  9. package/dist-cjs/lib/Store.js +1 -20
  10. package/dist-cjs/lib/Store.js.map +2 -2
  11. package/dist-cjs/lib/StoreSchema.js +24 -8
  12. package/dist-cjs/lib/StoreSchema.js.map +3 -3
  13. package/dist-cjs/lib/migrate.js +57 -43
  14. package/dist-cjs/lib/migrate.js.map +2 -2
  15. package/dist-esm/index.d.mts +10 -42
  16. package/dist-esm/index.mjs +1 -3
  17. package/dist-esm/index.mjs.map +2 -2
  18. package/dist-esm/lib/RecordType.mjs +0 -16
  19. package/dist-esm/lib/RecordType.mjs.map +2 -2
  20. package/dist-esm/lib/RecordsDiff.mjs +3 -3
  21. package/dist-esm/lib/RecordsDiff.mjs.map +2 -2
  22. package/dist-esm/lib/Store.mjs +1 -20
  23. package/dist-esm/lib/Store.mjs.map +2 -2
  24. package/dist-esm/lib/StoreSchema.mjs +24 -8
  25. package/dist-esm/lib/StoreSchema.mjs.map +3 -3
  26. package/dist-esm/lib/migrate.mjs +57 -43
  27. package/dist-esm/lib/migrate.mjs.map +2 -2
  28. package/package.json +12 -19
  29. package/src/index.ts +0 -1
  30. package/src/lib/RecordType.ts +0 -17
  31. package/src/lib/RecordsDiff.ts +9 -3
  32. package/src/lib/Store.ts +1 -22
  33. package/src/lib/StoreSchema.ts +33 -8
  34. package/src/lib/migrate.ts +106 -57
  35. package/src/lib/test/AtomMap.test.ts +2 -1
  36. package/src/lib/test/dependsOn.test.ts +2 -2
  37. package/src/lib/test/migrationCaching.test.ts +209 -0
  38. package/src/lib/test/recordStore.test.ts +40 -37
  39. package/src/lib/test/sortMigrations.test.ts +36 -4
  40. package/src/lib/test/validateMigrations.test.ts +8 -8
  41. package/src/lib/test/defineMigrations.test.ts +0 -232
package/README.md CHANGED
@@ -40,11 +40,11 @@ const store = new RecordStore<Book | Author>()
40
40
  Then you can create records, add them to the store, update, and remove them.
41
41
 
42
42
  ```ts
43
- const tolkeinId = Author.createCustomId('tolkein')
43
+ const tolkeinId = Author.createId('tolkein')
44
44
 
45
45
  store.put([
46
46
  Author.create({
47
- id: jrrTolkeinId,
47
+ id: tolkeinId,
48
48
  name: 'J.R.R Tolkein',
49
49
  }),
50
50
  ])
@@ -77,7 +77,7 @@ Add some records to the store. It's an error if they already exist.
77
77
  ```ts
78
78
  const record = Author.create({
79
79
  name: 'J.R.R Tolkein',
80
- id: Author.createCustomId('tolkein'),
80
+ id: Author.createId('tolkein'),
81
81
  })
82
82
 
83
83
  store.put([record])
@@ -88,7 +88,7 @@ store.put([record])
88
88
  Update a record. To update multiple records at once, use the `update` method of the `TypedRecordStore` class.
89
89
 
90
90
  ```ts
91
- const id = Author.createCustomId('tolkein')
91
+ const id = Author.createId('tolkein')
92
92
 
93
93
  store.update(id, (r) => ({ ...r, name: 'Jimmy Tolks' }))
94
94
  ```
@@ -98,7 +98,7 @@ store.update(id, (r) => ({ ...r, name: 'Jimmy Tolks' }))
98
98
  Remove some records from the store via their ids.
99
99
 
100
100
  ```ts
101
- const id = Author.createCustomId('tolkein')
101
+ const id = Author.createId('tolkein')
102
102
 
103
103
  store.remove([id])
104
104
  ```
@@ -108,7 +108,7 @@ store.remove([id])
108
108
  Get the value of a store record by its id.
109
109
 
110
110
  ```ts
111
- const id = Author.createCustomId('tolkein')
111
+ const id = Author.createId('tolkein')
112
112
 
113
113
  const result = store.get(id)
114
114
  ```
@@ -134,7 +134,7 @@ store.clear()
134
134
  Get whether the record store has an record stored under the given id.
135
135
 
136
136
  ```ts
137
- const id = Author.createCustomId('tolkein')
137
+ const id = Author.createId('tolkein')
138
138
 
139
139
  const result = store.has(id)
140
140
  ```
@@ -163,7 +163,7 @@ store.deserialize(serialized)
163
163
 
164
164
  ### `listen(listener: ((entry: HistoryEntry) => void): () => void`
165
165
 
166
- Add a new listener to the store The store will call the function each time the history changes. Returns a function to remove the listener.
166
+ Add a new listener to the store. The store will call the function each time the history changes. Returns a function to remove the listener.
167
167
 
168
168
  ```ts
169
169
  store.listen((entry) => doSomethingWith(entry))
@@ -227,12 +227,12 @@ Create an Id for a record of this type.
227
227
  const id = recordType.createId()
228
228
  ```
229
229
 
230
- ### `createCustomId(id: string): ID<R>`
230
+ ### `createId(id: string): ID<R>`
231
231
 
232
232
  Create a custom Id for a record of this type.
233
233
 
234
234
  ```ts
235
- const id = recordType.createCustomId('tolkein')
235
+ const id = recordType.createId('tolkein')
236
236
  ```
237
237
 
238
238
  ### `isInstance`
@@ -251,7 +251,7 @@ const result2 = recordType.isInstance(someOtherRecord) // false
251
251
  Check if a value is an id for a record of this type.
252
252
 
253
253
  ```ts
254
- const id = recordType.createCustomId('tolkein')
254
+ const id = recordType.createId('tolkein')
255
255
 
256
256
  const result1 = recordType.isId(id) // true
257
257
  const result2 = recordType.isId(someOtherId) // false
@@ -300,7 +300,7 @@ const recordType = createRecordType('author'))
300
300
  A helper used to assert that a value is an id for a record of a given type.
301
301
 
302
302
  ```ts
303
- const id = recordType.createCustomId('tolkein')
303
+ const id = recordType.createId('tolkein')
304
304
 
305
305
  assertIdType(id, recordType)
306
306
  ```
@@ -314,7 +314,7 @@ assertIdType(id, recordType)
314
314
  A type used to represent a record's id.
315
315
 
316
316
  ```ts
317
- const id: ID<Author> = Author.createCustomId('tolkein')
317
+ const id: ID<Author> = Author.createId('tolkein')
318
318
  ```
319
319
 
320
320
  ### `BaseRecord`
@@ -149,18 +149,6 @@ export declare function createRecordType<R extends UnknownRecord>(typeName: R['t
149
149
  validator?: StoreValidator<R>;
150
150
  }): RecordType<R, keyof Omit<R, 'id' | 'typeName'>>;
151
151
 
152
- /**
153
- * @public
154
- * @deprecated use `createShapePropsMigrationSequence` instead. See [the docs](https://tldraw.dev/docs/persistence#Updating-legacy-shape-migrations-defineMigrations) for how to migrate.
155
- */
156
- export declare function defineMigrations(opts: {
157
- currentVersion?: number;
158
- firstVersion?: number;
159
- migrators?: Record<number, LegacyMigration>;
160
- subTypeKey?: string;
161
- subTypeMigrations?: Record<string, LegacyBaseMigrationsInfo>;
162
- }): LegacyMigrations;
163
-
164
152
  /**
165
153
  * Freeze an object when in development mode. Copied from
166
154
  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
@@ -378,20 +366,6 @@ export declare class RecordType<R extends UnknownRecord, RequiredProperties exte
378
366
  * @public
379
367
  */
380
368
  createId(customUniquePart?: string): IdOf<R>;
381
- /**
382
- * Create a new ID for this record type based on the given ID.
383
- *
384
- * @example
385
- *
386
- * ```ts
387
- * const id = recordType.createCustomId('myId')
388
- * ```
389
- *
390
- * @deprecated - Use `createId` instead.
391
- * @param id - The ID to base the new ID on.
392
- * @returns The new ID.
393
- */
394
- createCustomId(id: string): IdOf<R>;
395
369
  /**
396
370
  * Takes an id like `user:123` and returns the part after the colon `123`
397
371
  *
@@ -500,10 +474,13 @@ export declare type SerializedStore<R extends UnknownRecord> = Record<IdOf<R>, R
500
474
  * Squash a collection of diffs into a single diff.
501
475
  *
502
476
  * @param diffs - An array of diffs to squash.
477
+ * @param options - An optional object with a `mutateFirstDiff` property. If `mutateFirstDiff` is true, the first diff in the array will be mutated in-place.
503
478
  * @returns A single diff that represents the squashed diffs.
504
479
  * @public
505
480
  */
506
- export declare function squashRecordDiffs<T extends UnknownRecord>(diffs: RecordsDiff<T>[]): RecordsDiff<T>;
481
+ export declare function squashRecordDiffs<T extends UnknownRecord>(diffs: RecordsDiff<T>[], options?: {
482
+ mutateFirstDiff?: boolean;
483
+ }): RecordsDiff<T>;
507
484
 
508
485
  /* Excluded from this release type: squashRecordDiffsMutable */
509
486
 
@@ -627,15 +604,11 @@ export declare class Store<R extends UnknownRecord = UnknownRecord, Props = unkn
627
604
  * @public
628
605
  */
629
606
  getStoreSnapshot(scope?: 'all' | RecordScope): StoreSnapshot<R>;
630
- /**
631
- * @deprecated use `getSnapshot` from the 'tldraw' package instead.
632
- */
633
- getSnapshot(scope?: 'all' | RecordScope): StoreSnapshot<R>;
634
607
  /**
635
608
  * Migrate a serialized snapshot of the store and its schema.
636
609
  *
637
610
  * ```ts
638
- * const snapshot = store.getSnapshot()
611
+ * const snapshot = store.getStoreSnapshot()
639
612
  * store.migrateSnapshot(snapshot)
640
613
  * ```
641
614
  *
@@ -655,11 +628,6 @@ export declare class Store<R extends UnknownRecord = UnknownRecord, Props = unkn
655
628
  * @public
656
629
  */
657
630
  loadStoreSnapshot(snapshot: StoreSnapshot<R>): void;
658
- /**
659
- * @public
660
- * @deprecated use `loadSnapshot` from the 'tldraw' package instead.
661
- */
662
- loadSnapshot(snapshot: StoreSnapshot<R>): void;
663
631
  /**
664
632
  * Get an array of all values in the store.
665
633
  *
@@ -892,17 +860,17 @@ export declare class StoreSchema<R extends UnknownRecord, P = unknown> {
892
860
  }, options?: StoreSchemaOptions<R, P>): StoreSchema<R, P>;
893
861
  readonly migrations: Record<string, MigrationSequence>;
894
862
  readonly sortedMigrations: readonly Migration[];
863
+ private readonly migrationCache;
895
864
  private constructor();
896
865
  validateRecord(store: Store<R>, record: R, phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord', recordBefore: null | R): R;
897
866
  getMigrationsSince(persistedSchema: SerializedSchema): Result<Migration[], string>;
898
867
  migratePersistedRecord(record: R, persistedSchema: SerializedSchema, direction?: 'down' | 'up'): MigrationResult<R>;
899
- migrateStoreSnapshot(snapshot: StoreSnapshot<R>): MigrationResult<SerializedStore<R>>;
868
+ migrateStoreSnapshot(snapshot: StoreSnapshot<R>, opts?: {
869
+ mutateInputStore?: boolean;
870
+ }): MigrationResult<SerializedStore<R>>;
900
871
  /* Excluded from this release type: createIntegrityChecker */
901
872
  serialize(): SerializedSchemaV2;
902
- /**
903
- * @deprecated This is only here for legacy reasons, don't use it unless you have david's blessing!
904
- */
905
- serializeEarliestVersion(): SerializedSchema;
873
+ /* Excluded from this release type: serializeEarliestVersion */
906
874
  /* Excluded from this release type: getType */
907
875
  }
908
876
 
package/dist-cjs/index.js CHANGED
@@ -33,7 +33,6 @@ __export(index_exports, {
33
33
  createMigrationSequence: () => import_migrate.createMigrationSequence,
34
34
  createRecordMigrationSequence: () => import_migrate.createRecordMigrationSequence,
35
35
  createRecordType: () => import_RecordType.createRecordType,
36
- defineMigrations: () => import_migrate.defineMigrations,
37
36
  devFreeze: () => import_devFreeze.devFreeze,
38
37
  isRecordsDiffEmpty: () => import_RecordsDiff.isRecordsDiffEmpty,
39
38
  parseMigrationId: () => import_migrate.parseMigrationId,
@@ -55,7 +54,7 @@ var import_StoreSchema = require("./lib/StoreSchema");
55
54
  var import_StoreSideEffects = require("./lib/StoreSideEffects");
56
55
  (0, import_utils.registerTldrawLibraryVersion)(
57
56
  "@tldraw/store",
58
- "3.16.0-internal.a478398270c6",
57
+ "3.16.0-internal.f8b97f0c414f",
59
58
  "cjs"
60
59
  );
61
60
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import { registerTldrawLibraryVersion } from '@tldraw/utils'\nexport { AtomMap } from './lib/AtomMap'\nexport type { BaseRecord, IdOf, RecordId, UnknownRecord } from './lib/BaseRecord'\nexport { devFreeze } from './lib/devFreeze'\nexport { type QueryExpression, type QueryValueMatcher } from './lib/executeQuery'\nexport { IncrementalSetConstructor } from './lib/IncrementalSetConstructor'\nexport {\n\tcreateMigrationIds,\n\tcreateMigrationSequence,\n\tcreateRecordMigrationSequence,\n\tdefineMigrations,\n\tMigrationFailureReason,\n\tparseMigrationId,\n\ttype LegacyBaseMigrationsInfo,\n\ttype LegacyMigration,\n\ttype LegacyMigrations,\n\ttype Migration,\n\ttype MigrationId,\n\ttype MigrationResult,\n\ttype MigrationSequence,\n\ttype StandaloneDependsOn,\n} from './lib/migrate'\nexport {\n\tcreateEmptyRecordsDiff,\n\tisRecordsDiffEmpty,\n\treverseRecordsDiff,\n\tsquashRecordDiffs,\n\tsquashRecordDiffsMutable,\n\ttype RecordsDiff,\n} from './lib/RecordsDiff'\nexport { assertIdType, createRecordType, RecordType, type RecordScope } from './lib/RecordType'\nexport {\n\tcreateComputedCache,\n\tStore,\n\ttype ChangeSource,\n\ttype CollectionDiff,\n\ttype ComputedCache,\n\ttype CreateComputedCacheOpts,\n\ttype HistoryEntry,\n\ttype RecordFromId,\n\ttype SerializedStore,\n\ttype StoreError,\n\ttype StoreListener,\n\ttype StoreListenerFilters,\n\ttype StoreObject,\n\ttype StoreObjectRecordType,\n\ttype StoreRecord,\n\ttype StoreSnapshot,\n\ttype StoreValidator,\n\ttype StoreValidators,\n} from './lib/Store'\nexport { StoreQueries, type RSIndex, type RSIndexDiff, type RSIndexMap } from './lib/StoreQueries'\nexport { StoreSchema, type StoreValidationFailure } from './lib/StoreSchema'\nexport type {\n\tSerializedSchema,\n\tSerializedSchemaV1,\n\tSerializedSchemaV2,\n\tStoreSchemaOptions,\n} from './lib/StoreSchema'\nexport {\n\tStoreSideEffects,\n\ttype StoreAfterChangeHandler,\n\ttype StoreAfterCreateHandler,\n\ttype StoreAfterDeleteHandler,\n\ttype StoreBeforeChangeHandler,\n\ttype StoreBeforeCreateHandler,\n\ttype StoreBeforeDeleteHandler,\n\ttype StoreOperationCompleteHandler,\n} from './lib/StoreSideEffects'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAC7C,qBAAwB;AAExB,uBAA0B;AAE1B,uCAA0C;AAC1C,qBAeO;AACP,yBAOO;AACP,wBAA6E;AAC7E,mBAmBO;AACP,0BAA8E;AAC9E,yBAAyD;AAOzD,8BASO;AAAA,IAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
4
+ "sourcesContent": ["import { registerTldrawLibraryVersion } from '@tldraw/utils'\nexport { AtomMap } from './lib/AtomMap'\nexport type { BaseRecord, IdOf, RecordId, UnknownRecord } from './lib/BaseRecord'\nexport { devFreeze } from './lib/devFreeze'\nexport { type QueryExpression, type QueryValueMatcher } from './lib/executeQuery'\nexport { IncrementalSetConstructor } from './lib/IncrementalSetConstructor'\nexport {\n\tcreateMigrationIds,\n\tcreateMigrationSequence,\n\tcreateRecordMigrationSequence,\n\tMigrationFailureReason,\n\tparseMigrationId,\n\ttype LegacyBaseMigrationsInfo,\n\ttype LegacyMigration,\n\ttype LegacyMigrations,\n\ttype Migration,\n\ttype MigrationId,\n\ttype MigrationResult,\n\ttype MigrationSequence,\n\ttype StandaloneDependsOn,\n} from './lib/migrate'\nexport {\n\tcreateEmptyRecordsDiff,\n\tisRecordsDiffEmpty,\n\treverseRecordsDiff,\n\tsquashRecordDiffs,\n\tsquashRecordDiffsMutable,\n\ttype RecordsDiff,\n} from './lib/RecordsDiff'\nexport { assertIdType, createRecordType, RecordType, type RecordScope } from './lib/RecordType'\nexport {\n\tcreateComputedCache,\n\tStore,\n\ttype ChangeSource,\n\ttype CollectionDiff,\n\ttype ComputedCache,\n\ttype CreateComputedCacheOpts,\n\ttype HistoryEntry,\n\ttype RecordFromId,\n\ttype SerializedStore,\n\ttype StoreError,\n\ttype StoreListener,\n\ttype StoreListenerFilters,\n\ttype StoreObject,\n\ttype StoreObjectRecordType,\n\ttype StoreRecord,\n\ttype StoreSnapshot,\n\ttype StoreValidator,\n\ttype StoreValidators,\n} from './lib/Store'\nexport { StoreQueries, type RSIndex, type RSIndexDiff, type RSIndexMap } from './lib/StoreQueries'\nexport { StoreSchema, type StoreValidationFailure } from './lib/StoreSchema'\nexport type {\n\tSerializedSchema,\n\tSerializedSchemaV1,\n\tSerializedSchemaV2,\n\tStoreSchemaOptions,\n} from './lib/StoreSchema'\nexport {\n\tStoreSideEffects,\n\ttype StoreAfterChangeHandler,\n\ttype StoreAfterCreateHandler,\n\ttype StoreAfterDeleteHandler,\n\ttype StoreBeforeChangeHandler,\n\ttype StoreBeforeCreateHandler,\n\ttype StoreBeforeDeleteHandler,\n\ttype StoreOperationCompleteHandler,\n} from './lib/StoreSideEffects'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAC7C,qBAAwB;AAExB,uBAA0B;AAE1B,uCAA0C;AAC1C,qBAcO;AACP,yBAOO;AACP,wBAA6E;AAC7E,mBAmBO;AACP,0BAA8E;AAC9E,yBAAyD;AAOzD,8BASO;AAAA,IAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
6
6
  "names": []
7
7
  }
@@ -88,22 +88,6 @@ class RecordType {
88
88
  createId(customUniquePart) {
89
89
  return this.typeName + ":" + (customUniquePart ?? (0, import_utils.uniqueId)());
90
90
  }
91
- /**
92
- * Create a new ID for this record type based on the given ID.
93
- *
94
- * @example
95
- *
96
- * ```ts
97
- * const id = recordType.createCustomId('myId')
98
- * ```
99
- *
100
- * @deprecated - Use `createId` instead.
101
- * @param id - The ID to base the new ID on.
102
- * @returns The new ID.
103
- */
104
- createCustomId(id) {
105
- return this.typeName + ":" + id;
106
- }
107
91
  /**
108
92
  * Takes an id like `user:123` and returns the part after the colon `123`
109
93
  *
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/RecordType.ts"],
4
- "sourcesContent": ["import { Expand, objectMapEntries, structuredClone, uniqueId } from '@tldraw/utils'\nimport { IdOf, UnknownRecord } from './BaseRecord'\nimport { StoreValidator } from './Store'\n\nexport type RecordTypeRecord<R extends RecordType<any, any>> = ReturnType<R['create']>\n\n/**\n * Defines the scope of the record\n *\n * session: The record belongs to a single instance of the store. It should not be synced, and any persistence logic should 'de-instance-ize' the record before persisting it, and apply the reverse when rehydrating.\n * document: The record is persisted and synced. It is available to all store instances.\n * presence: The record belongs to a single instance of the store. It may be synced to other instances, but other instances should not make changes to it. It should not be persisted.\n *\n * @public\n * */\nexport type RecordScope = 'session' | 'document' | 'presence'\n\n/**\n * A record type is a type that can be stored in a record store. It is created with\n * `createRecordType`.\n *\n * @public\n */\nexport class RecordType<\n\tR extends UnknownRecord,\n\tRequiredProperties extends keyof Omit<R, 'id' | 'typeName'>,\n> {\n\treadonly createDefaultProperties: () => Exclude<Omit<R, 'id' | 'typeName'>, RequiredProperties>\n\treadonly validator: StoreValidator<R>\n\treadonly ephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }\n\treadonly ephemeralKeySet: ReadonlySet<string>\n\treadonly scope: RecordScope\n\n\tconstructor(\n\t\t/**\n\t\t * The unique type associated with this record.\n\t\t *\n\t\t * @public\n\t\t * @readonly\n\t\t */\n\t\tpublic readonly typeName: R['typeName'],\n\t\tconfig: {\n\t\t\t// eslint-disable-next-line @typescript-eslint/method-signature-style\n\t\t\treadonly createDefaultProperties: () => Exclude<\n\t\t\t\tOmit<R, 'id' | 'typeName'>,\n\t\t\t\tRequiredProperties\n\t\t\t>\n\t\t\treadonly validator?: StoreValidator<R>\n\t\t\treadonly scope?: RecordScope\n\t\t\treadonly ephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }\n\t\t}\n\t) {\n\t\tthis.createDefaultProperties = config.createDefaultProperties\n\t\tthis.validator = config.validator ?? { validate: (r: unknown) => r as R }\n\t\tthis.scope = config.scope ?? 'document'\n\t\tthis.ephemeralKeys = config.ephemeralKeys\n\n\t\tconst ephemeralKeySet = new Set<string>()\n\t\tif (config.ephemeralKeys) {\n\t\t\tfor (const [key, isEphemeral] of objectMapEntries(config.ephemeralKeys)) {\n\t\t\t\tif (isEphemeral) ephemeralKeySet.add(key)\n\t\t\t}\n\t\t}\n\t\tthis.ephemeralKeySet = ephemeralKeySet\n\t}\n\n\t/**\n\t * Create a new record of this type.\n\t *\n\t * @param properties - The properties of the record.\n\t * @returns The new record.\n\t */\n\tcreate(\n\t\tproperties: Expand<Pick<R, RequiredProperties> & Omit<Partial<R>, RequiredProperties>>\n\t): R {\n\t\tconst result = {\n\t\t\t...this.createDefaultProperties(),\n\t\t\tid: 'id' in properties ? properties.id : this.createId(),\n\t\t} as any\n\n\t\tfor (const [k, v] of Object.entries(properties)) {\n\t\t\tif (v !== undefined) {\n\t\t\t\tresult[k] = v\n\t\t\t}\n\t\t}\n\n\t\tresult.typeName = this.typeName\n\n\t\treturn result as R\n\t}\n\n\t/**\n\t * Clone a record of this type.\n\t *\n\t * @param record - The record to clone.\n\t * @returns The cloned record.\n\t * @public\n\t */\n\tclone(record: R): R {\n\t\treturn { ...structuredClone(record), id: this.createId() }\n\t}\n\n\t/**\n\t * Create a new ID for this record type.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const id = recordType.createId()\n\t * ```\n\t *\n\t * @returns The new ID.\n\t * @public\n\t */\n\tcreateId(customUniquePart?: string): IdOf<R> {\n\t\treturn (this.typeName + ':' + (customUniquePart ?? uniqueId())) as IdOf<R>\n\t}\n\n\t/**\n\t * Create a new ID for this record type based on the given ID.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const id = recordType.createCustomId('myId')\n\t * ```\n\t *\n\t * @deprecated - Use `createId` instead.\n\t * @param id - The ID to base the new ID on.\n\t * @returns The new ID.\n\t */\n\tcreateCustomId(id: string): IdOf<R> {\n\t\treturn (this.typeName + ':' + id) as IdOf<R>\n\t}\n\n\t/**\n\t * Takes an id like `user:123` and returns the part after the colon `123`\n\t *\n\t * @param id - The id\n\t * @returns\n\t */\n\tparseId(id: IdOf<R>): string {\n\t\tif (!this.isId(id)) {\n\t\t\tthrow new Error(`ID \"${id}\" is not a valid ID for type \"${this.typeName}\"`)\n\t\t}\n\n\t\treturn id.slice(this.typeName.length + 1)\n\t}\n\n\t/**\n\t * Check whether a record is an instance of this record type.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const result = recordType.isInstance(someRecord)\n\t * ```\n\t *\n\t * @param record - The record to check.\n\t * @returns Whether the record is an instance of this record type.\n\t */\n\tisInstance(record?: UnknownRecord): record is R {\n\t\treturn record?.typeName === this.typeName\n\t}\n\n\t/**\n\t * Check whether an id is an id of this type.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const result = recordType.isIn('someId')\n\t * ```\n\t *\n\t * @param id - The id to check.\n\t * @returns Whether the id is an id of this type.\n\t */\n\tisId(id?: string): id is IdOf<R> {\n\t\tif (!id) return false\n\t\tfor (let i = 0; i < this.typeName.length; i++) {\n\t\t\tif (id[i] !== this.typeName[i]) return false\n\t\t}\n\n\t\treturn id[this.typeName.length] === ':'\n\t}\n\n\t/**\n\t * Create a new RecordType that has the same type name as this RecordType and includes the given\n\t * default properties.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const authorType = createRecordType('author', () => ({ living: true }))\n\t * const deadAuthorType = authorType.withDefaultProperties({ living: false })\n\t * ```\n\t *\n\t * @param createDefaultProperties - A function that returns the default properties of the new RecordType.\n\t * @returns The new RecordType.\n\t */\n\twithDefaultProperties<DefaultProps extends Omit<Partial<R>, 'typeName' | 'id'>>(\n\t\tcreateDefaultProperties: () => DefaultProps\n\t): RecordType<R, Exclude<RequiredProperties, keyof DefaultProps>> {\n\t\treturn new RecordType<R, Exclude<RequiredProperties, keyof DefaultProps>>(this.typeName, {\n\t\t\tcreateDefaultProperties: createDefaultProperties as any,\n\t\t\tvalidator: this.validator,\n\t\t\tscope: this.scope,\n\t\t\tephemeralKeys: this.ephemeralKeys,\n\t\t})\n\t}\n\n\t/**\n\t * Check that the passed in record passes the validations for this type. Returns its input\n\t * correctly typed if it does, but throws an error otherwise.\n\t */\n\tvalidate(record: unknown, recordBefore?: R): R {\n\t\tif (recordBefore && this.validator.validateUsingKnownGoodVersion) {\n\t\t\treturn this.validator.validateUsingKnownGoodVersion(recordBefore, record)\n\t\t}\n\t\treturn this.validator.validate(record)\n\t}\n}\n\n/**\n * Create a record type.\n *\n * @example\n *\n * ```ts\n * const Book = createRecordType<Book>('book')\n * ```\n *\n * @param typeName - The name of the type to create.\n * @public\n */\nexport function createRecordType<R extends UnknownRecord>(\n\ttypeName: R['typeName'],\n\tconfig: {\n\t\tvalidator?: StoreValidator<R>\n\t\tscope: RecordScope\n\t\tephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }\n\t}\n): RecordType<R, keyof Omit<R, 'id' | 'typeName'>> {\n\treturn new RecordType<R, keyof Omit<R, 'id' | 'typeName'>>(typeName, {\n\t\tcreateDefaultProperties: () => ({}) as any,\n\t\tvalidator: config.validator,\n\t\tscope: config.scope,\n\t\tephemeralKeys: config.ephemeralKeys,\n\t})\n}\n\n/**\n * Assert whether an id correspond to a record type.\n *\n * @example\n *\n * ```ts\n * assertIdType(myId, \"shape\")\n * ```\n *\n * @param id - The id to check.\n * @param type - The type of the record.\n * @public\n */\nexport function assertIdType<R extends UnknownRecord>(\n\tid: string | undefined,\n\ttype: RecordType<R, any>\n): asserts id is IdOf<R> {\n\tif (!id || !type.isId(id)) {\n\t\tthrow new Error(`string ${JSON.stringify(id)} is not a valid ${type.typeName} id`)\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Expand, objectMapEntries, structuredClone, uniqueId } from '@tldraw/utils'\nimport { IdOf, UnknownRecord } from './BaseRecord'\nimport { StoreValidator } from './Store'\n\nexport type RecordTypeRecord<R extends RecordType<any, any>> = ReturnType<R['create']>\n\n/**\n * Defines the scope of the record\n *\n * session: The record belongs to a single instance of the store. It should not be synced, and any persistence logic should 'de-instance-ize' the record before persisting it, and apply the reverse when rehydrating.\n * document: The record is persisted and synced. It is available to all store instances.\n * presence: The record belongs to a single instance of the store. It may be synced to other instances, but other instances should not make changes to it. It should not be persisted.\n *\n * @public\n * */\nexport type RecordScope = 'session' | 'document' | 'presence'\n\n/**\n * A record type is a type that can be stored in a record store. It is created with\n * `createRecordType`.\n *\n * @public\n */\nexport class RecordType<\n\tR extends UnknownRecord,\n\tRequiredProperties extends keyof Omit<R, 'id' | 'typeName'>,\n> {\n\treadonly createDefaultProperties: () => Exclude<Omit<R, 'id' | 'typeName'>, RequiredProperties>\n\treadonly validator: StoreValidator<R>\n\treadonly ephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }\n\treadonly ephemeralKeySet: ReadonlySet<string>\n\treadonly scope: RecordScope\n\n\tconstructor(\n\t\t/**\n\t\t * The unique type associated with this record.\n\t\t *\n\t\t * @public\n\t\t * @readonly\n\t\t */\n\t\tpublic readonly typeName: R['typeName'],\n\t\tconfig: {\n\t\t\t// eslint-disable-next-line @typescript-eslint/method-signature-style\n\t\t\treadonly createDefaultProperties: () => Exclude<\n\t\t\t\tOmit<R, 'id' | 'typeName'>,\n\t\t\t\tRequiredProperties\n\t\t\t>\n\t\t\treadonly validator?: StoreValidator<R>\n\t\t\treadonly scope?: RecordScope\n\t\t\treadonly ephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }\n\t\t}\n\t) {\n\t\tthis.createDefaultProperties = config.createDefaultProperties\n\t\tthis.validator = config.validator ?? { validate: (r: unknown) => r as R }\n\t\tthis.scope = config.scope ?? 'document'\n\t\tthis.ephemeralKeys = config.ephemeralKeys\n\n\t\tconst ephemeralKeySet = new Set<string>()\n\t\tif (config.ephemeralKeys) {\n\t\t\tfor (const [key, isEphemeral] of objectMapEntries(config.ephemeralKeys)) {\n\t\t\t\tif (isEphemeral) ephemeralKeySet.add(key)\n\t\t\t}\n\t\t}\n\t\tthis.ephemeralKeySet = ephemeralKeySet\n\t}\n\n\t/**\n\t * Create a new record of this type.\n\t *\n\t * @param properties - The properties of the record.\n\t * @returns The new record.\n\t */\n\tcreate(\n\t\tproperties: Expand<Pick<R, RequiredProperties> & Omit<Partial<R>, RequiredProperties>>\n\t): R {\n\t\tconst result = {\n\t\t\t...this.createDefaultProperties(),\n\t\t\tid: 'id' in properties ? properties.id : this.createId(),\n\t\t} as any\n\n\t\tfor (const [k, v] of Object.entries(properties)) {\n\t\t\tif (v !== undefined) {\n\t\t\t\tresult[k] = v\n\t\t\t}\n\t\t}\n\n\t\tresult.typeName = this.typeName\n\n\t\treturn result as R\n\t}\n\n\t/**\n\t * Clone a record of this type.\n\t *\n\t * @param record - The record to clone.\n\t * @returns The cloned record.\n\t * @public\n\t */\n\tclone(record: R): R {\n\t\treturn { ...structuredClone(record), id: this.createId() }\n\t}\n\n\t/**\n\t * Create a new ID for this record type.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const id = recordType.createId()\n\t * ```\n\t *\n\t * @returns The new ID.\n\t * @public\n\t */\n\tcreateId(customUniquePart?: string): IdOf<R> {\n\t\treturn (this.typeName + ':' + (customUniquePart ?? uniqueId())) as IdOf<R>\n\t}\n\n\t/**\n\t * Takes an id like `user:123` and returns the part after the colon `123`\n\t *\n\t * @param id - The id\n\t * @returns\n\t */\n\tparseId(id: IdOf<R>): string {\n\t\tif (!this.isId(id)) {\n\t\t\tthrow new Error(`ID \"${id}\" is not a valid ID for type \"${this.typeName}\"`)\n\t\t}\n\n\t\treturn id.slice(this.typeName.length + 1)\n\t}\n\n\t/**\n\t * Check whether a record is an instance of this record type.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const result = recordType.isInstance(someRecord)\n\t * ```\n\t *\n\t * @param record - The record to check.\n\t * @returns Whether the record is an instance of this record type.\n\t */\n\tisInstance(record?: UnknownRecord): record is R {\n\t\treturn record?.typeName === this.typeName\n\t}\n\n\t/**\n\t * Check whether an id is an id of this type.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const result = recordType.isIn('someId')\n\t * ```\n\t *\n\t * @param id - The id to check.\n\t * @returns Whether the id is an id of this type.\n\t */\n\tisId(id?: string): id is IdOf<R> {\n\t\tif (!id) return false\n\t\tfor (let i = 0; i < this.typeName.length; i++) {\n\t\t\tif (id[i] !== this.typeName[i]) return false\n\t\t}\n\n\t\treturn id[this.typeName.length] === ':'\n\t}\n\n\t/**\n\t * Create a new RecordType that has the same type name as this RecordType and includes the given\n\t * default properties.\n\t *\n\t * @example\n\t *\n\t * ```ts\n\t * const authorType = createRecordType('author', () => ({ living: true }))\n\t * const deadAuthorType = authorType.withDefaultProperties({ living: false })\n\t * ```\n\t *\n\t * @param createDefaultProperties - A function that returns the default properties of the new RecordType.\n\t * @returns The new RecordType.\n\t */\n\twithDefaultProperties<DefaultProps extends Omit<Partial<R>, 'typeName' | 'id'>>(\n\t\tcreateDefaultProperties: () => DefaultProps\n\t): RecordType<R, Exclude<RequiredProperties, keyof DefaultProps>> {\n\t\treturn new RecordType<R, Exclude<RequiredProperties, keyof DefaultProps>>(this.typeName, {\n\t\t\tcreateDefaultProperties: createDefaultProperties as any,\n\t\t\tvalidator: this.validator,\n\t\t\tscope: this.scope,\n\t\t\tephemeralKeys: this.ephemeralKeys,\n\t\t})\n\t}\n\n\t/**\n\t * Check that the passed in record passes the validations for this type. Returns its input\n\t * correctly typed if it does, but throws an error otherwise.\n\t */\n\tvalidate(record: unknown, recordBefore?: R): R {\n\t\tif (recordBefore && this.validator.validateUsingKnownGoodVersion) {\n\t\t\treturn this.validator.validateUsingKnownGoodVersion(recordBefore, record)\n\t\t}\n\t\treturn this.validator.validate(record)\n\t}\n}\n\n/**\n * Create a record type.\n *\n * @example\n *\n * ```ts\n * const Book = createRecordType<Book>('book')\n * ```\n *\n * @param typeName - The name of the type to create.\n * @public\n */\nexport function createRecordType<R extends UnknownRecord>(\n\ttypeName: R['typeName'],\n\tconfig: {\n\t\tvalidator?: StoreValidator<R>\n\t\tscope: RecordScope\n\t\tephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }\n\t}\n): RecordType<R, keyof Omit<R, 'id' | 'typeName'>> {\n\treturn new RecordType<R, keyof Omit<R, 'id' | 'typeName'>>(typeName, {\n\t\tcreateDefaultProperties: () => ({}) as any,\n\t\tvalidator: config.validator,\n\t\tscope: config.scope,\n\t\tephemeralKeys: config.ephemeralKeys,\n\t})\n}\n\n/**\n * Assert whether an id correspond to a record type.\n *\n * @example\n *\n * ```ts\n * assertIdType(myId, \"shape\")\n * ```\n *\n * @param id - The id to check.\n * @param type - The type of the record.\n * @public\n */\nexport function assertIdType<R extends UnknownRecord>(\n\tid: string | undefined,\n\ttype: RecordType<R, any>\n): asserts id is IdOf<R> {\n\tif (!id || !type.isId(id)) {\n\t\tthrow new Error(`string ${JSON.stringify(id)} is not a valid ${type.typeName} id`)\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAoE;AAuB7D,MAAM,WAGX;AAAA,EAOD,YAOiB,UAChB,QAUC;AAXe;AAYhB,SAAK,0BAA0B,OAAO;AACtC,SAAK,YAAY,OAAO,aAAa,EAAE,UAAU,CAAC,MAAe,EAAO;AACxE,SAAK,QAAQ,OAAO,SAAS;AAC7B,SAAK,gBAAgB,OAAO;AAE5B,UAAM,kBAAkB,oBAAI,IAAY;AACxC,QAAI,OAAO,eAAe;AACzB,iBAAW,CAAC,KAAK,WAAW,SAAK,+BAAiB,OAAO,aAAa,GAAG;AACxE,YAAI,YAAa,iBAAgB,IAAI,GAAG;AAAA,MACzC;AAAA,IACD;AACA,SAAK,kBAAkB;AAAA,EACxB;AAAA,EArCS;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyCT,OACC,YACI;AACJ,UAAM,SAAS;AAAA,MACd,GAAG,KAAK,wBAAwB;AAAA,MAChC,IAAI,QAAQ,aAAa,WAAW,KAAK,KAAK,SAAS;AAAA,IACxD;AAEA,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,UAAU,GAAG;AAChD,UAAI,MAAM,QAAW;AACpB,eAAO,CAAC,IAAI;AAAA,MACb;AAAA,IACD;AAEA,WAAO,WAAW,KAAK;AAEvB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAc;AACnB,WAAO,EAAE,OAAG,8BAAgB,MAAM,GAAG,IAAI,KAAK,SAAS,EAAE;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,SAAS,kBAAoC;AAC5C,WAAQ,KAAK,WAAW,OAAO,wBAAoB,uBAAS;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAQ,IAAqB;AAC5B,QAAI,CAAC,KAAK,KAAK,EAAE,GAAG;AACnB,YAAM,IAAI,MAAM,OAAO,EAAE,iCAAiC,KAAK,QAAQ,GAAG;AAAA,IAC3E;AAEA,WAAO,GAAG,MAAM,KAAK,SAAS,SAAS,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAW,QAAqC;AAC/C,WAAO,QAAQ,aAAa,KAAK;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,KAAK,IAA4B;AAChC,QAAI,CAAC,GAAI,QAAO;AAChB,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC9C,UAAI,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,EAAG,QAAO;AAAA,IACxC;AAEA,WAAO,GAAG,KAAK,SAAS,MAAM,MAAM;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,sBACC,yBACiE;AACjE,WAAO,IAAI,WAA+D,KAAK,UAAU;AAAA,MACxF;AAAA,MACA,WAAW,KAAK;AAAA,MAChB,OAAO,KAAK;AAAA,MACZ,eAAe,KAAK;AAAA,IACrB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,QAAiB,cAAqB;AAC9C,QAAI,gBAAgB,KAAK,UAAU,+BAA+B;AACjE,aAAO,KAAK,UAAU,8BAA8B,cAAc,MAAM;AAAA,IACzE;AACA,WAAO,KAAK,UAAU,SAAS,MAAM;AAAA,EACtC;AACD;AAcO,SAAS,iBACf,UACA,QAKkD;AAClD,SAAO,IAAI,WAAgD,UAAU;AAAA,IACpE,yBAAyB,OAAO,CAAC;AAAA,IACjC,WAAW,OAAO;AAAA,IAClB,OAAO,OAAO;AAAA,IACd,eAAe,OAAO;AAAA,EACvB,CAAC;AACF;AAeO,SAAS,aACf,IACA,MACwB;AACxB,MAAI,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,GAAG;AAC1B,UAAM,IAAI,MAAM,UAAU,KAAK,UAAU,EAAE,CAAC,mBAAmB,KAAK,QAAQ,KAAK;AAAA,EAClF;AACD;",
6
6
  "names": []
7
7
  }
@@ -39,9 +39,9 @@ function reverseRecordsDiff(diff) {
39
39
  function isRecordsDiffEmpty(diff) {
40
40
  return Object.keys(diff.added).length === 0 && Object.keys(diff.updated).length === 0 && Object.keys(diff.removed).length === 0;
41
41
  }
42
- function squashRecordDiffs(diffs) {
43
- const result = { added: {}, removed: {}, updated: {} };
44
- squashRecordDiffsMutable(result, diffs);
42
+ function squashRecordDiffs(diffs, options) {
43
+ const result = options?.mutateFirstDiff ? diffs[0] : { added: {}, removed: {}, updated: {} };
44
+ squashRecordDiffsMutable(result, options?.mutateFirstDiff ? diffs.slice(1) : diffs);
45
45
  return result;
46
46
  }
47
47
  function squashRecordDiffsMutable(target, diffs) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/RecordsDiff.ts"],
4
- "sourcesContent": ["import { objectMapEntries } from '@tldraw/utils'\nimport { IdOf, UnknownRecord } from './BaseRecord'\n\n/**\n * A diff describing the changes to a record.\n *\n * @public\n */\nexport interface RecordsDiff<R extends UnknownRecord> {\n\tadded: Record<IdOf<R>, R>\n\tupdated: Record<IdOf<R>, [from: R, to: R]>\n\tremoved: Record<IdOf<R>, R>\n}\n\n/** @internal */\nexport function createEmptyRecordsDiff<R extends UnknownRecord>(): RecordsDiff<R> {\n\treturn { added: {}, updated: {}, removed: {} } as RecordsDiff<R>\n}\n\n/** @public */\nexport function reverseRecordsDiff(diff: RecordsDiff<any>) {\n\tconst result: RecordsDiff<any> = { added: diff.removed, removed: diff.added, updated: {} }\n\tfor (const [from, to] of Object.values(diff.updated)) {\n\t\tresult.updated[from.id] = [to, from]\n\t}\n\treturn result\n}\n\n/**\n * Is a records diff empty?\n * @internal\n */\nexport function isRecordsDiffEmpty<T extends UnknownRecord>(diff: RecordsDiff<T>) {\n\treturn (\n\t\tObject.keys(diff.added).length === 0 &&\n\t\tObject.keys(diff.updated).length === 0 &&\n\t\tObject.keys(diff.removed).length === 0\n\t)\n}\n\n/**\n * Squash a collection of diffs into a single diff.\n *\n * @param diffs - An array of diffs to squash.\n * @returns A single diff that represents the squashed diffs.\n * @public\n */\nexport function squashRecordDiffs<T extends UnknownRecord>(\n\tdiffs: RecordsDiff<T>[]\n): RecordsDiff<T> {\n\tconst result = { added: {}, removed: {}, updated: {} } as RecordsDiff<T>\n\n\tsquashRecordDiffsMutable(result, diffs)\n\treturn result\n}\n\n/**\n * Apply the array `diffs` to the `target` diff, mutating it in-place.\n * @internal\n */\nexport function squashRecordDiffsMutable<T extends UnknownRecord>(\n\ttarget: RecordsDiff<T>,\n\tdiffs: RecordsDiff<T>[]\n): void {\n\tfor (const diff of diffs) {\n\t\tfor (const [id, value] of objectMapEntries(diff.added)) {\n\t\t\tif (target.removed[id]) {\n\t\t\t\tconst original = target.removed[id]\n\t\t\t\tdelete target.removed[id]\n\t\t\t\tif (original !== value) {\n\t\t\t\t\ttarget.updated[id] = [original, value]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttarget.added[id] = value\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, [_from, to]] of objectMapEntries(diff.updated)) {\n\t\t\tif (target.added[id]) {\n\t\t\t\ttarget.added[id] = to\n\t\t\t\tdelete target.updated[id]\n\t\t\t\tdelete target.removed[id]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (target.updated[id]) {\n\t\t\t\ttarget.updated[id] = [target.updated[id][0], to]\n\t\t\t\tdelete target.removed[id]\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttarget.updated[id] = diff.updated[id]\n\t\t\tdelete target.removed[id]\n\t\t}\n\n\t\tfor (const [id, value] of objectMapEntries(diff.removed)) {\n\t\t\t// the same record was added in this diff sequence, just drop it\n\t\t\tif (target.added[id]) {\n\t\t\t\tdelete target.added[id]\n\t\t\t} else if (target.updated[id]) {\n\t\t\t\ttarget.removed[id] = target.updated[id][0]\n\t\t\t\tdelete target.updated[id]\n\t\t\t} else {\n\t\t\t\ttarget.removed[id] = value\n\t\t\t}\n\t\t}\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AAe1B,SAAS,yBAAkE;AACjF,SAAO,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AAC9C;AAGO,SAAS,mBAAmB,MAAwB;AAC1D,QAAM,SAA2B,EAAE,OAAO,KAAK,SAAS,SAAS,KAAK,OAAO,SAAS,CAAC,EAAE;AACzF,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,OAAO,KAAK,OAAO,GAAG;AACrD,WAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI;AAAA,EACpC;AACA,SAAO;AACR;AAMO,SAAS,mBAA4C,MAAsB;AACjF,SACC,OAAO,KAAK,KAAK,KAAK,EAAE,WAAW,KACnC,OAAO,KAAK,KAAK,OAAO,EAAE,WAAW,KACrC,OAAO,KAAK,KAAK,OAAO,EAAE,WAAW;AAEvC;AASO,SAAS,kBACf,OACiB;AACjB,QAAM,SAAS,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AAErD,2BAAyB,QAAQ,KAAK;AACtC,SAAO;AACR;AAMO,SAAS,yBACf,QACA,OACO;AACP,aAAW,QAAQ,OAAO;AACzB,eAAW,CAAC,IAAI,KAAK,SAAK,+BAAiB,KAAK,KAAK,GAAG;AACvD,UAAI,OAAO,QAAQ,EAAE,GAAG;AACvB,cAAM,WAAW,OAAO,QAAQ,EAAE;AAClC,eAAO,OAAO,QAAQ,EAAE;AACxB,YAAI,aAAa,OAAO;AACvB,iBAAO,QAAQ,EAAE,IAAI,CAAC,UAAU,KAAK;AAAA,QACtC;AAAA,MACD,OAAO;AACN,eAAO,MAAM,EAAE,IAAI;AAAA,MACpB;AAAA,IACD;AAEA,eAAW,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,SAAK,+BAAiB,KAAK,OAAO,GAAG;AAC/D,UAAI,OAAO,MAAM,EAAE,GAAG;AACrB,eAAO,MAAM,EAAE,IAAI;AACnB,eAAO,OAAO,QAAQ,EAAE;AACxB,eAAO,OAAO,QAAQ,EAAE;AACxB;AAAA,MACD;AACA,UAAI,OAAO,QAAQ,EAAE,GAAG;AACvB,eAAO,QAAQ,EAAE,IAAI,CAAC,OAAO,QAAQ,EAAE,EAAE,CAAC,GAAG,EAAE;AAC/C,eAAO,OAAO,QAAQ,EAAE;AACxB;AAAA,MACD;AAEA,aAAO,QAAQ,EAAE,IAAI,KAAK,QAAQ,EAAE;AACpC,aAAO,OAAO,QAAQ,EAAE;AAAA,IACzB;AAEA,eAAW,CAAC,IAAI,KAAK,SAAK,+BAAiB,KAAK,OAAO,GAAG;AAEzD,UAAI,OAAO,MAAM,EAAE,GAAG;AACrB,eAAO,OAAO,MAAM,EAAE;AAAA,MACvB,WAAW,OAAO,QAAQ,EAAE,GAAG;AAC9B,eAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE,EAAE,CAAC;AACzC,eAAO,OAAO,QAAQ,EAAE;AAAA,MACzB,OAAO;AACN,eAAO,QAAQ,EAAE,IAAI;AAAA,MACtB;AAAA,IACD;AAAA,EACD;AACD;",
4
+ "sourcesContent": ["import { objectMapEntries } from '@tldraw/utils'\nimport { IdOf, UnknownRecord } from './BaseRecord'\n\n/**\n * A diff describing the changes to a record.\n *\n * @public\n */\nexport interface RecordsDiff<R extends UnknownRecord> {\n\tadded: Record<IdOf<R>, R>\n\tupdated: Record<IdOf<R>, [from: R, to: R]>\n\tremoved: Record<IdOf<R>, R>\n}\n\n/** @internal */\nexport function createEmptyRecordsDiff<R extends UnknownRecord>(): RecordsDiff<R> {\n\treturn { added: {}, updated: {}, removed: {} } as RecordsDiff<R>\n}\n\n/** @public */\nexport function reverseRecordsDiff(diff: RecordsDiff<any>) {\n\tconst result: RecordsDiff<any> = { added: diff.removed, removed: diff.added, updated: {} }\n\tfor (const [from, to] of Object.values(diff.updated)) {\n\t\tresult.updated[from.id] = [to, from]\n\t}\n\treturn result\n}\n\n/**\n * Is a records diff empty?\n * @internal\n */\nexport function isRecordsDiffEmpty<T extends UnknownRecord>(diff: RecordsDiff<T>) {\n\treturn (\n\t\tObject.keys(diff.added).length === 0 &&\n\t\tObject.keys(diff.updated).length === 0 &&\n\t\tObject.keys(diff.removed).length === 0\n\t)\n}\n\n/**\n * Squash a collection of diffs into a single diff.\n *\n * @param diffs - An array of diffs to squash.\n * @param options - An optional object with a `mutateFirstDiff` property. If `mutateFirstDiff` is true, the first diff in the array will be mutated in-place.\n * @returns A single diff that represents the squashed diffs.\n * @public\n */\nexport function squashRecordDiffs<T extends UnknownRecord>(\n\tdiffs: RecordsDiff<T>[],\n\toptions?: {\n\t\tmutateFirstDiff?: boolean\n\t}\n): RecordsDiff<T> {\n\tconst result = options?.mutateFirstDiff\n\t\t? diffs[0]\n\t\t: ({ added: {}, removed: {}, updated: {} } as RecordsDiff<T>)\n\n\tsquashRecordDiffsMutable(result, options?.mutateFirstDiff ? diffs.slice(1) : diffs)\n\treturn result\n}\n\n/**\n * Apply the array `diffs` to the `target` diff, mutating it in-place.\n * @internal\n */\nexport function squashRecordDiffsMutable<T extends UnknownRecord>(\n\ttarget: RecordsDiff<T>,\n\tdiffs: RecordsDiff<T>[]\n): void {\n\tfor (const diff of diffs) {\n\t\tfor (const [id, value] of objectMapEntries(diff.added)) {\n\t\t\tif (target.removed[id]) {\n\t\t\t\tconst original = target.removed[id]\n\t\t\t\tdelete target.removed[id]\n\t\t\t\tif (original !== value) {\n\t\t\t\t\ttarget.updated[id] = [original, value]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttarget.added[id] = value\n\t\t\t}\n\t\t}\n\n\t\tfor (const [id, [_from, to]] of objectMapEntries(diff.updated)) {\n\t\t\tif (target.added[id]) {\n\t\t\t\ttarget.added[id] = to\n\t\t\t\tdelete target.updated[id]\n\t\t\t\tdelete target.removed[id]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (target.updated[id]) {\n\t\t\t\ttarget.updated[id] = [target.updated[id][0], to]\n\t\t\t\tdelete target.removed[id]\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttarget.updated[id] = diff.updated[id]\n\t\t\tdelete target.removed[id]\n\t\t}\n\n\t\tfor (const [id, value] of objectMapEntries(diff.removed)) {\n\t\t\t// the same record was added in this diff sequence, just drop it\n\t\t\tif (target.added[id]) {\n\t\t\t\tdelete target.added[id]\n\t\t\t} else if (target.updated[id]) {\n\t\t\t\ttarget.removed[id] = target.updated[id][0]\n\t\t\t\tdelete target.updated[id]\n\t\t\t} else {\n\t\t\t\ttarget.removed[id] = value\n\t\t\t}\n\t\t}\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AAe1B,SAAS,yBAAkE;AACjF,SAAO,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AAC9C;AAGO,SAAS,mBAAmB,MAAwB;AAC1D,QAAM,SAA2B,EAAE,OAAO,KAAK,SAAS,SAAS,KAAK,OAAO,SAAS,CAAC,EAAE;AACzF,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,OAAO,KAAK,OAAO,GAAG;AACrD,WAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI;AAAA,EACpC;AACA,SAAO;AACR;AAMO,SAAS,mBAA4C,MAAsB;AACjF,SACC,OAAO,KAAK,KAAK,KAAK,EAAE,WAAW,KACnC,OAAO,KAAK,KAAK,OAAO,EAAE,WAAW,KACrC,OAAO,KAAK,KAAK,OAAO,EAAE,WAAW;AAEvC;AAUO,SAAS,kBACf,OACA,SAGiB;AACjB,QAAM,SAAS,SAAS,kBACrB,MAAM,CAAC,IACN,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,EAAE;AAE1C,2BAAyB,QAAQ,SAAS,kBAAkB,MAAM,MAAM,CAAC,IAAI,KAAK;AAClF,SAAO;AACR;AAMO,SAAS,yBACf,QACA,OACO;AACP,aAAW,QAAQ,OAAO;AACzB,eAAW,CAAC,IAAI,KAAK,SAAK,+BAAiB,KAAK,KAAK,GAAG;AACvD,UAAI,OAAO,QAAQ,EAAE,GAAG;AACvB,cAAM,WAAW,OAAO,QAAQ,EAAE;AAClC,eAAO,OAAO,QAAQ,EAAE;AACxB,YAAI,aAAa,OAAO;AACvB,iBAAO,QAAQ,EAAE,IAAI,CAAC,UAAU,KAAK;AAAA,QACtC;AAAA,MACD,OAAO;AACN,eAAO,MAAM,EAAE,IAAI;AAAA,MACpB;AAAA,IACD;AAEA,eAAW,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,SAAK,+BAAiB,KAAK,OAAO,GAAG;AAC/D,UAAI,OAAO,MAAM,EAAE,GAAG;AACrB,eAAO,MAAM,EAAE,IAAI;AACnB,eAAO,OAAO,QAAQ,EAAE;AACxB,eAAO,OAAO,QAAQ,EAAE;AACxB;AAAA,MACD;AACA,UAAI,OAAO,QAAQ,EAAE,GAAG;AACvB,eAAO,QAAQ,EAAE,IAAI,CAAC,OAAO,QAAQ,EAAE,EAAE,CAAC,GAAG,EAAE;AAC/C,eAAO,OAAO,QAAQ,EAAE;AACxB;AAAA,MACD;AAEA,aAAO,QAAQ,EAAE,IAAI,KAAK,QAAQ,EAAE;AACpC,aAAO,OAAO,QAAQ,EAAE;AAAA,IACzB;AAEA,eAAW,CAAC,IAAI,KAAK,SAAK,+BAAiB,KAAK,OAAO,GAAG;AAEzD,UAAI,OAAO,MAAM,EAAE,GAAG;AACrB,eAAO,OAAO,MAAM,EAAE;AAAA,MACvB,WAAW,OAAO,QAAQ,EAAE,GAAG;AAC9B,eAAO,QAAQ,EAAE,IAAI,OAAO,QAAQ,EAAE,EAAE,CAAC;AACzC,eAAO,OAAO,QAAQ,EAAE;AAAA,MACzB,OAAO;AACN,eAAO,QAAQ,EAAE,IAAI;AAAA,MACtB;AAAA,IACD;AAAA,EACD;AACD;",
6
6
  "names": []
7
7
  }
@@ -328,20 +328,11 @@ class Store {
328
328
  schema: this.schema.serialize()
329
329
  };
330
330
  }
331
- /**
332
- * @deprecated use `getSnapshot` from the 'tldraw' package instead.
333
- */
334
- getSnapshot(scope = "document") {
335
- console.warn(
336
- "[tldraw] `Store.getSnapshot` is deprecated and will be removed in a future release. Use `getSnapshot` from the `tldraw` package instead."
337
- );
338
- return this.getStoreSnapshot(scope);
339
- }
340
331
  /**
341
332
  * Migrate a serialized snapshot of the store and its schema.
342
333
  *
343
334
  * ```ts
344
- * const snapshot = store.getSnapshot()
335
+ * const snapshot = store.getStoreSnapshot()
345
336
  * store.migrateSnapshot(snapshot)
346
337
  * ```
347
338
  *
@@ -386,16 +377,6 @@ class Store {
386
377
  this.sideEffects.setIsEnabled(prevSideEffectsEnabled);
387
378
  }
388
379
  }
389
- /**
390
- * @public
391
- * @deprecated use `loadSnapshot` from the 'tldraw' package instead.
392
- */
393
- loadSnapshot(snapshot) {
394
- console.warn(
395
- "[tldraw] `Store.loadSnapshot` is deprecated and will be removed in a future release. Use `loadSnapshot` from the 'tldraw' package instead."
396
- );
397
- this.loadStoreSnapshot(snapshot);
398
- }
399
380
  /**
400
381
  * Get an array of all values in the store.
401
382
  *