This plugin implements nested mutations based on both forward and reverse foreign key relationships in PostGraphile v4. Nested mutations can be of infinite depth.
postgraphile --append-plugins postgraphile-plugin-nested-mutationsSee here for more information about loading plugins with PostGraphile.
const express = require('express');
const { postgraphile } = require('postgraphile');
const PostGraphileNestedMutations = require('postgraphile-plugin-nested-mutations');
const app = express();
app.use(
  postgraphile(pgConfig, schema, {
    appendPlugins: [
      PostGraphileNestedMutations,
    ],
  })
);
app.listen(5000);When using PostGraphile as a library, the following plugin options can be passed
via graphileBuildOptions:
nestedMutationsSimpleFieldNames
Use simple field names for nested mutations.  Instead of names suffixed with
tableBy<Key> and tableUsing<Key>, tables with a single foreign key relationship
between them will have their nested relation fields named table.  Defaults to
false.
postgraphile(pgConfig, schema, {
  graphileBuildOptions: {
    nestedMutationsSimpleFieldNames: true,
  }
});nestedMutationsDeleteOthers
Controls whether the deleteOthers field is available on nested mutations.  Defaults
to true.
postgraphile(pgConfig, schema, {
  graphileBuildOptions: {
    nestedMutationsDeleteOthers: false,
  }
});nestedMutationsOldUniqueFields
If enabled, plural names for one-to-one relations will be used.  For backwards
compatibility.  Defaults to false.
postgraphile(pgConfig, schema, {
  graphileBuildOptions: {
    nestedMutationsOldUniqueFields: false,
  }
});This plugin creates an additional field on each GraphQL Input type for every forward
and reverse foreign key relationship on a table, with the same name as the foreign table.
Each nested mutation field will have the following fields. They will accept an array if the relationship is a one-to-many relationship, or a single input if they are one-to-one.
Connect using a nodeId from the nested table.
Connect using any readable primary key or unique constraint on the nested table.
Create a new record in the nested table.
Delete using a nodeId from the nested table.
Delete using any readable primary key or unique constraint on the nested table.
Update a record using a nodeId from the nested table.
Update a record using any readable primary key or unique constraint on the nested table.
create table parent (
  id serial primary key,
  name text not null
);
create table child (
  id serial primary key,
  parent_id integer,
  name text not null,
  constraint child_parent_fkey foreign key (parent_id)
    references p.parent (id)
);A nested mutation against this schema, using Parent as the base mutation
would look like this:
mutation {
  createParent(input: {
    parent: {
      name: "Parent 1"
      childrenUsingId: {
        connectById: [{
          id: 1
        }]
        create: [{
          name: "Child 1"
        }, {
          name: "Child 2"
        }]
      }
    }
  }) {
    parent {
      id
      name
      childrenByParentId {
        nodes {
          id
          name
        }
      }
    }
  }
}Or using Child as the base mutation:
mutation {
  createChild(input: {
    child: {
      name: "Child 1"
      parentToParentId: {
        create: {
          name: "Parent of Child 1"
        }
      }
    },
  }) {
    child {
      id
      name
      parentByParentId {
        id
        name
      }
    }
  }
}Smart comments are supported for renaming the nested mutation fields.
comment on constraint child_parent_fkey on child is
  E'@fieldName parent\n@foreignFieldName children';