import { Description } from 'joi'; import _ from 'lodash'; export enum ESchemaComponentType { Text = 'text', Select = 'select', Number = 'number', NumberSlider = 'number-slider', Checkbox = 'checkbox', DatePicker = 'date-picker', Alternatives = 'alternatives', List = 'list', Currency = 'currency', CurrencySlider = 'currency-slider', Country = 'country', Radio = 'radio', RadioButton = 'radio-button', MultipleCheckbox = 'multiple-checkbox', Cellphone = 'cellphone', } export const mapJoiTypeToComponentType = (properties: Description): ESchemaComponentType | undefined => { const meta = Object.assign({}, ...(properties.metas ?? properties.meta ?? [])); const rootTypeFromMeta = _.snakeCase(meta.root_type ?? ''); const joiType = properties.type ?? 'any'; const mapping: Record = { string: ESchemaComponentType.Text, select: ESchemaComponentType.Select, number: ESchemaComponentType.Number, number_slider: ESchemaComponentType.NumberSlider, boolean: ESchemaComponentType.Checkbox, date: ESchemaComponentType.DatePicker, alternatives: ESchemaComponentType.Alternatives, array: ESchemaComponentType.List, currency: ESchemaComponentType.Currency, currency_slider: ESchemaComponentType.CurrencySlider, country: ESchemaComponentType.Country, radio: ESchemaComponentType.Radio, radio_button: ESchemaComponentType.RadioButton, multiple_checkbox: ESchemaComponentType.MultipleCheckbox, cellphone: ESchemaComponentType.Cellphone, }; let results = mapping[joiType]; // Joi v18: when() produces type 'any' with whens array instead of type 'alternatives'. // Use `?? 0` so TypeScript narrows to a number before the comparison — without it, // `whens?.length > 0` is `(number | undefined) > 0` which TS flags under strict options. if ((properties.whens?.length ?? 0) > 0) { results = ESchemaComponentType.Alternatives; } if ((properties.allow?.length ?? 0) > 0 && (properties.flags as any)?.only) { results = ESchemaComponentType.Select; } if (rootTypeFromMeta && mapping[rootTypeFromMeta]) { results = mapping[rootTypeFromMeta]; } return results; };