@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; } });