import { SerializedValue } from '../components/GenericComponent'; export type State = { type: string; value: Record | null; readonly: boolean; doc: string | null; }; export function setNestedValueByPath( serializationDict: Record, path: string, serializedValue: SerializedValue ): Record { const parentPathParts = path.split('.').slice(0, -1); const attrName = path.split('.').pop(); if (!attrName) { throw new Error('Invalid path'); } let currentSerializedValue: SerializedValue; const newSerializationDict: Record = JSON.parse( JSON.stringify(serializationDict) ); let currentDict = newSerializationDict; try { for (const pathPart of parentPathParts) { currentSerializedValue = getNextLevelDictByKey(currentDict, pathPart, false); // @ts-expect-error The value will be of type SerializedValue as we are still // looping through the parent parts currentDict = currentSerializedValue['value']; } currentSerializedValue = getNextLevelDictByKey(currentDict, attrName, true); Object.assign(currentSerializedValue, serializedValue); return newSerializationDict; } catch (error) { console.error(error); return currentDict; } } function getNextLevelDictByKey( serializationDict: Record, attrName: string, allowAppend: boolean = false ): SerializedValue { const [key, index] = parseListAttrAndIndex(attrName); let currentDict: SerializedValue; try { if (index !== null) { if (!serializationDict[key] || !Array.isArray(serializationDict[key]['value'])) { throw new Error(`Expected an array at '${key}', but found something else.`); } if (index < serializationDict[key]['value'].length) { currentDict = serializationDict[key]['value'][index]; } else if (allowAppend && index === serializationDict[key]['value'].length) { // Appending to list // @ts-expect-error When the index is not null, I expect an array serializationDict[key]['value'].push({}); currentDict = serializationDict[key]['value'][index]; } else { throw new Error(`Index out of range for '${key}[${index}]'.`); } } else { if (!serializationDict[key]) { throw new Error(`Key '${key}' not found.`); } currentDict = serializationDict[key]; } } catch (error) { throw new Error(`Error occurred trying to access '${attrName}': ${error}`); } if (typeof currentDict !== 'object' || currentDict === null) { throw new Error( `Expected a dictionary at '${attrName}', but found type '${typeof currentDict}' instead.` ); } return currentDict; } function parseListAttrAndIndex(attrString: string): [string, number | null] { let index: number | null = null; let attrName = attrString; if (attrString.includes('[') && attrString.endsWith(']')) { const parts = attrString.split('['); attrName = parts[0]; const indexPart = parts[1].slice(0, -1); // Removes the closing ']' if (!isNaN(parseInt(indexPart))) { index = parseInt(indexPart); } else { console.error(`Invalid index format in key: ${attrString}`); } } return [attrName, index]; }