import type { LoaderComponent } from "next/dynamic"; import type { DefaultErrorData } from "@trpc/server/unstable-core-do-not-import"; import type { IntegrationKind, WidgetKind } from "@homarr/definitions"; import type { stringOrTranslation } from "@homarr/translation"; import type { TablerIcon } from "@homarr/ui"; import type { WidgetImports } from "."; import type { inferOptionsFromDefinition, WidgetOptionsRecord } from "./options"; type ServerDataLoader = () => Promise<{ default: (props: WidgetProps) => Promise>; }>; const createWithDynamicImport = < TKind extends WidgetKind, TDefinition extends WidgetDefinition, TServerDataLoader extends ServerDataLoader | undefined, >( kind: TKind, definition: TDefinition, serverDataLoader: TServerDataLoader, ) => ( componentLoader: () => LoaderComponent< WidgetComponentProps & (TServerDataLoader extends ServerDataLoader ? { serverData: Awaited>["default"]>>; } : never) >, ) => ({ definition: { ...definition, kind, }, kind, serverDataLoader, componentLoader, }); const createWithServerData = (kind: TKind, definition: TDefinition) => >(serverDataLoader: TServerDataLoader) => ({ definition: { ...definition, kind, }, kind, serverDataLoader, withDynamicImport: createWithDynamicImport(kind, definition, serverDataLoader), }); export const createWidgetDefinition = ( kind: TKind, definition: TDefinition, ) => ({ withServerData: createWithServerData(kind, definition), withDynamicImport: createWithDynamicImport(kind, definition, undefined), }); export interface WidgetDefinition { icon: TablerIcon; supportedIntegrations?: IntegrationKind[]; options: WidgetOptionsRecord; errors?: Partial< Record< DefaultErrorData["code"], { icon: TablerIcon; message: stringOrTranslation; } > >; } export interface WidgetProps { options: inferOptionsFromDefinition>; integrationIds: string[]; itemId: string | undefined; // undefined when in preview mode } type inferServerDataForKind = WidgetImports[TKind] extends { serverDataLoader: ServerDataLoader; } ? Awaited>["default"]>> : undefined; export type WidgetComponentProps = WidgetProps & { serverData?: inferServerDataForKind; } & { boardId: string | undefined; // undefined when in preview mode isEditMode: boolean; width: number; height: number; }; export type WidgetOptionsRecordOf = WidgetImports[TKind]["definition"]["options"];