/** * `@nifrajs/core/binary` - a route that returns bytes, and says so in its type. * * A download route had no way to be part of the contract. Returning a raw `Response` is the only way * to send bytes, and a raw `Response` is exactly what the typed client cannot describe - so the route * needed a `// nifra-expect raw-response` pragma to quiet the advisory, and its caller got no type at * all. One whole category of endpoint sat outside the thing the framework is otherwise strict about. * * import { bytes } from "@nifrajs/core/binary" * * app.get("/invoice.pdf", async (c) => bytes(await render(c.params.id), { * type: "application/pdf", * filename: "invoice.pdf", * })) * * The client types `data` as `Blob` for that route, and gets the bytes intact. * * The brand is a phantom: `bytes()` returns a real `Response` and nothing is added to it at runtime. * It exists so the type carries a fact the value cannot - that these bytes are the payload rather than * a serialization accident - which is what lets `Jsonify` answer `Blob` instead of trying to describe * a `Response`'s properties. */ /** * Marker on a binary response's TYPE. A unique symbol rather than a string key, so no ordinary object * can satisfy it by accident, and declared required rather than optional - an optional brand is * satisfied by every type that lacks it, which would make the check match `Response` itself. */ declare const NIFRA_BYTES: unique symbol; /** Runtime marker paired with the type-only brand so clients do not have to guess from media type. */ export declare const NIFRA_BINARY_HEADER = "x-nifra-binary"; /** A `Response` a route declared as binary. `Jsonify` maps this to `Blob`. */ export type BinaryResponse = Response & { readonly [NIFRA_BYTES]: true; }; /** * Marker on a raw response's TYPE carrying the payload it serializes to. Like {@link NIFRA_BYTES} it is * a unique symbol declared *required*, so an ordinary `Response` cannot satisfy it by accident - an * optional brand would be met by every `Response`, and every raw-response route would wrongly claim a * typed body. */ declare const NIFRA_RAW: unique symbol; /** * A raw `Response` whose JSON body a route declared as `T`. Returning a bare `Response` drops a route * out of the typed contract - the client reads its `data` as `never`, since a `Response`'s own * properties say nothing about the payload. {@link raw} brands the `Response` with the shape it * actually serializes, so `Jsonify` answers `Jsonify` and the route stays inside the typed client. * The brand is a phantom: nothing is added at runtime. */ export type RawResponse = Response & { readonly [NIFRA_RAW]: T; }; /** What can be sent as bytes without being re-encoded on the way out. */ export type BinaryBody = ArrayBuffer | ArrayBufferView | Blob | ReadableStream; export interface BytesOptions { /** Media type. Defaults to `application/octet-stream`, the honest answer for unlabelled bytes. */ readonly type?: string; /** * Offer the body as a download under this name. * * A filename derived from user data is the ordinary case - an upload's original name, a document * title - so this has to survive anything a person can type. Two things follow, and both are tested: * a `"` or a newline cannot end the value and write further parameters, and a non-Latin-1 name is * encoded rather than thrown on. */ readonly filename?: string; readonly status?: number; readonly headers?: Readonly>; } export declare function bytes(body: BinaryBody, options?: BytesOptions): BinaryResponse; /** * Brand a hand-built `Response` with the payload type `T` its body serializes to, so a route that must * return a `Response` directly still types `res.data` as `Jsonify` on the client instead of `never`. * Use it for the endpoints that build their own `Response` - a token minted by a third-party SDK, a * redirect that also carries a JSON body, a hand-tuned cache header - but should still be part of the * contract. Purely a type assertion: the `Response` is returned unchanged, nothing is added at runtime. * * app.get("/livekit-token", async (c) => * raw<{ token: string }>(Response.json({ token: await mint(c) }))) * // client: res.data is typed { token: string } * * The payload `T` is the type the body serializes to - it is not validated, so it is a promise the route * must keep. For bytes prefer {@link bytes}, which also sets the media-type headers. */ export declare function raw(response: Response): RawResponse; export {}; //# sourceMappingURL=binary.d.ts.map