@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
JavaScript
;
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;