graphile-settings
Version:
graphile settings
97 lines (96 loc) • 4.05 kB
TypeScript
import type { GraphileConfig } from 'graphile-config';
/**
* Configuration options for unique lookup behavior.
*/
export interface UniqueLookupOptions {
/**
* If true, disables ALL unique constraint lookups including primary keys.
* Users must use collection queries with filters instead.
* Default: false (primary key lookups are kept)
*/
disableAllUniqueLookups?: boolean;
}
/**
* PrimaryKeyOnlyPlugin - Disables non-primary-key unique constraint lookups for
* BOTH queries AND mutations.
*
* WHY THIS EXISTS:
* PostGraphile v5 creates fields for EVERY unique constraint on a table:
*
* QUERIES (PgRowByUniquePlugin):
* - `user(id)`, `userByEmail(email)`, `userByUsername(username)`
*
* MUTATIONS (PgMutationUpdateDeletePlugin):
* - `updateUser`, `updateUserByEmail`, `updateUserByUsername`
* - `deleteUser`, `deleteUserByEmail`, `deleteUserByUsername`
*
* For code generation (React Query, etc.), this creates unnecessary complexity.
* The same operations can be done using the primary key lookup or filters.
* Standardizing on primary keys reduces the API surface and generated code.
*
* SOURCE CODE REFERENCES:
*
* 1. Query fields (PgRowByUniquePlugin):
* https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgRowByUniquePlugin.ts#L42-L257
*
* The behavior check for queries:
* ```typescript
* const fieldBehaviorScope = "query:resource:single";
* if (!build.behavior.pgResourceUniqueMatches([resource, unique], fieldBehaviorScope)) {
* return memo; // Skip this field
* }
* ```
*
* 2. Mutation fields (PgMutationUpdateDeletePlugin):
* https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgMutationUpdateDeletePlugin.ts
*
* The behavior check for mutations:
* ```typescript
* const constraintMode = `constraint:${mode}`; // "constraint:resource:update" or "constraint:resource:delete"
* ...resource.uniques.filter((unique) => {
* return build.behavior.pgResourceUniqueMatches([resource, unique], constraintMode);
* })
* ```
*
* OUR FIX:
* We use the behavior system's OVERRIDE phase (not inferred) to disable these behaviors.
* The override phase runs AFTER the behavior multiplication/preferences system processes
* behaviors, giving us the final say on what's enabled/disabled.
*
* Behaviors we control:
* - `-single` - Disables query lookups (userByEmail, etc.)
* - `-constraint:resource:update` - Disables updateByX mutations
* - `-constraint:resource:delete` - Disables deleteByX mutations
*
* CONFIGURATION OPTIONS:
*
* 1. `disableAllUniqueLookups: false` (default - PrimaryKeyOnlyPreset):
* - Primary key: query lookup + mutations enabled
* - Non-primary-key: everything disabled
* Result: `user(id)`, `updateUser`, `deleteUser` only
*
* 2. `disableAllUniqueLookups: true` (NoUniqueLookupPreset):
* - Primary key: query lookup DISABLED, mutations ENABLED
* - Non-primary-key: everything disabled
* Result: No query lookups (use filters), but `updateUser`, `deleteUser` still work
*/
/**
* Creates a plugin that controls unique constraint lookup behavior.
*
* @param options - Configuration options
* @param options.disableAllUniqueLookups - If true, disables ALL unique lookups including primary keys
*/
export declare function createUniqueLookupPlugin(options?: UniqueLookupOptions): GraphileConfig.Plugin;
export declare const PrimaryKeyOnlyPlugin: GraphileConfig.Plugin;
export declare const NoUniqueLookupPlugin: GraphileConfig.Plugin;
/**
* Preset that keeps only primary key lookups.
* Use this in your main preset's `extends` array.
*/
export declare const PrimaryKeyOnlyPreset: GraphileConfig.Preset;
/**
* Preset that disables ALL unique lookups (including primary keys).
* Users must use collection queries with filters instead.
* Use this in your main preset's `extends` array.
*/
export declare const NoUniqueLookupPreset: GraphileConfig.Preset;