gramps-graphql/gramps

View on GitHub
packages/gramps/src/lib/handleRemoteSchemas.js

Summary

Maintainability
A
0 mins
Test Coverage
import {
  introspectSchema,
  makeRemoteExecutableSchema,
  RenameTypes,
  RenameRootFields,
  transformSchema,
} from 'graphql-tools';
import { HttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import 'isomorphic-fetch';

export default async remoteSchemas => {
  const schemas = await Promise.all(
    remoteSchemas.map(async ({ namespace, remoteSchema }) => {
      const {
        url,
        setContextCallback = null,
        prefix,
        exitOnRemoteFail = true, // Exit build if an error occurs getting the remote schema. Default true.
      } = remoteSchema;

      const http = new HttpLink({
        uri: url,
        fetch,
      });

      let link = http;

      // If a setContextCallback is provided attach it to the link
      if (setContextCallback) {
        link = setContext(setContextCallback).concat(http);
      }

      try {
        // Get the remote schema
        const schema = await introspectSchema(link);

        const executableSchema = makeRemoteExecutableSchema({
          schema,
          link,
        });

        // If a prefix was provided rename the schema to include it
        if (prefix) {
          // Transforms the first letter of a string to uppercase, used in RenameRootFields
          const capitalizeFirstLetter = string => {
            const characters = string.split('');
            characters[0] = characters[0].toUpperCase();
            return characters.join('');
          };

          const renamedSchema = transformSchema(executableSchema, [
            new RenameTypes(type => `${prefix}_${type}`),
            new RenameRootFields(
              (operation, name) => `${namespace}${capitalizeFirstLetter(name)}`,
            ),
          ]);

          return renamedSchema;
        }

        return executableSchema;
      } catch (error) {
        // If exitOnRemoteFail is set to true, print error and exit
        if (process.env.NODE_ENV === 'production' && exitOnRemoteFail) {
          console.error(
            `Error retrieving remote schema at: ${url}. Exiting Build. Error: ${error}`,
          );

          return process.exit(1); //eslint-disable-line no-process-exit
        }

        // Otherwise if something goes wrong when getting the remote schema return the error and ignore this namespace
        console.error(
          `Error retrieving remote schema at: ${url}. Ignoring remote schema. Error: ${error}`,
        );

        return null;
      }
    }),
  );

  // Filter out failed remoteSchemas
  return schemas.filter(schema => schema);
};