@snups/rjsf-utils
Version:
Utility functions for @snups/rjsf-core
45 lines (40 loc) • 1.91 kB
text/typescript
import { GenericObjectType } from './types';
/** Given a list of `properties` and an `order` list, returns a list that contains the `properties` ordered correctly.
* If `order` is not an array, then the untouched `properties` list is returned. Otherwise `properties` is ordered per
* the `order` list. If `order` contains a '*' then any `properties` that are not mentioned explicity in `order` will be
* places in the location of the `*`.
*
* @param properties - The list of property keys to be ordered
* @param order - An array of property keys to be ordered first, with an optional '*' property
* @returns - A list with the `properties` ordered
* @throws - Error when the properties cannot be ordered correctly
*/
export default function orderProperties(properties: string[], order?: string[]): string[] {
if (!Array.isArray(order)) {
return properties;
}
const arrayToHash = (arr: string[]) =>
arr.reduce((prev: GenericObjectType, curr) => {
prev[curr] = true;
return prev;
}, {});
const errorPropList = (arr: string[]) =>
arr.length > 1 ? `properties '${arr.join("', '")}'` : `property '${arr[0]}'`;
const propertyHash = arrayToHash(properties);
const orderFiltered = order.filter((prop) => prop === '*' || propertyHash[prop]);
const orderHash = arrayToHash(orderFiltered);
const rest = properties.filter((prop: string) => !orderHash[prop]);
const restIndex = orderFiltered.indexOf('*');
if (restIndex === -1) {
if (rest.length) {
throw new Error(`uiSchema order list does not contain ${errorPropList(rest)}`);
}
return orderFiltered;
}
if (restIndex !== orderFiltered.lastIndexOf('*')) {
throw new Error('uiSchema order list contains more than one wildcard item');
}
const complete = [...orderFiltered];
complete.splice(restIndex, 1, ...rest);
return complete;
}