rx-postmessenger
Version:
Minimal RxJS adapter for the window.postMessage API for request-response streams and notification streams across frame windows.
70 lines (69 loc) • 3.83 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Messenger = void 0;
var rxjs_1 = require("rxjs");
var operators_1 = require("rxjs/operators");
var RxPostmessengerRequest_1 = require("./RxPostmessengerRequest");
var Messenger = /** @class */ (function () {
/**
* @param {IMessageFactory} messageFactory - Factory instance for scalar message objects.
* @param {IMessageValidator} messageValidator - Validator instance for incoming messages.
* @param {IPostmessageAdapter} adapter - Adapter for interacting with the postMessage API
*/
function Messenger(messageFactory, messageValidator, adapter) {
var _this = this;
this.messageFactory = messageFactory;
this.messageValidator = messageValidator;
this.adapter = adapter;
this.inboundMessages$ = rxjs_1.fromEvent(window, 'message').pipe(operators_1.filter(function (message) { return _this.messageValidator.validate(message); }), operators_1.pluck('data'), rxjs_1.share());
this.requests$ = this.messagesOfType('request');
this.responses$ = this.messagesOfType('response');
this.notifications$ = this.messagesOfType('notification');
this.inboundMessages$.subscribe(function (_a) {
var id = _a.id;
return _this.messageFactory.invalidateID(id);
});
}
Messenger.prototype.request = function (channel, payload) {
var request = this.messageFactory.makeRequest(channel, payload);
var responseObservable = this.createResponseObservable(request.id);
this.adapter.postMessage(request);
return responseObservable;
};
Messenger.prototype.notify = function (channel, payload) {
this.adapter.postMessage(this.messageFactory.makeNotification(channel, payload));
};
Messenger.prototype.requests = function (channel) {
var _this = this;
return this.requests$.pipe(operators_1.filter(function (request) { return request.channel === channel; }), operators_1.map(function (request) { return new RxPostmessengerRequest_1.RxPostmessengerRequest(request.id, request.channel, request.payload, function (payload) { return _this.respond(request.id, channel, payload); }); }));
};
Messenger.prototype.notifications = function (channel) {
return this.notifications$.pipe(operators_1.filter(function (notification) { return notification.channel === channel; }), operators_1.pluck('payload'));
};
/**
* Sends a response through given channel to the remote window, carrying given payload.
*/
Messenger.prototype.respond = function (requestId, channel, payload) {
this.adapter.postMessage(this.messageFactory.makeResponse(requestId, channel, payload));
return this;
};
/**
* Creates an Observable that completes after a single emission of the MessageEvent
* response for request of given requestId. If no matching response is ever received,
* the Observable never completes.
*/
Messenger.prototype.createResponseObservable = function (requestId) {
return this.responses$.pipe(operators_1.filter(function (response) { return response.requestId === requestId; }), operators_1.pluck('payload'), operators_1.take(1));
};
/**
* Returns an Observable emitting all inbound messages` of given type.
* Returns an Observable emitting a subset of MessageEvent objects emitted
* by this.inboundMessages$, passing through all MessageEvent objects whose
* data.type property matches given type.
*/
Messenger.prototype.messagesOfType = function (type) {
return this.inboundMessages$.pipe(operators_1.filter(function (message) { return message.type === type; }));
};
return Messenger;
}());
exports.Messenger = Messenger;