export const selectorKinds = ["css", "xpath", "accessibility"] as const; export type SelectorKind = typeof selectorKinds[number]; export type SelectorPolicy = { readonly css: boolean; readonly xpath: boolean; readonly accessibility: boolean; }; export type SelectorPolicyInput = { readonly enable?: readonly SelectorKind[]; readonly disable?: readonly SelectorKind[]; }; export type SelectorPolicyResult = { readonly ok: true; readonly policy: SelectorPolicy; } | { readonly ok: false; readonly problem: "unknown_selector_kind" | "conflicting_selector_kind" | "empty_selector_policy"; readonly selector_kind: string | null; }; export function resolveSelectorPolicy(input: SelectorPolicyInput): SelectorPolicyResult { const explicitEnable = input.enable !== undefined; const enabled = new Set(input.enable ?? selectorKinds); const disabled = new Set(input.disable ?? []); for (const kind of [...enabled, ...disabled]) { if (!isSelectorKind(kind)) { return { ok: false, problem: "unknown_selector_kind", selector_kind: String(kind) }; } } for (const kind of disabled) { if (explicitEnable && enabled.has(kind)) { return { ok: false, problem: "conflicting_selector_kind", selector_kind: kind }; } } for (const kind of disabled) enabled.delete(kind); const policy: SelectorPolicy = { css: enabled.has("css"), xpath: enabled.has("xpath"), accessibility: enabled.has("accessibility"), }; if (!policy.css && !policy.xpath && !policy.accessibility) { return { ok: false, problem: "empty_selector_policy", selector_kind: null }; } return { ok: true, policy }; } function isSelectorKind(value: string): value is SelectorKind { return (selectorKinds as readonly string[]).includes(value); }