refactor: add schema migration helper APIs
This commit is contained in:
+16
-25
@@ -54,7 +54,7 @@ import {
|
||||
restoreElements,
|
||||
} from "@excalidraw/excalidraw/data/restore";
|
||||
import {
|
||||
migrateElementsBySchema,
|
||||
migrateSceneElements,
|
||||
resolveSchemaVersion,
|
||||
SCHEMA_VERSIONS,
|
||||
} from "@excalidraw/excalidraw/data/schema";
|
||||
@@ -242,15 +242,12 @@ const initializeScene = async (opts: {
|
||||
scrollToContent?: boolean;
|
||||
} = {
|
||||
elements: restoreElements(
|
||||
migrateElementsBySchema(
|
||||
migrateSceneElements(
|
||||
localDataState?.elements,
|
||||
{
|
||||
schemaVersion: resolveSchemaVersion(
|
||||
localDataState?.schemaVersion,
|
||||
SCHEMA_VERSIONS.initial,
|
||||
),
|
||||
scope: "scene",
|
||||
},
|
||||
resolveSchemaVersion(
|
||||
localDataState?.schemaVersion,
|
||||
SCHEMA_VERSIONS.initial,
|
||||
),
|
||||
),
|
||||
null,
|
||||
{
|
||||
@@ -281,15 +278,12 @@ const initializeScene = async (opts: {
|
||||
scene = {
|
||||
elements: bumpElementVersions(
|
||||
restoreElements(
|
||||
migrateElementsBySchema(
|
||||
migrateSceneElements(
|
||||
imported.elements,
|
||||
{
|
||||
schemaVersion: resolveSchemaVersion(
|
||||
imported.schemaVersion,
|
||||
SCHEMA_VERSIONS.initial,
|
||||
),
|
||||
scope: "scene",
|
||||
},
|
||||
resolveSchemaVersion(
|
||||
imported.schemaVersion,
|
||||
SCHEMA_VERSIONS.initial,
|
||||
),
|
||||
),
|
||||
null,
|
||||
{
|
||||
@@ -580,15 +574,12 @@ const ExcalidrawWrapper = () => {
|
||||
if (isBrowserStorageStateNewer(STORAGE_KEYS.VERSION_DATA_STATE)) {
|
||||
const localDataState = importFromLocalStorage();
|
||||
const username = importUsernameFromLocalStorage();
|
||||
const migratedElements = migrateElementsBySchema(
|
||||
const migratedElements = migrateSceneElements(
|
||||
localDataState?.elements,
|
||||
{
|
||||
schemaVersion: resolveSchemaVersion(
|
||||
localDataState?.schemaVersion,
|
||||
SCHEMA_VERSIONS.initial,
|
||||
),
|
||||
scope: "scene",
|
||||
},
|
||||
resolveSchemaVersion(
|
||||
localDataState?.schemaVersion,
|
||||
SCHEMA_VERSIONS.initial,
|
||||
),
|
||||
);
|
||||
setLangCode(getPreferredLanguage());
|
||||
excalidrawAPI.updateScene({
|
||||
|
||||
@@ -356,7 +356,10 @@ import { exportCanvas, loadFromBlob } from "../data";
|
||||
import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library";
|
||||
import { restoreAppState, restoreElements } from "../data/restore";
|
||||
import {
|
||||
migrateElementsBySchema,
|
||||
migrateAPIElements,
|
||||
migrateClipboardElements,
|
||||
migrateLibraryElements,
|
||||
migrateSceneElements,
|
||||
resolveSchemaVersion,
|
||||
SCHEMA_VERSIONS,
|
||||
type SchemaMigrationScope,
|
||||
@@ -2819,15 +2822,12 @@ class App extends React.Component<AppProps, AppState> {
|
||||
? SCHEMA_VERSIONS.initial
|
||||
: SCHEMA_VERSIONS.latest;
|
||||
const restoredElements = restoreElements(
|
||||
migrateElementsBySchema(
|
||||
migrateSceneElements(
|
||||
initialData?.elements,
|
||||
{
|
||||
schemaVersion: resolveSchemaVersion(
|
||||
initialData?.schemaVersion,
|
||||
initialDataSchemaFallback,
|
||||
),
|
||||
scope: "scene",
|
||||
},
|
||||
resolveSchemaVersion(
|
||||
initialData?.schemaVersion,
|
||||
initialDataSchemaFallback,
|
||||
),
|
||||
),
|
||||
null,
|
||||
{
|
||||
@@ -3754,17 +3754,19 @@ class App extends React.Component<AppProps, AppState> {
|
||||
retainSeed?: boolean;
|
||||
fitToContent?: boolean;
|
||||
}) => {
|
||||
const schemaVersion = resolveSchemaVersion(
|
||||
opts.schemaVersion,
|
||||
SCHEMA_VERSIONS.latest,
|
||||
);
|
||||
const migratedElements =
|
||||
opts.migrationScope === "clipboard"
|
||||
? migrateClipboardElements(opts.elements, schemaVersion)
|
||||
: opts.migrationScope === "library"
|
||||
? migrateLibraryElements(opts.elements, schemaVersion)
|
||||
: migrateAPIElements(opts.elements, schemaVersion);
|
||||
|
||||
const elements = restoreElements(
|
||||
migrateElementsBySchema(
|
||||
opts.elements,
|
||||
{
|
||||
schemaVersion: resolveSchemaVersion(
|
||||
opts.schemaVersion,
|
||||
SCHEMA_VERSIONS.latest,
|
||||
),
|
||||
scope: opts.migrationScope,
|
||||
},
|
||||
),
|
||||
migratedElements,
|
||||
null,
|
||||
{
|
||||
deleteInvisibleElements: true,
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
restoreLibraryItems,
|
||||
} from "./restore";
|
||||
import {
|
||||
migrateElementsBySchema,
|
||||
migrateSceneElements,
|
||||
resolveSchemaVersion,
|
||||
SCHEMA_VERSIONS,
|
||||
} from "./schema";
|
||||
@@ -166,12 +166,9 @@ export const loadSceneOrLibraryFromBlob = async (
|
||||
data.schemaVersion,
|
||||
SCHEMA_VERSIONS.initial,
|
||||
);
|
||||
const migratedElements = migrateElementsBySchema(
|
||||
const migratedElements = migrateSceneElements(
|
||||
data.elements,
|
||||
{
|
||||
schemaVersion,
|
||||
scope: "scene",
|
||||
},
|
||||
schemaVersion,
|
||||
);
|
||||
return {
|
||||
type: MIME_TYPES.excalidraw,
|
||||
|
||||
@@ -81,7 +81,7 @@ import {
|
||||
getNormalizedGridStep,
|
||||
getNormalizedZoom,
|
||||
} from "../scene";
|
||||
import { migrateElementsBySchema, SCHEMA_VERSIONS } from "./schema";
|
||||
import { migrateLibraryElements, SCHEMA_VERSIONS } from "./schema";
|
||||
|
||||
import type {
|
||||
AppState,
|
||||
@@ -962,12 +962,9 @@ const restoreLibraryItem = (
|
||||
schemaVersion: number,
|
||||
) => {
|
||||
const elements = restoreElements(
|
||||
migrateElementsBySchema(
|
||||
migrateLibraryElements(
|
||||
getNonDeletedElements(libraryItem.elements),
|
||||
{
|
||||
schemaVersion,
|
||||
scope: "library",
|
||||
},
|
||||
schemaVersion,
|
||||
),
|
||||
null,
|
||||
);
|
||||
|
||||
@@ -4,7 +4,10 @@ import { API } from "../tests/helpers/api";
|
||||
import {
|
||||
ALL_SCOPES,
|
||||
type SchemaMigration,
|
||||
migrateElementsBySchema,
|
||||
migrateAPIElements,
|
||||
migrateClipboardElements,
|
||||
migrateLibraryElements,
|
||||
migrateSceneElements,
|
||||
resolveSchemaVersion,
|
||||
SCHEMA_MIGRATIONS,
|
||||
SCHEMA_VERSIONS,
|
||||
@@ -18,10 +21,7 @@ describe("schema migration", () => {
|
||||
backgroundColor: "#ffc9c9",
|
||||
});
|
||||
|
||||
const migrated = migrateElementsBySchema([frame], {
|
||||
schemaVersion: SCHEMA_VERSIONS.initial,
|
||||
scope: "scene",
|
||||
})!;
|
||||
const migrated = migrateSceneElements([frame], SCHEMA_VERSIONS.initial)!;
|
||||
|
||||
expect(migrated[0].backgroundColor).toBe(
|
||||
DEFAULT_ELEMENT_PROPS.backgroundColor,
|
||||
@@ -34,10 +34,7 @@ describe("schema migration", () => {
|
||||
backgroundColor: "#ffc9c9",
|
||||
});
|
||||
|
||||
const migrated = migrateElementsBySchema([frame], {
|
||||
schemaVersion: SCHEMA_VERSIONS.latest,
|
||||
scope: "scene",
|
||||
})!;
|
||||
const migrated = migrateSceneElements([frame], SCHEMA_VERSIONS.latest)!;
|
||||
|
||||
expect(migrated[0].backgroundColor).toBe("#ffc9c9");
|
||||
});
|
||||
@@ -48,11 +45,18 @@ describe("schema migration", () => {
|
||||
backgroundColor: "#a5d8ff",
|
||||
});
|
||||
|
||||
const migrationsByScope = {
|
||||
scene: migrateSceneElements,
|
||||
library: migrateLibraryElements,
|
||||
clipboard: migrateClipboardElements,
|
||||
api: migrateAPIElements,
|
||||
} as const;
|
||||
|
||||
for (const scope of ALL_SCOPES) {
|
||||
const migrated = migrateElementsBySchema([frame], {
|
||||
schemaVersion: SCHEMA_VERSIONS.initial,
|
||||
scope,
|
||||
})!;
|
||||
const migrated = migrationsByScope[scope](
|
||||
[frame],
|
||||
SCHEMA_VERSIONS.initial,
|
||||
)!;
|
||||
expect(migrated[0].backgroundColor).toBe(
|
||||
DEFAULT_ELEMENT_PROPS.backgroundColor,
|
||||
);
|
||||
|
||||
@@ -154,3 +154,39 @@ export const migrateElementsBySchema = (
|
||||
elements,
|
||||
);
|
||||
};
|
||||
|
||||
export const migrateSceneElements = (
|
||||
elements: readonly ExcalidrawElement[] | null | undefined,
|
||||
schemaVersion: number,
|
||||
) =>
|
||||
migrateElementsBySchema(elements, {
|
||||
schemaVersion,
|
||||
scope: "scene",
|
||||
});
|
||||
|
||||
export const migrateLibraryElements = (
|
||||
elements: readonly ExcalidrawElement[] | null | undefined,
|
||||
schemaVersion: number,
|
||||
) =>
|
||||
migrateElementsBySchema(elements, {
|
||||
schemaVersion,
|
||||
scope: "library",
|
||||
});
|
||||
|
||||
export const migrateClipboardElements = (
|
||||
elements: readonly ExcalidrawElement[] | null | undefined,
|
||||
schemaVersion: number,
|
||||
) =>
|
||||
migrateElementsBySchema(elements, {
|
||||
schemaVersion,
|
||||
scope: "clipboard",
|
||||
});
|
||||
|
||||
export const migrateAPIElements = (
|
||||
elements: readonly ExcalidrawElement[] | null | undefined,
|
||||
schemaVersion: number,
|
||||
) =>
|
||||
migrateElementsBySchema(elements, {
|
||||
schemaVersion,
|
||||
scope: "api",
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user