UNPKG

@shopify/app-bridge

Version:

**Shopify is doubling our engineering staff in 2021! [Join our team and work on libraries like this one.](https://smrtr.io/5GGrc)**

166 lines (165 loc) 6.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createTransportListener = exports.fromWindow = exports.fromFrame = exports.Context = void 0; var Error_1 = require("./actions/Error"); var validator_1 = require("./actions/validator"); var types_1 = require("./client/types"); var collection_1 = require("./util/collection"); var env_1 = require("./util/env"); var unframed_1 = require("./util/unframed"); var Context; (function (Context) { Context["Modal"] = "Modal"; Context["Main"] = "Main"; })(Context = exports.Context || (exports.Context = {})); /** * Create a MessageTransport from an IFrame. * @remarks * Used on the host-side to create a postMessage MessageTransport. * @beta */ function fromFrame(frame, localOrigin, context) { var handlers = []; if (typeof frame === 'undefined' || !frame.ownerDocument || !frame.ownerDocument.defaultView) { throw Error_1.fromAction('App frame is undefined', Error_1.AppActionType.WINDOW_UNDEFINED); } var parent = frame.ownerDocument.defaultView; parent.addEventListener('message', function (event) { if (!validator_1.isAppMessage(event)) { return; } if (event.origin !== localOrigin) { var contentWindow = frame.contentWindow; if (contentWindow) { var errorMessage = "Message origin '" + event.origin + "' does not match app origin '" + localOrigin + "'."; var payload = Error_1.invalidOriginAction(errorMessage); var message = { type: 'dispatch', payload: payload, }; contentWindow.postMessage(message, event.origin); } return; } for (var _i = 0, handlers_1 = handlers; _i < handlers_1.length; _i++) { var handler = handlers_1[_i]; handler(event); } }); return { context: context, localOrigin: localOrigin, frameWindow: frame.contentWindow, hostFrame: parent, dispatch: function (message) { var contentWindow = frame.contentWindow; if (contentWindow) { contentWindow.postMessage(message, localOrigin); } }, subscribe: function (handler) { return collection_1.addAndRemoveFromCollection(handlers, handler); }, }; } exports.fromFrame = fromFrame; /** * Create a MessageTransport from a parent window. * @remarks * Used on the client-side to create a postMessage MessageTransport. * @internalremarks * In unframed mode, message should be dispatched via MobileWebView.postMessage instead of postMessage. * @beta */ function fromWindow(contentWindow, localOrigin) { var handlers = []; if (typeof window !== undefined) { window.addEventListener('message', function (event) { if ((window === contentWindow && !env_1.isUnframed) || event.source !== contentWindow || !(validator_1.isAppBridgeAction(event.data.payload) || validator_1.isAppMessage(event))) { return; } for (var _i = 0, handlers_2 = handlers; _i < handlers_2.length; _i++) { var handler = handlers_2[_i]; handler(event); } }); } return { localOrigin: localOrigin, hostFrame: contentWindow, dispatch: function (message) { var _a; if (!((_a = message.source) === null || _a === void 0 ? void 0 : _a.host)) { return; } if (env_1.isUnframed && window && window.MobileWebView) { var payloadWithContext = unframed_1.parsePayloadWithContext({ id: 'unframed://fromClient', origin: localOrigin, data: message, }); window.MobileWebView.postMessage(payloadWithContext); return; } var messageOrigin = new URL("https://" + message.source.host).origin; contentWindow.postMessage(message, messageOrigin); }, subscribe: function (handler) { return collection_1.addAndRemoveFromCollection(handlers, handler); }, }; } exports.fromWindow = fromWindow; function createTransportListener() { var listeners = []; var actionListeners = {}; function createSubscribeHandler(dispatcher) { function subscribe() { if (arguments.length < 2) { // eslint-disable-next-line prefer-rest-params return collection_1.addAndRemoveFromCollection(listeners, { callback: arguments[0] }); } // eslint-disable-next-line prefer-rest-params var _a = Array.from(arguments), type = _a[0], callback = _a[1], id = _a[2]; var actionCallback = { callback: callback, id: id }; var payload = { type: type, id: id }; if (!actionListeners[type]) { actionListeners[type] = []; } if (dispatcher) { dispatcher(types_1.MessageType.Subscribe, payload); } return collection_1.addAndRemoveFromCollection(actionListeners[type], actionCallback, function () { if (dispatcher) { dispatcher(types_1.MessageType.Unsubscribe, payload); } }); } return subscribe; } return { createSubscribeHandler: createSubscribeHandler, handleMessage: function (message) { listeners.forEach(function (listener) { return listener.callback(message); }); }, handleActionDispatch: function (_a) { var type = _a.type, payload = _a.payload; var hasCallback = false; if (actionListeners[type]) { for (var _i = 0, _b = actionListeners[type]; _i < _b.length; _i++) { var listener = _b[_i]; var id = listener.id, callback = listener.callback; var matchId = payload && payload.id === id; if (matchId || !id) { callback(payload); hasCallback = true; } } } return hasCallback; }, }; } exports.createTransportListener = createTransportListener;