HTTP
@flattype/http adds Flat Notation to an existing API without breaking anyone. A response is re-encoded only when the request says Accept: text/x-flat, and Vary: Accept keeps caches correct.
Server
ts
import { flatExpress, flatFastify, flatHono, negotiate } from "@flattype/http";
expressApp.use(flatExpress()); // Express: res.json(...)
await fastifyApp.register(flatFastify); // Fastify: object replies
honoApp.use(flatHono()); // Hono: c.json(...)
return negotiate(request, Response.json(data)); // Bun, Deno, Next.js route handlers, WorkersClient
ts
import { createClient, flatAxios, flatFetch, streamRows } from "@flattype/http";
const user = await flatFetch("/api/users/7", { model: User }); // typed, throws HttpError on 4xx/5xx
const api = createClient({ baseURL: "https://api.example.com/v1", headers: { authorization } });
const page = await api.get("/users", { query: { page: 2 } });
await api.post("/users", { name: "Chen" }); // JSON request body
const axiosApi = flatAxios(axios.create({ baseURL: "/api" })); // axios: response.data is decoded
for await (const { path, index, value } of streamRows("/api/export")) { // rows while still downloading
table.append(value);
}A JSON-only server works with every client helper: the response is just read as JSON.
Mixed versions. Clients from 1.14 send Accept: text/x-flat; version=1.1, and the servers write Flat Notation 1.1 only for them. A client on an older version asks without a version and gets 1.0 text, which it can read, so the server and its clients can be upgraded in any order.