Server
Adapter
Web-standard `Request` and `URL` helpers for request-scoped decoding.
- Package
- @queryweave/server
- Runtime
- Any web-standard server, edge, or worker runtime
- Depends on
- @queryweave/core
- Framework required
- No
What it owns
Section titled “What it owns”- Decoding the query of a
Requestor aURLwith a model. - Building a canonical query string, or a complete
URL, from typed state. - Producing a read-only
QuerySourcescoped to one request.
What it does not own
Section titled “What it does not own”Navigation. A request is read once and then ends; there is no history to push to. That is why this
package produces a QuerySource rather than a QueryAdapter — the capability is absent from the
type, not present and throwing.
Request-scoped source — reads once, never navigates
Request-scoped source — reads once, never navigates
- Request (incoming)
- QuerySource (read-only)
- QueryModel.decode() (typed result)
Request → QuerySource. QuerySource → QueryModel.decode().
Install
Section titled “Install”pnpm add @queryweave/core @queryweave/serverNo Node built-in is used anywhere in the package, so it runs unchanged on Node.js, Deno, Bun,
Cloudflare Workers, and any other runtime with Request and URL.
Example
Section titled “Example”import { readRequestQuery } from "@queryweave/server";
export async function handler(request: Request): Promise<Response> { const result = readRequestQuery(request, products); const values = result.ok ? result.value : { ...products.defaults(), ...result.partial };
return Response.json({ products: await search(values), issues: result.issues, });}The merge on the second line is the standard pattern: render something useful, and keep the issues for diagnostics.
Reading
Section titled “Reading”readUrlQuery(url, model); // string | URLreadRequestQuery(request, model); // Request
await readUrlQueryAsync(url, model); // when validation is asynchronousawait readRequestQueryAsync(request, model);A relative URL string is accepted. It is resolved against relativeUrlBase
(http://queryweave.invalid), which is exported so tests can assert against it. Only the query is
ever read, so the base is irrelevant to the result.
const result = readUrlQuery("/products?search=vue&page=2", products);
result.ok; // trueif (result.ok) result.value; // { search: "vue", page: 2, ...defaults }A request-scoped source
Section titled “A request-scoped source”import { createRequestQuerySource } from "@queryweave/server";
const source = createRequestQuerySource(request);
source.read(); // "?page=2"source.request; // the original RequestUse this when a helper wants a QuerySource rather than a decoded result — for example, code that
should work with any read-only environment.
Building links
Section titled “Building links”import { createQueryUrl, encodeQuery } from "@queryweave/server";
encodeQuery(products, { search: "vue", page: 2, sort: "created_at", status: "all" });// "search=vue&page=2"
createQueryUrl("https://example.com/products?utm_source=email", products, values);// https://example.com/products?search=vue&page=2&utm_source=emailencodeQuery returns the canonical query string with no leading ?. createQueryUrl returns a
URL, and it is the one place outside the runtime that preserves unmanaged keys: managed keys are
written first, and everything the model does not declare follows in its original order.
Server mode in the simulator
Section titled “Server mode in the simulator”History—
- Request URL
- decode
- typed result
- canonical URL
A request is read once. There is no history to move through, so navigation is absent.
Type a query, press Enter.
Typed state
{
"page": 1,
"sort": "created_at",
"status": "all"
}Canonical URL
Valid/productsEdge cases
Section titled “Edge cases”- An absolute URL is used as given. A string that parses as absolute is not re-based.
- A malformed query does not throw. It decodes with issues, exactly as in the browser.
createQueryUrlmutates nothing. It copies the base URL before writing tosearch.- Repeated unmanaged keys keep their order and multiplicity.
How it is tested
Section titled “How it is tested”tests/server/server.test.ts covers reading, encoding, and link building, including unmanaged-key
preservation and the relative-base fallback. The universal consumer fixture installs the packed
archive and runs the same helpers outside the workspace.