@arrowhealth/bridge-sdk
Version:
Bridge SDK provides web applications the ability to integrate with the Bridge Platform.
1 lines • 13.7 kB
Source Map (JSON)
{"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\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\tHENO = 'heno',\n\tIKNOWMED = 'iknowmed',\n\tNETHEALTH = 'nethealth',\n\tNETSMART = 'netsmart',\n\tNEXTGEN = 'nextgen',\n\tOFFICEALLY = 'Office Ally',\n\tONCOEMR = 'oncoemr',\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\tTHRIVE = 'thrive',\n\tTEBRA = 'tebra',\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::on_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 appId?: string\n data?: unknown\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\tif (numSubs++ === 0) window.addEventListener('message', messageListener, false)\n\tconst eventHandler = (evt: CustomEvent<MessageInternal>) => handle(evt.detail, evt.detail.srcWindow)\n\twindow.addEventListener(event, eventHandler)\n\treturn () => { if(--numSubs === 0) window.removeEventListener(event, eventHandler) }\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 (e) {\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.8.0'\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 })\n}\n"],"names":["PlatformKind","MessageKind","numSubs","on","event","handle","window","addEventListener","messageListener","eventHandler","evt","detail","srcWindow","removeEventListener","MAGIC_VALUE","data","payload","JSON","parse","e","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","console","warn"],"mappings":"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"}