refactor: share warning collector projections

This commit is contained in:
Peter Steinberger
2026-03-22 23:31:16 +00:00
parent 2cfc7bca10
commit 39faf4725d
8 changed files with 123 additions and 27 deletions

View File

@@ -1,4 +1,5 @@
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import {
collectAllowlistProviderGroupPolicyWarnings,
collectAllowlistProviderRestrictSendersWarnings,
@@ -11,6 +12,10 @@ import {
createOpenGroupPolicyRestrictSendersWarningCollector,
createOpenProviderGroupPolicyWarningCollector,
createOpenProviderConfiguredRouteWarningCollector,
projectAccountConfigWarningCollector,
projectAccountWarningCollector,
projectConfigAccountIdWarningCollector,
projectConfigWarningCollector,
projectWarningCollector,
collectOpenGroupPolicyConfiguredRouteWarnings,
collectOpenProviderGroupPolicyWarnings,
@@ -42,6 +47,62 @@ describe("group policy warning builders", () => {
expect(collect({ value: "abc" })).toEqual(["ABC"]);
});
it("projects cfg-only warning collector inputs", () => {
const collect = projectConfigWarningCollector<{ cfg: OpenClawConfig; accountId: string }>(
({ cfg }) => [cfg.channels ? "configured" : "none"],
);
expect(
collect({
cfg: { channels: { slack: {} } } as OpenClawConfig,
accountId: "acct-1",
}),
).toEqual(["configured"]);
});
it("projects cfg+accountId warning collector inputs", () => {
const collect = projectConfigAccountIdWarningCollector<{
cfg: OpenClawConfig;
accountId?: string | null;
account: { accountId: string };
}>(({ accountId }) => [accountId ?? "default"]);
expect(
collect({
cfg: {} as OpenClawConfig,
accountId: "acct-1",
account: { accountId: "ignored" },
}),
).toEqual(["acct-1"]);
});
it("projects account-only warning collector inputs", () => {
const collect = projectAccountWarningCollector<
{ accountId: string },
{ account: { accountId: string } }
>((account) => [account.accountId]);
expect(collect({ account: { accountId: "acct-1" } })).toEqual(["acct-1"]);
});
it("projects account+cfg warning collector inputs", () => {
const collect = projectAccountConfigWarningCollector<
{ accountId: string },
Record<string, unknown>,
{ account: { accountId: string }; cfg: OpenClawConfig }
>(
(cfg: OpenClawConfig) => cfg.channels ?? {},
({ account, cfg }) => [String(account.accountId), Object.keys(cfg).join(",") || "none"],
);
expect(
collect({
account: { accountId: "acct-1" },
cfg: { channels: { slack: {} } } as OpenClawConfig,
}),
).toEqual(["acct-1", "slack"]);
});
it("builds conditional warning collectors", () => {
const collect = createConditionalWarningCollector<{ open: boolean; token?: string }>(
({ open }) => (open ? "open" : undefined),

View File

@@ -29,6 +29,44 @@ export function projectWarningCollector<Params, Projected>(
return (params) => collector(project(params));
}
export function projectConfigWarningCollector<Params extends { cfg: OpenClawConfig }>(
collector: WarningCollector<{ cfg: OpenClawConfig }>,
): WarningCollector<Params> {
return projectWarningCollector((params) => ({ cfg: params.cfg }), collector);
}
export function projectConfigAccountIdWarningCollector<
Params extends { cfg: OpenClawConfig; accountId?: string | null },
>(
collector: WarningCollector<{ cfg: OpenClawConfig; accountId?: string | null }>,
): WarningCollector<Params> {
return projectWarningCollector(
(params) => ({ cfg: params.cfg, accountId: params.accountId }),
collector,
);
}
export function projectAccountWarningCollector<
ResolvedAccount,
Params extends { account: ResolvedAccount },
>(collector: WarningCollector<ResolvedAccount>): WarningCollector<Params> {
return projectWarningCollector((params) => params.account, collector);
}
export function projectAccountConfigWarningCollector<
ResolvedAccount,
ProjectedCfg,
Params extends { account: ResolvedAccount; cfg: OpenClawConfig },
>(
projectCfg: (cfg: OpenClawConfig) => ProjectedCfg,
collector: WarningCollector<{ account: ResolvedAccount; cfg: ProjectedCfg }>,
): WarningCollector<Params> {
return projectWarningCollector(
(params) => ({ account: params.account, cfg: projectCfg(params.cfg) }),
collector,
);
}
export function createConditionalWarningCollector<Params>(
...collectors: Array<(params: Params) => string | string[] | null | undefined | false>
): WarningCollector<Params> {