Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@graphile-contrib/pg-simplify-inflector

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@graphile-contrib/pg-simplify-inflector - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

161

index.js

@@ -11,10 +11,37 @@ /*

module.exports = function PgSimplifyInflectorPlugin(builder, { pgSimpleCollections, pgOmitListSuffix }) {
function fixCapitalisedPlural(fn) {
return function(str) {
const original = fn.call(this, str);
return original.replace(/[0-9]S(?=[A-Z]|$)/g, match => match.toLowerCase());
};
}
module.exports = function PgSimplifyInflectorPlugin(
builder,
{
pgSimpleCollections,
pgOmitListSuffix,
pgSimplifyPatch = true,
pgSimplifyAllRows = true,
}
) {
const hasConnections = pgSimpleCollections !== "only";
const hasSimpleCollections = pgSimpleCollections === "only" || pgSimpleCollections === "both";
const hasSimpleCollections =
pgSimpleCollections === "only" || pgSimpleCollections === "both";
if (hasConnections && hasSimpleCollections && pgOmitListSuffix) {
throw new Error("Cannot omit -list suffix (`pgOmitListSuffix`) if both relay connections and simple collections are enabled.");
throw new Error(
"Cannot omit -list suffix (`pgOmitListSuffix`) if both relay connections and simple collections are enabled."
);
}
if (hasSimpleCollections && !hasConnections && pgOmitListSuffix !== true && pgOmitListSuffix !== false) {
console.warn("You can simplify the inflector further by adding `{graphileOptions: {pgOmitListSuffix: true}}` to the options passed to PostGraphile, however be aware that doing so will mean that later enabling relay connections will be a breaking change. To dismiss this message, set `pgOmitListSuffix` to false instead.");
if (
hasSimpleCollections &&
!hasConnections &&
pgOmitListSuffix !== true &&
pgOmitListSuffix !== false
) {
console.warn(
"You can simplify the inflector further by adding `{graphileBuildOptions: {pgOmitListSuffix: true}}` to the options passed to PostGraphile, however be aware that doing so will mean that later enabling relay connections will be a breaking change. To dismiss this message, set `pgOmitListSuffix` to false instead."
);
}

@@ -26,16 +53,105 @@

singleRelationByKeys(detailedKeys, table, _foreignTable, constraint) {
if (constraint.tags.fieldName) {
return constraint.tags.fieldName;
/*
* This solves the issue with `blah-table1s` becoming `blahTable1S`
* (i.e. the capital S at the end) or `table1-connection becoming `Table1SConnection`
*/
camelCase: fixCapitalisedPlural(inflection.camelCase),
upperCamelCase: fixCapitalisedPlural(inflection.upperCamelCase),
getBaseName(columnName) {
const matches = columnName.match(
/^(.+?)(_row_id|_id|_uuid|_fk|RowId|Id|Uuid|UUID|Fk)$/
);
if (matches) {
return matches[1];
}
return null;
},
/* This is a good method to override. */
getOppositeBaseName(baseName) {
return (
{
/*
* Changes to this list are breaking changes and will require a
* major version update, so we need to group as many together as
* possible! Rather than sending a PR, please look for an open
* issue called something like "Add more opposites" (if there isn't
* one then please open it) and add your suggestions to the GitHub
* comments.
*/
parent: "child",
child: "parent",
author: "authored",
editor: "edited",
reviewer: "reviewed",
}[baseName] || null
);
},
getBaseNameFromKeys(detailedKeys) {
if (detailedKeys.length === 1) {
const key = detailedKeys[0];
const columnName = this._columnName(key);
const matches = columnName.match(/^(.*)(_id|_uuid|Id|Uuid)$/);
if (matches) {
return this.camelCase(matches[1]);
return this.getBaseName(columnName);
}
return null;
},
...(pgSimplifyPatch
? {
patchField() {
return "patch";
},
}
: null),
...(pgSimplifyAllRows
? {
allRows(table) {
return this.camelCase(
this.pluralize(this._singularizedTableName(table))
);
},
allRowsSimple(table) {
return this.camelCase(
`${this.pluralize(this._singularizedTableName(table))}-list`
);
},
}
: null),
singleRelationByKeys(detailedKeys, table, _foreignTable, constraint) {
if (constraint.tags.fieldName) {
return constraint.tags.fieldName;
}
const baseName = this.getBaseNameFromKeys(detailedKeys);
if (baseName) {
return this.camelCase(baseName);
}
return this.camelCase(`${this._singularizedTableName(table)}`);
},
singleRelationByKeysBackwards(
detailedKeys,
table,
_foreignTable,
constraint
) {
if (constraint.tags.foreignSingleFieldName) {
return constraint.tags.foreignSingleFieldName;
}
if (constraint.tags.foreignFieldName) {
return constraint.tags.foreignFieldName;
}
const baseName = this.getBaseNameFromKeys(detailedKeys);
const oppositeBaseName = baseName && this.getOppositeBaseName(baseName);
if (oppositeBaseName) {
return this.camelCase(
`${oppositeBaseName}-${this._singularizedTableName(table)}`
);
}
return this.camelCase(`${this._singularizedTableName(table)}`);
},
manyRelationByKeys(detailedKeys, table, _foreignTable, constraint) {

@@ -45,2 +161,11 @@ if (constraint.tags.foreignFieldName) {

}
const baseName = this.getBaseNameFromKeys(detailedKeys);
const oppositeBaseName = baseName && this.getOppositeBaseName(baseName);
if (oppositeBaseName) {
return this.camelCase(
`${oppositeBaseName}-${this.pluralize(
this._singularizedTableName(table)
)}`
);
}
return this.camelCase(

@@ -50,8 +175,14 @@ `${this.pluralize(this._singularizedTableName(table))}`

},
manyRelationByKeysSimple(detailedKeys, table, _foreignTable, constraint) {
if (constraint.tags.foreignFieldName) {
return constraint.tags.foreignFieldName;
if (constraint.tags.foreignSimpleFieldName) {
return constraint.tags.foreignSimpleFieldName;
}
return this.camelCase(
`${this.pluralize(this._singularizedTableName(table))}` + (pgOmitListSuffix ? '' : '-list')
return (
this.manyRelationByKeys(
detailedKeys,
table,
_foreignTable,
constraint
) + (pgOmitListSuffix ? "" : "-list")
);

@@ -58,0 +189,0 @@ },

7

package.json
{
"name": "@graphile-contrib/pg-simplify-inflector",
"version": "2.0.1",
"version": "3.0.0",
"description": "Simplifies the graphile-build-pg inflector to trim the `ByFooIdAndBarId` from relations",

@@ -31,3 +31,6 @@ "main": "index.js",

"index.js"
]
],
"devDependencies": {
"prettier": "^1.14.3"
}
}
# @graphile-contrib/pg-simplify-inflector
Simplifies relation names; e.g. `postsByAuthorId` becomes simply `posts`.
This plugin simplifies relation names in the PostGraphile schema; e.g.
`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 recommended for most PostGraphile users, but it does require
familiarity with smart comments to override certain potential naming conflicts
(e.g. `Company.beveragesByManufacturerId` and
`Company.beveragesByDistributorId` both want to become simply
`Company.beverages` which would cause a conflict).
## 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](https://www.graphile.org/postgraphile/inflection/).
## Changes:
Given these tables:
```sql
create table companies (
id serial primary key,
name text not null
);
create table beverages (
id serial primary key,
name text not null,
manufacturer_id int references companies,
distributor_id int references companies
);
comment on constraint "beverages_distributor_id_fkey" on "beverages" is
E'@foreignFieldName distributedBeverages';
```
- `Beverage.companyByManufacturerId` and `Beverage.companyByDistributorId`
become `Beverage.manufacturer` and `Beverage.distributor` respectively
- `Company.beveragesByManufacturerId` and `Company.beveragesByDistributorId`
would both become `Company.beverages` and cause an error (but we have a smart
comment above to rename the latter to `Company.distributedBeverages` to avoid
the issue)
- `Query.allCompanies` and `Query.allBeverages` become `Query.companies` and
`Query.beverages` respectively (disable via `pgSimplifyAllRows = false`)
- 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
## Installation:

@@ -28,4 +80,3 @@

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

@@ -36,5 +87,3 @@ // ...

postgraphile(process.env.AUTH_DATABASE_URL, "app_public", {
appendPlugins: [
PgSimplifyInflectorPlugin,
],
appendPlugins: [PgSimplifyInflectorPlugin],
// ... other settings ...

@@ -45,6 +94,54 @@ })

## Naming your foreign key fields
By naming your foreign key along the lines of `author_id` or `author_fk`, e.g.:
```sql
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 relations `posts`. The default inflector refers to these as
`postsByAuthorId`, `postsByEditorId`, etc. but this plugin exists to simplify
these relations.
To this end, 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'll just call
the relation 'posts' and it will be up to you to add smart comments to handle
the field conflicts.
## Handling field conflicts:
In most cases, the conflict errors will guide you on how to fix these issues:
```
⚠️⚠️⚠️ An error occured when building the schema on watch:
Error: A naming conflict has occurred - two entities have tried to define the same key 'beverages'.
The first entity was:
Backward relation (connection) for constraint "beverages_manufacturer_id_fkey" on table "a"."beverages". To rename this relation with smart comments:
COMMENT ON CONSTRAINT "beverages_manufacturer_id_fkey" ON "a"."beverages" IS E'@foreignFieldName newNameHere';
The second entity was:
Backward relation (connection) for constraint "beverages_distributor_id_fkey" on table "a"."beverages". To rename this relation with smart comments:
COMMENT ON CONSTRAINT "beverages_distributor_id_fkey" ON "a"."beverages" IS E'@foreignFieldName newNameHere';
```
If you have two relations that will result in a conflict (e.g.
`postsByAuthorId` and `postsByEditorId` would both become `posts` with this
`postsByFooId` and `postsByBarId` would both become `posts` with this
plugin) then you will need to rename one of them - you can do so using [smart

@@ -54,4 +151,4 @@ comments](https://www.graphile.org/postgraphile/smart-comments/), e.g.:

```sql
comment on constraint posts_editor_id_fkey on posts is
E'@foreignFieldName editedPosts\n@fieldName editor';
comment on constraint posts_foo_id_fkey on posts is
E'@foreignFieldName fooPosts\n@fieldName editor';
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc