UNPKG

graphile-settings

Version:
97 lines (96 loc) 4.05 kB
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;