Parse, build, and content-negotiate the Accept-Query HTTP header (RFC 10008) — the response header a server uses to advertise which query-format media types it accepts on a QUERY request.
Zero dependencies. Fully typed. Isomorphic (Node, Deno, Bun, browsers, edge).
import{negotiateQuery}from"@danmat/accept-query";// The server told us what it accepts; we pick the best format we can produce.constformat=negotiateQuery(response.headers.get("accept-query")??"",["application/json","application/sql",]);// → "application/sql"RFC 10008 introduces the QUERY method — a safe, idempotent request with a body. To tell clients how to shape that body, a server answers with an Accept-Query response header:
Accept-Query: application/sql;q=0.9, application/json;q=0.4, application/graphqlIt's the Accept grammar (media ranges + q weights + parameters), but for query payloads. This library gives you the three things you actually need for it: parse it, negotiate against it, and build it (for servers).
npm install @danmat/accept-queryParses a header value into media ranges, sorted by quality then specificity. Parsing is lenient — malformed entries are skipped, quoted parameter values are respected, and types/subtypes/param keys are lowercased.
parseAcceptQuery("application/sql;q=0.8, application/json");// [// { type: "application", subtype: "json", quality: 1, params: {}},// { type: "application", subtype: "sql", quality: 0.8, params: {}},// ]Given the server's Accept-Query value and the media types your client can produce (in your preference order), returns the best one to send — or null if the server accepts none of them. Wildcards (application/*, */*) and q=0 exclusions are handled per HTTP content-negotiation rules; the most specific matching range decides an offer's quality.
negotiateQuery("application/sql;q=0.9, application/json;q=0.4",["application/json","application/sql",]);// → "application/sql" (higher server quality wins)negotiateQuery("application/json",["text/csv"]);// → null (server accepts none of ours)Builds a header value from strings and/or structured ranges — for servers advertising what they accept. Omits q when it's 1, trims trailing zeros, and quotes non-token parameter values.
formatAcceptQuery(["application/json",{type: "application",subtype: "sql",quality: 0.8},]);// → "application/json, application/sql;q=0.8"interfaceMediaRange{type: string;// lowercased, "*" for wildcardsubtype: string;// lowercased, "*" for wildcardquality: number;// 0–1, defaults to 1params: Record<string,string>;// non-q params, lowercased keys}AcceptQueryError is thrown only for programmer misuse (e.g. formatAcceptQuery on a range missing its type/subtype). Parsing never throws — it's deliberately liberal in what it accepts.
@danmat/query-fetch— client for the QUERY method.@danmat/accept-query— parse/build/negotiate theAccept-Queryheader (you are here).@danmat/query-cache— body-aware response caching.@danmat/query-server— server-side request validation & negotiation.
MIT © Dan Matthew