Files
homarr/packages/widgets/src/releases/index.ts
T

80 lines
2.5 KiB
TypeScript

import { IconRocket } from "@tabler/icons-react";
import { z } from "zod/v4";
import { createId } from "@homarr/common";
import { releaseProviderKinds } from "@homarr/definitions";
import { createWidgetDefinition, widgetQueryInputMatches } from "../definition";
import { optionsBuilder } from "../options";
const relativeDateSchema = z
.string()
.regex(/^\d+[hdwmyHDWMY]$/)
.or(z.literal(""));
export const { definition, componentLoader } = createWidgetDefinition("releases", {
supportsAdvancedFocus: true,
icon: IconRocket,
queryKey: [["widget", "releases", "getLatest"]],
queryMatcher: ({ input }, scope) => widgetQueryInputMatches(input, { itemId: scope.itemId }),
refetchInterval: null,
createOptions() {
return optionsBuilder.from((factory) => ({
newReleaseWithin: factory.text({
defaultValue: "1w",
withDescription: true,
validate: relativeDateSchema,
}),
staleReleaseWithin: factory.text({
defaultValue: "6M",
withDescription: true,
validate: relativeDateSchema,
}),
showOnlyHighlighted: factory.switch({
withDescription: true,
defaultValue: true,
}),
showDetails: factory.switch({
defaultValue: true,
}),
showOnlyIcon: factory.switch({
defaultValue: false,
}),
topReleases: factory.number({
withDescription: true,
defaultValue: 0,
validate: z.number().min(0),
}),
repositories: factory.multiReleasesRepositories({
defaultValue: [
{
id: createId(),
provider: "github" as const,
identifier: "homarr-labs/homarr",
name: "Homarr",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/homarr.png",
versionFilter: { prefix: "v", precision: 3 },
},
],
validate: z.array(
z.object({
id: z.string().default(() => createId()),
provider: z.enum(releaseProviderKinds).optional(),
identifier: z.string().min(1),
name: z.string().optional(),
versionFilter: z
.object({
prefix: z.string().optional(),
precision: z.number(),
suffix: z.string().optional(),
})
.optional(),
iconUrl: z.string().optional(),
providerUrl: z.string().url().optional(),
}),
),
}),
}));
},
}).withDynamicImport(() => import("./component"));