mirror of
https://github.com/tiqi-group/pydase.git
synced 2025-04-22 17:10:02 +02:00
108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
import { SerializedValue } from '../components/GenericComponent';
|
|
|
|
export type State = {
|
|
type: string;
|
|
value: Record<string, SerializedValue> | null;
|
|
readonly: boolean;
|
|
doc: string | null;
|
|
};
|
|
|
|
export function setNestedValueByPath(
|
|
serializationDict: Record<string, SerializedValue>,
|
|
path: string,
|
|
serializedValue: SerializedValue
|
|
): Record<string, SerializedValue> {
|
|
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<string, SerializedValue> = 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<string, SerializedValue>,
|
|
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];
|
|
}
|