@graphql-yoga/plugin-persisted-operations
Version:
Persisted Operations plugin for GraphQL Yoga.
111 lines (110 loc) • 4.98 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultExtractPersistedOperationId = void 0;
exports.usePersistedOperations = usePersistedOperations;
const graphql_yoga_1 = require("graphql-yoga");
const promise_helpers_1 = require("@whatwg-node/promise-helpers");
const defaultExtractPersistedOperationId = (params) => {
if (params.extensions != null &&
typeof params.extensions === 'object' &&
params.extensions?.['persistedQuery'] != null &&
typeof params.extensions?.['persistedQuery'] === 'object' &&
params.extensions?.['persistedQuery']?.['version'] === 1 &&
typeof params.extensions?.['persistedQuery']?.['sha256Hash'] === 'string') {
return params.extensions?.['persistedQuery']?.['sha256Hash'];
}
return null;
};
exports.defaultExtractPersistedOperationId = defaultExtractPersistedOperationId;
function usePersistedOperations({ allowArbitraryOperations = false, extractPersistedOperationId = exports.defaultExtractPersistedOperationId, getPersistedOperation, skipDocumentValidation = false, customErrors, }) {
const operationASTByCtx = new WeakMap();
const persistedOperationCtx = new WeakSet();
const notFoundErrorFactory = createErrorFactory('PersistedQueryNotFound', customErrors?.notFound || {
message: 'PersistedQueryNotFound',
extensions: {
code: 'PERSISTED_QUERY_NOT_IN_LIST',
},
});
const keyNotFoundErrorFactory = createErrorFactory('PersistedQueryKeyNotFound', customErrors?.keyNotFound || {
message: 'PersistedQueryKeyNotFound',
extensions: {
code: 'PERSISTED_QUERY_ID_REQUIRED',
},
});
const persistentQueryOnlyErrorFactory = createErrorFactory('PersistedQueryOnly', customErrors?.persistedQueryOnly || {
message: 'PersistedQueryOnly',
extensions: {
code: 'CANNOT_SEND_PQ_ID_AND_BODY',
},
});
return {
onParams(payload) {
const { request, params, setParams, context } = payload;
if (params.query) {
if (allowArbitraryOperations === false) {
throw persistentQueryOnlyErrorFactory(payload);
}
if (typeof allowArbitraryOperations === 'function') {
return (0, promise_helpers_1.handleMaybePromise)(() => allowArbitraryOperations(request), result => {
if (!result) {
throw persistentQueryOnlyErrorFactory(payload);
}
});
}
return;
}
const persistedOperationKey = extractPersistedOperationId(params, request, payload.context);
if (persistedOperationKey == null) {
throw keyNotFoundErrorFactory(payload);
}
return (0, promise_helpers_1.handleMaybePromise)(() => getPersistedOperation(persistedOperationKey, request, payload.context), persistedOperation => {
if (persistedOperation == null) {
throw notFoundErrorFactory(payload);
}
if (typeof persistedOperation === 'object') {
if (persistedOperation.kind !== 'Document') {
throw new Error('Persisted operation object is not a valid DocumentNode');
}
setParams({
query: `__PERSISTED_OPERATION_${persistedOperationKey}__`,
operationName: params.operationName,
variables: params.variables,
extensions: params.extensions,
});
operationASTByCtx.set(context, persistedOperation);
}
else {
setParams({
query: persistedOperation,
operationName: params.operationName,
variables: params.variables,
extensions: params.extensions,
});
}
persistedOperationCtx.add(context);
});
},
onParse({ setParsedDocument, context }) {
const ast = operationASTByCtx.get(context);
if (ast) {
setParsedDocument(ast);
}
},
onValidate({ setResult, context }) {
if (skipDocumentValidation && persistedOperationCtx.has(context)) {
setResult([]); // skip validation
}
},
};
}
function createErrorFactory(defaultMessage, options) {
if (typeof options === 'string') {
return () => (0, graphql_yoga_1.createGraphQLError)(options);
}
if (typeof options === 'function') {
return options;
}
return () => {
return (0, graphql_yoga_1.createGraphQLError)(options?.message ?? defaultMessage, options);
};
}