{"size": 2002, "ext": "js", "max_stars_repo_path": "lib/modules/paginateCursor.js", "max_stars_repo_name": "campsi/campsi-mono", "max_stars_repo_stars_event_min_datetime": "2021-08-06T08:07:20.000Z", "max_stars_repo_stars_event_max_datetime": "2021-08-06T08:07:20.000Z", "max_issues_repo_path": "lib/modules/paginateCursor.js", "max_issues_repo_name": "campsi/campsi-mono", "max_issues_repo_issues_event_min_datetime": "2020-07-20T15:00:06.000Z", "max_issues_repo_issues_event_max_datetime": "2022-03-30T14:58:55.000Z", "max_forks_repo_path": "lib/modules/paginateCursor.js", "max_forks_repo_name": "campsi/campsi-mono", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 1, "max_issues_count": 30, "max_forks_count": null, "avg_line_length": 26.6933333333, "max_line_length": 231, "alphanum_fraction": 0.5974025974}
const AggregationCursor = require('mongodb').AggregationCursor;

const defaults = {
  page: 1,
  perPage: 100,
};

/**
 *
 * @param {Cursor} cursor
 * @param {object} [options]
 * @return {Promise}
 */
module.exports = function paginateCursor(cursor, options) {
  return new Promise((resolve, reject) => {
    const params = Object.assign({}, defaults, options);
    // page, perPage
    let page = parseInt(params.page);
    const perPage = parseInt(params.perPage);
    const skip = (page - 1) * parseInt(params.perPage);
    const limit = parseInt(params.perPage);
    cursor.skip(skip).limit(limit);

    if (options.infinite === true) {
      return resolve({
        skip: skip,
        limit: limit,
        page: page,
        perPage: perPage,
      });
    }
    const isAggregationCursor = cursor instanceof AggregationCursor;
    if (!isAggregationCursor) {
      cursor
        .count()
        .then((count) => {
          resolve(preparePagination(count, skip, limit, page, perPage));
        })
        .catch((error) => {
          reject(error);
        });
    } else {
      /*
        since count() doesn't exist with AggregationCursor
        Note: I could have used the code below for both types of cursor (Cursor and AggregationCursor), but since count() doesn't perform the query, I guessed that it would be better for performances to handle the count differently
       */
      cursor
        .toArray()
        .then((documents) => {
          const count = documents.length;
          resolve(preparePagination(count, skip, limit, page, perPage));
        })
        .catch((error) => {
          reject(error);
        });
    }
  });
};

const preparePagination = (count, skip, limit, page, perPage) => {
  // lastPage, bounded page
  const lastPage = count === 0 ? 1 : Math.ceil(count / perPage);
  page = Math.min(Math.max(page, 1), lastPage);
  return {
    count,
    skip,
    limit,
    page,
    perPage,
    lastPage,
  };
};

module.exports.defaults = defaults;
