[improvement] store snapshot types (#1657)
This PR improves the types for the Store. - renames `StoreSnapshot` to `SerializedStore`, which is the return type of `Store.serialize` - creates `StoreSnapshot` as a type for the return type of `Store.getSnapshot` / the argument type for `Store.loadSnapshot` - creates `TLStoreSnapshot` as the type used for the `TLStore`. This came out of a session I had with a user. This should prevent needing to import types from `@tldraw/store` directly. ### Change Type - [x] `major` — Breaking change ### Test Plan - [x] Unit Tests ### Release Notes - [dev] Rename `StoreSnapshot` to `SerializedStore` - [dev] Create new `StoreSnapshot` as type related to `getSnapshot`/`loadSnapshot`
This commit is contained in:
parent
faecd88220
commit
ed8d4d9e05
17 changed files with 71 additions and 57 deletions
|
@ -34,10 +34,10 @@ import { SelectionCorner } from '@tldraw/primitives';
|
||||||
import { SelectionEdge } from '@tldraw/primitives';
|
import { SelectionEdge } from '@tldraw/primitives';
|
||||||
import { SelectionHandle } from '@tldraw/primitives';
|
import { SelectionHandle } from '@tldraw/primitives';
|
||||||
import { SerializedSchema } from '@tldraw/store';
|
import { SerializedSchema } from '@tldraw/store';
|
||||||
|
import { SerializedStore } from '@tldraw/store';
|
||||||
import { ShapeProps } from '@tldraw/tlschema';
|
import { ShapeProps } from '@tldraw/tlschema';
|
||||||
import { Signal } from '@tldraw/state';
|
import { Signal } from '@tldraw/state';
|
||||||
import { StoreSchema } from '@tldraw/store';
|
import { StoreSchema } from '@tldraw/store';
|
||||||
import { StoreSnapshot } from '@tldraw/store';
|
|
||||||
import { StrokePoint } from '@tldraw/primitives';
|
import { StrokePoint } from '@tldraw/primitives';
|
||||||
import { StyleProp } from '@tldraw/tlschema';
|
import { StyleProp } from '@tldraw/tlschema';
|
||||||
import { TLArrowShape } from '@tldraw/tlschema';
|
import { TLArrowShape } from '@tldraw/tlschema';
|
||||||
|
@ -2228,7 +2228,7 @@ export type TldrawEditorProps = {
|
||||||
store: TLStore | TLStoreWithStatus;
|
store: TLStore | TLStoreWithStatus;
|
||||||
} | {
|
} | {
|
||||||
store?: undefined;
|
store?: undefined;
|
||||||
initialData?: StoreSnapshot<TLRecord>;
|
initialData?: SerializedStore<TLRecord>;
|
||||||
persistenceKey?: string;
|
persistenceKey?: string;
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
defaultName?: string;
|
defaultName?: string;
|
||||||
|
@ -2661,7 +2661,7 @@ export type TLStoreEventInfo = HistoryEntry<TLRecord>;
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export type TLStoreOptions = {
|
export type TLStoreOptions = {
|
||||||
initialData?: StoreSnapshot<TLRecord>;
|
initialData?: SerializedStore<TLRecord>;
|
||||||
defaultName?: string;
|
defaultName?: string;
|
||||||
} & ({
|
} & ({
|
||||||
schema: StoreSchema<TLRecord, TLStoreProps>;
|
schema: StoreSchema<TLRecord, TLStoreProps>;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Store, StoreSnapshot } from '@tldraw/store'
|
import { SerializedStore, Store } from '@tldraw/store'
|
||||||
import { TLRecord, TLStore } from '@tldraw/tlschema'
|
import { TLRecord, TLStore } from '@tldraw/tlschema'
|
||||||
import { RecursivePartial, Required, annotateError } from '@tldraw/utils'
|
import { RecursivePartial, Required, annotateError } from '@tldraw/utils'
|
||||||
import React, {
|
import React, {
|
||||||
|
@ -70,7 +70,7 @@ export type TldrawEditorProps = {
|
||||||
/**
|
/**
|
||||||
* The editor's initial data.
|
* The editor's initial data.
|
||||||
*/
|
*/
|
||||||
initialData?: StoreSnapshot<TLRecord>
|
initialData?: SerializedStore<TLRecord>
|
||||||
/**
|
/**
|
||||||
* The id under which to sync and persist the editor's data. If none is given tldraw will not sync or persist
|
* The id under which to sync and persist the editor's data. If none is given tldraw will not sync or persist
|
||||||
* the editor's data.
|
* the editor's data.
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { HistoryEntry, Store, StoreSchema, StoreSnapshot } from '@tldraw/store'
|
import { HistoryEntry, SerializedStore, Store, StoreSchema } from '@tldraw/store'
|
||||||
import { TLRecord, TLStore, TLStoreProps, createTLSchema } from '@tldraw/tlschema'
|
import { TLRecord, TLStore, TLStoreProps, createTLSchema } from '@tldraw/tlschema'
|
||||||
import { checkShapesAndAddCore } from './defaultShapes'
|
import { checkShapesAndAddCore } from './defaultShapes'
|
||||||
import { AnyTLShapeInfo, TLShapeInfo } from './defineShape'
|
import { AnyTLShapeInfo, TLShapeInfo } from './defineShape'
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export type TLStoreOptions = {
|
export type TLStoreOptions = {
|
||||||
initialData?: StoreSnapshot<TLRecord>
|
initialData?: SerializedStore<TLRecord>
|
||||||
defaultName?: string
|
defaultName?: string
|
||||||
} & ({ shapes: readonly AnyTLShapeInfo[] } | { schema: StoreSchema<TLRecord, TLStoreProps> })
|
} & ({ shapes: readonly AnyTLShapeInfo[] } | { schema: StoreSchema<TLRecord, TLStoreProps> })
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { RecordsDiff, SerializedSchema, StoreSnapshot } from '@tldraw/store'
|
import { RecordsDiff, SerializedSchema, SerializedStore } from '@tldraw/store'
|
||||||
import { TLRecord, TLStoreSchema } from '@tldraw/tlschema'
|
import { TLRecord, TLStoreSchema } from '@tldraw/tlschema'
|
||||||
import { IDBPDatabase, openDB } from 'idb'
|
import { IDBPDatabase, openDB } from 'idb'
|
||||||
import { TLSessionStateSnapshot } from '../../config/TLSessionStateSnapshot'
|
import { TLSessionStateSnapshot } from '../../config/TLSessionStateSnapshot'
|
||||||
|
@ -156,7 +156,7 @@ export async function storeSnapshotInIndexedDb({
|
||||||
}: {
|
}: {
|
||||||
persistenceKey: string
|
persistenceKey: string
|
||||||
schema: TLStoreSchema
|
schema: TLStoreSchema
|
||||||
snapshot: StoreSnapshot<any>
|
snapshot: SerializedStore<any>
|
||||||
sessionId?: string | null
|
sessionId?: string | null
|
||||||
sessionStateSnapshot?: TLSessionStateSnapshot | null
|
sessionStateSnapshot?: TLSessionStateSnapshot | null
|
||||||
didCancel?: () => boolean
|
didCancel?: () => boolean
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
MigrationResult,
|
MigrationResult,
|
||||||
RecordId,
|
RecordId,
|
||||||
SerializedSchema,
|
SerializedSchema,
|
||||||
StoreSnapshot,
|
SerializedStore,
|
||||||
UnknownRecord,
|
UnknownRecord,
|
||||||
} from '@tldraw/store'
|
} from '@tldraw/store'
|
||||||
import { TLUiToastsContextType, TLUiTranslationKey } from '@tldraw/ui'
|
import { TLUiToastsContextType, TLUiTranslationKey } from '@tldraw/ui'
|
||||||
|
@ -119,7 +119,7 @@ export function parseTldrawJsonFile({
|
||||||
// even if the file version is up to date, it might contain old-format
|
// even if the file version is up to date, it might contain old-format
|
||||||
// records. lets create a store with the records and migrate it to the
|
// records. lets create a store with the records and migrate it to the
|
||||||
// latest version
|
// latest version
|
||||||
let migrationResult: MigrationResult<StoreSnapshot<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(storeSnapshot, data.schema)
|
||||||
|
|
|
@ -213,13 +213,16 @@ export interface SerializedSchema {
|
||||||
storeVersion: number;
|
storeVersion: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @public
|
||||||
|
export type SerializedStore<R extends UnknownRecord> = Record<IdOf<R>, R>;
|
||||||
|
|
||||||
// @public
|
// @public
|
||||||
export function squashRecordDiffs<T extends UnknownRecord>(diffs: RecordsDiff<T>[]): RecordsDiff<T>;
|
export function squashRecordDiffs<T extends UnknownRecord>(diffs: RecordsDiff<T>[]): RecordsDiff<T>;
|
||||||
|
|
||||||
// @public
|
// @public
|
||||||
export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
constructor(config: {
|
constructor(config: {
|
||||||
initialData?: StoreSnapshot<R>;
|
initialData?: SerializedStore<R>;
|
||||||
schema: StoreSchema<R, Props>;
|
schema: StoreSchema<R, Props>;
|
||||||
props: Props;
|
props: Props;
|
||||||
});
|
});
|
||||||
|
@ -241,20 +244,14 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
_flushHistory(): void;
|
_flushHistory(): void;
|
||||||
get: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
|
get: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
|
||||||
getSnapshot(scope?: 'all' | RecordScope): {
|
getSnapshot(scope?: 'all' | RecordScope): StoreSnapshot<R>;
|
||||||
store: StoreSnapshot<R>;
|
|
||||||
schema: SerializedSchema;
|
|
||||||
};
|
|
||||||
has: <K extends IdOf<R>>(id: K) => boolean;
|
has: <K extends IdOf<R>>(id: K) => boolean;
|
||||||
readonly history: Atom<number, RecordsDiff<R>>;
|
readonly history: Atom<number, RecordsDiff<R>>;
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
// @internal (undocumented)
|
// @internal (undocumented)
|
||||||
isPossiblyCorrupted(): boolean;
|
isPossiblyCorrupted(): boolean;
|
||||||
listen: (onHistory: StoreListener<R>, filters?: Partial<StoreListenerFilters>) => () => void;
|
listen: (onHistory: StoreListener<R>, filters?: Partial<StoreListenerFilters>) => () => void;
|
||||||
loadSnapshot(snapshot: {
|
loadSnapshot(snapshot: StoreSnapshot<R>): void;
|
||||||
store: StoreSnapshot<R>;
|
|
||||||
schema: SerializedSchema;
|
|
||||||
}): void;
|
|
||||||
// @internal (undocumented)
|
// @internal (undocumented)
|
||||||
markAsPossiblyCorrupted(): void;
|
markAsPossiblyCorrupted(): void;
|
||||||
mergeRemoteChanges: (fn: () => void) => void;
|
mergeRemoteChanges: (fn: () => void) => void;
|
||||||
|
@ -273,7 +270,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
readonly scopedTypes: {
|
readonly scopedTypes: {
|
||||||
readonly [K in RecordScope]: ReadonlySet<R['typeName']>;
|
readonly [K in RecordScope]: ReadonlySet<R['typeName']>;
|
||||||
};
|
};
|
||||||
serialize: (scope?: 'all' | RecordScope) => StoreSnapshot<R>;
|
serialize: (scope?: 'all' | RecordScope) => SerializedStore<R>;
|
||||||
unsafeGetWithoutCapture: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
|
unsafeGetWithoutCapture: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
|
||||||
update: <K extends IdOf<R>>(id: K, updater: (record: RecFromId<K>) => RecFromId<K>) => void;
|
update: <K extends IdOf<R>>(id: K, updater: (record: RecFromId<K>) => RecFromId<K>) => void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
@ -307,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: StoreSnapshot<R>, persistedSchema: SerializedSchema): MigrationResult<StoreSnapshot<R>>;
|
migrateStoreSnapshot(storeSnapshot: SerializedStore<R>, persistedSchema: SerializedSchema): MigrationResult<SerializedStore<R>>;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
serialize(): SerializedSchema;
|
serialize(): SerializedSchema;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
@ -333,8 +330,11 @@ export type StoreSchemaOptions<R extends UnknownRecord, P> = {
|
||||||
createIntegrityChecker?: (store: Store<R, P>) => void;
|
createIntegrityChecker?: (store: Store<R, P>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
// @public
|
// @public (undocumented)
|
||||||
export type StoreSnapshot<R extends UnknownRecord> = Record<IdOf<R>, R>;
|
export type StoreSnapshot<R extends UnknownRecord> = {
|
||||||
|
store: SerializedStore<R>;
|
||||||
|
schema: SerializedSchema;
|
||||||
|
};
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export type StoreValidator<R extends UnknownRecord> = {
|
export type StoreValidator<R extends UnknownRecord> = {
|
||||||
|
|
|
@ -7,6 +7,7 @@ export type {
|
||||||
ComputedCache,
|
ComputedCache,
|
||||||
HistoryEntry,
|
HistoryEntry,
|
||||||
RecordsDiff,
|
RecordsDiff,
|
||||||
|
SerializedStore,
|
||||||
StoreError,
|
StoreError,
|
||||||
StoreListener,
|
StoreListener,
|
||||||
StoreSnapshot,
|
StoreSnapshot,
|
||||||
|
|
|
@ -73,7 +73,13 @@ export type ComputedCache<Data, R extends UnknownRecord> = {
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export type StoreSnapshot<R extends UnknownRecord> = Record<IdOf<R>, R>
|
export type SerializedStore<R extends UnknownRecord> = Record<IdOf<R>, R>
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export type StoreSnapshot<R extends UnknownRecord> = {
|
||||||
|
store: SerializedStore<R>
|
||||||
|
schema: SerializedSchema
|
||||||
|
}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export type StoreValidator<R extends UnknownRecord> = {
|
export type StoreValidator<R extends UnknownRecord> = {
|
||||||
|
@ -163,7 +169,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
|
|
||||||
constructor(config: {
|
constructor(config: {
|
||||||
/** The store's initial data. */
|
/** The store's initial data. */
|
||||||
initialData?: StoreSnapshot<R>
|
initialData?: SerializedStore<R>
|
||||||
/**
|
/**
|
||||||
* A map of validators for each record type. A record's validator will be called when the record
|
* A map of validators for each record type. A record's validator will be called when the record
|
||||||
* is created or updated. It should throw an error if the record is invalid.
|
* is created or updated. It should throw an error if the record is invalid.
|
||||||
|
@ -503,8 +509,8 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
* @param scope - The scope of records to serialize. Defaults to 'document'.
|
* @param scope - The scope of records to serialize. Defaults to 'document'.
|
||||||
* @returns The record store snapshot as a JSON payload.
|
* @returns The record store snapshot as a JSON payload.
|
||||||
*/
|
*/
|
||||||
serialize = (scope: RecordScope | 'all' = 'document'): StoreSnapshot<R> => {
|
serialize = (scope: RecordScope | 'all' = 'document'): SerializedStore<R> => {
|
||||||
const result = {} as StoreSnapshot<R>
|
const result = {} as SerializedStore<R>
|
||||||
for (const [id, atom] of objectMapEntries(this.atoms.value)) {
|
for (const [id, atom] of objectMapEntries(this.atoms.value)) {
|
||||||
const record = atom.value
|
const record = atom.value
|
||||||
if (scope === 'all' || this.scopedTypes[scope].has(record.typeName)) {
|
if (scope === 'all' || this.scopedTypes[scope].has(record.typeName)) {
|
||||||
|
@ -525,7 +531,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
* @param scope - The scope of records to serialize. Defaults to 'document'.
|
* @param scope - The scope of records to serialize. Defaults to 'document'.
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
getSnapshot(scope: RecordScope | 'all' = 'document') {
|
getSnapshot(scope: RecordScope | 'all' = 'document'): StoreSnapshot<R> {
|
||||||
return {
|
return {
|
||||||
store: this.serialize(scope),
|
store: this.serialize(scope),
|
||||||
schema: this.schema.serialize(),
|
schema: this.schema.serialize(),
|
||||||
|
@ -544,7 +550,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
loadSnapshot(snapshot: { store: StoreSnapshot<R>; schema: SerializedSchema }): void {
|
loadSnapshot(snapshot: StoreSnapshot<R>): void {
|
||||||
const migrationResult = this.schema.migrateStoreSnapshot(snapshot.store, snapshot.schema)
|
const migrationResult = this.schema.migrateStoreSnapshot(snapshot.store, snapshot.schema)
|
||||||
|
|
||||||
if (migrationResult.type === 'error') {
|
if (migrationResult.type === 'error') {
|
||||||
|
|
|
@ -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 { Store, StoreSnapshot } from './Store'
|
import { SerializedStore, Store } from './Store'
|
||||||
import {
|
import {
|
||||||
MigrationFailureReason,
|
MigrationFailureReason,
|
||||||
MigrationResult,
|
MigrationResult,
|
||||||
|
@ -189,9 +189,9 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
||||||
}
|
}
|
||||||
|
|
||||||
migrateStoreSnapshot(
|
migrateStoreSnapshot(
|
||||||
storeSnapshot: StoreSnapshot<R>,
|
storeSnapshot: SerializedStore<R>,
|
||||||
persistedSchema: SerializedSchema
|
persistedSchema: SerializedSchema
|
||||||
): MigrationResult<StoreSnapshot<R>> {
|
): 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: storeSnapshot }
|
||||||
|
@ -205,7 +205,7 @@ export class StoreSchema<R extends UnknownRecord, P = unknown> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ourStoreVersion > persistedStoreVersion) {
|
if (ourStoreVersion > persistedStoreVersion) {
|
||||||
const result = migrate<StoreSnapshot<R>>({
|
const result = migrate<SerializedStore<R>>({
|
||||||
value: storeSnapshot,
|
value: storeSnapshot,
|
||||||
migrations,
|
migrations,
|
||||||
fromVersion: persistedStoreVersion,
|
fromVersion: persistedStoreVersion,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { MigrationFailureReason } from '../migrate'
|
import { MigrationFailureReason } from '../migrate'
|
||||||
import { StoreSnapshot } from '../Store'
|
import { SerializedStore } from '../Store'
|
||||||
import { testSchemaV0 } from './testSchema.v0'
|
import { testSchemaV0 } from './testSchema.v0'
|
||||||
import { testSchemaV1 } from './testSchema.v1'
|
import { testSchemaV1 } from './testSchema.v1'
|
||||||
|
|
||||||
|
@ -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: StoreSnapshot<any> = {
|
const snapshot: SerializedStore<any> = {
|
||||||
'user-1': {
|
'user-1': {
|
||||||
id: 'user-1',
|
id: 'user-1',
|
||||||
typeName: 'user',
|
typeName: 'user',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { assert } from '@tldraw/utils'
|
import { assert } from '@tldraw/utils'
|
||||||
import { BaseRecord, RecordId } from '../BaseRecord'
|
import { BaseRecord, RecordId } from '../BaseRecord'
|
||||||
import { createRecordType } from '../RecordType'
|
import { createRecordType } from '../RecordType'
|
||||||
import { StoreSnapshot } from '../Store'
|
import { SerializedStore } from '../Store'
|
||||||
import { StoreSchema } from '../StoreSchema'
|
import { StoreSchema } from '../StoreSchema'
|
||||||
import { defineMigrations } from '../migrate'
|
import { defineMigrations } from '../migrate'
|
||||||
|
|
||||||
|
@ -203,10 +203,10 @@ const snapshotMigrations = defineMigrations({
|
||||||
currentVersion: StoreVersions.RemoveOrg,
|
currentVersion: StoreVersions.RemoveOrg,
|
||||||
migrators: {
|
migrators: {
|
||||||
[StoreVersions.RemoveOrg]: {
|
[StoreVersions.RemoveOrg]: {
|
||||||
up: (store: StoreSnapshot<any>) => {
|
up: (store: SerializedStore<any>) => {
|
||||||
return Object.fromEntries(Object.entries(store).filter(([_, r]) => r.typeName !== 'org'))
|
return Object.fromEntries(Object.entries(store).filter(([_, r]) => r.typeName !== 'org'))
|
||||||
},
|
},
|
||||||
down: (store: StoreSnapshot<any>) => {
|
down: (store: SerializedStore<any>) => {
|
||||||
// noop
|
// noop
|
||||||
return store
|
return store
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { BaseRecord, IdOf, RecordId } from '../BaseRecord'
|
import { BaseRecord, IdOf, RecordId } from '../BaseRecord'
|
||||||
import { createRecordType } from '../RecordType'
|
import { createRecordType } from '../RecordType'
|
||||||
import { Store, StoreSnapshot } from '../Store'
|
import { SerializedStore, Store } from '../Store'
|
||||||
import { StoreSchema } from '../StoreSchema'
|
import { StoreSchema } from '../StoreSchema'
|
||||||
|
|
||||||
interface Book extends BaseRecord<'book', RecordId<Book>> {
|
interface Book extends BaseRecord<'book', RecordId<Book>> {
|
||||||
|
@ -90,7 +90,7 @@ describe('Store with validation', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Validating initial data', () => {
|
describe('Validating initial data', () => {
|
||||||
let snapshot: StoreSnapshot<Book | Author>
|
let snapshot: SerializedStore<Book | Author>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const authorId = Author.createId('tolkein')
|
const authorId = Author.createId('tolkein')
|
||||||
|
|
|
@ -9,10 +9,10 @@ import { Expand } from '@tldraw/utils';
|
||||||
import { Migrations } from '@tldraw/store';
|
import { Migrations } from '@tldraw/store';
|
||||||
import { RecordId } from '@tldraw/store';
|
import { RecordId } from '@tldraw/store';
|
||||||
import { RecordType } from '@tldraw/store';
|
import { RecordType } from '@tldraw/store';
|
||||||
|
import { SerializedStore } from '@tldraw/store';
|
||||||
import { Signal } from '@tldraw/state';
|
import { Signal } from '@tldraw/state';
|
||||||
import { Store } from '@tldraw/store';
|
import { Store } from '@tldraw/store';
|
||||||
import { StoreSchema } from '@tldraw/store';
|
import { StoreSchema } from '@tldraw/store';
|
||||||
import { StoreSnapshot } from '@tldraw/store';
|
|
||||||
import { T } from '@tldraw/validate';
|
import { T } from '@tldraw/validate';
|
||||||
import { UnknownRecord } from '@tldraw/store';
|
import { UnknownRecord } from '@tldraw/store';
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ export const CameraRecordType: RecordType<TLCamera, never>;
|
||||||
export const canvasUiColorTypeValidator: T.Validator<"accent" | "black" | "laser" | "muted-1" | "selection-fill" | "selection-stroke" | "white">;
|
export const canvasUiColorTypeValidator: T.Validator<"accent" | "black" | "laser" | "muted-1" | "selection-fill" | "selection-stroke" | "white">;
|
||||||
|
|
||||||
// @internal (undocumented)
|
// @internal (undocumented)
|
||||||
export function CLIENT_FIXUP_SCRIPT(persistedStore: StoreSnapshot<TLRecord>): StoreSnapshot<TLRecord>;
|
export function CLIENT_FIXUP_SCRIPT(persistedStore: SerializedStore<TLRecord>): SerializedStore<TLRecord>;
|
||||||
|
|
||||||
// @public
|
// @public
|
||||||
export function createAssetValidator<Type extends string, Props extends object>(type: Type, props: T.Validator<Props>): T.ObjectValidator<{
|
export function createAssetValidator<Type extends string, Props extends object>(type: Type, props: T.Validator<Props>): T.ObjectValidator<{
|
||||||
|
@ -1131,6 +1131,9 @@ export type TLScribble = {
|
||||||
delay: number;
|
delay: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @public (undocumented)
|
||||||
|
export type TLSerializedStore = SerializedStore<TLRecord>;
|
||||||
|
|
||||||
// @public
|
// @public
|
||||||
export type TLShape = TLDefaultShape | TLUnknownShape;
|
export type TLShape = TLDefaultShape | TLUnknownShape;
|
||||||
|
|
||||||
|
@ -1162,7 +1165,7 @@ export type TLStoreProps = {
|
||||||
export type TLStoreSchema = StoreSchema<TLRecord, TLStoreProps>;
|
export type TLStoreSchema = StoreSchema<TLRecord, TLStoreProps>;
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export type TLStoreSnapshot = StoreSnapshot<TLRecord>;
|
export type TLStoreSnapshot = SerializedStore<TLRecord>;
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export type TLTextShape = TLBaseShape<'text', TLTextShapeProps>;
|
export type TLTextShape = TLBaseShape<'text', TLTextShapeProps>;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Store, StoreSchema, StoreSchemaOptions, StoreSnapshot } from '@tldraw/store'
|
import { SerializedStore, Store, StoreSchema, StoreSchemaOptions } from '@tldraw/store'
|
||||||
import { annotateError, structuredClone } from '@tldraw/utils'
|
import { annotateError, structuredClone } from '@tldraw/utils'
|
||||||
import { CameraRecordType, TLCameraId } from './records/TLCamera'
|
import { CameraRecordType, TLCameraId } from './records/TLCamera'
|
||||||
import { DocumentRecordType, TLDOCUMENT_ID } from './records/TLDocument'
|
import { DocumentRecordType, TLDOCUMENT_ID } from './records/TLDocument'
|
||||||
|
@ -33,7 +33,10 @@ function redactRecordForErrorReporting(record: any) {
|
||||||
export type TLStoreSchema = StoreSchema<TLRecord, TLStoreProps>
|
export type TLStoreSchema = StoreSchema<TLRecord, TLStoreProps>
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export type TLStoreSnapshot = StoreSnapshot<TLRecord>
|
export type TLSerializedStore = SerializedStore<TLRecord>
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export type TLStoreSnapshot = SerializedStore<TLRecord>
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export type TLStoreProps = {
|
export type TLStoreProps = {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { StoreSnapshot } from '@tldraw/store'
|
import { SerializedStore } from '@tldraw/store'
|
||||||
import { Vec2dModel } from './misc/geometry-types'
|
import { Vec2dModel } from './misc/geometry-types'
|
||||||
import { TLRecord } from './records/TLRecord'
|
import { TLRecord } from './records/TLRecord'
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export function CLIENT_FIXUP_SCRIPT(persistedStore: StoreSnapshot<TLRecord>) {
|
export function CLIENT_FIXUP_SCRIPT(persistedStore: SerializedStore<TLRecord>) {
|
||||||
const records = Object.values(persistedStore)
|
const records = Object.values(persistedStore)
|
||||||
|
|
||||||
for (let i = 0; i < records.length; i++) {
|
for (let i = 0; i < records.length; i++) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export {
|
export {
|
||||||
|
type TLSerializedStore,
|
||||||
type TLStore,
|
type TLStore,
|
||||||
type TLStoreProps,
|
type TLStoreProps,
|
||||||
type TLStoreSchema,
|
type TLStoreSchema,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { defineMigrations, StoreSnapshot } from '@tldraw/store'
|
import { defineMigrations, SerializedStore } from '@tldraw/store'
|
||||||
import { TLRecord } from './records/TLRecord'
|
import { TLRecord } from './records/TLRecord'
|
||||||
|
|
||||||
const Versions = {
|
const Versions = {
|
||||||
|
@ -15,47 +15,47 @@ export const storeMigrations = defineMigrations({
|
||||||
currentVersion: Versions.RemoveUserDocument,
|
currentVersion: Versions.RemoveUserDocument,
|
||||||
migrators: {
|
migrators: {
|
||||||
[Versions.RemoveCodeAndIconShapeTypes]: {
|
[Versions.RemoveCodeAndIconShapeTypes]: {
|
||||||
up: (store: StoreSnapshot<TLRecord>) => {
|
up: (store: SerializedStore<TLRecord>) => {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(store).filter(
|
Object.entries(store).filter(
|
||||||
([_, v]) => v.typeName !== 'shape' || (v.type !== 'icon' && v.type !== 'code')
|
([_, v]) => v.typeName !== 'shape' || (v.type !== 'icon' && v.type !== 'code')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
down: (store: StoreSnapshot<TLRecord>) => {
|
down: (store: SerializedStore<TLRecord>) => {
|
||||||
// noop
|
// noop
|
||||||
return store
|
return store
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[Versions.AddInstancePresenceType]: {
|
[Versions.AddInstancePresenceType]: {
|
||||||
up: (store: StoreSnapshot<TLRecord>) => {
|
up: (store: SerializedStore<TLRecord>) => {
|
||||||
return store
|
return store
|
||||||
},
|
},
|
||||||
down: (store: StoreSnapshot<TLRecord>) => {
|
down: (store: SerializedStore<TLRecord>) => {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(store).filter(([_, v]) => v.typeName !== 'instance_presence')
|
Object.entries(store).filter(([_, v]) => v.typeName !== 'instance_presence')
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[Versions.RemoveTLUserAndPresenceAndAddPointer]: {
|
[Versions.RemoveTLUserAndPresenceAndAddPointer]: {
|
||||||
up: (store: StoreSnapshot<TLRecord>) => {
|
up: (store: SerializedStore<TLRecord>) => {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(store).filter(([_, v]) => !v.typeName.match(/^(user|user_presence)$/))
|
Object.entries(store).filter(([_, v]) => !v.typeName.match(/^(user|user_presence)$/))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
down: (store: StoreSnapshot<TLRecord>) => {
|
down: (store: SerializedStore<TLRecord>) => {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(store).filter(([_, v]) => v.typeName !== 'pointer')
|
Object.entries(store).filter(([_, v]) => v.typeName !== 'pointer')
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[Versions.RemoveUserDocument]: {
|
[Versions.RemoveUserDocument]: {
|
||||||
up: (store: StoreSnapshot<TLRecord>) => {
|
up: (store: SerializedStore<TLRecord>) => {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(store).filter(([_, v]) => !v.typeName.match('user_document'))
|
Object.entries(store).filter(([_, v]) => !v.typeName.match('user_document'))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
down: (store: StoreSnapshot<TLRecord>) => {
|
down: (store: SerializedStore<TLRecord>) => {
|
||||||
return store
|
return store
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue