UNPKG

@graphile/persisted-operations

Version:

Persisted operations (aka persisted queries) support for PostGraphile's server

98 lines (97 loc) 4.46 kB
import type { IncomingMessage } from "http"; import type { DocumentNode } from "graphql"; /** * Given a persisted operation hash, return the associated GraphQL operation * document. */ export declare type PersistedOperationGetter = (hash: string) => string; declare module "postgraphile" { interface PostGraphileOptions { /** * This function will be passed a GraphQL request object (normally `{query: * string, variables?: any, operationName?: string, extensions?: any}`, but * in the case of persisted operations it likely won't have a `query` * property), and must extract the hash to use to identify the persisted * operation. For Apollo Client, this might be something like: * `request?.extensions?.persistedQuery?.sha256Hash`; for Relay something * like: `request?.documentId`. */ hashFromPayload?(request: RequestPayload): string; /** * We can read persisted operations from a folder (they must be named * `<hash>.graphql`); this is mostly used for PostGraphile CLI. When used * in this way, the first request for a hash will read the file * synchronously, and then the result will be cached such that the * **synchronous filesystem read** will only impact the first use of that * hash. We periodically scan the folder for new files, requests for hashes * that were not present in our last scan of the folder will be rejected to * mitigate denial of service attacks asking for non-existent hashes. */ persistedOperationsDirectory?: string; /** * An optional string-string key-value object defining the persisted * operations, where the keys are the hashes, and the values are the * operation document strings to use. */ persistedOperations?: { [hash: string]: string; }; /** * If your known persisted operations may change over time, or you'd rather * load them on demand, you may supply this function. Note this function is * both **synchronous** and **performance critical** so you should use * caching to improve performance of any follow-up requests for the same * hash. This function is not suitable for fetching operations from remote * stores (e.g. S3). */ persistedOperationsGetter?: PersistedOperationGetter; /** * There are situations where you may want to allow arbitrary operations * (for example using GraphiQL in development, or allowing an admin to * make arbitrary requests in production) whilst enforcing Persisted * Operations for the application and non-admin users. This function * allows you to determine under which circumstances persisted operations * may be bypassed. * * IMPORTANT: this function must not throw! * * @example * * ``` * app.use(postgraphile(DATABASE_URL, SCHEMAS, { * allowUnpersistedOperation(req) { * return process.env.NODE_ENV === "development" && req.headers.referer.endsWith("/graphiql"); * } * }); * ``` */ allowUnpersistedOperation?: boolean | ((request: IncomingMessage, payload: RequestPayload) => boolean); } } /** * The payload of the request would normally have * query/operationName/variables/extensions; but in persisted operations it may * have something else other than `query`. We've typed a few of the more common * versions, if this doesn't work for you you'll need to cast `payload as any`. */ interface RequestPayload { /** As used by Apollo https://github.com/apollographql/apollo-link-persisted-queries#protocol */ extensions?: { persistedQuery?: { sha256Hash?: string; }; }; /** As used by Relay https://relay.dev/docs/en/persisted-queries#network-layer-changes */ documentId?: string; /** Non-standard. */ id?: string; /** The actual query; we're generally expecting a hash via one of the methods above instead */ query?: string | DocumentNode; /** GraphQL operation variables */ variables?: { [key: string]: unknown; }; /** If the document contains more than one operation; the name of the one to execute. */ operationName?: string; } export {};