Skip to content

Instantly share code, notes, and snippets.

@devuxer
Last active June 5, 2018 17:26
Show Gist options
  • Save devuxer/0a514e8aa688bead5de7b6d5e28bc749 to your computer and use it in GitHub Desktop.
Save devuxer/0a514e8aa688bead5de7b6d5e28bc749 to your computer and use it in GitHub Desktop.
postgraphile typings file proposal
declare module "postgraphile" {
import { GraphQLError, ExecutionResult } from "graphql";
import { Pool, PoolConfig } from "pg";
import { IncomingMessage, ServerResponse, Server } from "http";
import * as jwt from "jsonwebtoken";
import { createPostGraphileSchema, watchPostGraphileSchema } from "postgraphile-core";
export type mixed = {} | string | number | boolean | undefined | null;
export type PluginHookFn = <T>(hookName: string, argument: T, context?: {}) => T;
export type AddFlagFn = (optionString: string, description: string, parse?: (option: string) => mixed) => AddFlagFn;
export type HookFn<T> = (arg: T, context: {}) => T;
export type GraphQLErrorExtended = GraphQLError & {
hint: string;
detail: string;
code: string;
};
export type WithPostGraphileContextFn = (
options: {
pgPool: Pool;
jwtToken?: string;
jwtSecret?: string;
jwtAudiences?: Array<string>;
jwtRole: Array<string>;
jwtVerifyOptions?: jwt.VerifyOptions;
pgDefaultRole?: string;
pgSettings?: { [key: string]: mixed };
},
callback: (context: mixed) => Promise<ExecutionResult>
) => Promise<ExecutionResult>;
export type PostGraphileOptions = {
/**
* When true, PostGraphile will watch your database schemas and re-create the
* GraphQL API whenever your schema changes, notifying you as it does. This
* feature requires an event trigger to be added to the database by a
* superuser. When enabled PostGraphile will try to add this trigger, if you
* did not connect as a superuser you will get a warning and the trigger
* won’t be added.
*/
watchPg?: boolean;
/**
* The default Postgres role to use. If no role was provided in a provided
* JWT token, this role will be used.
*/
pgDefaultRole?: string;
/**
* Setting this to `true` enables dynamic JSON which will allow you to use
* any JSON as input and get any arbitrary JSON as output. By default JSON
* types are just a JSON string.
*/
dynamicJson?: boolean;
/**
* If none of your `RETURNS SETOF compound_type` functions mix NULLs with the
* results then you may set this true to reduce the nullables in the GraphQL
* schema
*/
setofFunctionsContainNulls?: boolean;
/**
* Enables classic ids for Relay support. Instead of using the field name
* `nodeId` for globally unique ids, PostGraphile will instead use the field
* name `id` for its globally unique ids. This means that table `id` columns
* will also get renamed to `rowId`.
*/
classicIds?: boolean;
/**
* Setting this to `true` will prevent the creation of the default mutation
* types & fields. Database mutation will only be possible through Postgres
* functions.
*/
disableDefaultMutations?: boolean;
/**
* Enables adding a `stack` field to the error response. Can be either the
* boolean `true` (which results in a single stack string) or the string
* `json` (which causes the stack to become an array with elements for each
* line of the stack).
*/
showErrorStack?: boolean;
/**
* Enables ability to modify errors before sending them down to the client
* optionally can send down custom responses
* (@middlewareOnly)
*/
handleErrors?: ((
errors: Array<GraphQLError>,
req: IncomingMessage,
res: ServerResponse
) => Array<GraphQLErrorExtended>);
/**
* Extends the error response with additional details from the Postgres
* error. Can be any combination of `['hint', 'detail', 'errcode']`.
* Default is `[]`.
*/
extendedErrors?: Array<string>;
/**
* an array of [Graphile Build](/graphile-build/plugins/) plugins to load
* after the default plugins
*/
appendPlugins?: Array<(builder: mixed) => {}>;
/**
* an array of [Graphile Build](/graphile-build/plugins/) plugins to load
* before the default plugins (you probably don't want this)
*/
prependPlugins?: Array<(builder: mixed) => {}>;
/**
* the full array of [Graphile Build](/graphile-build/plugins/) plugins to
* use for schema generation (you almost definitely don't want this!)
*/
replaceAllPlugins?: Array<(builder: mixed) => {}>;
/**
* A file path string. Reads cached values from local cache file to improve
* startup time (you may want to do this in production).
*/
readCache?: string;
/**
* A file path string. Writes computed values to local cache file so startup
* can be faster (do this during the build phase).
*/
writeCache?: string;
/**
* Enables saving the detected schema, in JSON format, to the given location.
* The directories must exist already, if the file exists it will be
* overwritten.
* (@middlewareOnly)
*/
exportJsonSchemaPath?: string;
/**
* Enables saving the detected schema, in GraphQL schema format, to the given
* location. The directories must exist already, if the file exists it will
* be overwritten.
* (@middlewareOnly)
*/
exportGqlSchemaPath?: string;
/**
* The endpoint the GraphQL executer will listen on. Defaults to `/graphql`.
* (@middlewareOnly)
*/
graphqlRoute?: string;
/**
* The endpoint the GraphiQL query interface will listen on (**NOTE:**
* GraphiQL will not be enabled unless the `graphiql` option is set to
* `true`). Defaults to `/graphiql`.
* (@middlewareOnly)
*/
graphiqlRoute?: string;
/**
* Set this to `true` to enable the GraphiQL interface.
* (@middlewareOnly)
*/
graphiql?: boolean;
/**
* Enables some generous CORS settings for the GraphQL endpoint. There are
* some costs associated when enabling this, if at all possible try to put
* your API behind a reverse proxy.
* (@middlewareOnly)
*/
enableCors?: boolean;
/**
* Set the maximum size of JSON bodies that can be parsed (default 100kB).
* The size can be given as a human-readable string, such as '200kB' or '5MB'
* (case insensitive).
* (@middlewareOnly)
*/
bodySizeLimit?: string;
/**
* [Experimental] Enable the middleware to process multiple GraphQL queries
* in one request
* (@middlewareOnly)
*/
enableQueryBatching?: string;
/**
* The secret for your JSON web tokens. This will be used to verify tokens in
* the `Authorization` header, and signing JWT tokens you return in
* procedures.
*/
jwtSecret?: string;
/**
* Options with which to perform JWT verification - see
* https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback
* (@middlewareOnly)
*/
jwtVerifyOptions?: jwt.VerifyOptions;
/**
* A comma separated list of strings that give a path in the jwt from which
* to extract the postgres role. If none is provided it will use the key
* `role` on the root of the jwt.
* (@middlewareOnly)
*/
jwtRole?: Array<string>;
/**
* The Postgres type identifier for the compound type which will be signed as
* a JWT token if ever found as the return type of a procedure. Can be of the
* form: `my_schema.my_type`. You may use quotes as needed:
* `"my-special-schema".my_type`.
*/
jwtPgTypeIdentifier?: string;
/**
* The audiences to use when verifing the JWT token. If not set the audience
* will be `['postgraphile']`.
* (@middlewareOnly)
*/
jwtAudiences?: Array<string>;
/**
* Some one-to-one relations were previously detected as one-to-many - should
* we export 'only' the old relation shapes, both new and old but mark the
* old ones as 'deprecated', or 'omit' the old relation shapes entirely
*/
legacyRelations?: "only" | "deprecated" | "omit";
/**
* ONLY use this option if you require the v3 typenames 'Json' and 'Uuid'
* over 'JSON' and 'UUID'
*/
legacyJsonUuid?: boolean;
/**
* Turns off GraphQL query logging. By default PostGraphile will log every
* GraphQL query it processes along with some other information. Set this to
* `true` to disable that feature.
* (@middlewareOnly)
*/
disableQueryLog?: boolean;
/**
* A plain object specifying custom config values to set in the PostgreSQL
* transaction (accessed via `current_setting('my.custom.setting')`) or a
* function which will return the same (or a Promise to the same) based on
* the incoming web request (e.g. to extract session data)
* (@middlewareOnly)
*/
pgSettings?: { [key: string]: mixed } | ((req: IncomingMessage) => Promise<{ [key: string]: mixed }>);
/**
* Some graphile-build plugins may need additional information available on
* the `context` argument to the resolver - you can use this function to
* provide such information based on the incoming request - you can even use
* this to change the response [experimental], e.g. setting cookies
* (@middlewareOnly)
*/
additionalGraphQLContextFromRequest?: (req: IncomingMessage, res: ServerResponse) => Promise<{}>;
/**
* [experimental] Plugin hook function, enables functionality within
* PostGraphile to be expanded with plugins. Generate with
* `makePluginHook(plugins)` passing a list of plugin objects.
* (@middlewareOnly)
*/
pluginHook?: PluginHookFn;
};
export interface HttpRequestHandler {
(req: IncomingMessage, res: ServerResponse, next?: (error?: mixed) => void): void;
(ctx: { req: IncomingMessage; res: ServerResponse }, next: () => void): Promise<void>;
}
export function postgraphile(
poolOrConfig?: Pool | PoolConfig | string,
schema?: string | Array<string>,
options?: PostGraphileOptions
): HttpRequestHandler;
export function postgraphile(
poolOrConfig?: Pool | PoolConfig | string,
options?: PostGraphileOptions
): HttpRequestHandler;
export interface PostGraphilePlugin {
pluginHook?: HookFn<PluginHookFn>;
"cli:flags:add:standard"?: HookFn<AddFlagFn>;
"cli:flags:add:schema"?: HookFn<AddFlagFn>;
"cli:flags:add:errorHandling"?: HookFn<AddFlagFn>;
"cli:flags:add:plugins"?: HookFn<AddFlagFn>;
"cli:flags:add:noServer"?: HookFn<AddFlagFn>;
"cli:flags:add:webserver"?: HookFn<AddFlagFn>;
"cli:flags:add:jwt"?: HookFn<AddFlagFn>;
"cli:flags:add"?: HookFn<AddFlagFn>;
"cli:flags:add:deprecated"?: HookFn<AddFlagFn>;
"cli:flags:add:workarounds"?: HookFn<AddFlagFn>;
"cli:server:middleware"?: HookFn<HttpRequestHandler>;
"cli:server:created"?: HookFn<Server>;
"postgraphile:options"?: HookFn<PostGraphileOptions>;
withPostGraphileContext?: HookFn<WithPostGraphileContextFn>;
}
export function makePluginHook(plugins: Array<PostGraphilePlugin>): PluginHookFn;
type WithPostGraphileContextFn = (
options: {
pgPool: Pool;
jwtToken?: string | undefined;
jwtSecret?: string | undefined;
jwtAudiences?: string[] | undefined;
jwtRole: string[];
jwtVerifyOptions?: jwt.VerifyOptions | undefined;
pgDefaultRole?: string | undefined;
pgSettings?:
| {
[key: string]: mixed;
}
| undefined;
},
callback: (context: mixed) => Promise<ExecutionResult>
) => Promise<ExecutionResult>;
const withPostGraphileContext: WithPostGraphileContextFn;
export {
createPostGraphileSchema,
watchPostGraphileSchema,
withPostGraphileContext,
// Backwards compatability
postgraphile as postgraphql,
createPostGraphileSchema as createPostGraphQLSchema,
watchPostGraphileSchema as watchPostGraphQLSchema,
withPostGraphileContext as withPostGraphQLContext
};
}
@sjmcdowall
Copy link

I'm a fairly new programmer @ Typescript -- and am working on a new Postgraphile server implementation etc. I am just wondering how I could use your wonderful ts bindings in my project so I don't keep getting errors about postgraphile not having any bindings, etc. :) Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment