Provides URL state management for REST APIs by syncing typed parameters to/from URL search params without requiring GraphQL schema introspection. ## Key Components ### Types & Interfaces - **`ParamConfig`** — Defines type, default value, and required flag for a single URL parameter - **`ParamSchema`** — Record mapping parameter names to their `ParamConfig` - **`InferParamsFromSchema`** — Utility type that infers the typed output shape from a schema - **`InferInputParamsFromSchema`** — More permissive input variant allowing `null`/`undefined` - **`UseApiParamsReturn`** — Full return type including `params`, `setParam`, `setParams`, `clearParams`, `resetParams`, and `urlSearchParams` ### Functions - **`defineParamSchema`** — Identity helper that preserves literal types on schema definitions - **`useApiParams`** — Primary hook; reads, coerces, and syncs URL search params using a manual schema - **`useContentStable`** *(internal)* — Stabilizes object references across renders using JSON key comparison - **`reuseIfShallowEqual`** *(internal)* — Prevents array reference churn when content is unchanged ## Usage Example ```typescript import { defineParamSchema, useApiParams } from './use-api-params' const schema = defineParamSchema({ search: { type: 'string', default: '' }, page: { type: 'number', default: 1 }, tags: { type: 'array', default: [] }, }) function ProductList() { const { params, setParam, setParams, urlSearchParams } = useApiParams(schema) // params is fully typed: { search: string; page: number; tags: string[] } useEffect(() => { fetch(`/api/products?${urlSearchParams}`) }, [urlSearchParams]) return ( setParam('search', e.target.value)} /> ) } ``` > **Reference stability:** Internal memoization ensures `params`, array fields, and setter callbacks keep stable references across renders unless the URL or schema content actually changes — safe to use directly in `useEffect` dependency arrays.