import { is, predicates } from "@sealcode/ts-predicates"; import { Context } from "koa"; import { Checkbox } from "../controls/checkbox.js"; import { FormDataValue } from "../form-types.js"; import { FieldParseResult, FormField } from "./field.js"; import { FormControlContext } from "../controls/form-control.js"; const truthy = ["true", "on", "yes", "1"]; const falsy = ["false", "off", "no", "0"]; export class Boolean extends FormField< Required, boolean, Checkbox > { predicate = predicates.boolean; constructor( required: Required, public error_message: string = "" ) { super(required); } public async isValueValid( _: Context, value: boolean ): Promise<{ valid: boolean; message: string }> { if (this.required && !value) { return { valid: false, message: this.error_message }; } return { valid: true, message: "" }; } async parse( _: Context, value: FormDataValue ): Promise> { if (is(value, predicates.boolean)) { return { parsable: true, parsed_value: value, error: null }; } else if ( is(value, predicates.string) && [...truthy, ...falsy].includes(value) ) { return { parsable: true, parsed_value: truthy.includes(value), error: null, }; } else if (is(value, predicates.undefined)) { return { parsable: true, parsed_value: false, error: null, }; } else if (value === null || value === "") { return { parsable: true, parsed_value: false, error: null }; } else { return { parsable: false, parsed_value: null, error: "Please enter a boolean", }; } } public getEmptyValue(): boolean { return false; } public getControl(): Checkbox { return new Checkbox(this, { label: this.label || this.name }); } async getSealiousCreateValue(fctx: FormControlContext): Promise { const { parsed } = await this.getParsedValue( fctx.ctx, fctx.data.raw_values ); return !!parsed; } async sealiousValueToForm( _: Context, value: boolean | null ): Promise { return value ? "true" : "false"; } }