93 lines
2.7 KiB
TypeScript
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;
|
|
};
|