Bidirectional URL state management hook that automatically generates GraphQL-compatible variables from URL search parameters by parsing a GraphQL `DocumentNode` AST, optionally enriching it via schema introspection, and flattening nested input types into flat URL params. ## Key Components | Export | Type | Description | |--------|------|-------------| | `useQueryParams` | Hook | Core hook — parses query AST, fetches schema, syncs URL ↔ GraphQL variables | | `UseQueryParamsOptions` | Interface | Configuration: defaults, introspection endpoint/headers, param mapping, debug | | `UseQueryParamsReturn` | Interface | Hook return shape: `variables`, `params`, `schema`, setters, state flags | | `applyParamMapping` | Function (internal) | Remaps flattened schema keys using a custom `paramMapping` record | ### Initialization Flow ```mermaid graph TD A["Parse Query AST"] --> B{"skipIntrospection?"} B -- No --> C["Fetch GraphQL Schema"] B -- Yes --> D["Flatten Schema"] C --> D D --> E["Apply paramMapping"] E --> F["Merge Defaults"] F --> G["setSchema / setIsReady"] ``` ## Usage Example ```typescript import { gql, useQuery } from '@apollo/client' import { useQueryParams } from './use-query-params' const LOGS_QUERY = gql` query GetLogs($search: String, $filter: LogFilterInput) { logs(search: $search, filter: $filter) { id message severity } } ` function LogsPage() { const { variables, setParam, setParams, clearParams, resetParams, isReady } = useQueryParams(LOGS_QUERY, { defaultValues: { filter: { severity: ['info'] } }, introspectionEndpoint: 'https://api.example.com/graphql', introspectionHeaders: { Authorization: 'Bearer token' }, debug: true, }) const { data } = useQuery(LOGS_QUERY, { variables, skip: !isReady }) return ( <> {/* URL: /logs?search=error&severity=critical */} {/* variables: { search: 'error', filter: { severity: ['critical'] } } */} setParam('search', e.target.value)} /> ) } ``` > **Note:** Schema introspection results are cached via `introspector` — subsequent calls with the same endpoint skip the network fetch. Set `skipIntrospection: true` if your input types are shallow (no nested objects) to avoid the extra request.