Odoo GraphQL Subscription using Node, Express JS for Sample
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
10 KiB

4 months ago
import { __assign } from "tslib";
import { invariant } from "../../utilities/globals/index.js";
import { print } from "../../utilities/index.js";
import { ApolloLink } from "../core/index.js";
import { Observable, compact, isNonEmptyArray } from "../../utilities/index.js";
import { cacheSizes, AutoCleanedWeakCache, } from "../../utilities/index.js";
export var VERSION = 1;
function processErrors(graphQLErrors) {
var byMessage = Object.create(null), byCode = Object.create(null);
if (isNonEmptyArray(graphQLErrors)) {
graphQLErrors.forEach(function (error) {
var _a;
byMessage[error.message] = error;
if (typeof ((_a = error.extensions) === null || _a === void 0 ? void 0 : _a.code) == "string")
byCode[error.extensions.code] = error;
});
}
return {
persistedQueryNotSupported: !!(byMessage.PersistedQueryNotSupported ||
byCode.PERSISTED_QUERY_NOT_SUPPORTED),
persistedQueryNotFound: !!(byMessage.PersistedQueryNotFound || byCode.PERSISTED_QUERY_NOT_FOUND),
};
}
var defaultOptions = {
disable: function (_a) {
var meta = _a.meta;
return meta.persistedQueryNotSupported;
},
retry: function (_a) {
var meta = _a.meta;
return meta.persistedQueryNotSupported || meta.persistedQueryNotFound;
},
useGETForHashedQueries: false,
};
function operationDefinesMutation(operation) {
return operation.query.definitions.some(function (d) { return d.kind === "OperationDefinition" && d.operation === "mutation"; });
}
export var createPersistedQueryLink = function (options) {
var hashesByQuery;
function resetHashCache() {
hashesByQuery = undefined;
}
// Ensure a SHA-256 hash function is provided, if a custom hash
// generation function is not provided. We don't supply a SHA-256 hash
// function by default, to avoid forcing one as a dependency. Developers
// should pick the most appropriate SHA-256 function (sync or async) for
// their needs/environment, or provide a fully custom hash generation
// function (via the `generateHash` option) if they want to handle
// hashing with something other than SHA-256.
invariant(options &&
(typeof options.sha256 === "function" ||
typeof options.generateHash === "function"), 40);
var _a = compact(defaultOptions, options), sha256 = _a.sha256,
// If both a `sha256` and `generateHash` option are provided, the
// `sha256` option will be ignored. Developers can configure and
// use any hashing approach they want in a custom `generateHash`
// function; they aren't limited to SHA-256.
_b = _a.generateHash,
// If both a `sha256` and `generateHash` option are provided, the
// `sha256` option will be ignored. Developers can configure and
// use any hashing approach they want in a custom `generateHash`
// function; they aren't limited to SHA-256.
generateHash = _b === void 0 ? function (query) {
return Promise.resolve(sha256(print(query)));
} : _b, disable = _a.disable, retry = _a.retry, useGETForHashedQueries = _a.useGETForHashedQueries;
var supportsPersistedQueries = true;
var getHashPromise = function (query) {
return new Promise(function (resolve) { return resolve(generateHash(query)); });
};
function getQueryHash(query) {
if (!query || typeof query !== "object") {
// If the query is not an object, we won't be able to store its hash as
// a property of query[hashesKey], so we let generateHash(query) decide
// what to do with the bogus query.
return getHashPromise(query);
}
if (!hashesByQuery) {
hashesByQuery = new AutoCleanedWeakCache(cacheSizes["PersistedQueryLink.persistedQueryHashes"] ||
2000 /* defaultCacheSizes["PersistedQueryLink.persistedQueryHashes"] */);
}
var hash = hashesByQuery.get(query);
if (!hash)
hashesByQuery.set(query, (hash = getHashPromise(query)));
return hash;
}
return Object.assign(new ApolloLink(function (operation, forward) {
invariant(forward, 41);
var query = operation.query;
return new Observable(function (observer) {
var subscription;
var retried = false;
var originalFetchOptions;
var setFetchOptions = false;
var maybeRetry = function (_a, cb) {
var response = _a.response, networkError = _a.networkError;
if (!retried && ((response && response.errors) || networkError)) {
retried = true;
var graphQLErrors = [];
var responseErrors = response && response.errors;
if (isNonEmptyArray(responseErrors)) {
graphQLErrors.push.apply(graphQLErrors, responseErrors);
}
// Network errors can return GraphQL errors on for example a 403
var networkErrors = void 0;
if (typeof (networkError === null || networkError === void 0 ? void 0 : networkError.result) !== "string") {
networkErrors =
networkError &&
networkError.result &&
networkError.result.errors;
}
if (isNonEmptyArray(networkErrors)) {
graphQLErrors.push.apply(graphQLErrors, networkErrors);
}
var disablePayload = {
response: response,
networkError: networkError,
operation: operation,
graphQLErrors: isNonEmptyArray(graphQLErrors) ? graphQLErrors : void 0,
meta: processErrors(graphQLErrors),
};
// if the server doesn't support persisted queries, don't try anymore
supportsPersistedQueries = !disable(disablePayload);
if (!supportsPersistedQueries) {
// clear hashes from cache, we don't need them anymore
resetHashCache();
}
// if its not found, we can try it again, otherwise just report the error
if (retry(disablePayload)) {
// need to recall the link chain
if (subscription)
subscription.unsubscribe();
// actually send the query this time
operation.setContext({
http: {
includeQuery: true,
includeExtensions: supportsPersistedQueries,
},
fetchOptions: {
// Since we're including the full query, which may be
// large, we should send it in the body of a POST request.
// See issue #7456.
method: "POST",
},
});
if (setFetchOptions) {
operation.setContext({ fetchOptions: originalFetchOptions });
}
subscription = forward(operation).subscribe(handler);
return;
}
}
cb();
};
var handler = {
next: function (response) {
maybeRetry({ response: response }, function () { return observer.next(response); });
},
error: function (networkError) {
maybeRetry({ networkError: networkError }, function () { return observer.error(networkError); });
},
complete: observer.complete.bind(observer),
};
// don't send the query the first time
operation.setContext({
http: {
includeQuery: !supportsPersistedQueries,
includeExtensions: supportsPersistedQueries,
},
});
// If requested, set method to GET if there are no mutations. Remember the
// original fetchOptions so we can restore them if we fall back to a
// non-hashed request.
if (useGETForHashedQueries &&
supportsPersistedQueries &&
!operationDefinesMutation(operation)) {
operation.setContext(function (_a) {
var _b = _a.fetchOptions, fetchOptions = _b === void 0 ? {} : _b;
originalFetchOptions = fetchOptions;
return {
fetchOptions: __assign(__assign({}, fetchOptions), { method: "GET" }),
};
});
setFetchOptions = true;
}
if (supportsPersistedQueries) {
getQueryHash(query)
.then(function (sha256Hash) {
operation.extensions.persistedQuery = {
version: VERSION,
sha256Hash: sha256Hash,
};
subscription = forward(operation).subscribe(handler);
})
.catch(observer.error.bind(observer));
}
else {
subscription = forward(operation).subscribe(handler);
}
return function () {
if (subscription)
subscription.unsubscribe();
};
});
}), {
resetHashCache: resetHashCache,
}, globalThis.__DEV__ !== false ?
{
getMemoryInternals: function () {
var _a;
return {
PersistedQueryLink: {
persistedQueryHashes: (_a = hashesByQuery === null || hashesByQuery === void 0 ? void 0 : hashesByQuery.size) !== null && _a !== void 0 ? _a : 0,
},
};
},
}
: {});
};
//# sourceMappingURL=index.js.map