Files
homarr/packages/old-import/src/import/collections/board-collection.ts

152 lines
5.0 KiB
TypeScript

import { createId } from "@homarr/common";
import { createDbInsertCollectionForTransaction } from "@homarr/db/collection";
import { logger } from "@homarr/log";
import type { BoardSize, OldmarrConfig } from "@homarr/old-schema";
import { boardSizes, getBoardSizeName } from "@homarr/old-schema";
import { fixSectionIssues } from "../../fix-section-issues";
import { OldHomarrImportError } from "../../import-error";
import { mapBoard } from "../../mappers/map-board";
import { mapBreakpoint } from "../../mappers/map-breakpoint";
import { mapColumnCount } from "../../mappers/map-column-count";
import { moveWidgetsAndAppsIfMerge } from "../../move-widgets-and-apps-merge";
import { prepareItems } from "../../prepare/prepare-items";
import type { prepareMultipleImports } from "../../prepare/prepare-multiple";
import { prepareSections } from "../../prepare/prepare-sections";
import type { InitialOldmarrImportSettings } from "../../settings";
export const createBoardInsertCollection = (
{ preparedApps, preparedBoards }: Omit<ReturnType<typeof prepareMultipleImports>, "preparedIntegrations">,
settings: InitialOldmarrImportSettings,
) => {
const insertCollection = createDbInsertCollectionForTransaction([
"apps",
"boards",
"layouts",
"sections",
"items",
"itemLayouts",
]);
logger.info("Preparing boards for insert collection");
const appsMap = new Map(
preparedApps.flatMap(({ ids, ...app }) => {
const id = app.existingId ?? createId();
return ids.map((oldId) => [oldId, { id, ...app }] as const);
}),
);
for (const app of appsMap.values()) {
// Skip duplicate apps
if (insertCollection.apps.some((appEntry) => appEntry.id === app.id)) {
continue;
}
// Skip apps that already exist in the database
if (app.existingId) {
continue;
}
insertCollection.apps.push(app);
}
if (settings.onlyImportApps) {
logger.info(
`Skipping boards and sections import due to onlyImportApps setting appCount=${insertCollection.apps.length}`,
);
return insertCollection;
}
logger.debug(`Added apps to board insert collection count=${insertCollection.apps.length}`);
preparedBoards.forEach((board) => {
if (!hasEnoughItemShapes(board.config)) {
throw new OldHomarrImportError(
board.config,
new Error("Your config contains items without shapes for all board sizes."),
);
}
const { wrappers, categories, wrapperIdsToMerge } = fixSectionIssues(board.config);
const { apps, widgets } = moveWidgetsAndAppsIfMerge(board.config, wrapperIdsToMerge, {
...settings,
name: board.name,
});
logger.debug(`Fixed issues with sections and item positions fileName=${board.name}`);
const mappedBoard = mapBoard(board);
logger.debug(`Mapped board fileName=${board.name} boardId=${mappedBoard.id}`);
insertCollection.boards.push(mappedBoard);
const layoutMapping = boardSizes.reduce(
(acc, size) => {
acc[size] = createId();
return acc;
},
{} as Record<BoardSize, string>,
);
insertCollection.layouts.push(
...boardSizes.map((size) => ({
id: layoutMapping[size],
boardId: mappedBoard.id,
columnCount: mapColumnCount(board.config.settings.customization.gridstack, size),
breakpoint: mapBreakpoint(size),
name: getBoardSizeName(size),
})),
);
const preparedSections = prepareSections(mappedBoard.id, { wrappers, categories });
for (const section of preparedSections.values()) {
insertCollection.sections.push(section);
}
logger.debug(`Added sections to board insert collection count=${insertCollection.sections.length}`);
const preparedItems = prepareItems(
{
apps,
widgets,
settings: board.config.settings,
},
appsMap,
preparedSections,
layoutMapping,
mappedBoard.id,
);
preparedItems.forEach(({ layouts, ...item }) => {
insertCollection.items.push(item);
insertCollection.itemLayouts.push(...layouts);
});
logger.debug(`Added items to board insert collection count=${insertCollection.items.length}`);
});
logger.info(
`Board collection prepared boardCount=${insertCollection.boards.length} sectionCount=${insertCollection.sections.length} itemCount=${insertCollection.items.length} appCount=${insertCollection.apps.length}`,
);
return insertCollection;
};
export const hasEnoughItemShapes = (config: {
apps: Pick<OldmarrConfig["apps"][number], "shape">[];
widgets: Pick<OldmarrConfig["widgets"][number], "shape">[];
}) => {
const invalidSizes: BoardSize[] = [];
for (const size of boardSizes) {
if (invalidSizes.includes(size)) continue;
if (config.apps.some((app) => app.shape[size] === undefined)) {
invalidSizes.push(size);
}
if (invalidSizes.includes(size)) continue;
if (config.widgets.some((widget) => widget.shape[size] === undefined)) {
invalidSizes.push(size);
}
}
return invalidSizes.length <= 2;
};