<commit_before>/* @flow */
/* eslint-disable no-param-reassign, no-use-before-define */

import type {
  ResolveParams,
  ConnectionResolveParams,
  composeWithConnectionOpts,
  connectionSortOpts,
  GraphQLConnectionType,
} from '../definition';
import { Resolver, TypeComposer } from 'graphql-compose';
import { GraphQLInt } from 'graphql';
import { prepareConnectionType } from '../types/connectionType';
import { prepareSortType } from '../types/sortInputType';
import CursorType from '../types/cursorType';
import { cursorToData, dataToCursor } from '../cursor';

export function prepareConnectionResolver(
  typeComposer: TypeComposer,
  opts: composeWithConnectionOpts
): Resolver {
  if (!(typeComposer instanceof TypeComposer)) {
    throw new Error('First arg for prepareConnectionResolver() should be instance of TypeComposer');
  }

  if (!opts.countResolverName) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + 'should have option `opts.countResolverName`.');
  }
  const countResolver = typeComposer.getResolver(opts.countResolverName);
  if (!countResolver) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + `should have resolver with name '${opts.countResolverName}' `
                  + 'due opts.countResolverName.');
  }
  const countResolve = countResolver.composeResolve();

  if (!opts.findResolverName) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + 'should have option `opts.findResolverName`.');
  }
  const findManyResolver = typeComposer.getResolver(opts.findResolverName);
  if (!findManyResolver) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + `should have resolver with name '${opts.findResolverName}' `
                  + 'due opts.countResolverName.');
  }
  const findManyResolve = findManyResolver.composeResolve();

  const additionalArgs = {};
  if (findManyResolver.hasArg('filter')) {
    additionalArgs.filter = findManyResolver.getArg('filter');
  }

  const sortEnumType = prepareSortType(typeComposer, opts);

  return new Resolver(typeComposer, {
    outputType: prepareConnectionType(typeComposer),
    name: 'connection',
    kind: 'query',
    args: {
      first: {
        type: GraphQLInt,
        description: 'Forward pagination argument for returning at most first edges',
      },
      after: {
        type: CursorType,
        description: 'Forward pagination argument for returning at most first edges',
      },
      last: {
        type: GraphQLInt,
        description: 'Backward pagination argument for returning at most last edges',
      },
      before: {
        type: CursorType,
        description: 'Backward pagination argument for returning at most last edges',
      },
      ...additionalArgs,
      sort: {
        type: sortEnumType,
        defaultValue: sortEnumType.getValues()[0].value,
        description: 'Sort argument for data ordering',
      },
    },
    resolve: async (resolveParams: ConnectionResolveParams) => {
      let countPromise;
      const { projection = {}, args } = resolveParams;
      const findManyParams: ResolveParams = Object.assign(
        {},
        resolveParams,
        { args: {} } // clear this params in copy
      );

      const sortOptions: connectionSortOpts = args.sort;

      findManyParams.args.filter = prepareFilter(args);
      findManyParams.args.sort = sortOptions.sortValue;

      if (projection && projection.edges) {
        findManyParams.projection = projection.edges.node || {};
      } else {
        findManyParams.projection = {};
      }
      sortOptions.uniqueFields.forEach(fieldName => {
        findManyParams.projection[fieldName] = true;
      });

      let first = parseInt(args.first, 10) || 0;
      if (first < 0) {
        throw new Error('Argument `first` should be non-negative number.');
      }
      const last = parseInt(args.last, 10) || 0;
      if (last < 0) {
        throw new Error('Argument `last` should be non-negative number.');
      }

      if (projection.count) {
        countPromise = countResolve(findManyParams);
      } else if (!first && last) {
        countPromise = countResolve(findManyParams);
      } else {
        countPromise = Promise.resolve(0);
      }

      if (!first && last) {
        first = await countPromise;
        first = parseInt(first, 10) || 0;
      }

      const limit = last || first;
      const skip = last > 0 ? first - last : 0;

      findManyParams.args.limit = limit + 1; // +1 document, to check next page presence
      if (skip > 0) {
        findManyParams.args.skip = skip;
      }

      const filterDataForCursor = (record) => {<commit_msg>If `first` or `last` args not provided, then get first 20 records by default.<commit_after>/* @flow */
/* eslint-disable no-param-reassign, no-use-before-define */

import type {
  ResolveParams,
  ConnectionResolveParams,
  composeWithConnectionOpts,
  connectionSortOpts,
  GraphQLConnectionType,
} from '../definition';
import { Resolver, TypeComposer } from 'graphql-compose';
import { GraphQLInt } from 'graphql';
import { prepareConnectionType } from '../types/connectionType';
import { prepareSortType } from '../types/sortInputType';
import CursorType from '../types/cursorType';
import { cursorToData, dataToCursor } from '../cursor';

export function prepareConnectionResolver(
  typeComposer: TypeComposer,
  opts: composeWithConnectionOpts
): Resolver {
  if (!(typeComposer instanceof TypeComposer)) {
    throw new Error('First arg for prepareConnectionResolver() should be instance of TypeComposer');
  }

  if (!opts.countResolverName) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + 'should have option `opts.countResolverName`.');
  }
  const countResolver = typeComposer.getResolver(opts.countResolverName);
  if (!countResolver) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + `should have resolver with name '${opts.countResolverName}' `
                  + 'due opts.countResolverName.');
  }
  const countResolve = countResolver.composeResolve();

  if (!opts.findResolverName) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + 'should have option `opts.findResolverName`.');
  }
  const findManyResolver = typeComposer.getResolver(opts.findResolverName);
  if (!findManyResolver) {
    throw new Error(`TypeComposer(${typeComposer.getTypeName()}) provided to composeWithConnection `
                  + `should have resolver with name '${opts.findResolverName}' `
                  + 'due opts.countResolverName.');
  }
  const findManyResolve = findManyResolver.composeResolve();

  const additionalArgs = {};
  if (findManyResolver.hasArg('filter')) {
    additionalArgs.filter = findManyResolver.getArg('filter');
  }

  const sortEnumType = prepareSortType(typeComposer, opts);

  return new Resolver(typeComposer, {
    outputType: prepareConnectionType(typeComposer),
    name: 'connection',
    kind: 'query',
    args: {
      first: {
        type: GraphQLInt,
        description: 'Forward pagination argument for returning at most first edges',
      },
      after: {
        type: CursorType,
        description: 'Forward pagination argument for returning at most first edges',
      },
      last: {
        type: GraphQLInt,
        description: 'Backward pagination argument for returning at most last edges',
      },
      before: {
        type: CursorType,
        description: 'Backward pagination argument for returning at most last edges',
      },
      ...additionalArgs,
      sort: {
        type: sortEnumType,
        defaultValue: sortEnumType.getValues()[0].value,
        description: 'Sort argument for data ordering',
      },
    },
    resolve: async (resolveParams: ConnectionResolveParams) => {
      let countPromise;
      const { projection = {}, args } = resolveParams;
      const findManyParams: ResolveParams = Object.assign(
        {},
        resolveParams,
        { args: {} } // clear this params in copy
      );

      const sortOptions: connectionSortOpts = args.sort;

      findManyParams.args.filter = prepareFilter(args);
      findManyParams.args.sort = sortOptions.sortValue;

      if (projection && projection.edges) {
        findManyParams.projection = projection.edges.node || {};
      } else {
        findManyParams.projection = {};
      }
      sortOptions.uniqueFields.forEach(fieldName => {
        findManyParams.projection[fieldName] = true;
      });

      let first = parseInt(args.first, 10) || 0;
      if (first < 0) {
        throw new Error('Argument `first` should be non-negative number.');
      }
      const last = parseInt(args.last, 10) || 0;
      if (last < 0) {
        throw new Error('Argument `last` should be non-negative number.');
      }

      if (projection.count) {
        countPromise = countResolve(findManyParams);
      } else if (!first && last) {
        countPromise = countResolve(findManyParams);
      } else {
        countPromise = Promise.resolve(0);
      }

      if (!first && last) {
        first = await countPromise;
        first = parseInt(first, 10) || 0;
      }

      const limit = last || first || 20;
      const skip = last > 0 ? first - last : 0;

      findManyParams.args.limit = limit + 1; // +1 document, to check next page presence
      if (skip > 0) {
        findManyParams.args.skip = skip;
      }

      const filterDataForCursor = (record) => {
{'fraction_non_alphanumeric': 0.11301509587923296, 'fraction_numerical': 0.004079967360261118, 'mean_word_length': 2.9456740442655938, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '110999', 'n_tokens_mistral': 2687, 'n_tokens_neox': 2650, 'n_words': 690}