From 09fc834c7520f5c275b658a1d4cbe89e64eb62ee Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 6 Apr 2026 18:03:55 +0100 Subject: [PATCH] refactor: dedupe legacy config record helpers --- .../shared/legacy-config-record-shared.ts | 25 +++++++++++++++ .../doctor/shared/legacy-web-fetch-migrate.ts | 31 +++++-------------- .../shared/legacy-web-search-migrate.ts | 31 +++++-------------- 3 files changed, 39 insertions(+), 48 deletions(-) create mode 100644 src/commands/doctor/shared/legacy-config-record-shared.ts diff --git a/src/commands/doctor/shared/legacy-config-record-shared.ts b/src/commands/doctor/shared/legacy-config-record-shared.ts new file mode 100644 index 00000000000..32b18efa7a1 --- /dev/null +++ b/src/commands/doctor/shared/legacy-config-record-shared.ts @@ -0,0 +1,25 @@ +type JsonRecord = Record; + +export type { JsonRecord }; + +export function isRecord(value: unknown): value is JsonRecord { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +export function cloneRecord(value: T | undefined): T { + return { ...value } as T; +} + +export function ensureRecord(target: JsonRecord, key: string): JsonRecord { + const current = target[key]; + if (isRecord(current)) { + return current; + } + const next: JsonRecord = {}; + target[key] = next; + return next; +} + +export function hasOwnKey(target: JsonRecord, key: string): boolean { + return Object.prototype.hasOwnProperty.call(target, key); +} diff --git a/src/commands/doctor/shared/legacy-web-fetch-migrate.ts b/src/commands/doctor/shared/legacy-web-fetch-migrate.ts index 4235627fd9e..dc389a34e89 100644 --- a/src/commands/doctor/shared/legacy-web-fetch-migrate.ts +++ b/src/commands/doctor/shared/legacy-web-fetch-migrate.ts @@ -1,27 +1,14 @@ import type { OpenClawConfig } from "../../../config/config.js"; import { mergeMissing } from "../../../config/legacy.shared.js"; - -type JsonRecord = Record; +import { + cloneRecord, + ensureRecord, + hasOwnKey, + isRecord, + type JsonRecord, +} from "./legacy-config-record-shared.js"; const DANGEROUS_RECORD_KEYS = new Set(["__proto__", "prototype", "constructor"]); -function isRecord(value: unknown): value is JsonRecord { - return typeof value === "object" && value !== null && !Array.isArray(value); -} - -function cloneRecord(value: T | undefined): T { - return { ...value } as T; -} - -function ensureRecord(target: JsonRecord, key: string): JsonRecord { - const current = target[key]; - if (isRecord(current)) { - return current; - } - const next: JsonRecord = {}; - target[key] = next; - return next; -} - function resolveLegacyFetchConfig(raw: unknown): JsonRecord | undefined { if (!isRecord(raw)) { return undefined; @@ -31,10 +18,6 @@ function resolveLegacyFetchConfig(raw: unknown): JsonRecord | undefined { return isRecord(web?.fetch) ? web.fetch : undefined; } -function hasOwnKey(target: JsonRecord, key: string): boolean { - return Object.prototype.hasOwnProperty.call(target, key); -} - function copyLegacyFirecrawlFetchConfig(fetch: JsonRecord): JsonRecord | undefined { const current = fetch.firecrawl; if (!isRecord(current)) { diff --git a/src/commands/doctor/shared/legacy-web-search-migrate.ts b/src/commands/doctor/shared/legacy-web-search-migrate.ts index a580712cfe7..5e40fb23acb 100644 --- a/src/commands/doctor/shared/legacy-web-search-migrate.ts +++ b/src/commands/doctor/shared/legacy-web-search-migrate.ts @@ -4,8 +4,13 @@ import { loadPluginManifestRegistry, resolveManifestContractOwnerPluginId, } from "../../../plugins/manifest-registry.js"; - -type JsonRecord = Record; +import { + cloneRecord, + ensureRecord, + hasOwnKey, + isRecord, + type JsonRecord, +} from "./legacy-config-record-shared.js"; const MODERN_SCOPED_WEB_SEARCH_KEYS = new Set(["openaiCodex"]); @@ -20,24 +25,6 @@ const LEGACY_WEB_SEARCH_PROVIDER_IDS = loadPluginManifestRegistry({ cache: true const LEGACY_WEB_SEARCH_PROVIDER_ID_SET = new Set(LEGACY_WEB_SEARCH_PROVIDER_IDS); const LEGACY_GLOBAL_WEB_SEARCH_PROVIDER_ID = "brave"; -function isRecord(value: unknown): value is JsonRecord { - return typeof value === "object" && value !== null && !Array.isArray(value); -} - -function cloneRecord(value: T | undefined): T { - return { ...value } as T; -} - -function ensureRecord(target: JsonRecord, key: string): JsonRecord { - const current = target[key]; - if (isRecord(current)) { - return current; - } - const next: JsonRecord = {}; - target[key] = next; - return next; -} - function resolveLegacySearchConfig(raw: unknown): JsonRecord | undefined { if (!isRecord(raw)) { return undefined; @@ -52,10 +39,6 @@ function copyLegacyProviderConfig(search: JsonRecord, providerKey: string): Json return isRecord(current) ? cloneRecord(current) : undefined; } -function hasOwnKey(target: JsonRecord, key: string): boolean { - return Object.prototype.hasOwnProperty.call(target, key); -} - function hasMappedLegacyWebSearchConfig(raw: unknown): boolean { const search = resolveLegacySearchConfig(raw); if (!search) {