GSA/code-gov-api

View on GitHub
routes/routes.js

Summary

Maintainability
C
1 day
Test Coverage
const _ = require('lodash');
const Logger = require('../utils/logger');
const {
  ElasticsearchAdapter,
  createFieldSearchQuery,
  createReposSearchQuery,
  searchTermsQuery,
  getLanguagesSearchQuery
} = require('@code.gov/code-gov-adapter').elasticsearch;
const {
  getInvalidRepoQueryParams,
  getAgencies,
  getAgencyTerms,
  getRepoJson,
  getVersion,
  getRootMessage,
  getAgencyMetaData,
  formatIssues,
  getAgency
} = require('./utils');

const mappings = require('../indexes/repo/mapping.json');
const settings = require('../indexes/repo/settings.json');

function getApiRoutes(config, router) {

  const logger = new Logger({ name: 'routes.index', level: config.LOGGER_LEVEL });
  const adapter = new ElasticsearchAdapter({ hosts: config.ES_HOST, logger: Logger, mappings, settings });

  router.get('/repos/:id', async (request, response, next) => {
    try {
      const searchQuery = createFieldSearchQuery({
        queryType: 'match',
        field: 'repoID',
        value: request.params.id
      });
      const results = await adapter.search({ index: 'repos', type: 'repo', body: searchQuery });

      if(results.hasOwnProperty('data') === false || results.data.length === 0) {
        const error = new Error('Not Found');
        error.status = 404;
        throw error;
      }

      response.json(results.data);

    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get('/repos', async (request, response, next) => {
    const queryParamKeys = request.query;

    try {
      if(Object.keys(queryParamKeys).length) {
        let invalidParams = getInvalidRepoQueryParams(queryParamKeys);

        if (invalidParams.length > 0) {
          const error = new Error(`Invalid query parameters: ${invalidParams}`);
          error.status = 400;
          throw error;
        }
      }

      const searchQuery = createReposSearchQuery({ queryParams: request.query });
      const results = await adapter.search({ index: 'repos', type: 'repo', body: searchQuery });

      if(results.hasOwnProperty('data') === false || results.data.length === 0) {
        logger.warning(`No repos data was found for the query params: ${JSON.stringify(request.query)}`);
      }

      response.json({
        total: results.total,
        repos: results.data
      });

    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get('/terms', async (request, response, next) => {
    try {
      const searchQuery = searchTermsQuery({
        queryParams: request.query,
        termTypesToSearch: config.TERM_TYPES_TO_SEARCH
      });

      const results = await adapter.search({
        index: 'terms',
        type: 'term',
        body: searchQuery
      });

      if(results.hasOwnProperty('data') === false || results.data.length === 0) {
        logger.warning(`No terms data was found for the query params: ${JSON.stringify(request.query)}`);
      }

      response.json({
        total: results.total,
        terms: results.data
      });

    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get('/open-tasks', async (request, response, next) => {
    let formattedResults = [];
    try {
      const size = request.query.size || 10;
      const from = request.query.from || 0;

      const results = await adapter.search({ index: 'issues', type: 'issue', body: { size, from } });

      if(results.hasOwnProperty('data') === false || results.data.length === 0) {
        logger.warning(`No issues data was found for the query params: ${JSON.stringify(request.query)}`);
      } else {
        formattedResults = formatIssues(results.data);
      }

      response.json({ total: results.total, items: formattedResults });

    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get(`/agencies`, async (request, response, next) => {
    try {
      const agenciesMetaData = await getAgencyMetaData(config, logger);

      const queryParams = getAgencyTerms(request);
      const searchQuery = searchTermsQuery({ queryParams, termTypesToSearch: config.TERM_TYPES_TO_SEARCH });
      const results = await adapter.search({ index: 'terms', type: 'term', body: searchQuery });

      const agenciesData = {
        agencyTerms: {
          terms: results.data
        },
        agenciesDataHash: agenciesMetaData
      };

      const {total, agencies} = getAgencies(agenciesData, request.query, logger);

      if(total === 0) {
        logger.warning(`No agencies data was found for the query params: ${JSON.stringify(request.query)}`);
      }
      response.json({ total, agencies });
    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get(`/agencies/:agency_acronym`, async (request, response, next) => {

    try {
      const agency = await getAgency(request, adapter, config, logger);

      response.json(agency || {} );
    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get(`/languages`, async (request, response, next) => {
    try {
      const searchQeury = getLanguagesSearchQuery(request.query);
      const { total, data } = await adapter.search({ index: 'terms', type: 'term', body: searchQeury });

      if(data || data.length === 0) {
        logger.warning(`No data for languages was found`);
      }

      const languages = data.map(language => {
        return {
          name: language.term,
          numRepos: language.count
        };
      });

      response.json({ total, languages });

    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get('/repo.json', (request, response, next) => {
    try{
      response.json(getRepoJson(response));
    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  router.get('/status.json', async (request, response, next) => {
    try {
      const { total, data } = await adapter.search({ index: 'status', type: 'status' });

      if(total === 0){
        logger.warning(`No data for statuses was found`);
      }

      const { timestamp, statuses } = _.omit( data[0], config.AGENCIES_TO_OMIT_FROM_STATUS );
      response.json({ total, timestamp, statuses });

    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });
  // router.get(`/status`, async (request, response, next) => {
  //   try {
  //     const { total, data } = await adapter.search({ index: 'status', type: 'status' });

  //     if(total === 0){
  //       response.render('status', { title: "Code.gov API Status", statusData: {} });
  //     }

  //     const filteredData = _.omit( data[0], config.AGENCIES_TO_OMIT_FROM_STATUS );
  //     response.render('status', { title: "Code.gov API Status", statusData: filteredData });

  //   } catch(error) {
  //     logger.trace(error);
  //     next(error);
  //   }
  // });

  // router.get(`/status/:agency/issues`, async (request, response, next) => {
  //   try {
  //     let agency = request.params.agency.toUpperCase();
  //     const results = await adapter.search({ index: 'status', type: 'status' });

  //     if(results.total === 0){
  //       response.render('status/agency/issues', { title: `Code.gov API Status for ${agency}`, statusData: {} });
  //     }

  //     const data = _.omit( results.data[0], config.AGENCIES_TO_OMIT_FROM_STATUS );
  //     const agencyIssues = data.statuses[agency].issues;
  //     response.render('status/agency/issues', {
  //       title: `Code.gov API Status for ${agency}`,
  //       statusData: agencyIssues
  //     });

  //   } catch(error) {
  //     logger.trace(error);
  //     next(error);
  //   }
  // });
  router.get('/version', async (request, response, next) => {
    try {
      const versionInfo = await getVersion(response);
      response.json(versionInfo);
    } catch(error) {
      logger.trace(error);
      next(error);
    }
  });

  router.get('/', async (request, response, next) => {
    try {
      const rootMessage = await getRootMessage();
      response.json(rootMessage);
    } catch(error){
      logger.trace(error);
      next(error);
    }
  });

  return router;
}

module.exports = {
  getApiRoutes
};