hansololai/postgraphile-polymorphic-relation-plugin

View on GitHub
src/add_backward_poly_association_plugin.ts

Summary

Maintainability
B
5 hrs
Test Coverage
A
92%
import { SchemaBuilder, Options } from 'postgraphile';
import {
  GraphileBuild, PgPolymorphicConstraints,
} from './postgraphile_types';
import {
  validatePrerequisit, polyForeignKeyUnique, generateFieldWithHookFunc,
  polymorphicCondition, getPrimaryKey, ensureBuilderUniqueOrder,
} from './utils';

export const addBackwardPolyAssociation = (builder: SchemaBuilder, option: Options) => {

  // const { pgSimpleCollections } = option;
  // const hasConnections = pgSimpleCollections !== 'only';
  builder.hook('GraphQLObjectType:fields', (fields, build, context) => {
    const {
      extend,
      inflection,
      pgOmit: omit,
      pgPolymorphicClassAndTargetModels,
    } = build as GraphileBuild;
    const {
      scope: { isPgRowType, pgIntrospection: table },
      fieldWithHooks,
      // Self,
    } = context;
    if (!isPgRowType || !table || table.kind !== 'class') {
      return fields;
    }
    const tablePKey = getPrimaryKey(table);
    if (!tablePKey) {
      return fields;
    }
    validatePrerequisit(build as GraphileBuild);

    const modelName = inflection.tableType(table);
    // Find  all the forward relations with polymorphic
    const isConnection = true;

    const backwardPolyAssociation = (<PgPolymorphicConstraints>pgPolymorphicClassAndTargetModels)
      .filter(con => con.to.find(c => c.pgClass.id === table.id))
      .reduce((memo, currentPoly) => {
        // const { name } = currentPoly;
        const foreignTable = currentPoly.from;
        if (omit(foreignTable, 'read')) {
          return memo;
        }
        const isForeignKeyUnique = polyForeignKeyUnique(build as GraphileBuild,
          foreignTable, currentPoly);
        const fieldName = inflection.backwardRelationByPolymorphic(
          foreignTable,
          currentPoly,
          isForeignKeyUnique,
        );

        const fieldFunction = generateFieldWithHookFunc(
          build as GraphileBuild,
          foreignTable,
          (qBuilder, innerBuilder) => {
            innerBuilder.where(polymorphicCondition(build as GraphileBuild,
              currentPoly, innerBuilder, qBuilder, modelName, tablePKey));
            if (!isForeignKeyUnique) {
              ensureBuilderUniqueOrder(build, innerBuilder, foreignTable);
            }
          },
          isForeignKeyUnique,
          isConnection,
        );
        return {
          ...memo,
          [fieldName]: fieldWithHooks(
            fieldName,
            fieldFunction,
            {
              isPgFieldConnection: isConnection,
              isPgFieldSimpleCollection: !isConnection,
              isPgBackwardPolymorphicField: true,
              pgFieldIntrospection: foreignTable,
            },
          ),
        };
      }, {});
    return extend(fields, backwardPolyAssociation);
  });
};