[tweak] migrate store snapshot arguments (#1659)
This PR updates the `migrateStoreSnapshot` method in @tldraw/store ### Change Type - [x] `major` — Breaking change ### Test Plan - [x] Unit Tests
This commit is contained in:
parent
ed8d4d9e05
commit
2d5b2bdc94
6 changed files with 23 additions and 23 deletions
|
@ -181,10 +181,10 @@ export class TLLocalSyncClient {
|
||||||
const documentSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r]))
|
const documentSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r]))
|
||||||
const sessionStateSnapshot =
|
const sessionStateSnapshot =
|
||||||
data.sessionStateSnapshot ?? extractSessionStateFromLegacySnapshot(documentSnapshot)
|
data.sessionStateSnapshot ?? extractSessionStateFromLegacySnapshot(documentSnapshot)
|
||||||
const migrationResult = this.store.schema.migrateStoreSnapshot(
|
const migrationResult = this.store.schema.migrateStoreSnapshot({
|
||||||
documentSnapshot,
|
store: documentSnapshot,
|
||||||
data.schema ?? this.store.schema.serializeEarliestVersion()
|
schema: data.schema ?? this.store.schema.serializeEarliestVersion(),
|
||||||
)
|
})
|
||||||
|
|
||||||
if (migrationResult.type === 'error') {
|
if (migrationResult.type === 'error') {
|
||||||
console.error('failed to migrate store', migrationResult)
|
console.error('failed to migrate store', migrationResult)
|
||||||
|
|
|
@ -122,7 +122,7 @@ export function parseTldrawJsonFile({
|
||||||
let migrationResult: MigrationResult<SerializedStore<TLRecord>>
|
let migrationResult: MigrationResult<SerializedStore<TLRecord>>
|
||||||
try {
|
try {
|
||||||
const storeSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r as TLRecord]))
|
const storeSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r as TLRecord]))
|
||||||
migrationResult = schema.migrateStoreSnapshot(storeSnapshot, data.schema)
|
migrationResult = schema.migrateStoreSnapshot({ store: storeSnapshot, schema: data.schema })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// junk data in the migration
|
// junk data in the migration
|
||||||
return Result.err({ type: 'invalidRecords', cause: e })
|
return Result.err({ type: 'invalidRecords', cause: e })
|
||||||
|
|
|
@ -304,7 +304,7 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
migratePersistedRecord(record: R, persistedSchema: SerializedSchema, direction?: 'down' | 'up'): MigrationResult<R>;
|
migratePersistedRecord(record: R, persistedSchema: SerializedSchema, direction?: 'down' | 'up'): MigrationResult<R>;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
migrateStoreSnapshot(storeSnapshot: SerializedStore<R>, persistedSchema: SerializedSchema): MigrationResult<SerializedStore<R>>;
|
migrateStoreSnapshot(snapshot: StoreSnapshot<R>): MigrationResult<SerializedStore<R>>;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
serialize(): SerializedSchema;
|
serialize(): SerializedSchema;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
|
|
@ -551,7 +551,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
loadSnapshot(snapshot: StoreSnapshot<R>): void {
|
loadSnapshot(snapshot: StoreSnapshot<R>): void {
|
||||||
const migrationResult = this.schema.migrateStoreSnapshot(snapshot.store, snapshot.schema)
|
const migrationResult = this.schema.migrateStoreSnapshot(snapshot)
|
||||||
|
|
||||||
if (migrationResult.type === 'error') {
|
if (migrationResult.type === 'error') {
|
||||||
throw new Error(`Failed to migrate snapshot: ${migrationResult.reason}`)
|
throw new Error(`Failed to migrate snapshot: ${migrationResult.reason}`)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { getOwnProperty, objectMapValues } from '@tldraw/utils'
|
import { getOwnProperty, objectMapValues } from '@tldraw/utils'
|
||||||
import { IdOf, UnknownRecord } from './BaseRecord'
|
import { IdOf, UnknownRecord } from './BaseRecord'
|
||||||
import { RecordType } from './RecordType'
|
import { RecordType } from './RecordType'
|
||||||
import { SerializedStore, Store } from './Store'
|
import { SerializedStore, Store, StoreSnapshot } from './Store'
|
||||||
import {
|
import {
|
||||||
MigrationFailureReason,
|
MigrationFailureReason,
|
||||||
MigrationResult,
|
MigrationResult,
|
||||||
|
@ -188,17 +188,14 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
||||||
return { type: 'success', value: result.value }
|
return { type: 'success', value: result.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
migrateStoreSnapshot(
|
migrateStoreSnapshot(snapshot: StoreSnapshot<R>): MigrationResult<SerializedStore<R>> {
|
||||||
storeSnapshot: SerializedStore<R>,
|
|
||||||
persistedSchema: SerializedSchema
|
|
||||||
): MigrationResult<SerializedStore<R>> {
|
|
||||||
const migrations = this.options.snapshotMigrations
|
const migrations = this.options.snapshotMigrations
|
||||||
if (!migrations) {
|
if (!migrations) {
|
||||||
return { type: 'success', value: storeSnapshot }
|
return { type: 'success', value: snapshot.store }
|
||||||
}
|
}
|
||||||
// apply store migrations first
|
// apply store migrations first
|
||||||
const ourStoreVersion = migrations.currentVersion
|
const ourStoreVersion = migrations.currentVersion
|
||||||
const persistedStoreVersion = persistedSchema.storeVersion ?? 0
|
const persistedStoreVersion = snapshot.schema.storeVersion ?? 0
|
||||||
|
|
||||||
if (ourStoreVersion < persistedStoreVersion) {
|
if (ourStoreVersion < persistedStoreVersion) {
|
||||||
return { type: 'error', reason: MigrationFailureReason.TargetVersionTooOld }
|
return { type: 'error', reason: MigrationFailureReason.TargetVersionTooOld }
|
||||||
|
@ -206,7 +203,7 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
||||||
|
|
||||||
if (ourStoreVersion > persistedStoreVersion) {
|
if (ourStoreVersion > persistedStoreVersion) {
|
||||||
const result = migrate<SerializedStore<R>>({
|
const result = migrate<SerializedStore<R>>({
|
||||||
value: storeSnapshot,
|
value: snapshot.store,
|
||||||
migrations,
|
migrations,
|
||||||
fromVersion: persistedStoreVersion,
|
fromVersion: persistedStoreVersion,
|
||||||
toVersion: ourStoreVersion,
|
toVersion: ourStoreVersion,
|
||||||
|
@ -215,12 +212,12 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
||||||
if (result.type === 'error') {
|
if (result.type === 'error') {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
storeSnapshot = result.value
|
snapshot.store = result.value
|
||||||
}
|
}
|
||||||
|
|
||||||
const updated: R[] = []
|
const updated: R[] = []
|
||||||
for (const r of objectMapValues(storeSnapshot)) {
|
for (const r of objectMapValues(snapshot.store)) {
|
||||||
const result = this.migratePersistedRecord(r, persistedSchema)
|
const result = this.migratePersistedRecord(r, snapshot.schema)
|
||||||
if (result.type === 'error') {
|
if (result.type === 'error') {
|
||||||
return result
|
return result
|
||||||
} else if (result.value && result.value !== r) {
|
} else if (result.value && result.value !== r) {
|
||||||
|
@ -228,12 +225,12 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updated.length) {
|
if (updated.length) {
|
||||||
storeSnapshot = { ...storeSnapshot }
|
snapshot.store = { ...snapshot.store }
|
||||||
for (const r of updated) {
|
for (const r of updated) {
|
||||||
storeSnapshot[r.id as IdOf<R>] = r
|
snapshot.store[r.id as IdOf<R>] = r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { type: 'success', value: storeSnapshot }
|
return { type: 'success', value: snapshot.store }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
|
|
@ -305,7 +305,7 @@ test('subtype versions in the future fail', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('migrating a whole store snapshot works', () => {
|
test('migrating a whole store snapshot works', () => {
|
||||||
const snapshot: SerializedStore<any> = {
|
const serializedStore: SerializedStore<any> = {
|
||||||
'user-1': {
|
'user-1': {
|
||||||
id: 'user-1',
|
id: 'user-1',
|
||||||
typeName: 'user',
|
typeName: 'user',
|
||||||
|
@ -329,7 +329,10 @@ test('migrating a whole store snapshot works', () => {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = testSchemaV1.migrateStoreSnapshot(snapshot, serializedV0Schenma)
|
const result = testSchemaV1.migrateStoreSnapshot({
|
||||||
|
store: serializedStore,
|
||||||
|
schema: serializedV0Schenma,
|
||||||
|
})
|
||||||
|
|
||||||
if (result.type !== 'success') {
|
if (result.type !== 'success') {
|
||||||
console.error(result)
|
console.error(result)
|
||||||
|
|
Loading…
Reference in a new issue