UNPKG

shinsu-senju

Version:
106 lines (91 loc) 2.53 kB
import { customSort } from './sort.ts'; import { doCondition, getBy } from './utils.ts'; import type { Condition, Getter, UnknownObject } from './utils.ts'; declare global { // eslint-disable-next-line vars-on-top var DEBUG: boolean | undefined; } type TreeNodeBase = { disabled?: boolean; selectable?: boolean; $original: UnknownObject; $mapper: Mapper; }; export type TreeNode = TreeNodeBase & { [key: string]: unknown; }; export type Tree = TreeNode[]; export type Mapper = { [key: string]: Getter | Condition | undefined; selectable?: Condition; disabled?: Condition; sortBy?: Getter; children?: Getter; childrenKey?: string; label?: Getter; ident?: string; }; export function treeMapper(data: UnknownObject[], options: Mapper = {}): Tree { if (data.length === 0) { return [] as Tree; } if (Object.values(options).filter(Boolean).length === 0) { return treeMapper(data, { label: 'name', value: 'id' }); } const { sortBy = options.label, ident = options.value, selectable, disabled, childrenKey = 'children', children: _children, ...rest } = options; const tmp = data.map((node: UnknownObject): TreeNode => { const childrenData = options.children ? getBy(node, options.children) : node.children; const children = childrenData && Array.isArray(childrenData) ? treeMapper(childrenData, options) : undefined; const mapped: TreeNodeBase = { ...Object.fromEntries( Object.entries(rest) .filter(([key]) => key !== options.children) .map(([key, getter]) => [ key, getter && getBy(node, getter as Getter), ]), ), ...(children ? { [childrenKey]: children } : undefined), ...(selectable ? { selectable: doCondition(node, selectable), } : undefined), ...(disabled ? { disabled: doCondition(node, disabled), } : undefined), ...(ident ? { ident } : undefined), $original: node, $mapper: options, }; if (!globalThis.DEBUG) { Object.defineProperty(mapped, '$original', { enumerable: false, }); Object.defineProperty(mapped, '$mapper', { enumerable: false, }); } return mapped; }); return sortBy === undefined ? tmp : tmp.toSorted((a: TreeNode, b: TreeNode) => customSort(getBy(a.$original, sortBy), getBy(b.$original, sortBy)), ); }