dashboard-test-app/src/common/utils/serialization.ts

93 lines
2.7 KiB
TypeScript

import type { ComponentNode, PagesData, StateData } from '../types/component.types';
import { v4 as uuidv4 } from 'uuid';
const STATE_VERSION = 1;
const PAGE_STATE_VERSION = 1;
const safeObject = (value: unknown): Record<string, any> =>
value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, any>) : {};
const createStateData = (state: unknown): StateData => {
return {
state: safeObject(state),
version: STATE_VERSION,
};
};
const createPageStateData = (pageStateById: Record<string, unknown> = {}): Record<string, StateData> => {
const entries = Object.entries(pageStateById).map(([pageId, state]) => {
return [pageId, { state: safeObject(state), version: PAGE_STATE_VERSION } satisfies StateData] as const;
});
return Object.fromEntries(entries);
};
export const exportToJSON = (
pagesData: PagesData,
globalState: Record<string, any> = {},
pageStateById: Record<string, Record<string, any>> = {}
): string => {
const payload: PagesData = {
...pagesData,
stateData: createStateData(globalState),
pageStateData: createPageStateData(pageStateById),
};
return JSON.stringify(payload, null, 2);
};
export const importFromJSON = (json: string): PagesData | null => {
try {
const parsed = JSON.parse(json);
// Check if it's the new PagesData format
if (parsed.pages && Array.isArray(parsed.pages)) {
return parsed as PagesData;
}
// Backward compatibility: if it's just a ComponentNode, convert to PagesData
if (parsed.id && parsed.type) {
const defaultPage = {
id: uuidv4(),
name: 'Home',
route: '/',
root: parsed as ComponentNode,
isDefault: true,
};
return {
pages: [defaultPage],
currentPageId: defaultPage.id,
};
}
return null;
} catch (error) {
console.error('Failed to parse JSON:', error);
return null;
}
};
export const deserializeStateData = (pagesData: PagesData | null): Record<string, any> | null => {
if (!pagesData?.stateData?.state) {
return null;
}
return pagesData.stateData.state;
};
export const deserializePageStateData = (pagesData: PagesData | null): Record<string, Record<string, any>> | null => {
const pageStateData = pagesData?.pageStateData;
if (!pageStateData || typeof pageStateData !== 'object') {
return null;
}
const byPageId: Record<string, Record<string, any>> = {};
for (const [pageId, stateData] of Object.entries(pageStateData)) {
if (!stateData || typeof stateData !== 'object') continue;
const state = (stateData as any).state;
if (state && typeof state === 'object') {
byPageId[pageId] = state as Record<string, any>;
}
}
return byPageId;
};