@beignet/nuqs
v0.0.56
Published
nuqs integration for Beignet
Downloads
1,175
Maintainers
Readme
@beignet/nuqs
Runtime: Beignet requires Node.js 22.12 or newer. Bun is optional.
nuqs integration for Beignet
[!CAUTION] Beignet is experimental alpha software. The
0.0.xpackage line is for early evaluation, and APIs may change between releases while the framework settles.
This package gives you a thin bridge between contract query params and nuqs URL state.
It does not replace @beignet/react-query. Instead, it helps you keep URL-backed filters aligned with a contract's query shape and then pass that state into rq(contract).queryOptions(...).
Installation
npm install @beignet/nuqs @beignet/core @beignet/react-query nuqs react @tanstack/react-queryIn Next.js App Router, mount the NuqsAdapter once near the root:
import { NuqsAdapter } from "@beignet/nuqs/next/app";
export function Providers({ children }: { children: React.ReactNode }) {
return <NuqsAdapter>{children}</NuqsAdapter>;
}Setup
import { createClient } from "@beignet/core/client";
import { createReactQuery } from "@beignet/react-query";
import { createNuqs } from "@beignet/nuqs";
const client = createClient({ baseUrl: "/api" });
export const rq = createReactQuery(client);
export const nq = createNuqs();Usage
"use client";
import { parseAsInteger, parseAsString } from "nuqs";
import { useQuery } from "@tanstack/react-query";
import { nq, rq } from "@/client";
import { listContacts } from "@/features/contacts/contracts";
const contactsSearch = nq(listContacts).query({
parsers: {
search: parseAsString.withDefault(""),
offset: parseAsInteger.withDefault(0),
},
});
function ContactsPage() {
const [filters, setFilters] = contactsSearch.useState();
const query = useQuery(
contactsSearch.toQueryOptions(rq(listContacts), filters)
);
return null;
}API
createNuqs()
Creates the Beignet nuqs adapter factory.
nq(contract).query({ parsers, ...options })
Creates a contract-aware URL query helper.
parsers: requirednuqsparser map keyed by the contract's query paramshistory,shallow,scroll,urlKeys, etc.: forwarded touseQueryStates
.useState(options?)
Wraps nuqs useQueryStates(parsers, options) with the configured parser map.
.toQuery(state, { omitNullish })
Converts nuqs state into a Beignet query object.
omitNullishdefaults totruenullandundefinedare removed- valid falsy values like
0,false, and""are preserved - parsed
Dateand object values are preserved for the typed client - the contract's explicit query transport determines their API representation:
query.date()sends ISO-8601 values andquery.deepObject(...)sends flat objects as bracketed parameters, such asfilter[owner]=user_1
Nuqs parsers control the browser page URL separately. parseAsJson stores JSON
there; it does not make the Beignet API request use JSON query parameters.
Declare every API query field with defineQueryTransport(...) from
@beignet/core/contracts. The typed client rejects invalid dates, nested
objects, and undeclared transport members with INVALID_QUERY_PARAM.
See the query transport example
for a contract and matching parser map.
.toQueryOptions(rq(contract), state, options?)
Convenience helper that calls rq(contract).queryOptions({ query, ...options }).
When to use this
@beignet/nuqs is a good fit for pages where the URL should reflect search or filter state:
- admin tables
- search screens
- dashboards
- reporting pages
- index/list views with tabs, pagination, or filters
If you just need typed fetching, use @beignet/react-query directly.
