| name | graphile-v5-minimal |
| description | Configure PostGraphile v5 default plugins and features. Use when asked to "configure default plugins", "customize base schema", "keep id as id", "configure Node/Relay features", or when setting up PostGraphile v5 for your specific needs. |
| compatibility | PostGraphile v5+, graphile-build, graphile-build-pg |
| metadata | {"author":"constructive-io","version":"1.0.0"} |
PostGraphile v5 Default Plugin Configuration
Configure PostGraphile v5's default plugins and features to match your project's needs.
Official Documentation
When to Apply
Use this skill when:
- Setting up PostGraphile v5 for a new project
- Deciding which default features to enable or disable
- Configuring how
id columns are exposed in your schema
- Understanding what the default Amber preset includes
Understanding Default Features
PostGraphile v5's Amber preset includes several features by default:
- Global Object Identification (Node interface) - Relay-compatible
node(id: ID!) query
- Node ID encoding - Base64-encoded global IDs for all types
id column renaming - Renames id columns to rowId to avoid conflict with global id
nodeId field - Adds nodeId field to all types
These features are useful for Relay clients but can be disabled if not needed.
Configuration Options
Option 1: Keep All Default Features (Relay-Compatible)
Use the default Amber preset as-is:
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber';
const preset: GraphileConfig.Preset = {
extends: [PostGraphileAmberPreset],
};
Option 2: Disable Global Object Identification
If you don't need Relay compatibility, disable the Node-related plugins:
import type { GraphileConfig } from 'graphile-config';
import { defaultPreset as graphileBuildPreset } from 'graphile-build';
import { defaultPreset as graphileBuildPgPreset } from 'graphile-build-pg';
const NODE_PLUGINS = [
'NodePlugin',
'AddNodeInterfaceToSuitableTypesPlugin',
'NodeIdCodecBase64JSONPlugin',
'NodeIdCodecPipeStringPlugin',
'RegisterQueryNodePlugin',
'NodeAccessorPlugin',
'PgNodeIdAttributesPlugin',
'PgTableNodePlugin',
];
export const CustomPreset: GraphileConfig.Preset = {
extends: [graphileBuildPreset, graphileBuildPgPreset],
disablePlugins: NODE_PLUGINS,
};
Plugin Reference
| Plugin | What it does | When to disable |
|---|
NodePlugin | Adds Node interface and node() query | Not using Relay |
AddNodeInterfaceToSuitableTypesPlugin | Makes types implement Node | Not using Relay |
NodeIdCodecBase64JSONPlugin | Encodes node IDs as base64 JSON | Not using Relay |
NodeIdCodecPipeStringPlugin | Alternative node ID encoding | Not using Relay |
RegisterQueryNodePlugin | Registers node(id) query | Not using Relay |
NodeAccessorPlugin | Adds nodeId field to types | Not using Relay |
PgNodeIdAttributesPlugin | Handles node ID for PG tables | Not using Relay |
PgTableNodePlugin | Makes PG tables implement Node | Not using Relay |
Keeping id Columns as id
By default, PostGraphile renames id columns to rowId to avoid conflict with the global id field. If you've disabled the Node plugins and want to keep id as id, override the _attributeName inflector:
export const KeepIdPlugin: GraphileConfig.Plugin = {
name: 'KeepIdPlugin',
version: '1.0.0',
inflection: {
replace: {
_attributeName(_previous, _options, details) {
const attribute = details.codec.attributes[details.attributeName];
const name = attribute?.extensions?.tags?.name || details.attributeName;
return this.coerceToGraphQLName(name);
},
},
},
};
Source Code References
Why id gets renamed (PgAttributesPlugin)
_attributeName(options, { attributeName, codec, skipRowId }) {
const attribute = codec.attributes[attributeName];
const name = attribute.extensions?.tags?.name || attributeName;
const nonconflictName =
!skipRowId && name.toLowerCase() === "id" && !codec.isAnonymous
? "row_id"
: name;
return this.coerceToGraphQLName(nonconflictName);
}
Source: https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgAttributesPlugin.ts#L289-L298
Complete MinimalPreset
import type { GraphileConfig } from 'graphile-config';
import { defaultPreset as graphileBuildPreset } from 'graphile-build';
import { defaultPreset as graphileBuildPgPreset } from 'graphile-build-pg';
const NODE_PLUGINS_TO_DISABLE = [
'NodePlugin',
'AddNodeInterfaceToSuitableTypesPlugin',
'NodeIdCodecBase64JSONPlugin',
'NodeIdCodecPipeStringPlugin',
'RegisterQueryNodePlugin',
'NodeAccessorPlugin',
'PgNodeIdAttributesPlugin',
'PgTableNodePlugin',
];
const KeepIdPlugin: GraphileConfig.Plugin = {
name: 'KeepIdPlugin',
version: '1.0.0',
inflection: {
replace: {
_attributeName(_previous, _options, details) {
const attribute = details.codec.attributes[details.attributeName];
const name = attribute?.extensions?.tags?.name || details.attributeName;
return this.coerceToGraphQLName(name);
},
},
},
};
export const MinimalPreset: GraphileConfig.Preset = {
extends: [graphileBuildPreset, graphileBuildPgPreset],
disablePlugins: NODE_PLUGINS_TO_DISABLE,
plugins: [KeepIdPlugin],
};
Before and After
Before (with Node/Relay)
type User {
nodeId: ID!
rowId: UUID!
name: String!
}
type Query {
node(id: ID!): Node
userByNodeId(nodeId: ID!): User
user(rowId: UUID!): User
}
After (MinimalPreset)
type User {
id: UUID!
name: String!
}
type Query {
user(id: UUID!): User
}
Usage
import { postgraphile } from 'postgraphile';
import { makePgService } from 'postgraphile/adaptors/pg';
import { MinimalPreset } from './minimal-preset';
const preset: GraphileConfig.Preset = {
extends: [MinimalPreset],
pgServices: [
makePgService({
connectionString: process.env.DATABASE_URL,
schemas: ['public'],
}),
],
};
const pgl = postgraphile(preset);
Troubleshooting
| Issue | Solution |
|---|
id still renamed to rowId | Add the KeepIdPlugin inflector override |
nodeId field still appears | Ensure all Node plugins are in disablePlugins |
| Type errors | Install graphile-build and graphile-build-pg types |
| Missing mutations | Node plugins don't affect mutations, check other plugins |
References