export interface DispatchType { // The type of the input type: string; // The minimum length of the input minlength: number | undefined; // The maximum length of the input maxlength: number | undefined; // The allowed values of the input allowed_values: { [label: string]: string } | undefined; // If bitflag, then the values of the bitflag bitflag_values: { [label: string]: bigint } | undefined; } // Returns the type to be dispatched to InputDispatcher export const getDispatchType = (fields: Record, column: CanonicalColumn): DispatchType => { const _setOnDispatchType = ( dispatchType: DispatchType, key: T, value: DispatchType[T] ) => { if (!dispatchType[key] || (Array.isArray(dispatchType[key]) && dispatchType[key].length == 0)) { dispatchType[key] = value; } return dispatchType; }; // Check for __{}_displaytype /* "channel" => return format!("<#{}>", value), "role" => return format!("<@&{}>", value), "user" => return format!("<@{}>", value), */ let dispatchType: DispatchType = { type: '', minlength: undefined, maxlength: undefined, allowed_values: undefined, bitflag_values: undefined }; if (fields[`__${column.id}_displaytype`]) { // Set the dispatch type to string:displaytype _setOnDispatchType(dispatchType, 'type', `string:${fields[`__${column.id}_displaytype`]}`); } const handleInner = ( dispatchType: DispatchType, inner: CanonicalInnerColumnType ): DispatchType => { /* #[derive(Debug, Clone, PartialEq)] #[allow(dead_code)] pub enum InnerColumnType { Uuid {}, String { min_length: Option, max_length: Option, allowed_values: Vec<&'static str>, // If empty, all values are allowed kind: InnerColumnTypeStringKind, }, Timestamp {}, TimestampTz {}, Integer {}, Float {}, BitFlag { /// The bit flag values values: indexmap::IndexMap<&'static str, i64>, }, Boolean {}, Json {}, } */ if (inner.String) { _setOnDispatchType(dispatchType, 'minlength', inner.String.min_length); _setOnDispatchType(dispatchType, 'maxlength', inner.String.max_length); if (inner.String.allowed_values) { // Set the allowed values let allowedValues: { [label: string]: string } = {}; inner.String.allowed_values.forEach((value) => { allowedValues[value] = value; }); _setOnDispatchType(dispatchType, 'allowed_values', allowedValues); } // Handle the kind if (inner.String.kind == 'Normal') { _setOnDispatchType(dispatchType, 'type', 'string'); } else if (inner.String.kind == 'User') { _setOnDispatchType(dispatchType, 'type', 'string:user'); } else if (inner.String.kind == 'Channel') { _setOnDispatchType(dispatchType, 'type', 'string:channel'); } else if (inner.String.kind == 'Role') { _setOnDispatchType(dispatchType, 'type', 'string:role'); } else if (inner.String.kind == 'Emoji') { _setOnDispatchType(dispatchType, 'type', 'string:emoji'); } else if (inner.String.kind == 'Message') { _setOnDispatchType(dispatchType, 'type', 'string:message'); } else if (inner.String.kind == 'Template') { _setOnDispatchType(dispatchType, 'type', 'string:template'); } else { _setOnDispatchType( dispatchType, 'type', inner.String.kind ? `string:${inner.String.kind?.toLowerCase()}` : 'string' ); } } else if (inner.Uuid) { _setOnDispatchType(dispatchType, 'type', 'uuid'); } else if (inner.Timestamp) { _setOnDispatchType(dispatchType, 'type', 'timestamp'); } else if (inner.TimestampTz) { _setOnDispatchType(dispatchType, 'type', 'timestamptz'); } else if (inner.Integer) { _setOnDispatchType(dispatchType, 'type', 'integer'); } else if (inner.Float) { _setOnDispatchType(dispatchType, 'type', 'float'); } else if (inner.Boolean) { _setOnDispatchType(dispatchType, 'type', 'boolean'); } else if (inner.BitFlag) { _setOnDispatchType(dispatchType, 'type', 'bitflag'); // Until the rust server code can handle bigint correctly, convert them here ourselves let values: { [label: string]: bigint } = {}; Object.keys(inner.BitFlag.values).forEach((value) => { if (!inner.BitFlag) return; // TS can't infer that inner.BitFlag is still not null here values[value] = BigInt(inner.BitFlag.values[value]); }); _setOnDispatchType(dispatchType, 'bitflag_values', values); } else if (inner.Json) { _setOnDispatchType(dispatchType, 'type', 'json'); } else { _setOnDispatchType(dispatchType, 'type', Object.keys(inner)[0].toLowerCase()); } return dispatchType; }; if (column.column_type.Scalar) { return handleInner(dispatchType, column.column_type.Scalar.column_type); } else if (column.column_type.Array) { return handleInner(dispatchType, column.column_type.Array.inner); } else { return dispatchType; } };