<commit_before>import BaseRouter from "falcor-router";
import { ghostArticleQuery } from 'lib/ghostAPI';
import dbFunctions from 'lib/db';
import falcor from 'falcor';
import _ from 'lodash';

const $ref = falcor.Model.ref;

export const mapGhostNames = (falcorName) => {
  switch (falcorName) {
    case "teaser":
      return "meta_description";
    case "issueNumber":
      return "issue_order";
    default:
      return falcorName;
  }
}

// This is just a cleaner way to import all the functions from db.js
// compared to listing all the 20+ functions exported from there
const db = new dbFunctions();

export default class FalcorRouter extends BaseRouter.createClass([
  {
    route: "infoPages[{keys:slugs}]['title', 'html', 'slug']",
    get: (pathSet) => {
      return new Promise((resolve) => {
        const requestedFields = pathSet[2];
        db.infoPagesQuery(pathSet.slugs, requestedFields).then((data) => {
          // data function parameter is an array of objects with keys equal to the columns requested.
          // Always returns the slug so we know which one we got
          const results = [];
          data.forEach((row) => {
            requestedFields.forEach((key) => {
              if (!row.hasOwnProperty(key)) {
                throw new Error("missing data in infoPages, it is not even null, simply doesn't return");
              }
              else {
                results.push({
                  path: ['infoPages', row.slug, key],
                  value: row[key],
                });
              }
            });
          });
          resolve(results);
        });
      });
    },
  },
  {
    route: "authorsBySlug[{keys:slugs}]['id', 'name', 'image', 'biography', 'slug', 'job_title']",
    get: (pathSet) => {
      return new Promise((resolve) => {
        const requestedFields = pathSet[2];
        db.authorQuery(pathSet.slugs, requestedFields).then((data) => {
          // always returns slug in the object no matter what.
          const results = [];
          data.forEach((author) => {
            requestedFields.forEach((field) => {
              results.push({
                path: ["authorsBySlug", author.slug, field],
                value: author[field],
              });
            });
          });
          resolve(results);
        });
      });
    },
    set: (jsonGraphArg) => {
      return new Promise((resolve, reject) => {
        const authorsBySlug = jsonGraphArg.authorsBySlug;
        db.updateMainAuthorData(authorsBySlug).then((flag) => {
          if (!flag) {
            throw new Error("For unknown reasons updateMainAuthorData returned a non-true flag");
          }
          const results = [];
          _.forEach(authorsBySlug, (authorObject, slug) => {
            _.forEach(authorObject, (value, field) => {
              results.push({
                path: ['authorsBySlug', slug, field],
                value: value,
              });
            });
          });
          resolve(results);
        })
        .catch((e) => {
          reject(e);
        });
      });
    },
  },
  {
    route: "authorsBySlug[{keys:slugs}]['teams'][{integers:indices}]",
    get: (pathSet) => {
      return new Promise((resolve) => {
        db.authorTeamQuery(pathSet.slugs).then((data) => {
          const results = [];
          _.forEach(data, (teamSlugArray, authorSlug) => {
            pathSet.indices.forEach((index) => {
              if (index < teamSlugArray.length) {
                results.push({
                  path: ['authorsBySlug', authorSlug, 'teams', index],
                  value: $ref(['teamsBySlug', teamSlugArray[index]]),
                });
              }
            });
          });
          resolve(results);
        })
      });
    },
  },
  {
    route: "authorsBySlug[{keys:slugs}]['articles'][{integers:indices}]",
    // This could be a bit vulnerable as it fetches all articles written by an author
    // no matter what indices are called, but I think in reality it shouldn't be a problem
    get: (pathSet) => {
      return new Promise((resolve) => {
        db.authorArticleQuery(pathSet.slugs).then((data) => {
          // We receive the data as an object with keys equalling author slugs
          // and values being an array of article slugs where the most recent is first
          const results = [];
          _.forEach(data, (postSlugArray, authorSlug) => {
            pathSet.indices.forEach((index) => {
              if (index < postSlugArray.length) {
                results.push({
                  path: ['authorsBySlug', authorSlug, 'articles', index],
                  value: $ref(['articlesBySlug', postSlugArray[index]]),
                });
              }
            });
          });
          resolve(results);
        })
      });
    },
  },
  {
    route: "authorsBySlug['createAuthor']",
    call: (callPath, args) => {
      return new Promise((resolve) => {
        const authorObject = args[0];
        if (!(authorObject.hasOwnProperty('slug') && authorObject.hasOwnProperty('name'))) {
          throw new Error("When creating an author you must provide both name and slug");
        }
        db.createAuthor(authorObject).then((flag) => {
          if (flag !== true) {
            throw new Error("Create Author function returned non-true flag");
          }
          const results = [];
          const authorSlug = authorObject.slug;
          _.forEach(authorObject, (value, field) => {
            results.push({
              path: ['authorsBySlug', authorSlug, field],
              value: value,
            });
          });
          resolve(results);
        });
      });
    },
  },
  {
    // Get article data from Ghost API
    route: "articlesBySlug[{keys:slugs}]['id', 'image', 'slug', 'title', 'markdown', 'html', 'teaser']",
    get: (pathSet) => {
      return new Promise((resolve) => {
        const requestedFields = pathSet[2];
        let query = "filter=";
        pathSet.slugs.forEach((slug, index) => {
          query += (index > 0 ? "," : "") + `slug:'${slug}'`;
        });
        query += "&fields=slug"
        requestedFields.forEach((field) => {
          if (field !== 'slug') {
            query += "," + mapGhostNames(field);
          }
        })
        query += "&limit=" + pathSet.slugs.length.toString();
        ghostArticleQuery(query).then((data) => {
          data = data.posts;
          const results = [];
          data.forEach((article) => {
            requestedFields.forEach((field) => {
              let ghostField = mapGhostNames(field);
              results.push({
                path: ["articlesBySlug", article.slug, field],
                value: article[ghostField],
              });
            });
          });
          resolve(results);
        })
        .catch((e) => {
          console.error("Error was found in Ghost query for slugs:");
          console.error(pathSet.slugs);
          resolve([]);
        });
      });
    },
    set: (jsonGraphArg) => {
      return new Promise((resolve) => {
        const articlesBySlug = jsonGraphArg.articlesBySlug;
        const slugs = Object.keys(articlesBySlug);
        db.updateGhostFields(articlesBySlug).then((flag) => {
          const results = [];
          if (flag !== true) {
            throw new Error("For unknown reasons updateGhostFields returned a non-true flag");
          }
          slugs.forEach((slug) => {
            const slugObject = articlesBySlug[slug];
            _.forEach(slugObject, (value, field) => {
              results.push({
                path: ['articlesBySlug', slug, field],
                value: value,
              });
            });
          });
          resolve(results);
        });<commit_msg>Fix linting and extend error message<commit_after>import BaseRouter from "falcor-router";
import { ghostArticleQuery } from 'lib/ghostAPI';
import dbFunctions from 'lib/db';
import falcor from 'falcor';
import _ from 'lodash';

const $ref = falcor.Model.ref;

export const mapGhostNames = (falcorName) => {
  switch (falcorName) {
    case "teaser":
      return "meta_description";
    case "issueNumber":
      return "issue_order";
    default:
      return falcorName;
  }
}

// This is just a cleaner way to import all the functions from db.js
// compared to listing all the 20+ functions exported from there
const db = new dbFunctions();

export default class FalcorRouter extends BaseRouter.createClass([
  {
    route: "infoPages[{keys:slugs}]['title', 'html', 'slug']",
    get: (pathSet) => {
      return new Promise((resolve) => {
        const requestedFields = pathSet[2];
        db.infoPagesQuery(pathSet.slugs, requestedFields).then((data) => {
          // data function parameter is an array of objects with keys equal to the columns requested.
          // Always returns the slug so we know which one we got
          const results = [];
          data.forEach((row) => {
            requestedFields.forEach((key) => {
              if (!row.hasOwnProperty(key)) {
                throw new Error("missing data in infoPages, it is not even null, simply doesn't return");
              }
              else {
                results.push({
                  path: ['infoPages', row.slug, key],
                  value: row[key],
                });
              }
            });
          });
          resolve(results);
        });
      });
    },
  },
  {
    route: "authorsBySlug[{keys:slugs}]['id', 'name', 'image', 'biography', 'slug', 'job_title']",
    get: (pathSet) => {
      return new Promise((resolve) => {
        const requestedFields = pathSet[2];
        db.authorQuery(pathSet.slugs, requestedFields).then((data) => {
          // always returns slug in the object no matter what.
          const results = [];
          data.forEach((author) => {
            requestedFields.forEach((field) => {
              results.push({
                path: ["authorsBySlug", author.slug, field],
                value: author[field],
              });
            });
          });
          resolve(results);
        });
      });
    },
    set: (jsonGraphArg) => {
      return new Promise((resolve, reject) => {
        const authorsBySlug = jsonGraphArg.authorsBySlug;
        db.updateMainAuthorData(authorsBySlug).then((flag) => {
          if (!flag) {
            throw new Error("For unknown reasons updateMainAuthorData returned a non-true flag");
          }
          const results = [];
          _.forEach(authorsBySlug, (authorObject, slug) => {
            _.forEach(authorObject, (value, field) => {
              results.push({
                path: ['authorsBySlug', slug, field],
                value: value,
              });
            });
          });
          resolve(results);
        })
        .catch((e) => {
          reject(e);
        });
      });
    },
  },
  {
    route: "authorsBySlug[{keys:slugs}]['teams'][{integers:indices}]",
    get: (pathSet) => {
      return new Promise((resolve) => {
        db.authorTeamQuery(pathSet.slugs).then((data) => {
          const results = [];
          _.forEach(data, (teamSlugArray, authorSlug) => {
            pathSet.indices.forEach((index) => {
              if (index < teamSlugArray.length) {
                results.push({
                  path: ['authorsBySlug', authorSlug, 'teams', index],
                  value: $ref(['teamsBySlug', teamSlugArray[index]]),
                });
              }
            });
          });
          resolve(results);
        })
      });
    },
  },
  {
    route: "authorsBySlug[{keys:slugs}]['articles'][{integers:indices}]",
    // This could be a bit vulnerable as it fetches all articles written by an author
    // no matter what indices are called, but I think in reality it shouldn't be a problem
    get: (pathSet) => {
      return new Promise((resolve) => {
        db.authorArticleQuery(pathSet.slugs).then((data) => {
          // We receive the data as an object with keys equalling author slugs
          // and values being an array of article slugs where the most recent is first
          const results = [];
          _.forEach(data, (postSlugArray, authorSlug) => {
            pathSet.indices.forEach((index) => {
              if (index < postSlugArray.length) {
                results.push({
                  path: ['authorsBySlug', authorSlug, 'articles', index],
                  value: $ref(['articlesBySlug', postSlugArray[index]]),
                });
              }
            });
          });
          resolve(results);
        })
      });
    },
  },
  {
    route: "authorsBySlug['createAuthor']",
    call: (callPath, args) => {
      return new Promise((resolve) => {
        const authorObject = args[0];
        if (!(authorObject.hasOwnProperty('slug') && authorObject.hasOwnProperty('name'))) {
          throw new Error("When creating an author you must provide both name and slug");
        }
        db.createAuthor(authorObject).then((flag) => {
          if (flag !== true) {
            throw new Error("Create Author function returned non-true flag");
          }
          const results = [];
          const authorSlug = authorObject.slug;
          _.forEach(authorObject, (value, field) => {
            results.push({
              path: ['authorsBySlug', authorSlug, field],
              value: value,
            });
          });
          resolve(results);
        });
      });
    },
  },
  {
    // Get article data from Ghost API
    route: "articlesBySlug[{keys:slugs}]['id', 'image', 'slug', 'title', 'markdown', 'html', 'teaser']",
    get: (pathSet) => {
      return new Promise((resolve) => {
        const requestedFields = pathSet[2];
        let query = "filter=";
        pathSet.slugs.forEach((slug, index) => {
          query += (index > 0 ? "," : "") + `slug:'${slug}'`;
        });
        query += "&fields=slug"
        requestedFields.forEach((field) => {
          if (field !== 'slug') {
            query += "," + mapGhostNames(field);
          }
        })
        query += "&limit=" + pathSet.slugs.length.toString();
        ghostArticleQuery(query).then((data) => {
          data = data.posts;
          const results = [];
          data.forEach((article) => {
            requestedFields.forEach((field) => {
              let ghostField = mapGhostNames(field);
              results.push({
                path: ["articlesBySlug", article.slug, field],
                value: article[ghostField],
              });
            });
          });
          resolve(results);
        })
        .catch((e) => {
          console.error("Error was found in Ghost query for slugs:"); //eslint-disable-line no-console
          console.error(pathSet.slugs); //eslint-disable-line no-console
          console.error(e); //eslint-disable-line no-console
          resolve([]);
        });
      });
    },
    set: (jsonGraphArg) => {
      return new Promise((resolve) => {
        const articlesBySlug = jsonGraphArg.articlesBySlug;
        const slugs = Object.keys(articlesBySlug);
        db.updateGhostFields(articlesBySlug).then((flag) => {
          const results = [];
          if (flag !== true) {
            throw new Error("For unknown reasons updateGhostFields returned a non-true flag");
          }
          slugs.forEach((slug) => {
            const slugObject = articlesBySlug[slug];
            _.forEach(slugObject, (value, field) => {
              results.push({
                path: ['articlesBySlug', slug, field],
                value: value,
              });
            });
          });
          resolve(results);
        });
{'fraction_non_alphanumeric': 0.14180913498341413, 'fraction_numerical': 0.0008930849706557795, 'mean_word_length': 1.821126507108152, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 93, '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': '5084724', 'n_tokens_mistral': 4328, 'n_tokens_neox': 4235, 'n_words': 1008}