{"id":13254,"library":"graphile-utils","title":"Graphile Utilities","description":"graphile-utils is a pivotal utility package within the Graphile ecosystem, designed to facilitate the creation and enhancement of plugins for GraphQL schemas built with Graphile Build. It is an integral part of the Graphile v5 \"Crystal\" suite, with the current stable version being 5.0.1, reflecting ongoing active development and frequent updates across its monorepo. This package differentiates itself by providing specialized helpers like `extendSchema` for dynamically adding or modifying types within a GraphQL schema, and a custom `gql` tagged template literal that supports dynamic field names and raw value embedding, an advanced feature not found in standard `graphql-tag`. Additionally, it offers utilities such as `changeNullability` for schema field adjustments and `processSchema` for post-build schema manipulation. It is indispensable for developers seeking to extensively customize and extend their Graphile-powered GraphQL APIs, moving beyond the default outputs of tools like PostGraphile.","status":"active","version":"5.0.1","language":"javascript","source_language":"en","source_url":"https://github.com/graphile/crystal","tags":["javascript","graphile","graphql","engine","plugin","build","extension","utils","utilities","typescript"],"install":[{"cmd":"npm install graphile-utils","lang":"bash","label":"npm"},{"cmd":"yarn add graphile-utils","lang":"bash","label":"yarn"},{"cmd":"pnpm add graphile-utils","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core data planning layer for PostgreSQL, essential for database interactions within Graphile v5 plugins.","package":"@dataplan/pg","optional":false},{"reason":"The Graphile 'fast' execution engine, providing core GraphQL execution capabilities for v5.","package":"grafast","optional":false},{"reason":"The foundational schema building toolkit that graphile-utils plugins extend and interact with.","package":"graphile-build","optional":false},{"reason":"PostgreSQL-specific build extensions for graphile-build, used when building a schema from a PostgreSQL database.","package":"graphile-build-pg","optional":false},{"reason":"Configuration system for the Graphile v5 ecosystem, defining how plugins are loaded and applied.","package":"graphile-config","optional":false},{"reason":"The primary GraphQL.js library, providing core GraphQL types and utilities.","package":"graphql","optional":false},{"reason":"A utility for safely evaluating JavaScript code strings, used internally by some Graphile components.","package":"tamedevil","optional":false}],"imports":[{"note":"Graphile v5 and its utilities are primarily ESM-first. While some CJS compatibility exists, direct ESM imports are preferred and safer.","wrong":"const { extendSchema } = require('graphile-utils');","symbol":"extendSchema","correct":"import { extendSchema } from 'graphile-utils';"},{"note":"The `gql` export from `graphile-utils` is distinct from `graphql-tag` and includes advanced interpolation features like `embed` for dynamic schema generation within Graphile plugins.","wrong":"import gql from 'graphql-tag';","symbol":"gql","correct":"import { gql } from 'graphile-utils';"},{"note":"Used as a plugin to modify field nullability; direct ESM import is standard.","wrong":"const changeNullability = require('graphile-utils').changeNullability;","symbol":"changeNullability","correct":"import { changeNullability } from 'graphile-utils';"}],"quickstart":{"code":"import { extendSchema } from 'graphile-utils';\nimport type { GraphileConfig } from 'graphile-config';\n\nconst MyRandomPlugin: GraphileConfig.Plugin = extendSchema((build) => {\n  const {\n    grafast: { constant, lambda },\n  } = build;\n  return {\n    typeDefs: /* GraphQL */ `\n      type Random {\n        float: Float!\n        number(min: Int!, max: Int!): Int!\n      }\n      extend type Query {\n        random: Random\n      }\n    `,\n    objects: {\n      Query: {\n        plans: {\n          random() {\n            return constant({});\n          },\n        },\n      },\n      Random: {\n        plans: {\n          float() {\n            return lambda(null, () => Math.random());\n          },\n          number(_parent, { $min, $max }) {\n            return lambda(\n              [$min, $max],\n              ([min, max]) => min + Math.floor(Math.random() * (max - min + 1)),\n            );\n          },\n        },\n      },\n    },\n  };\n});\n\n// To use this plugin, you would typically add it to your GraphileConfig:\n// const config: GraphileConfig.ResolvedPreset = {\n//   extends: [require('postgraphile/presets/v4')],\n//   plugins: [MyRandomPlugin],\n// };\n// export default config;\n\nconsole.log('MyRandomPlugin defined successfully, ready for GraphileConfig.');","lang":"typescript","description":"This quickstart demonstrates how to create a custom Graphile plugin using `extendSchema` to add a new `Random` type and field to the `Query` type, providing random float and integer generation."},"warnings":[{"fix":"Upgrade your Node.js environment to version 22 or newer to ensure compatibility with Graphile v5 packages.","message":"`graphile-utils` is part of the Graphile v5 ecosystem, which mandates Node.js version 22 or higher. Deployments on older Node.js versions will fail.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Consult the official Graphile v5 migration guides and documentation. Specifically, review changes to the `build` object, `grafast` integration, and plugin API.","message":"Migration from Graphile v4 to v5 (Crystal) involves significant architectural changes. Plugins built with v4 `graphile-utils` will require substantial refactoring due to changes in the build object, plan system (Grafast), and configuration structure.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Familiarize yourself with the `graphile-utils` `gql` documentation. Do not assume `graphql-tag` patterns will work without modification, especially for dynamic schema generation.","message":"The `gql` tagged template literal provided by `graphile-utils` is a powerful, custom implementation distinct from `graphql-tag`. It supports advanced features like dynamic field naming and `embed` for injecting raw values, which means it will not behave identically to `graphql-tag`.","severity":"gotcha","affected_versions":">=5.0.0"},{"fix":"Ensure you are using `graphile-utils@5.0.1` (or higher) and `pg-sql2@5.0.1` (or higher) to access these specific SQL constants. If on an older RC, update your package versions.","message":"Early release candidates of Graphile v5 removed or changed access paths for certain `pg-sql2` constants like `sql.TRUE`, `sql.FALSE`, and `sql.NULL`. While `graphile-utils@5.0.1` and `pg-sql2@5.0.1` have restored these, older v5 RCs might lack them.","severity":"breaking","affected_versions":">=5.0.0-rc.0 <5.0.1"},{"fix":"Prefer using `build.sql` directly for SQL query building within your plugins to ensure future compatibility and align with the v5 conventions.","message":"For backward compatibility with PostGraphile v4 presets in v5, `build.pgSql` was re-added as an alias for `build.sql`. This implies that `build.sql` is the canonical reference in v5, and reliance on `build.pgSql` directly may be deprecated in future versions or only exist for specific presets.","severity":"breaking","affected_versions":">=5.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Install all peer dependencies listed in `graphile-utils`'s `package.json`, e.g., `npm install @dataplan/pg grafast graphile-build graphile-build-pg graphile-config graphql tamedevil`.","cause":"A peer dependency of `graphile-utils` is missing from your project's `node_modules`.","error":"Error: Cannot find module '@dataplan/pg' or its corresponding type declarations."},{"fix":"Ensure your project is configured for ESM and use `import { extendSchema } from 'graphile-utils';`. If using CommonJS, verify your environment supports it or adjust imports accordingly, though ESM is preferred for Graphile v5.","cause":"Attempting to use `extendSchema` with CommonJS `require()` syntax in an ESM-only context, or incorrect named import.","error":"TypeError: extendSchema is not a function"},{"fix":"When interpolating complex objects or non-string values into `gql`, use the `embed` helper provided by `graphile-utils` (e.g., `gql`...${embed(someValue)}...). For dynamic field names or types, ensure correct string interpolation.","cause":"Incorrectly interpolating values into the `gql` tagged template literal from `graphile-utils`, especially when expecting behavior similar to `graphql-tag`.","error":"Error: Invalid 'gql' interpolation: expected a GraphQL AST node or a string, received [object Object]"},{"fix":"Ensure your `processSchema` implementation adheres to the expected plugin signature, accepting the `schema` object as its first argument, as shown in the Graphile documentation.","cause":"`processSchema` was not correctly implemented as a plugin or its argument signature is incorrect.","error":"Error: The plugin passed to processSchema must be a function that accepts 'schema' as an argument."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null}