import { boolean as decode } from "./decode.ts"; import { dasherize } from "./dasherize.ts"; import { type Param, param, schema } from "./param.ts"; import { brand, type Check, type Fold, type ParamElement, type Unary, } from "./pipeline.ts"; import type { CLIRead, ReadCLI } from "./read.ts"; import type { Flag } from "./tokenize.ts"; import type { AnyRoute, Definition, Schema } from "./types.ts"; export function toggle< const N extends string, const E extends readonly Unary[], >( named: Definition, ...elements: E & Check, E> ): ElementOf, E>> { const added = elements.reduce( (value, element) => element(value as never), { ...param(named, binding(named.name), schema(bool)), decode, }, ) as Param; return brand, E>>>( (route: AnyRoute) => { let phases = [...route.phases]; let phase = phases.pop()!; phases.push({ ...phase, params: { ...phase.params, [added.name]: added, }, }); return { ...route, phases, }; }, ); } type ValueOf

= P extends Param ? T : never; type ElementOf = P extends Param ? ParamElement> : never; function binding( name: string, ):

>(param: P) => P { const stem = dasherize(name); const yes = `--${stem}`; const no = `--no-${stem}`; return (param) => ({ ...param, cli: { read: reader(name), syntax: { type: "option", label: `${yes}, ${no}`, }, }, }); } function reader(name: string): ReadCLI { const stem = dasherize(name); const yes = `--${stem}`; const no = `--no-${stem}`; return (tokens): CLIRead => { let claim = tokens.claimOne((token): token is Flag => { return token.type === "flag" && (token.text === yes || token.text === no); }); let [flag] = claim.tokens; return flag ? { claim, result: { ok: true, value: { exists: true, value: flag.text === yes }, issues: [], }, } : { claim, result: { ok: true, value: { exists: false }, issues: [], }, }; }; } const bool: Schema = { "~standard": { version: 1, vendor: "configliere", validate(value) { return typeof value === "undefined" ? { value: false } : typeof value === "boolean" ? { value } : { issues: [{ message: "expected boolean" }] }; }, }, };