From eed595bba9ac40740095ffb9e9d2fc81e8793f3c Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 13 Apr 2026 17:28:01 +0100 Subject: [PATCH] perf(channels): isolate loaded target parsing --- src/channels/plugins/target-parsing-loaded.ts | 83 ++++++++++++++++++ src/channels/plugins/target-parsing.test.ts | 17 ++++ src/channels/plugins/target-parsing.ts | 86 ++++--------------- src/infra/outbound/targets-session.ts | 2 +- 4 files changed, 116 insertions(+), 72 deletions(-) create mode 100644 src/channels/plugins/target-parsing-loaded.ts diff --git a/src/channels/plugins/target-parsing-loaded.ts b/src/channels/plugins/target-parsing-loaded.ts new file mode 100644 index 00000000000..1a5b303f2e6 --- /dev/null +++ b/src/channels/plugins/target-parsing-loaded.ts @@ -0,0 +1,83 @@ +import { + normalizeOptionalString, + normalizeOptionalThreadValue, +} from "../../shared/string-coerce.js"; +import type { ChatType } from "../chat-type.js"; +import { getLoadedChannelPluginForRead } from "./registry-loaded-read.js"; + +export type ParsedChannelExplicitTarget = { + to: string; + threadId?: string | number; + chatType?: ChatType; +}; + +export type ComparableChannelTarget = { + rawTo: string; + to: string; + threadId?: string | number; + chatType?: ChatType; +}; + +export function parseExplicitTargetForLoadedChannel( + channel: string, + rawTarget: string, +): ParsedChannelExplicitTarget | null { + const resolvedChannel = normalizeOptionalString(channel); + if (!resolvedChannel) { + return null; + } + return ( + getLoadedChannelPluginForRead(resolvedChannel)?.messaging?.parseExplicitTarget?.({ + raw: rawTarget, + }) ?? null + ); +} + +export function resolveComparableTargetForLoadedChannel(params: { + channel: string; + rawTarget?: string | null; + fallbackThreadId?: string | number | null; +}): ComparableChannelTarget | null { + const rawTo = normalizeOptionalString(params.rawTarget); + if (!rawTo) { + return null; + } + const parsed = parseExplicitTargetForLoadedChannel(params.channel, rawTo); + const fallbackThreadId = normalizeOptionalThreadValue(params.fallbackThreadId); + return { + rawTo, + to: parsed?.to ?? rawTo, + threadId: normalizeOptionalThreadValue(parsed?.threadId ?? fallbackThreadId), + chatType: parsed?.chatType, + }; +} + +export function comparableChannelTargetsMatch(params: { + left?: ComparableChannelTarget | null; + right?: ComparableChannelTarget | null; +}): boolean { + const left = params.left; + const right = params.right; + if (!left || !right) { + return false; + } + return left.to === right.to && left.threadId === right.threadId; +} + +export function comparableChannelTargetsShareRoute(params: { + left?: ComparableChannelTarget | null; + right?: ComparableChannelTarget | null; +}): boolean { + const left = params.left; + const right = params.right; + if (!left || !right) { + return false; + } + if (left.to !== right.to) { + return false; + } + if (left.threadId == null || right.threadId == null) { + return true; + } + return left.threadId === right.threadId; +} diff --git a/src/channels/plugins/target-parsing.test.ts b/src/channels/plugins/target-parsing.test.ts index 790f7bd41a2..966932e5dc9 100644 --- a/src/channels/plugins/target-parsing.test.ts +++ b/src/channels/plugins/target-parsing.test.ts @@ -5,7 +5,9 @@ import { comparableChannelTargetsMatch, comparableChannelTargetsShareRoute, parseExplicitTargetForChannel, + parseExplicitTargetForLoadedChannel, resolveComparableTargetForChannel, + resolveComparableTargetForLoadedChannel, } from "./target-parsing.js"; function parseTelegramTargetForTest(raw: string): { @@ -115,6 +117,10 @@ describe("parseExplicitTargetForChannel", () => { to: "TEAM-ROOM", chatType: "direct", }); + expect(parseExplicitTargetForLoadedChannel("demo-target", "team-room")).toEqual({ + to: "TEAM-ROOM", + chatType: "direct", + }); }); it("builds comparable targets from plugin-owned grammar", () => { @@ -129,6 +135,17 @@ describe("parseExplicitTargetForChannel", () => { threadId: 77, chatType: "group", }); + expect( + resolveComparableTargetForLoadedChannel({ + channel: "telegram", + rawTarget: "telegram:group:-100123:topic:77", + }), + ).toEqual({ + rawTo: "telegram:group:-100123:topic:77", + to: "-100123", + threadId: 77, + chatType: "group", + }); }); it("matches comparable targets when only the plugin grammar differs", () => { diff --git a/src/channels/plugins/target-parsing.ts b/src/channels/plugins/target-parsing.ts index b02a6a5f289..9d16fbc230d 100644 --- a/src/channels/plugins/target-parsing.ts +++ b/src/channels/plugins/target-parsing.ts @@ -2,22 +2,22 @@ import { normalizeOptionalString, normalizeOptionalThreadValue, } from "../../shared/string-coerce.js"; -import type { ChatType } from "../chat-type.js"; import { normalizeChatChannelId } from "../registry.js"; -import { getChannelPlugin, getLoadedChannelPlugin, normalizeChannelId } from "./index.js"; - -export type ParsedChannelExplicitTarget = { - to: string; - threadId?: string | number; - chatType?: ChatType; -}; - -export type ComparableChannelTarget = { - rawTo: string; - to: string; - threadId?: string | number; - chatType?: ChatType; -}; +import { getChannelPlugin, normalizeChannelId } from "./index.js"; +import type { + ComparableChannelTarget, + ParsedChannelExplicitTarget, +} from "./target-parsing-loaded.js"; +export { + comparableChannelTargetsMatch, + comparableChannelTargetsShareRoute, + parseExplicitTargetForLoadedChannel, + resolveComparableTargetForLoadedChannel, +} from "./target-parsing-loaded.js"; +export type { + ComparableChannelTarget, + ParsedChannelExplicitTarget, +} from "./target-parsing-loaded.js"; function parseWithPlugin( getPlugin: (channel: string) => ReturnType, @@ -38,13 +38,6 @@ export function parseExplicitTargetForChannel( return parseWithPlugin(getChannelPlugin, channel, rawTarget); } -export function parseExplicitTargetForLoadedChannel( - channel: string, - rawTarget: string, -): ParsedChannelExplicitTarget | null { - return parseWithPlugin(getLoadedChannelPlugin, channel, rawTarget); -} - export function resolveComparableTargetForChannel(params: { channel: string; rawTarget?: string | null; @@ -63,52 +56,3 @@ export function resolveComparableTargetForChannel(params: { chatType: parsed?.chatType, }; } - -export function resolveComparableTargetForLoadedChannel(params: { - channel: string; - rawTarget?: string | null; - fallbackThreadId?: string | number | null; -}): ComparableChannelTarget | null { - const rawTo = normalizeOptionalString(params.rawTarget); - if (!rawTo) { - return null; - } - const parsed = parseExplicitTargetForLoadedChannel(params.channel, rawTo); - const fallbackThreadId = normalizeOptionalThreadValue(params.fallbackThreadId); - return { - rawTo, - to: parsed?.to ?? rawTo, - threadId: normalizeOptionalThreadValue(parsed?.threadId ?? fallbackThreadId), - chatType: parsed?.chatType, - }; -} - -export function comparableChannelTargetsMatch(params: { - left?: ComparableChannelTarget | null; - right?: ComparableChannelTarget | null; -}): boolean { - const left = params.left; - const right = params.right; - if (!left || !right) { - return false; - } - return left.to === right.to && left.threadId === right.threadId; -} - -export function comparableChannelTargetsShareRoute(params: { - left?: ComparableChannelTarget | null; - right?: ComparableChannelTarget | null; -}): boolean { - const left = params.left; - const right = params.right; - if (!left || !right) { - return false; - } - if (left.to !== right.to) { - return false; - } - if (left.threadId == null || right.threadId == null) { - return true; - } - return left.threadId === right.threadId; -} diff --git a/src/infra/outbound/targets-session.ts b/src/infra/outbound/targets-session.ts index bc04b733b66..6964ba49a08 100644 --- a/src/infra/outbound/targets-session.ts +++ b/src/infra/outbound/targets-session.ts @@ -2,7 +2,7 @@ import { comparableChannelTargetsShareRoute, parseExplicitTargetForLoadedChannel, resolveComparableTargetForLoadedChannel, -} from "../../channels/plugins/target-parsing.js"; +} from "../../channels/plugins/target-parsing-loaded.js"; import type { ChannelOutboundTargetMode } from "../../channels/plugins/types.public.js"; import type { SessionEntry } from "../../config/sessions.js"; import { deliveryContextFromSession } from "../../utils/delivery-context.shared.js";