From ff414f5870ab5e5108df78a0f53ca3c4a5c13364 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 20 Apr 2026 13:44:41 +0100 Subject: [PATCH] refactor: share channel manifest metadata mapping --- src/channels/chat-meta-shared.ts | 45 ++++---------------- src/channels/plugins/catalog.ts | 37 ++++------------ src/channels/plugins/channel-meta.ts | 63 ++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 src/channels/plugins/channel-meta.ts diff --git a/src/channels/chat-meta-shared.ts b/src/channels/chat-meta-shared.ts index 9ddefcd8723..d65d7702ccc 100644 --- a/src/channels/chat-meta-shared.ts +++ b/src/channels/chat-meta-shared.ts @@ -2,7 +2,7 @@ import type { PluginPackageChannel } from "../plugins/manifest.js"; import { normalizeOptionalString } from "../shared/string-coerce.js"; import { listBundledChannelCatalogEntries } from "./bundled-channel-catalog-read.js"; import { CHAT_CHANNEL_ORDER, type ChatChannelId } from "./ids.js"; -import { resolveChannelExposure } from "./plugins/exposure.js"; +import { buildManifestChannelMeta } from "./plugins/channel-meta.js"; import type { ChannelMeta } from "./plugins/types.core.js"; export type ChatChannelMeta = ChannelMeta; @@ -17,49 +17,20 @@ function toChatChannelMeta(params: { if (!label) { throw new Error(`Missing label for bundled chat channel "${params.id}"`); } - const exposure = resolveChannelExposure(params.channel); - return { + return buildManifestChannelMeta({ id: params.id, + channel: params.channel, label, selectionLabel: normalizeOptionalString(params.channel.selectionLabel) || label, docsPath: normalizeOptionalString(params.channel.docsPath) || `/channels/${params.id}`, docsLabel: normalizeOptionalString(params.channel.docsLabel), blurb: normalizeOptionalString(params.channel.blurb) || "", - ...(params.channel.aliases?.length ? { aliases: params.channel.aliases } : {}), - ...(params.channel.order !== undefined ? { order: params.channel.order } : {}), - ...(params.channel.selectionDocsPrefix !== undefined - ? { selectionDocsPrefix: params.channel.selectionDocsPrefix } - : {}), - ...(params.channel.selectionDocsOmitLabel !== undefined - ? { selectionDocsOmitLabel: params.channel.selectionDocsOmitLabel } - : {}), - ...(params.channel.selectionExtras?.length - ? { selectionExtras: params.channel.selectionExtras } - : {}), - ...(normalizeOptionalString(params.channel.detailLabel) - ? { detailLabel: normalizeOptionalString(params.channel.detailLabel)! } - : {}), - ...(normalizeOptionalString(params.channel.systemImage) - ? { systemImage: normalizeOptionalString(params.channel.systemImage)! } - : {}), - ...(params.channel.markdownCapable !== undefined - ? { markdownCapable: params.channel.markdownCapable } - : {}), - exposure, - ...(params.channel.quickstartAllowFrom !== undefined - ? { quickstartAllowFrom: params.channel.quickstartAllowFrom } - : {}), - ...(params.channel.forceAccountBinding !== undefined - ? { forceAccountBinding: params.channel.forceAccountBinding } - : {}), - ...(params.channel.preferSessionLookupForAnnounceTarget !== undefined - ? { - preferSessionLookupForAnnounceTarget: params.channel.preferSessionLookupForAnnounceTarget, - } - : {}), - ...(params.channel.preferOver?.length ? { preferOver: params.channel.preferOver } : {}), - }; + detailLabel: normalizeOptionalString(params.channel.detailLabel), + systemImage: normalizeOptionalString(params.channel.systemImage), + arrayFieldMode: "non-empty", + selectionDocsPrefixMode: "defined", + }); } export function buildChatChannelMetaById(): Record { diff --git a/src/channels/plugins/catalog.ts b/src/channels/plugins/catalog.ts index 2affb4a16b8..4f3db32bdb0 100644 --- a/src/channels/plugins/catalog.ts +++ b/src/channels/plugins/catalog.ts @@ -8,7 +8,7 @@ import type { PluginPackageChannel, PluginPackageInstall } from "../../plugins/m import type { PluginOrigin } from "../../plugins/plugin-origin.types.js"; import { normalizeOptionalString } from "../../shared/string-coerce.js"; import { isRecord, resolveConfigDir, resolveUserPath } from "../../utils.js"; -import { resolveChannelExposure } from "./exposure.js"; +import { buildManifestChannelMeta } from "./channel-meta.js"; import type { ChannelMeta } from "./types.public.js"; export type ChannelUiMetaEntry = { @@ -182,43 +182,20 @@ function toChannelMeta(params: { const docsPath = params.channel.docsPath?.trim() || `/channels/${params.id}`; const blurb = params.channel.blurb?.trim() || ""; const systemImage = params.channel.systemImage?.trim(); - const exposure = resolveChannelExposure(params.channel); - return { + return buildManifestChannelMeta({ id: params.id, + channel: params.channel, label, selectionLabel, - ...(detailLabel ? { detailLabel } : {}), docsPath, docsLabel: normalizeOptionalString(params.channel.docsLabel), blurb, - ...(params.channel.aliases ? { aliases: params.channel.aliases } : {}), - ...(params.channel.preferOver ? { preferOver: params.channel.preferOver } : {}), - ...(params.channel.order !== undefined ? { order: params.channel.order } : {}), - ...(params.channel.selectionDocsPrefix - ? { selectionDocsPrefix: params.channel.selectionDocsPrefix } - : {}), - ...(params.channel.selectionDocsOmitLabel !== undefined - ? { selectionDocsOmitLabel: params.channel.selectionDocsOmitLabel } - : {}), - ...(params.channel.selectionExtras ? { selectionExtras: params.channel.selectionExtras } : {}), + detailLabel, ...(systemImage ? { systemImage } : {}), - ...(params.channel.markdownCapable !== undefined - ? { markdownCapable: params.channel.markdownCapable } - : {}), - exposure, - ...(params.channel.quickstartAllowFrom !== undefined - ? { quickstartAllowFrom: params.channel.quickstartAllowFrom } - : {}), - ...(params.channel.forceAccountBinding !== undefined - ? { forceAccountBinding: params.channel.forceAccountBinding } - : {}), - ...(params.channel.preferSessionLookupForAnnounceTarget !== undefined - ? { - preferSessionLookupForAnnounceTarget: params.channel.preferSessionLookupForAnnounceTarget, - } - : {}), - }; + arrayFieldMode: "defined", + selectionDocsPrefixMode: "truthy", + }); } function resolveInstallInfo(params: { diff --git a/src/channels/plugins/channel-meta.ts b/src/channels/plugins/channel-meta.ts new file mode 100644 index 00000000000..1c515ddb2cb --- /dev/null +++ b/src/channels/plugins/channel-meta.ts @@ -0,0 +1,63 @@ +import type { PluginPackageChannel } from "../../plugins/manifest.js"; +import { resolveChannelExposure } from "./exposure.js"; +import type { ChannelMeta } from "./types.core.js"; + +type ArrayFieldMode = "defined" | "non-empty"; +type OptionalStringMode = "defined" | "truthy"; + +export function buildManifestChannelMeta(params: { + id: string; + channel: PluginPackageChannel; + label: string; + selectionLabel: string; + docsPath: string; + docsLabel?: string; + blurb: string; + detailLabel?: string; + systemImage?: string; + arrayFieldMode: ArrayFieldMode; + selectionDocsPrefixMode: OptionalStringMode; +}): ChannelMeta { + const hasArrayField = (value: readonly string[] | undefined) => + params.arrayFieldMode === "defined" ? value !== undefined : Boolean(value?.length); + const hasSelectionDocsPrefix = + params.selectionDocsPrefixMode === "defined" + ? params.channel.selectionDocsPrefix !== undefined + : Boolean(params.channel.selectionDocsPrefix); + + return { + id: params.id, + label: params.label, + selectionLabel: params.selectionLabel, + docsPath: params.docsPath, + docsLabel: params.docsLabel, + blurb: params.blurb, + ...(hasArrayField(params.channel.aliases) ? { aliases: params.channel.aliases } : {}), + ...(params.channel.order !== undefined ? { order: params.channel.order } : {}), + ...(hasSelectionDocsPrefix ? { selectionDocsPrefix: params.channel.selectionDocsPrefix } : {}), + ...(params.channel.selectionDocsOmitLabel !== undefined + ? { selectionDocsOmitLabel: params.channel.selectionDocsOmitLabel } + : {}), + ...(hasArrayField(params.channel.selectionExtras) + ? { selectionExtras: params.channel.selectionExtras } + : {}), + ...(params.detailLabel ? { detailLabel: params.detailLabel } : {}), + ...(params.systemImage ? { systemImage: params.systemImage } : {}), + ...(params.channel.markdownCapable !== undefined + ? { markdownCapable: params.channel.markdownCapable } + : {}), + exposure: resolveChannelExposure(params.channel), + ...(params.channel.quickstartAllowFrom !== undefined + ? { quickstartAllowFrom: params.channel.quickstartAllowFrom } + : {}), + ...(params.channel.forceAccountBinding !== undefined + ? { forceAccountBinding: params.channel.forceAccountBinding } + : {}), + ...(params.channel.preferSessionLookupForAnnounceTarget !== undefined + ? { + preferSessionLookupForAnnounceTarget: params.channel.preferSessionLookupForAnnounceTarget, + } + : {}), + ...(hasArrayField(params.channel.preferOver) ? { preferOver: params.channel.preferOver } : {}), + }; +}