@graphprotocol/client-auto-pagination
Version:
`graph-client` implements automatic pagination using `first:` and `after:` filters of `graph-node`.
118 lines (117 loc) • 5.94 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAutoPagination = void 0;
const tslib_1 = require("tslib");
const delegate_1 = require("@graphql-tools/delegate");
const graphql_1 = require("graphql");
const utils_1 = require("@graphql-tools/utils");
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const shared_js_1 = require("./shared.js");
const DEFAULTS = {
if: true,
validateSchema: true,
...shared_js_1.DEFAULT_OPTIONS,
};
const validateSchema = (0, utils_1.memoize2)(function validateSchema(schema, config) {
const queryType = schema.getQueryType();
if (queryType == null) {
throw new Error(`Make sure you have a query type in this source before applying Block Tracking`);
}
const queryFields = queryType.getFields();
for (const fieldName in queryFields) {
if (fieldName.startsWith('_')) {
continue;
}
const field = queryFields[fieldName];
const nullableType = (0, graphql_1.isNonNullType)(field.type) ? field.type.ofType : field.type;
if ((0, graphql_1.isListType)(nullableType)) {
if (!field.args.some((arg) => arg.name === config.firstArgumentName)) {
throw new Error(`Make sure you have a ${config.firstArgumentName} argument in the query field ${fieldName}`);
}
if (!field.args.some((arg) => arg.name === config.skipArgumentName)) {
throw new Error(`Make sure you have a ${config.skipArgumentName} argument in the query field ${fieldName}`);
}
}
}
});
/*
const getQueryFieldNames = memoize1(function getQueryFields(schema: GraphQLSchema) {
const queryType = schema.getQueryType()
if (queryType == null) {
throw new Error(`Make sure you have a query type in this source before applying Block Tracking`)
}
return Object.keys(queryType.getFields())
}) */
class AutoPaginationTransform {
constructor({ config } = {}) {
this.config = { ...DEFAULTS, ...config };
if (this.config.if === false) {
return {};
}
}
transformSchema(schema, subschemaConfig) {
if (this.config.validateSchema) {
validateSchema(subschemaConfig.schema, this.config);
}
if (schema != null) {
const queryType = schema.getQueryType();
if (queryType != null) {
const queryFields = queryType.getFields();
for (const fieldName in queryFields) {
if (!fieldName.startsWith('_')) {
const field = queryFields[fieldName];
const existingResolver = field.resolve;
field.resolve = async (root, args, context, info) => {
const totalRecords = args[this.config.firstArgumentName] || this.config.limitOfRecords;
const initialSkipValue = args[this.config.skipArgumentName] || 0;
if (totalRecords >= this.config.skipArgumentLimit * 2) {
let remainingRecords = totalRecords;
const records = [];
while (remainingRecords > 0) {
let skipValue = records.length === 0 ? initialSkipValue : 0;
const lastIdValue = records.length > 0 ? records[records.length - 1].id : null;
while (skipValue < this.config.skipArgumentLimit && remainingRecords > 0) {
const newArgs = {
...args,
};
if (lastIdValue) {
lodash_1.default.set(newArgs, this.config.lastIdArgumentName, lastIdValue);
}
lodash_1.default.set(newArgs, this.config.skipArgumentName, skipValue);
const askedRecords = Math.min(remainingRecords, this.config.skipArgumentLimit);
lodash_1.default.set(newArgs, this.config.firstArgumentName, askedRecords);
const result = await (0, delegate_1.delegateToSchema)({
schema,
fieldName,
args: newArgs,
context,
info,
});
if (!Array.isArray(result)) {
return result;
}
records.push(...result);
skipValue += askedRecords;
remainingRecords -= askedRecords;
}
}
return records;
}
return existingResolver(root, args, context, info);
};
}
}
}
}
return schema;
}
transformRequest(executionRequest, delegationContext) {
return (0, shared_js_1.transformExecutionRequest)(executionRequest, this.config, delegationContext);
}
transformResult(originalResult) {
return (0, shared_js_1.transformExecutionResponse)(originalResult);
}
}
exports.default = AutoPaginationTransform;
var plugin_js_1 = require("./plugin.js");
Object.defineProperty(exports, "useAutoPagination", { enumerable: true, get: function () { return plugin_js_1.useAutoPagination; } });
;