UNPKG

@arrowhealth/bridge-sdk

Version:

Bridge SDK provides web applications the ability to integrate with the Bridge Platform.

1 lines 14.3 kB
{"version":3,"file":"bridge.min.mjs","sources":["../src/types/platform.ts","../src/messages.ts","../src/index.ts"],"sourcesContent":["/**\n * Information about the platform Bridge is running on. `data` is platform specific.\n */\nexport type Platform = {\n\tkind: PlatformKind\n\tusername?: string\n\tdata?: unknown\n}\n\nexport enum PlatformKind {\n\tADVANCEDMD = 'advancedmd',\n\tATHELAS = 'athelas',\n\tATHENA = 'Athena',\n\tAZALEA = 'azalea',\n\tAZARA = 'azara',\n\tCAREECO = 'careeco',\n\tCLINICIENT = 'clinicient',\n\tCROSSTX = 'crosstx',\n\tECW = 'eCW',\n\tELATION = 'Elation',\n\tEMPOWER = 'empower',\n\tGGASTRO = 'ggastro',\n\tHELLONOTE = 'hellonote',\n\tHENO = 'heno',\n\tIKNOWMED = 'iknowmed',\n\tMATRIXCARE = 'matrixcare',\n\tMODMED = 'modmed',\n\tNETHEALTH = 'nethealth',\n\tNETSMART = 'netsmart',\n\tNEXTGEN = 'nextgen',\n\tOFFICEALLY = 'Office Ally',\n\tONCOEMR = 'oncoemr',\n\tPOINTCLICKCARE = 'pointclickcare',\n\tPRACTICEFUSION = 'practicefusion',\n\tPROMPT = 'prompt',\n\tPTEVERYWHERE = 'pteverywhere',\n\tPTPRACTICEPRO = 'ptpracticepro',\n\tRAINTREE = 'raintree',\n\tSIRRUS = 'sirrus',\n\tSTRATAEMR = 'strataemr',\n\tSTRATUS = 'stratus',\n\tSTRIDE = 'stride',\n\tTHRIVE = 'thrive',\n\tTEBRA = 'tebra',\n\tTOUCHWORKS = 'touchworks',\n\tTURBOPT = 'turbopt',\n\tWEBPT = 'webpt',\n\tOTHER = 'Other'\n}\n","export enum MessageKind {\n\tCAPTURE_USER_EVENTS = 'bridge::capture_user_events',\n\tCLOSE_APP = 'bridge::close_app',\n\tDISABLE_TILE = 'bridge::disable_tile',\n\tENABLE_TILE = 'bridge::enable_tile',\n\tGET_OPEN_ENCOUNTER = 'bridge::get_open_encounter',\n\tGET_PAGE = 'bridge::get_page',\n\tGET_PATIENT_INFO = 'bridge::get_patient',\n\tGET_PLATFORM = 'bridge::get_platform',\n\tHIDE_TILE = 'bridge::hide_tile',\n\tLOGIN = 'bridge::login',\n\tLOGOUT = 'bridge::logout',\n\tSET_OPEN_ENCOUNTER = 'bridge::set_open_encounter',\n\tPUSH_NOTIFICATION = 'bridge::push_notification',\n\tRELEASE_USER_EVENTS = 'bridge::release_user_events',\n\tSET_BADGE_COUNT = 'bridge::set_badge_count',\n\tSET_PATIENT_INFO = 'bridge::set_patient',\n\tSHOW_TILE = 'bridge::show_tile',\n\n\tDEPRECATED_GET_AUTH_USER = 'bridge::get_auth_user',\n}\n\nexport type Message = {\n\tappId?: string\n\tdata?: unknown\n\tsdkVersion: string\n}\ntype MessageInternal = Message & { event: MessageKind, eventType: typeof MAGIC_VALUE, srcWindow: Window }\n\ntype Off = () => void\nlet numSubs = 0\n\nexport function on(event: MessageKind, handle: (msg: Message, srcWindow: Window) => void): Off {\n\t// Start listening for messages on first subscription.\n\tif (numSubs++ === 0) {\n\t\twindow.addEventListener('message', messageListener, false)\n\t}\n\n\t// Listen for custom event triggered by message listener.\n\tconst eventHandler = (evt: CustomEvent<MessageInternal>) => handle(evt.detail, evt.detail.srcWindow)\n\twindow.addEventListener(event, eventHandler)\n\n\treturn () => {\n\t\twindow.removeEventListener(event, eventHandler)\n\n\t\t// Stop listening for messages when there are no more subscriptions.\n\t\tif(--numSubs === 0) {\n\t\t\twindow.removeEventListener('message', messageListener)\n\t\t}\n\t}\n}\n\nconst MAGIC_VALUE = 'BRIDGE_EVENT' // used for basic/preliminary filtering of messages\n\nfunction messageListener(event: MessageEvent<Message>) {\n\tif (typeof event.data !== 'string') return\n\tlet payload: MessageInternal\n\ttry {\n\t\tpayload = JSON.parse(event.data)\n\t} catch {\n\t\treturn\n\t}\n\tif (payload.eventType !== MAGIC_VALUE) return\n\tpayload.srcWindow = event.source as Window\n\twindow.dispatchEvent(new CustomEvent<Message>(payload.event, { detail: payload }))\n}\n\nexport function send(dest: Window, msgKind: MessageKind, message: Message) {\n\tconst messageInternal: Omit<MessageInternal, 'srcWindow'> = { event: msgKind, eventType: MAGIC_VALUE, ...message }\n\tdest.postMessage(JSON.stringify(messageInternal), '*')\n}\n","import type { Encounter, Page, Patient, Platform, PushNotification } from './types'\nimport { PlatformKind } from './types'\nexport { Encounter, Page, Patient, Platform, PlatformKind, PushNotification }\n\nimport { type Message, MessageKind, on, send } from './messages'\n\n/**\n * An unsubscribe function returned by subscription methods, such as `onPatientChanged()`.\n */\nexport type Unsubscribe = () => void\n\n/**\n * Indicates if application is running inside of popout\n */\nexport const inPopout: boolean = !!(window.opener && window.opener !== window)\n\n/**\n * Indicates if application is running inside of iframe\n */\nexport const inIframe: boolean = !inPopout && window.parent !== window\n\n/**\n * Indicates if application is running inside of Bridge\n */\nexport const inBridge: boolean = (window.name + '').includes('bridge_')\n\n/**\n * The Bridge SDK version.\n */\nexport const version = '2.9.3'\n\n/**\n * Return the current page HTML and href.\n */\nexport function getPage(deep: boolean = false): Promise<Page> {\n\treturn new Promise((resolve) => {\n\t\tif (!inBridge) resolve(null)\n\t\tconst off = on(MessageKind.GET_PAGE, ({ data }) => {\n\t\t\toff()\n\t\t\tresolve(data as Page)\n\t\t})\n\t\tsendToParent(MessageKind.GET_PAGE, { deep })\n\t})\n}\n\n/**\n * Get the current patient being displayed. This is typically used on application\n * initialization and thereafter onPatientChanged() is used to listen for additional\n * changes.\n */\nexport async function getPatient(): Promise<Patient> {\n\treturn new Promise(resolve => {\n\t\tif (!inBridge) resolve(null)\n\t\tconst off = on(MessageKind.GET_PATIENT_INFO, ({ data }) => {\n\t\t\toff()\n\t\t\tresolve(data as Patient)\n\t\t})\n\t\tsendToParent(MessageKind.GET_PATIENT_INFO)\n\t})\n}\n\nexport async function getPlatform(): Promise<Platform> {\n\treturn new Promise(resolve => {\n\t\tif (!inBridge) resolve(null)\n\t\tconst off = on(MessageKind.GET_PLATFORM, ({ data }) => {\n\t\t\toff()\n\t\t\tresolve(data as Platform)\n\t\t})\n\t\tsendToParent(MessageKind.GET_PLATFORM)\n\t})\n}\n\n/**\n * Sets the badge count on the tile. Setting the value to 0 will cause it to go away.\n */\nexport function setBadgeCount(count: number = 0): void {\n\tsendToParent(MessageKind.SET_BADGE_COUNT, count)\n}\n\n/**\n * Shows tile. Controlled by a Smart Tile based on the\n * information it receives through the available hooks such as \"onPatientChanged()\"\n */\nexport function showTile() {\n\tsendToParent(MessageKind.SHOW_TILE)\n}\n\n/**\n * Hide tile. Controlled by a Smart Tile based on the\n * information it receives through the available hooks such as \"onPatientChanged()\"\n */\nexport function hideTile() {\n\tsendToParent(MessageKind.HIDE_TILE)\n}\n\n/**\n * Enables tile allowing event handling. Controlled by a Smart Tile based on the\n * information it receives through the available hooks such as \"onPatientChanged()\"\n */\nexport function enableTile() {\n\tsendToParent(MessageKind.ENABLE_TILE)\n}\n\n/**\n * Disables tile preventing user events. Controlled by a Smart Tile based on the\n * information it receives through the available hooks such as \"onPatientChanged()\"\n */\nexport function disableTile() {\n\tsendToParent(MessageKind.DISABLE_TILE)\n}\n\n/**\n * Smart tile request to capture user events. Bridge will not open an application while\n * tile is capturing user events.\n */\nexport function captureUserEvents() {\n\tsendToParent(MessageKind.CAPTURE_USER_EVENTS)\n}\n\n/**\n * Smart tile returns the capturing user events back to Bridge. Bridge can only open\n * application when Bridge is capturing user events.\n */\nexport function releaseUserEvents() {\n\tsendToParent(MessageKind.RELEASE_USER_EVENTS)\n}\n\n/**\n * Closes app making the request. The tile can also call this and it will close the linked application.\n */\nexport function closeApp() {\n\tsendToParent(MessageKind.CLOSE_APP)\n}\n\n/**\n * Bridge will add the notification to the notifications array\n * with icon representing the application\n */\nexport function pushNotification(notification: PushNotification): void {\n\tsendToParent(MessageKind.PUSH_NOTIFICATION, notification)\n}\n\nexport function getOpenEncounter(): Promise<Encounter | null> {\n\treturn new Promise((resolve) => {\n\t\tif (!inBridge) resolve(null)\n\t\tconst off = on(MessageKind.GET_OPEN_ENCOUNTER, ({ data }) => {\n\t\t\toff()\n\t\t\tresolve(data as Encounter)\n\t\t})\n\t\tsendToParent(MessageKind.GET_OPEN_ENCOUNTER)\n\t})\n}\n\n/**\n * Subscribe to the open encounter change event.\n * When the user navigates to an open encounter page, `cb` is called with the encounter information.\n * When the user navigates away from an open encounter page, `cb` is called with `null`.\n *\n * @param cb - The callback function to be called when the open encounter changes.\n */\nexport function onOpenEncounterChanged(cb: (encounter: Encounter) => void): Unsubscribe {\n\treturn on(MessageKind.SET_OPEN_ENCOUNTER, (msg: Message) => cb(msg.data as Encounter))\n}\n\n/**\n * Subscribe to the patient change event.\n * When the user navigates to a patient page, `cb` is called with the patient information.\n * When the user navigates away from a patient page, `cb` with `null`.\n *\n * @param cb - The callback function to be called when the patient changes.\n */\nexport function onPatientChanged(cb: (patient: Patient) => void): Unsubscribe {\n\treturn on(MessageKind.SET_PATIENT_INFO, (msg: Message) => cb(msg.data as Patient))\n}\n\nfunction sendToParent(messageKind: MessageKind, data?: unknown) {\n\t// window.parent for iframe\n\tlet parentWindow = window.parent\n\t// if window.opener exists then it is a popup and needs to use the opener\n\tif (window.opener) {\n\t\tparentWindow = window.opener\n\t}\n\tif (window === parentWindow) {\n\t\tconsole.warn('Cannot post message to self. No parent window found.')\n\t\treturn\n\t}\n\tif(!window.name) {\n\t\tconsole.warn('No app id assigned. Cannot post request.')\n\t\treturn\n\t}\n\t// sends the appId from the window name with message to Bridge\n\tsend(parentWindow, messageKind, { appId: window.name, data, sdkVersion: version })\n}\n"],"names":["PlatformKind","MessageKind","numSubs","on","event","handle","window","addEventListener","messageListener","eventHandler","evt","detail","srcWindow","removeEventListener","MAGIC_VALUE","data","payload","JSON","parse","eventType","source","dispatchEvent","CustomEvent","inPopout","opener","inIframe","parent","inBridge","name","includes","version","getPage","deep","Promise","resolve","off","GET_PAGE","sendToParent","async","getPatient","GET_PATIENT_INFO","getPlatform","GET_PLATFORM","setBadgeCount","count","SET_BADGE_COUNT","showTile","SHOW_TILE","hideTile","HIDE_TILE","enableTile","ENABLE_TILE","disableTile","DISABLE_TILE","captureUserEvents","CAPTURE_USER_EVENTS","releaseUserEvents","RELEASE_USER_EVENTS","closeApp","CLOSE_APP","pushNotification","notification","PUSH_NOTIFICATION","getOpenEncounter","GET_OPEN_ENCOUNTER","onOpenEncounterChanged","cb","SET_OPEN_ENCOUNTER","msg","onPatientChanged","SET_PATIENT_INFO","messageKind","parentWindow","dest","msgKind","message","messageInternal","postMessage","stringify","send","appId","sdkVersion","console","warn"],"mappings":"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"}