Files
homarr/packages/old-import/src/mappers/map-item.ts
2025-08-29 20:50:51 +02:00

116 lines
3.9 KiB
TypeScript

import SuperJSON from "superjson";
import { createId } from "@homarr/common";
import type { InferInsertModel } from "@homarr/db";
import type { itemLayouts, items } from "@homarr/db/schema";
import { logger } from "@homarr/log";
import type { BoardSize, OldmarrApp, OldmarrWidget } from "@homarr/old-schema";
import { boardSizes } from "@homarr/old-schema";
import type { WidgetComponentProps } from "../../../widgets/src/definition";
import { mapKind } from "../widgets/definitions";
import { mapOptions } from "../widgets/options";
export const mapApp = (
app: OldmarrApp,
appsMap: Map<string, { id: string }>,
sectionMap: Map<string, { id: string }>,
layoutMap: Record<BoardSize, string>,
boardId: string,
): (InferInsertModel<typeof items> & { layouts: InferInsertModel<typeof itemLayouts>[] }) | null => {
if (app.area.type === "sidebar") throw new Error("Mapping app in sidebar is not supported");
const sectionId = sectionMap.get(app.area.properties.id)?.id;
if (!sectionId) {
logger.warn(`Failed to find section for app appId='${app.id}' sectionId='${app.area.properties.id}'. Removing app`);
return null;
}
const itemId = createId();
return {
id: itemId,
boardId,
kind: "app",
options: SuperJSON.stringify({
// it's safe to assume that the app exists in the map
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
appId: appsMap.get(app.id)?.id!,
openInNewTab: app.behaviour.isOpeningNewTab,
pingEnabled: app.network.enabledStatusChecker,
showTitle: app.appearance.appNameStatus === "normal",
layout: app.appearance.positionAppName,
descriptionDisplayMode: app.behaviour.tooltipDescription !== "" ? "tooltip" : "hidden",
} satisfies WidgetComponentProps<"app">["options"]),
layouts: boardSizes.map((size) => {
const shapeForSize = app.shape[size];
if (!shapeForSize) {
throw new Error(`Failed to find a shape for appId='${app.id}' screenSize='${size}'`);
}
return {
itemId,
height: shapeForSize.size.height,
width: shapeForSize.size.width,
xOffset: shapeForSize.location.x,
yOffset: shapeForSize.location.y,
sectionId,
layoutId: layoutMap[size],
};
}),
};
};
export const mapWidget = (
widget: OldmarrWidget,
appsMap: Map<string, { id: string }>,
sectionMap: Map<string, { id: string }>,
layoutMap: Record<BoardSize, string>,
boardId: string,
): (InferInsertModel<typeof items> & { layouts: InferInsertModel<typeof itemLayouts>[] }) | null => {
if (widget.area.type === "sidebar") throw new Error("Mapping widget in sidebar is not supported");
const kind = mapKind(widget.type);
if (!kind) {
logger.warn(`Failed to map widget type='${widget.type}'. It's no longer supported`);
return null;
}
const sectionId = sectionMap.get(widget.area.properties.id)?.id;
if (!sectionId) {
logger.warn(
`Failed to find section for widget widgetId='${widget.id}' sectionId='${widget.area.properties.id}'. Removing widget`,
);
return null;
}
const itemId = createId();
return {
id: itemId,
boardId,
kind,
options: SuperJSON.stringify(
mapOptions(
widget.type,
widget.properties,
new Map([...appsMap.entries()].map(([key, value]) => [key, value.id])),
),
),
layouts: boardSizes.map((size) => {
const shapeForSize = widget.shape[size];
if (!shapeForSize) {
throw new Error(`Failed to find a shape for widgetId='${widget.id}' screenSize='${size}'`);
}
return {
itemId,
height: shapeForSize.size.height,
width: shapeForSize.size.width,
xOffset: shapeForSize.location.x,
yOffset: shapeForSize.location.y,
sectionId,
layoutId: layoutMap[size],
};
}),
};
};