Add connection fields for many-to-many relations
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci chore: set up CI Jan 28, 2019
__tests__ chore: use eslint-plugin-jest Feb 7, 2019
scripts
src refactor: rename `key` variables to `keyAttribute` Jan 28, 2019
.eslintrc.js chore: use eslint-plugin-jest Feb 7, 2019
.gitattributes Initial version Nov 22, 2018
.gitignore Initial version Nov 22, 2018
.prettierrc.json chore: upgrade devDependencies; simplify config Jan 11, 2019
LICENSE Initial commit Nov 22, 2018
README.md refactor: rename `key` variables to `keyAttribute` Jan 28, 2019
index.js Bump minimum postgraphile version from 4.1.0-rc.2 to 4.1.0 Dec 20, 2018
package.json chore: use eslint-plugin-jest Feb 7, 2019
yarn.lock chore: upgrade dev deps Feb 7, 2019

README.md

@graphile-contrib/pg-many-to-many

Package on npm CircleCI

This Graphile Engine plugin adds connection fields for many-to-many relations.

Requires postgraphile@^4.1.0 or graphile-build-pg@^4.1.0

Example:

{
  allPeople {
    nodes {
      personName
      # 👇 many-to-many relation
      teamsByTeamMemberPersonIdAndTeamId {
        nodes {
          teamName
        }
      }
    }
  }
}

Usage

Append this plugin and the additional fields will be added to your schema.

CLI

yarn add postgraphile
yarn add @graphile-contrib/pg-many-to-many
npx postgraphile --append-plugins @graphile-contrib/pg-many-to-many

Library

const express = require("express");
const { postgraphile } = require("postgraphile");
const PgManyToManyPlugin = require("@graphile-contrib/pg-many-to-many");

const app = express();

app.use(
  postgraphile(process.env.DATABASE_URL, "app_public", {
    appendPlugins: [PgManyToManyPlugin],
    graphiql: true,
  })
);

app.listen(5000);

Inflection

To avoid naming conflicts, this plugin uses a verbose naming convention (e.g. teamsByTeamMemberTeamId), similar to how related fields are named by default in PostGraphile v4.

You can override this by adding an inflector plugin. For example, the following plugin shortens the names to just the table name (producing e.g. teams):

const { makeAddInflectorsPlugin } = require("graphile-utils");

module.exports = makeAddInflectorsPlugin(
  {
    manyToManyRelationByKeys(
      _leftKeyAttributes,
      _junctionLeftKeyAttributes,
      _junctionRightKeyAttributes,
      _rightKeyAttributes,
      _junctionTable,
      rightTable,
      _junctionLeftConstraint,
      junctionRightConstraint
    ) {
      if (junctionRightConstraint.tags.manyToManyFieldName) {
        return junctionRightConstraint.tags.manyToManyFieldName;
      }
      return this.camelCase(
        `${this.pluralize(this._singularizedTableName(rightTable))}`
      );
    },
    manyToManyRelationByKeysSimple(
      _leftKeyAttributes,
      _junctionLeftKeyAttributes,
      _junctionRightKeyAttributes,
      _rightKeyAttributes,
      _junctionTable,
      rightTable,
      _junctionLeftConstraint,
      junctionRightConstraint
    ) {
      if (junctionRightConstraint.tags.manyToManySimpleFieldName) {
        return junctionRightConstraint.tags.manyToManySimpleFieldName;
      }
      return this.camelCase(
        `${this.pluralize(this._singularizedTableName(rightTable))}-list`
      );
    },
  },
  true // Passing true here allows the plugin to overwrite existing inflectors.
);

See the makeAddInflectorsPlugin documentation for more information.

You can also override individual field names using @manyToManyFieldName and @manyToManySimpleFieldName smart comments:

comment on constraint team_member_team_id_fkey on p.team_member is E'@manyToManyFieldName teams';

This changes the GraphQL field name from teamsByTeamMemberTeamId to teams.