(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('apollo-utilities'), require('graphql/language/printer'), require('zen-observable-ts')) :
    typeof define === 'function' && define.amd ? define(['exports', 'apollo-utilities', 'graphql/language/printer', 'zen-observable-ts'], factory) :
    (factory((global.apolloLink = global.apolloLink || {}, global.apolloLink.core = {}),global.apollo.utilities,global.printer,global.apolloLink.zenObservable));
}(this, (function (exports,apolloUtilities,printer,Observable) { 'use strict';

    Observable = Observable && Observable.hasOwnProperty('default') ? Observable['default'] : Observable;

    var __extends = (undefined && undefined.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    var __assign = (undefined && undefined.__assign) || function () {
        __assign = Object.assign || function(t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
                s = arguments[i];
                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                    t[p] = s[p];
            }
            return t;
        };
        return __assign.apply(this, arguments);
    };
    function validateOperation(operation) {
        var OPERATION_FIELDS = [
            'query',
            'operationName',
            'variables',
            'extensions',
            'context',
        ];
        for (var _i = 0, _a = Object.keys(operation); _i < _a.length; _i++) {
            var key = _a[_i];
            if (OPERATION_FIELDS.indexOf(key) < 0) {
                throw new Error("illegal argument: " + key);
            }
        }
        return operation;
    }
    var LinkError = /** @class */ (function (_super) {
        __extends(LinkError, _super);
        function LinkError(message, link) {
            var _this = _super.call(this, message) || this;
            _this.link = link;
            return _this;
        }
        return LinkError;
    }(Error));
    function isTerminating(link) {
        return link.request.length <= 1;
    }
    function toPromise(observable) {
        var completed = false;
        return new Promise(function (resolve, reject) {
            observable.subscribe({
                next: function (data) {
                    if (completed) {
                        console.warn("Promise Wrapper does not support multiple results from Observable");
                    }
                    else {
                        completed = true;
                        resolve(data);
                    }
                },
                error: reject,
            });
        });
    }
    // backwards compat
    var makePromise = toPromise;
    function fromPromise(promise) {
        return new Observable(function (observer) {
            promise
                .then(function (value) {
                observer.next(value);
                observer.complete();
            })
                .catch(observer.error.bind(observer));
        });
    }
    function fromError(errorValue) {
        return new Observable(function (observer) {
            observer.error(errorValue);
        });
    }
    function transformOperation(operation) {
        var transformedOperation = {
            variables: operation.variables || {},
            extensions: operation.extensions || {},
            operationName: operation.operationName,
            query: operation.query,
        };
        // best guess at an operation name
        if (!transformedOperation.operationName) {
            transformedOperation.operationName =
                typeof transformedOperation.query !== 'string'
                    ? apolloUtilities.getOperationName(transformedOperation.query)
                    : '';
        }
        return transformedOperation;
    }
    function createOperation(starting, operation) {
        var context = __assign({}, starting);
        var setContext = function (next) {
            if (typeof next === 'function') {
                context = __assign({}, context, next(context));
            }
            else {
                context = __assign({}, context, next);
            }
        };
        var getContext = function () { return (__assign({}, context)); };
        Object.defineProperty(operation, 'setContext', {
            enumerable: false,
            value: setContext,
        });
        Object.defineProperty(operation, 'getContext', {
            enumerable: false,
            value: getContext,
        });
        Object.defineProperty(operation, 'toKey', {
            enumerable: false,
            value: function () { return getKey(operation); },
        });
        return operation;
    }
    function getKey(operation) {
        // XXX we're assuming here that variables will be serialized in the same order.
        // that might not always be true
        return printer.print(operation.query) + "|" + JSON.stringify(operation.variables) + "|" + operation.operationName;
    }

    var passthrough = function (op, forward) { return (forward ? forward(op) : Observable.of()); };
    var toLink = function (handler) {
        return typeof handler === 'function' ? new ApolloLink(handler) : handler;
    };
    var empty = function () {
        return new ApolloLink(function (op, forward) { return Observable.of(); });
    };
    var from = function (links) {
        if (links.length === 0)
            return empty();
        return links.map(toLink).reduce(function (x, y) { return x.concat(y); });
    };
    var split = function (test, left, right) {
        if (right === void 0) { right = new ApolloLink(passthrough); }
        var leftLink = toLink(left);
        var rightLink = toLink(right);
        if (isTerminating(leftLink) && isTerminating(rightLink)) {
            return new ApolloLink(function (operation) {
                return test(operation)
                    ? leftLink.request(operation) || Observable.of()
                    : rightLink.request(operation) || Observable.of();
            });
        }
        else {
            return new ApolloLink(function (operation, forward) {
                return test(operation)
                    ? leftLink.request(operation, forward) || Observable.of()
                    : rightLink.request(operation, forward) || Observable.of();
            });
        }
    };
    // join two Links together
    var concat = function (first, second) {
        var firstLink = toLink(first);
        if (isTerminating(firstLink)) {
            console.warn(new LinkError("You are calling concat on a terminating link, which will have no effect", firstLink));
            return firstLink;
        }
        var nextLink = toLink(second);
        if (isTerminating(nextLink)) {
            return new ApolloLink(function (operation) {
                return firstLink.request(operation, function (op) { return nextLink.request(op) || Observable.of(); }) || Observable.of();
            });
        }
        else {
            return new ApolloLink(function (operation, forward) {
                return (firstLink.request(operation, function (op) {
                    return nextLink.request(op, forward) || Observable.of();
                }) || Observable.of());
            });
        }
    };
    var ApolloLink = /** @class */ (function () {
        function ApolloLink(request) {
            if (request)
                this.request = request;
        }
        ApolloLink.prototype.split = function (test, left, right) {
            if (right === void 0) { right = new ApolloLink(passthrough); }
            return this.concat(split(test, left, right));
        };
        ApolloLink.prototype.concat = function (next) {
            return concat(this, next);
        };
        ApolloLink.prototype.request = function (operation, forward) {
            throw new Error('request is not implemented');
        };
        ApolloLink.empty = empty;
        ApolloLink.from = from;
        ApolloLink.split = split;
        ApolloLink.execute = execute;
        return ApolloLink;
    }());
    function execute(link, operation) {
        return (link.request(createOperation(operation.context, transformOperation(validateOperation(operation)))) || Observable.of());
    }

    exports.Observable = Observable;
    exports.createOperation = createOperation;
    exports.makePromise = makePromise;
    exports.toPromise = toPromise;
    exports.fromPromise = fromPromise;
    exports.fromError = fromError;
    exports.empty = empty;
    exports.from = from;
    exports.split = split;
    exports.concat = concat;
    exports.ApolloLink = ApolloLink;
    exports.execute = execute;

    Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=bundle.umd.js.map
