Files
Portal-Chart-Builder/src/host/bitrixAdapter.ts
T

57 lines
1.7 KiB
TypeScript

import type { DiagramDocument } from '../types';
import type { HostAdapter } from './HostAdapter';
/**
* postMessage handshake with the Bitrix bridge script (see
* docs/bitrix-integration.md for the PHP side). `targetOrigin` is always a
* concrete origin, never '*' — matches the security requirement from the
* original design doc.
*/
const READY_MESSAGE = 'diagram:ready';
const INIT_MESSAGE = 'diagram:init';
const CHANGE_MESSAGE = 'diagram:change';
function getBitrixOrigin(): string {
const origin = import.meta.env.VITE_BITRIX_ORIGIN;
if (!origin) {
throw new Error(
'VITE_BITRIX_ORIGIN is not set. The bridge needs a concrete parent origin — postMessage must never target "*".',
);
}
return origin;
}
export function createBitrixAdapter(): HostAdapter {
const targetOrigin = getBitrixOrigin();
return {
onReady(callback) {
let delivered = false;
function onMessage(event: MessageEvent) {
if (event.origin !== targetOrigin || event.source !== window.parent) return;
if (delivered || event.data?.type !== INIT_MESSAGE) return;
delivered = true;
window.removeEventListener('message', onMessage);
const payload = event.data.payload as string | null | undefined;
if (!payload) {
callback(null);
return;
}
try {
callback(JSON.parse(payload) as DiagramDocument);
} catch {
callback(null);
}
}
window.addEventListener('message', onMessage);
window.parent.postMessage({ type: READY_MESSAGE }, targetOrigin);
},
onChange(doc) {
window.parent.postMessage({ type: CHANGE_MESSAGE, payload: JSON.stringify(doc) }, targetOrigin);
},
};
}