@absinthe/socket
Version:
708 lines (510 loc) • 20 kB
JavaScript
import 'phoenix';
import 'core-js/modules/web.dom.iterable';
import 'core-js/modules/es6.array.for-each';
import 'core-js/modules/es6.array.find-index';
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import 'core-js/modules/es6.function.name';
import 'core-js/modules/es6.array.find';
import { hasIn, map } from '@jumpn/utils-composite';
import { remove, replace, append } from '@jumpn/utils-array';
import { requestToCompat, errorsToString, getOperationType } from '@jumpn/utils-graphql';
import _objectSpread from '@babel/runtime/helpers/objectSpread';
import 'core-js/modules/es6.function.bind';
import _newArrowCheck from '@babel/runtime/helpers/newArrowCheck';
var _this = undefined;
var handlePush = function handlePush(push, handler) {
_newArrowCheck(this, _this);
return push.receive("ok", handler.onSucceed).receive("error", handler.onError).receive("timeout", handler.onTimeout);
}.bind(undefined);
var _this$1 = undefined;
var getNotifier = function getNotifier(handlerName, payload) {
var _this2 = this;
_newArrowCheck(this, _this$1);
return function (observer) {
_newArrowCheck(this, _this2);
return observer[handlerName] && observer[handlerName](payload);
}.bind(this);
}.bind(undefined);
var getHandlerName = function getHandlerName(_ref) {
var name = _ref.name;
_newArrowCheck(this, _this$1);
return "on".concat(name);
}.bind(undefined);
var notifyAll = function notifyAll(observers, event) {
_newArrowCheck(this, _this$1);
return observers.forEach(getNotifier(getHandlerName(event), event.payload));
}.bind(undefined);
var _this$2 = undefined;
var notifyActive = function notifyActive(notifier, event) {
_newArrowCheck(this, _this$2);
notifyAll(notifier.activeObservers, event);
return notifier;
}.bind(undefined);
var eventNames = {
abort: "Abort",
cancel: "Cancel",
error: "Error",
result: "Result",
start: "Start"
};
var _this$3 = undefined;
var createStartEvent = function createStartEvent(payload) {
_newArrowCheck(this, _this$3);
return {
payload: payload,
name: eventNames.start
};
}.bind(undefined);
var createResultEvent = function createResultEvent(payload) {
_newArrowCheck(this, _this$3);
return {
payload: payload,
name: eventNames.result
};
}.bind(undefined);
var createErrorEvent = function createErrorEvent(payload) {
_newArrowCheck(this, _this$3);
return {
payload: payload,
name: eventNames.error
};
}.bind(undefined);
var createCancelEvent = function createCancelEvent() {
_newArrowCheck(this, _this$3);
return {
name: eventNames.cancel,
payload: undefined
};
}.bind(undefined);
var createAbortEvent = function createAbortEvent(payload) {
_newArrowCheck(this, _this$3);
return {
payload: payload,
name: eventNames.abort
};
}.bind(undefined);
var _this$4 = undefined;
var notifyResultEvent = function notifyResultEvent(notifier, result) {
_newArrowCheck(this, _this$4);
return notifyActive(notifier, createResultEvent(result));
}.bind(undefined);
var _this$5 = undefined;
var notifyStartEvent = function notifyStartEvent(notifier) {
_newArrowCheck(this, _this$5);
return notifyActive(notifier, createStartEvent(notifier));
}.bind(undefined);
var _this$6 = undefined;
var findIndex = function findIndex(notifiers, key, value // $FlowFixMe: flow is having some troubles to match hasIn signature (curry)
) {
_newArrowCheck(this, _this$6);
return notifiers.findIndex(hasIn([key], value));
}.bind(undefined);
var _this$7 = undefined;
var remove$1 = function remove$$1(notifier) {
var _this2 = this;
_newArrowCheck(this, _this$7);
return function (notifiers) {
_newArrowCheck(this, _this2);
return remove(findIndex(notifiers, "request", notifier.request), 1, notifiers);
}.bind(this);
}.bind(undefined);
var _this$8 = undefined;
var getObservers = function getObservers(_ref) {
var activeObservers = _ref.activeObservers,
canceledObservers = _ref.canceledObservers;
_newArrowCheck(this, _this$8);
return _toConsumableArray(activeObservers).concat(_toConsumableArray(canceledObservers));
}.bind(undefined);
var notify = function notify(notifier, event) {
_newArrowCheck(this, _this$8);
notifyAll(getObservers(notifier), event);
return notifier;
}.bind(undefined);
var _this$9 = undefined;
var updateNotifiers = function updateNotifiers(absintheSocket, updater) {
_newArrowCheck(this, _this$9);
absintheSocket.notifiers = updater(absintheSocket.notifiers);
return absintheSocket;
}.bind(undefined);
var _this$a = undefined;
var abortNotifier = function abortNotifier(absintheSocket, notifier, error) {
_newArrowCheck(this, _this$a);
return updateNotifiers(absintheSocket, remove$1(notify(notifier, createAbortEvent(error))));
}.bind(undefined);
var _this$b = undefined;
var find = function find(notifiers, key, value // $FlowFixMe: flow is having some troubles to match hasIn signature (curry)
) {
_newArrowCheck(this, _this$b);
return notifiers.find(hasIn([key], value));
}.bind(undefined);
var _this$c = undefined;
var getPushHandlerMethodGetter = function getPushHandlerMethodGetter(absintheSocket, request) {
var _this2 = this;
_newArrowCheck(this, _this$c);
return function (handle) {
var _this3 = this;
_newArrowCheck(this, _this2);
return function () {
_newArrowCheck(this, _this3);
var notifier = find(absintheSocket.notifiers, "request", request);
if (notifier) {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
handle.apply(void 0, [absintheSocket, notifier].concat(args));
}
}.bind(this);
}.bind(this);
}.bind(undefined);
var getPushHandler = function getPushHandler(absintheSocket, request, notifierPushHandler) {
_newArrowCheck(this, _this$c);
return map(getPushHandlerMethodGetter(absintheSocket, request), notifierPushHandler);
}.bind(undefined);
var pushAbsintheEvent = function pushAbsintheEvent(absintheSocket, request, notifierPushHandler, absintheEvent) {
_newArrowCheck(this, _this$c);
handlePush(absintheSocket.channel.push(absintheEvent.name, absintheEvent.payload), getPushHandler(absintheSocket, request, notifierPushHandler));
return absintheSocket;
}.bind(undefined);
var _this$d = undefined;
var refresh = function refresh(notifier) {
var _this2 = this;
_newArrowCheck(this, _this$d);
return function (notifiers) {
_newArrowCheck(this, _this2);
return replace(findIndex(notifiers, "request", notifier.request), [notifier], notifiers);
}.bind(this);
}.bind(undefined);
var _this$e = undefined;
var refreshNotifier = function refreshNotifier(absintheSocket, notifier) {
_newArrowCheck(this, _this$e);
updateNotifiers(absintheSocket, refresh(notifier));
return notifier;
}.bind(undefined);
var requestStatuses = {
canceled: "canceled",
canceling: "canceling",
pending: "pending",
sent: "sent",
sending: "sending"
};
var absintheEventNames = {
doc: "doc",
unsubscribe: "unsubscribe"
};
var _this$f = undefined;
var createAbsintheUnsubscribeEvent = function createAbsintheUnsubscribeEvent(payload) {
_newArrowCheck(this, _this$f);
return {
payload: payload,
name: absintheEventNames.unsubscribe
};
}.bind(undefined);
var createAbsintheDocEvent = function createAbsintheDocEvent(payload) {
_newArrowCheck(this, _this$f);
return {
payload: payload,
name: absintheEventNames.doc
};
}.bind(undefined);
var _this$g = undefined;
var pushAbsintheDocEvent = function pushAbsintheDocEvent(absintheSocket, _ref, notifierPushHandler) {
var request = _ref.request;
_newArrowCheck(this, _this$g);
return pushAbsintheEvent(absintheSocket, request, notifierPushHandler, createAbsintheDocEvent(requestToCompat(request)));
}.bind(undefined);
var setNotifierRequestStatusSending = function setNotifierRequestStatusSending(absintheSocket, notifier) {
_newArrowCheck(this, _this$g);
return refreshNotifier(absintheSocket, _objectSpread({}, notifier, {
requestStatus: requestStatuses.sending
}));
}.bind(undefined);
var createRequestError = function createRequestError(message) {
_newArrowCheck(this, _this$g);
return new Error("request: ".concat(message));
}.bind(undefined);
var onTimeout = function onTimeout(absintheSocket, notifier) {
_newArrowCheck(this, _this$g);
return notifyActive(notifier, createErrorEvent(createRequestError("timeout")));
}.bind(undefined);
var onError = function onError(absintheSocket, notifier, errorMessage) {
_newArrowCheck(this, _this$g);
return abortNotifier(absintheSocket, notifier, createRequestError(errorMessage));
}.bind(undefined);
var getNotifierPushHandler = function getNotifierPushHandler(onSucceed) {
_newArrowCheck(this, _this$g);
return {
onError: onError,
onSucceed: onSucceed,
onTimeout: onTimeout
};
}.bind(undefined);
var pushRequestUsing = function pushRequestUsing(absintheSocket, notifier, onSucceed) {
_newArrowCheck(this, _this$g);
return pushAbsintheDocEvent(absintheSocket, setNotifierRequestStatusSending(absintheSocket, notifier), getNotifierPushHandler(onSucceed));
}.bind(undefined);
var _this$h = undefined;
var notifyCanceled = function notifyCanceled(notifier, event) {
_newArrowCheck(this, _this$h);
notifyAll(notifier.canceledObservers, event);
return notifier;
}.bind(undefined);
var _this$i = undefined;
var clearCanceled = function clearCanceled(notifier) {
_newArrowCheck(this, _this$i);
return _objectSpread({}, notifier, {
canceledObservers: []
});
}.bind(undefined);
var flushCanceled = function flushCanceled(notifier) {
_newArrowCheck(this, _this$i);
return notifier.canceledObservers.length > 0 ? clearCanceled(notifyCanceled(notifier, createCancelEvent())) : notifier;
}.bind(undefined);
var _this$j = undefined;
var reset = function reset(notifier) {
_newArrowCheck(this, _this$j);
return flushCanceled(_objectSpread({}, notifier, {
isActive: true,
requestStatus: requestStatuses.pending,
subscriptionId: undefined
}));
}.bind(undefined);
var _this$k = undefined;
var onUnsubscribeSucceedCanceled = function onUnsubscribeSucceedCanceled(absintheSocket, notifier) {
_newArrowCheck(this, _this$k);
return updateNotifiers(absintheSocket, remove$1(flushCanceled(notifier)));
}.bind(undefined);
var onUnsubscribeSucceedActive = function onUnsubscribeSucceedActive(absintheSocket, notifier) {
_newArrowCheck(this, _this$k);
return subscribe(absintheSocket, refreshNotifier(absintheSocket, reset(notifier)));
}.bind(undefined);
var createUnsubscribeError = function createUnsubscribeError(message) {
_newArrowCheck(this, _this$k);
return new Error("unsubscribe: ".concat(message));
}.bind(undefined);
var unsubscribeHandler = {
onError: function onError$$1(absintheSocket, notifier, errorMessage) {
_newArrowCheck(this, _this$k);
return abortNotifier(absintheSocket, notifier, createUnsubscribeError(errorMessage));
}.bind(undefined),
onTimeout: function onTimeout(absintheSocket, notifier) {
_newArrowCheck(this, _this$k);
return notifyCanceled(notifier, createErrorEvent(createUnsubscribeError("timeout")));
}.bind(undefined),
onSucceed: function onSucceed(absintheSocket, notifier) {
_newArrowCheck(this, _this$k);
if (notifier.isActive) {
onUnsubscribeSucceedActive(absintheSocket, notifier);
} else {
onUnsubscribeSucceedCanceled(absintheSocket, notifier);
}
}.bind(undefined)
};
var pushAbsintheUnsubscribeEvent = function pushAbsintheUnsubscribeEvent(absintheSocket, _ref) {
var request = _ref.request,
subscriptionId = _ref.subscriptionId;
_newArrowCheck(this, _this$k);
return pushAbsintheEvent(absintheSocket, request, unsubscribeHandler, createAbsintheUnsubscribeEvent({
subscriptionId: subscriptionId
}));
}.bind(undefined);
var unsubscribe = function unsubscribe(absintheSocket, notifier) {
_newArrowCheck(this, _this$k);
return pushAbsintheUnsubscribeEvent(absintheSocket, refreshNotifier(absintheSocket, _objectSpread({}, notifier, {
requestStatus: requestStatuses.canceling
})));
}.bind(undefined);
var onSubscribeSucceed = function onSubscribeSucceed(absintheSocket, notifier, _ref2) {
var subscriptionId = _ref2.subscriptionId;
_newArrowCheck(this, _this$k);
var subscribedNotifier = refreshNotifier(absintheSocket, _objectSpread({}, notifier, {
subscriptionId: subscriptionId,
requestStatus: requestStatuses.sent
}));
if (subscribedNotifier.isActive) {
notifyStartEvent(subscribedNotifier);
} else {
unsubscribe(absintheSocket, subscribedNotifier);
}
}.bind(undefined);
var onSubscribe = function onSubscribe(absintheSocket, notifier, response) {
_newArrowCheck(this, _this$k);
if (response.errors) {
onError(absintheSocket, notifier, errorsToString(response.errors));
} else {
onSubscribeSucceed(absintheSocket, notifier, response);
}
}.bind(undefined);
var subscribe = function subscribe(absintheSocket, notifier) {
_newArrowCheck(this, _this$k);
return pushRequestUsing(absintheSocket, notifier, onSubscribe);
}.bind(undefined);
var onDataMessage = function onDataMessage(absintheSocket, _ref3) {
var payload = _ref3.payload;
_newArrowCheck(this, _this$k);
var notifier = find(absintheSocket.notifiers, "subscriptionId", payload.subscriptionId);
if (notifier) {
notifyResultEvent(notifier, payload.result);
}
}.bind(undefined);
var dataMessageEventName = "subscription:data";
var isDataMessage = function isDataMessage(message) {
_newArrowCheck(this, _this$k);
return message.event === dataMessageEventName;
}.bind(undefined);
var _this$l = undefined;
var setNotifierRequestStatusSent = function setNotifierRequestStatusSent(absintheSocket, notifier) {
_newArrowCheck(this, _this$l);
return refreshNotifier(absintheSocket, _objectSpread({}, notifier, {
requestStatus: requestStatuses.sent
}));
}.bind(undefined);
var onQueryOrMutationSucceed = function onQueryOrMutationSucceed(absintheSocket, notifier, response) {
_newArrowCheck(this, _this$l);
return updateNotifiers(absintheSocket, remove$1(notifyResultEvent(setNotifierRequestStatusSent(absintheSocket, notifier), response)));
}.bind(undefined);
var pushQueryOrMutation = function pushQueryOrMutation(absintheSocket, notifier) {
_newArrowCheck(this, _this$l);
return pushRequestUsing(absintheSocket, notifyStartEvent(notifier), onQueryOrMutationSucceed);
}.bind(undefined);
var pushRequest = function pushRequest(absintheSocket, notifier) {
_newArrowCheck(this, _this$l);
if (notifier.operationType === "subscription") {
subscribe(absintheSocket, notifier);
} else {
pushQueryOrMutation(absintheSocket, notifier);
}
}.bind(undefined);
var _this$m = undefined;
var createChannelJoinError = function createChannelJoinError(message) {
_newArrowCheck(this, _this$m);
return new Error("channel join: ".concat(message));
}.bind(undefined);
var notifyErrorToAllActive = function notifyErrorToAllActive(absintheSocket, errorMessage) {
var _this2 = this;
_newArrowCheck(this, _this$m);
return absintheSocket.notifiers.forEach(function (notifier) {
_newArrowCheck(this, _this2);
return notifyActive(notifier, createErrorEvent(createChannelJoinError(errorMessage)));
}.bind(this));
}.bind(undefined); // join Push is reused and so the handler
// https://github.com/phoenixframework/phoenix/blob/master/assets/js/phoenix.js#L356
var createChannelJoinHandler = function createChannelJoinHandler(absintheSocket) {
var _this3 = this;
_newArrowCheck(this, _this$m);
return {
onError: function onError(errorMessage) {
_newArrowCheck(this, _this3);
return notifyErrorToAllActive(absintheSocket, errorMessage);
}.bind(this),
onSucceed: function onSucceed() {
var _this4 = this;
_newArrowCheck(this, _this3);
return absintheSocket.notifiers.forEach(function (notifier) {
_newArrowCheck(this, _this4);
return pushRequest(absintheSocket, notifier);
}.bind(this));
}.bind(this),
onTimeout: function onTimeout() {
_newArrowCheck(this, _this3);
return notifyErrorToAllActive(absintheSocket, "timeout");
}.bind(this)
};
}.bind(undefined);
var joinChannel = function joinChannel(absintheSocket) {
_newArrowCheck(this, _this$m);
handlePush(absintheSocket.channel.join(), createChannelJoinHandler(absintheSocket));
absintheSocket.channelJoinCreated = true;
return absintheSocket;
}.bind(undefined);
var _this$n = undefined;
var createUsing = function createUsing(request, operationType) {
_newArrowCheck(this, _this$n);
return {
operationType: operationType,
request: request,
activeObservers: [],
canceledObservers: [],
isActive: true,
requestStatus: requestStatuses.pending,
subscriptionId: undefined
};
}.bind(undefined);
var create = function create(request) {
_newArrowCheck(this, _this$n);
return createUsing(request, getOperationType(request.operation));
}.bind(undefined);
var _this$o = undefined;
var reactivate = function reactivate(notifier) {
_newArrowCheck(this, _this$o);
return notifier.isActive ? notifier : _objectSpread({}, notifier, {
isActive: true
});
}.bind(undefined);
var _this$p = undefined;
var connectOrJoinChannel = function connectOrJoinChannel(absintheSocket) {
_newArrowCheck(this, _this$p);
if (absintheSocket.phoenixSocket.isConnected()) {
joinChannel(absintheSocket);
} else {
// socket ignores connect calls if a connection has already been created
absintheSocket.phoenixSocket.connect();
}
}.bind(undefined);
var sendNew = function sendNew(absintheSocket, request) {
_newArrowCheck(this, _this$p);
var notifier = create(request);
updateNotifiers(absintheSocket, append([notifier]));
if (absintheSocket.channelJoinCreated) {
pushRequest(absintheSocket, notifier);
} else {
connectOrJoinChannel(absintheSocket);
}
return notifier;
}.bind(undefined);
var updateCanceledReactivate = function updateCanceledReactivate(absintheSocket, notifier) {
_newArrowCheck(this, _this$p);
return refreshNotifier(absintheSocket, reactivate(notifier));
}.bind(undefined);
var updateCanceled = function updateCanceled(absintheSocket, notifier) {
_newArrowCheck(this, _this$p);
return notifier.requestStatus === requestStatuses.sending ? updateCanceledReactivate(absintheSocket, flushCanceled(notifier)) : updateCanceledReactivate(absintheSocket, notifier);
}.bind(undefined);
var updateIfCanceled = function updateIfCanceled(absintheSocket, notifier) {
_newArrowCheck(this, _this$p);
return notifier.isActive ? notifier : updateCanceled(absintheSocket, notifier);
}.bind(undefined);
var getExistentIfAny = function getExistentIfAny(absintheSocket, request) {
_newArrowCheck(this, _this$p);
var notifier = find(absintheSocket.notifiers, "request", request);
return notifier && updateIfCanceled(absintheSocket, notifier);
}.bind(undefined);
/**
* Sends given request and returns an object (notifier) to track its progress
* (see observe function)
*
* @example
* import * as withAbsintheSocket from "@absinthe/socket";
*
* const operation = `
* subscription userSubscription($userId: ID!) {
* user(userId: $userId) {
* id
* name
* }
* }
* `;
*
* // This example uses a subscription, but the functionallity is the same for
* // all operation types (queries, mutations and subscriptions)
*
* const notifier = withAbsintheSocket.send(absintheSocket, {
* operation,
* variables: {userId: 10}
* });
*/
var send = function send(absintheSocket, request) {
_newArrowCheck(this, _this$p);
return getExistentIfAny(absintheSocket, request) || sendNew(absintheSocket, request);
}.bind(undefined);
export default send;
//# sourceMappingURL=send.js.map