パッケージの詳細

@graphile-contrib/pg-simplify-inflector

graphile-contrib91kMIT6.1.0

Simplifies the graphile-build-pg inflector to trim the ByFooIdAndBarId from relations

graphile, postgraphile, plugin, simple

readme

@graphile-contrib/pg-simplify-inflector

This plugin simplifies field names in the PostGraphile schema; e.g. allUsers becomes simply users, User.postsByAuthorId becomes simply User.posts, and Post.userByAuthorId becomes simply Post.author.

Adding this plugin to your schema is almost certainly a breaking change, so do it before you ship anything! This is the primary reason this isn't enabled by default in PostGraphile.

This plugin is recommended for all PostGraphile users.

Customising

This plugin is implemented as a single JS file that does not need to be compiled at all - you can simply copy it into your project and customise it as you see fit.

Alternatively, you can write your own inflection plugin.

Changes:

Given these tables:

create table companies (
  id serial primary key,
  name text not null
);
create table beverages (
  id serial primary key,
  company_id int not null references companies,
  distributor_id int references companies,
  name text not null
);
  • Query.allCompanies 👉 Query.companies (disable via pgSimplifyAllRows = false)
  • Query.allBeverages 👉 Query.beverages
  • Beverage.companyByCompanyId 👉 Beverage.company
  • Beverage.companyByDistributorId 👉 Beverage.distributor
  • Company.beveragesByCompanyId 👉 Company.beverages (because the company_id column follows the [table_name]_id naming convention)
  • All update mutations now accept patch instead of companyPatch / beveragePatch (disable via pgSimplifyPatch = false)
  • If you are using pgSimpleCollections = "only" then you can set pgOmitListSuffix = true to omit the List suffix
  • Fields where the singular and plural are the same and a distinct plural is required are force-pluralised ("fishes") to avoid conflicts (e.g. singularize("fish") === pluralize("fish")).

Note: Company.beveragesByDistributorId will remain, because distributor_id does not follow the [table_name]_id naming convention, but you could rename this yourself with a smart comment:

comment on constraint "beverages_distributor_id_fkey" on "beverages" is
  E'@foreignFieldName distributedBeverages';

or with a custom inflector:

module.exports = makeAddInflectorsPlugin(
  {
    getOppositeBaseName(baseName) {
      return (
        {
          // These are the default opposites
          parent: "child",
          child: "parent",
          author: "authored",
          editor: "edited",
          reviewer: "reviewed",

          // 👇 Add/customise this line:
          distributor: "distributed",
        }[baseName] || null
      );
    },
  },
  true
);

Installation:

yarn add @graphile-contrib/pg-simplify-inflector

or

npm install --save @graphile-contrib/pg-simplify-inflector

Usage:

CLI:

postgraphile --append-plugins @graphile-contrib/pg-simplify-inflector

Library:

const PgSimplifyInflectorPlugin = require("@graphile-contrib/pg-simplify-inflector");

// ...

app.use(
  postgraphile(process.env.AUTH_DATABASE_URL, "app_public", {
    appendPlugins: [PgSimplifyInflectorPlugin],

    // Optional customisation
    graphileBuildOptions: {
      /*
       * Uncomment if you want simple collections to lose the 'List' suffix
       * (and connections to gain a 'Connection' suffix).
       */
      //pgOmitListSuffix: true,
      /*
       * Uncomment if you want 'userPatch' instead of 'patch' in update
       * mutations.
       */
      //pgSimplifyPatch: false,
      /*
       * Uncomment if you want 'allUsers' instead of 'users' at root level.
       */
      //pgSimplifyAllRows: false,
      /*
       * Uncomment if you want primary key queries and mutations to have
       * `ById` (or similar) suffix; and the `nodeId` queries/mutations
       * to lose their `ByNodeId` suffix.
       */
      // pgShortPk: true,
    },
    // ... other settings ...
  })
);

Naming your foreign key fields

By naming your foreign key along the lines of author_id or author_fk, e.g.:

CREATE TABLE posts (
  id serial primary key,
  author_id int not null references users,
  ...
);

We can automatically extract the field prefix: author and call the relation author rather than the default: user. This allows for a post to have an author, editor, reviewer, etc. all which point to users.

The reverse, however, is not so easy. On the User type, we can't call the reverse of all these different relations posts. The default inflector refers to these as postsByAuthorId, postsByEditorId, etc. However we'd rather use shorter names, so we introduce a new inflector: getOppositeBaseName. This inflector is passed a baseName (the part without the _id/_fk suffix, e.g. author, editor, reviewer above) and should return the opposite of that base name which will be prepended to the target type to produce, e.g. authoredPosts, editedPosts, reviewedPosts. Failing this, we just fall back to the default (verbose) inflector; it will be up to you to add smart comments or a custom inflector to override these.

Handling field conflicts:

In most cases, the conflict errors will guide you on how to fix these issues using smart comments.

Smart Tags

@foreignSimpleFieldName

@foreignSimpleFieldName was added to override the naming of the foreign-side of a one-to-many relationship's simple collections field (if you're using simple collections). By default we'll take the @foreignFieldName and add the "list suffix" ("List" by default, but "" if pgOmitListSuffix is set), but if you prefer you can override it entirely with @foreignSimpleFieldName. If you set @foreignSimpleFieldName and you're using simpleCollections 'both' then you should also set @foreignFieldName explicitly or unexpected things may occur.

Applies to:

  • foreign key constraints

@listSuffix

@listSuffix allows you to override the default naming on a per-entity basis, overriding pgOmitListSuffix. For example, with pgOmitListSuffix: true, you can apply @listSuffix include to have the -List suffix appended to the simple collection generated for that table, and remove the -Connection suffix from the Relay connection. When pgOmitListSuffix is not true, you can use @listSuffix omit to selectively omit the -List suffix on simple collections and append -Connection to the Relay connection instead.

If @listSuffix is set, the only valid values are "omit" and "include". Any other value will cause an error.

@listSuffix omit @listSuffix include
Relay Connection companiesConnection companies
Simple Collection companies companiesList

NOTE: @listSuffix will have no effect when using @foreignSimpleFieldName.

Applies to:

  • tables
  • foreign key constraints
  • computed column functions returning SETOF <record type>

更新履歴

ALL MAJOR RELEASES ARE BREAKING.

When the names in your GraphQL schema change you have to rewrite all your queries. You're not really meant to update major versions. Pick a major and stick to it.

It's unlikely we'll have much in the way of minor releases since all naming changes are breaking.

v6.1.0

Add @listSuffix smart tag

Previously there was no easy way to override pgOmitListSuffix on a per-entity basis. With the @listSuffix tag you can selectively control naming of both collection types:

create table companies (id serial primary key);
comment on table companies is E'@listSuffix omit';

By default (pgOmitListSuffix = null and simpleCollections = 'both') this produces:

-  allCompanies(
+  companiesConnection(
-  allCompaniesList(
+  companies(

v6.0.0

Pluralization fixes

Previously we fed the entire table/etc name into pluralize but this causes issues for special cases, for example while pluralize('genus') correctly gives genera, pluralize('old_genus') would give old_genus which is not correct.

Now we segment on underscores/capitals and only pluralize the final segment, so we're more likely to get the correct result.

This affects everywhere in your entire GraphQL schema where pluralize/singularize is used.

Simplify multi-key relationships.

  foreign key (organization_id, team_id, goal_uuid) references goals

Now named better:

-  goalByOrganizationIdAndTeamIdAndGoalUuid: Goal
+  organizationTeamGoal: Goal

Unique relations get shorter-named reverse field.

This was a bug (or, really, an omission) in v5.

For this table:

create table mascots (
    id serial primary key,
    company_id int unique not null references companies,
    name text not null
);

Previously we had the plural relationship simplified:

-  mascotsByCompanyId(
+  mascots(

But the singular was not. This update changes the singular too:

-  mascotByCompanyId: Mascot
+  mascot: Mascot

v5.0.0-beta.1

v5.0.0-beta.0

More advanced guesses at field names for reverse relations. Ability to omit list suffix, simplify patch names, turn on/off simplifying of the 'all' from 'allUsers', ability to change the 'ById' primary key fields to not have that suffix and instead have the node ID fetchers have a suffix.

v3.0.0

Simplifies naming in more of the schema.

v2.0.0

Breaking change: single relation names based on a single key are now named after the key rather than the target table so long as the key is of the form foo_id, foo_uuid.

create table posts (
  id serial primary key,
  author_id int not null references users,
  body text not null
);
 type Post {
   nodeId: ID!
   id: Int!
   authorId: Int!
-  user: User
+  author: User
   body: String!
 }

v1.0.0

Initial release