UNPKG

magnitude-core

Version:
82 lines (81 loc) 3.69 kB
import { Image } from './image'; export async function observableDataToJson(data) { if (data instanceof Image) { return await data.toJson(); //return imageToJson(data); } if (typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean') { return { type: "primitive", content: data }; } if (data === undefined) { return undefined; // JSON.stringify will omit keys with this value or handle standalone undefined } if (data === null) { return null; } if (Array.isArray(data)) { // Filter out undefined items first, then map and process the rest. return Promise.all(data .filter(item => item !== undefined) .map(item => observableDataToJson(item))); } if (typeof data === 'object') { // Known not to be null or array here const processedObject = {}; for (const key in data) { if (Object.prototype.hasOwnProperty.call(data, key)) { const value = data[key]; const processedValue = observableDataToJson(value); // Only add the key to the new object if its processed value is not undefined if (processedValue !== undefined) { processedObject[key] = processedValue; } } } return processedObject; } // Fallback for any unexpected data types not covered by ObservableData. // Returning undefined is consistent with how unrepresentable values are handled. return undefined; } // TODO: Implement deserialization, and actually leverage serde for logging stuff export async function jsonToObservableData(data) { // Handle null and undefined primitives if (data === null || data === undefined) { return data; } // Handle arrays by recursively converting each item if (Array.isArray(data)) { return Promise.all(data.map(item => jsonToObservableData(item))); } // Handle objects, which can be StoredMedia, StoredPrimitive, or a generic object if (typeof data === 'object') { // Check for our special typed objects if ('type' in data && typeof data.type === 'string') { switch (data.type) { case 'media': // Cast the object to StoredMedia and use the static `fromBase64` method. const media = data; if (media.storage === 'base64') { return Image.fromBase64(media.base64); } throw new Error(`Unsupported media storage type: ${media.storage}`); case 'primitive': // Unwrap the primitive value from its container object. return data.content; } } // Handle generic observable data object by recursively converting each property's value const result = {}; const keys = Object.keys(data); // Process all values concurrently for better performance const values = await Promise.all(keys.map(key => jsonToObservableData(data[key]))); // Reconstruct the object from the processed keys and values keys.forEach((key, index) => { result[key] = values[index]; }); return result; } // According to the MultiMediaJson type definition, raw primitives (string, number, boolean) // are not valid at the top level and should be wrapped in a StoredPrimitive object. // Throw an error if we encounter them, as the input is malformed. throw new Error(`Invalid MultiMediaJson format: Unexpected primitive value '${data}'.`); }