/** * Copyright (c) 2026 AzerothJS. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /** * A strong entity-tag for `value` within `scope`. * * FNV-1a over the serialized body: an ETag has to change when the bytes change and nothing more, * so a cryptographic hash would only cost time. The length is folded in as a cheap second * dimension against collisions. */ export declare function etagFor(value: unknown, scope: string): string; /** Whether the client's `If-None-Match` still covers `etag`. */ export declare function matchesEtag(ifNoneMatch: string | null, etag: string): boolean; /** * Options for {@link conditional}. `scope` is REQUIRED and it is the security half of the * ETag: the tag hashes scope + body, so two principals with different views of one URL can * never validate each other's cached copy. Omitting a per-principal scope is a cross-tenant * cache leak, which is why there is no default. */ export interface ConditionalOptions { /** * What the response varies by - the account, tenant, or role that produced these rows. * REQUIRED: see the module note. Pass a stable string, not a whole object. */ scope: string; /** Seconds the client may reuse the response without revalidating (default 0). */ maxAge?: number; /** * Whether a SHARED cache (a CDN, a proxy) may store this. Default false, because a scoped * response is per-caller by construction. Set true only for genuinely public data. */ shared?: boolean; } /** * A conditional JSON response: 200 with a validator, or a bodyless 304 when the client's validator * still holds. * * ```ts * app.get('/api/orgs/:org/branches', (context) => * conditional(context.request, { rows }, { scope: String(actor.userId), maxAge: 5 })); * ``` */ export declare function conditional(request: Request, value: unknown, options: ConditionalOptions): Response;