UNPKG

@eang/core

Version:

eang - model driven enterprise event processing

204 lines 7.72 kB
export function createEmptyDiagramDocument() { return { version: 1, viewport: { scale: 1, translateX: 0, translateY: 0 }, occurrences: { objs: {}, cnxs: {} } }; } export function isDiagramDocument(value) { if (!isRecord(value) || value.version !== 1) { return false; } const viewport = value.viewport; const occurrences = value.occurrences; return (isRecord(viewport) && typeof viewport.scale === 'number' && typeof viewport.translateX === 'number' && typeof viewport.translateY === 'number' && isRecord(occurrences) && isRecord(occurrences.objs) && isRecord(occurrences.cnxs) && (occurrences.texts === undefined || isRecord(occurrences.texts)) && (value.order === undefined || (Array.isArray(value.order) && value.order.every((item) => typeof item === 'string')))); } export function applyDiagramPatch(document, patch) { const nextDocument = cloneDiagramDocument(document); for (const operation of patch) { mutateDiagramDocument(nextDocument, operation); } return nextDocument; } export function applyDiagramPatchOperation(document, operation) { const nextDocument = cloneDiagramDocument(document); mutateDiagramDocument(nextDocument, operation); return nextDocument; } function cloneDiagramDocument(document) { return { version: document.version, viewport: { ...document.viewport }, occurrences: { objs: { ...document.occurrences.objs }, cnxs: { ...document.occurrences.cnxs }, ...(document.occurrences.texts ? { texts: { ...document.occurrences.texts } } : {}) }, ...(document.order ? { order: [...document.order] } : {}) }; } function mutateDiagramDocument(document, operation) { switch (operation.op) { case 'set_viewport': { if (!isRecord(operation.value)) { throw new Error('set_viewport requires a viewport object value'); } document.viewport = mergeObjects(document.viewport, operation.value); return; } case 'put_obj_occurrence': { const occurrence = getOperationValue(operation); const occurrenceId = resolveOccurrenceId(operation, occurrence); document.occurrences.objs[occurrenceId] = { ...occurrence, id: occurrenceId }; ensureOccurrenceInOrder(document, occurrenceId); return; } case 'patch_obj_occurrence': { const occurrenceId = resolveOccurrenceId(operation); const existing = document.occurrences.objs[occurrenceId]; if (!existing) { throw new Error(`Cannot patch missing object occurrence '${occurrenceId}'`); } document.occurrences.objs[occurrenceId] = mergeObjects(existing, getOperationValue(operation)); return; } case 'delete_obj_occurrence': { const occurrenceId = resolveOccurrenceId(operation); delete document.occurrences.objs[occurrenceId]; removeOccurrenceFromOrder(document, occurrenceId); return; } case 'put_cnx_occurrence': { const occurrence = getOperationValue(operation); const occurrenceId = resolveOccurrenceId(operation, occurrence); document.occurrences.cnxs[occurrenceId] = { ...occurrence, id: occurrenceId }; ensureOccurrenceInOrder(document, occurrenceId); return; } case 'patch_cnx_occurrence': { const occurrenceId = resolveOccurrenceId(operation); const existing = document.occurrences.cnxs[occurrenceId]; if (!existing) { throw new Error(`Cannot patch missing connection occurrence '${occurrenceId}'`); } document.occurrences.cnxs[occurrenceId] = mergeObjects(existing, getOperationValue(operation)); return; } case 'delete_cnx_occurrence': { const occurrenceId = resolveOccurrenceId(operation); delete document.occurrences.cnxs[occurrenceId]; removeOccurrenceFromOrder(document, occurrenceId); return; } case 'put_text_occurrence': { const occurrence = getOperationValue(operation); const occurrenceId = resolveOccurrenceId(operation, occurrence); if (!document.occurrences.texts) { document.occurrences.texts = {}; } document.occurrences.texts[occurrenceId] = { ...occurrence, id: occurrenceId }; ensureOccurrenceInOrder(document, occurrenceId); return; } case 'patch_text_occurrence': { const occurrenceId = resolveOccurrenceId(operation); const existing = document.occurrences.texts?.[occurrenceId]; if (!existing) { throw new Error(`Cannot patch missing text occurrence '${occurrenceId}'`); } document.occurrences.texts = { ...(document.occurrences.texts || {}), [occurrenceId]: mergeObjects(existing, getOperationValue(operation)) }; return; } case 'delete_text_occurrence': { const occurrenceId = resolveOccurrenceId(operation); if (document.occurrences.texts) { delete document.occurrences.texts[occurrenceId]; if (Object.keys(document.occurrences.texts).length === 0) { delete document.occurrences.texts; } } removeOccurrenceFromOrder(document, occurrenceId); return; } case 'reorder': { if (!Array.isArray(operation.value) || !operation.value.every((id) => typeof id === 'string')) { throw new Error('reorder requires a string[] value'); } document.order = [...operation.value]; return; } } } function ensureOccurrenceInOrder(document, occurrenceId) { if (!document.order || document.order.includes(occurrenceId)) { return; } document.order = [...document.order, occurrenceId]; } function removeOccurrenceFromOrder(document, occurrenceId) { if (!document.order) { return; } document.order = document.order.filter((id) => id !== occurrenceId); } function resolveOccurrenceId(operation, value) { const occurrenceId = operation.occurrenceId || value?.id; if (!occurrenceId) { throw new Error(`Operation '${operation.op}' requires an occurrenceId`); } return occurrenceId; } function getOperationValue(operation) { if (operation.value === undefined) { throw new Error(`Operation '${operation.op}' requires a value`); } return operation.value; } function isRecord(value) { return value !== null && typeof value === 'object' && !Array.isArray(value); } function mergeObjects(current, patch) { if (!isRecord(current) || !isRecord(patch)) { return patch; } const merged = { ...current }; for (const [key, value] of Object.entries(patch)) { const existingValue = merged[key]; merged[key] = isRecord(existingValue) && isRecord(value) ? mergeObjects(existingValue, value) : value; } return merged; } //# sourceMappingURL=diagram.js.map