import { validateAnyToNumber, validateAnyToString, validateArray, validateChoice, validateFunction, validateKeyValueDictionary, validateMaybeTrimmedString, validateMissing, validateNonEmptyTrimmedString, validateOption, validateTuple, } from "@biryani/core" import { IndicatorNodeType } from "../indicators" export const validateIndicatorData = validateOption( [ validateArray(validateTuple(validateAnyToString, validateAnyToNumber)), validateFunction(Object.fromEntries), ], validateKeyValueDictionary(validateAnyToString, validateAnyToNumber), ) export function validateIndicatorDimension(data: any): [any, any] { if (data === null || data === undefined) { return [data, "Missing value"] } if (typeof data !== "object") { return [data, `Expected an object, got ${typeof data}`] } data = { ...data, } const remainingKeys = new Set(Object.keys(data)) const errors: { [key: string]: any } = {} for (const key of ["keyField", "path"]) { remainingKeys.delete(key) const [value, error] = validateNonEmptyTrimmedString(data[key]) data[key] = value if (error !== null) { errors[key] = error } } { const key = "labelField" remainingKeys.delete(key) const [value, error] = validateMaybeTrimmedString(data[key]) data[key] = value if (error !== null) { errors[key] = error } } for (const key of remainingKeys) { errors[key] = "Unexpected entry" } return [data, Object.keys(errors).length === 0 ? null : errors] } export function validateIndicatorNode(data: any): [any, any] { if (data === null || data === undefined) { return [data, "Missing value"] } if (typeof data !== "object") { return [data, `Expected an object, got ${typeof data}`] } data = { ...data, } const remainingKeys = new Set(Object.keys(data)) const errors: { [key: string]: any } = {} { const key = "description" remainingKeys.delete(key) const [value, error] = validateMaybeTrimmedString(data[key]) if (value === null) { delete data[key] } else { data[key] = value } if (error !== null) { errors[key] = error } } { const key = "name" remainingKeys.delete(key) const [value, error] = validateNonEmptyTrimmedString(data[key]) data[key] = value if (error !== null) { errors[key] = error } } { const key = "path" remainingKeys.delete(key) const [value, error] = validateNonEmptyTrimmedString(data[key]) data[key] = value if (error !== null) { errors[key] = error } } { const key = "type" remainingKeys.delete(key) const [value, error] = validateChoice([ IndicatorNodeType.Indicator, IndicatorNodeType.Group, ])(data[key]) data[key] = value if (error !== null) { errors[key] = error } } if (errors.type === undefined && data.type === IndicatorNodeType.Indicator) { { const key = "data" remainingKeys.delete(key) const [value, error] = validateOption( validateMissing, validateIndicatorData, )(data[key]) if (value === null) { delete data[key] } else { data[key] = value } if (error !== null) { errors[key] = error } } { const key = "dimensions" remainingKeys.delete(key) const [value, error] = validateArray(validateIndicatorDimension)( data[key], ) data[key] = value if (error !== null) { errors[key] = error } } } for (const key of remainingKeys) { errors[key] = "Unexpected entry" } return [data, Object.keys(errors).length === 0 ? null : errors] }