import { Model, ModelDataType } from './model'; export const ensureValue = (inst, key, defaultValue: T = {} as any): T => { let value = inst[key]; if (value == null) { value = inst[key] = (typeof defaultValue == 'function') ? defaultValue() : defaultValue; } return value; } export const removeFromArray = (arr: T[], ...vals: T[]) => { let L = vals.length; while (L && arr.length) { let what = vals[--L]; let ax; while ((ax = arr.indexOf(what)) !== -1) { arr.splice(ax, 1); } } return arr; }; type ModelDataItem = T | ({ id: number } & ModelDataType); export const reconcileArray = ( existingItems: T[], newItems: ModelDataItem[], { init, deconstruct, indexKey = 'id', }: { init: (data: ModelDataItem, existing?: T) => T, indexKey?: string, deconstruct?: (item: T) => void, } ) => { const newArray: T[] = []; const existingIdMap: { [key: string]: T } = {}; for (let e of existingItems) { existingIdMap[e[indexKey]] = e; } for (let n of newItems) { const existing = existingIdMap[n[indexKey]]; delete existingIdMap[n[indexKey]]; newArray.push(init(n, existing)); } if (deconstruct) { Object.values(existingIdMap).forEach(deconstruct); } return newArray; } import type { Decorator } from "@matchlighter/common_library/decorators/20223fills" export function chainDecorators(access: Parameters[0], context: Parameters[1], decorators: T[]) { const inits = []; let current = access; for (let dec of decorators) { if (!dec) continue; current = { ...current, ...(dec(current, context as any) ?? {}), } inits.push(current.init); delete current.init; } inits.reverse(); return { ...current, init(value) { for (let init of inits) { if (!init) continue value = init.call(this, value); } return value; } }; }