export type InputRecord = Record<string, unknown>
export function inputRecord(value: unknown): InputRecord {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
throw new Error('Input must be an object.')
}
return value as InputRecord
}
export function requiredString(input: InputRecord, key: string): string {
const value = input[key]
if (typeof value !== 'string' || value.trim().length === 0) {
throw new Error(key + ' is required.')
}
return value.trim()
}
export function optionalString(input: InputRecord, key: string): string | undefined {
const value = input[key]
if (value === undefined || value === null || value === '') return undefined
if (typeof value !== 'string') throw new Error(key + ' must be a string.')
return value
}
export function optionalBoolean(input: InputRecord, key: string): boolean | undefined {
const value = input[key]
if (value === undefined || value === null) return undefined
if (typeof value !== 'boolean') throw new Error(key + ' must be a boolean.')
return value
}
export function optionalNumber(input: InputRecord, key: string): number | undefined {
const value = input[key]
if (value === undefined || value === null || value === '') return undefined
if (typeof value !== 'number' || !Number.isFinite(value)) {
throw new Error(key + ' must be a number.')
}
return value
}
export function boundedTop(value: unknown, fallback = 10, max = 50): number {
if (value === undefined || value === null) return fallback
if (!Number.isInteger(value) || Number(value) < 1 || Number(value) > max) {
throw new Error('top must be an integer from 1 through ' + max + '.')
}
return Number(value)
}
export function stringList(value: unknown, key: string): string[] {
if (value === undefined || value === null || value === '') return []
if (typeof value === 'string') return value.split(',').map((item) => item.trim()).filter(Boolean)
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || item.trim().length === 0)) {
throw new Error(key + ' must be a string or an array of strings.')
}
return value.map((item) => item.trim())
}
export function optionalRecord(input: InputRecord, key: string): InputRecord | undefined {
const value = input[key]
if (value === undefined || value === null) return undefined
if (typeof value !== 'object' || Array.isArray(value)) {
throw new Error(key + ' must be an object.')
}
return value as InputRecord
}