Skip to content

Commit

Permalink
feat(postgraphql) add extendedErrors option
Browse files Browse the repository at this point in the history
  • Loading branch information
zopf committed Jul 13, 2017
1 parent e62d7af commit e29380f
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 2 deletions.
2 changes: 2 additions & 0 deletions docs/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ Arguments include:
- `jwtRole`: 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.
- `jwtPgTypeIdentifier`: 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`.
- `watchPg`: When true, PostGraphQL 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 PostGraphQL 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.
- `showErrorStack`: 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).
- `extendedErrors`: Extends the error response with additional details from the Postgres error. Can be any combination of `['hint', 'detail', 'errcode']`. Default is `[]`.
- `disableQueryLog`: Turns off GraphQL query logging. By default PostGraphQL will log every GraphQL query it processes along with some other information. Set this to `true` to disable that feature.
- `enableCors`: 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.
- `exportJsonSchemaPath`: 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.
Expand Down
43 changes: 43 additions & 0 deletions src/graphql/utils/extendedFormatError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { GraphQLError } from 'graphql/error'

/**
* Given a GraphQLError, format it according to the rules described by the
* Response Format, Errors section of the GraphQL Specification, plus a few
* additional fields relevant to postgres errors, including HINT, DETAIL,
* and ERRCODE.
*/
export function extendedFormatError(error: GraphQLError, fields: Array<String>): GraphQLFormattedErrorExtended {
if (!error) {
throw new Error('Received null or undefined error.')
}
const originalError = error.originalError as GraphQLErrorExtended
fields = fields.map(field => field.toLowerCase())
return {
message: error.message,
locations: error.locations,
path: error.path,
hint: originalError && fields.indexOf('hint') > -1 ? originalError.hint : undefined,
detail: originalError && fields.indexOf('detail') > -1 ? originalError.detail : undefined,
errcode: originalError && fields.indexOf('errcode') > -1 ? originalError.code : undefined,
}
}

export type GraphQLFormattedErrorExtended = {
message: string,
locations: Array<GraphQLErrorLocation> | void,
path: Array<string | number> | void,
hint: string | void,
detail: string | void,
errcode: string | void,
}

export type GraphQLErrorLocation = {
line: number,
column: number,
}

export type GraphQLErrorExtended = GraphQLError & {
hint: string,
detail: string,
code: string,
}
2 changes: 2 additions & 0 deletions src/postgraphql/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ const {
exportSchemaJson: exportJsonSchemaPath,
exportSchemaGraphql: exportGqlSchemaPath,
showErrorStack,
extendedErrors = [],
bodySizeLimit,
// tslint:disable-next-line no-any
} = program as any
Expand Down Expand Up @@ -122,6 +123,7 @@ const server = createServer(postgraphql(pgConfig, schemas, {
pgDefaultRole,
watchPg,
showErrorStack,
extendedErrors,
disableQueryLog: false,
enableCors,
exportJsonSchemaPath,
Expand Down
4 changes: 4 additions & 0 deletions src/postgraphql/http/createPostGraphQLHttpRequestHandler.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export default function createPostGraphQLHttpRequestHandler (config: {
// in JSON. Helpful for debugging.
showErrorStack?: boolean | 'json',

// Enables reporting of additional details from errors that are thrown in postgres.
// Additional details include the HINT, DETAIL, and ERRCODE.
extendedErrors?: Array<string>,

// Disables the query log. Whenever a GraphQL query is about to be executed, it
// will first be logged to the console.
disableQueryLog?: boolean,
Expand Down
7 changes: 5 additions & 2 deletions src/postgraphql/http/createPostGraphQLHttpRequestHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
formatError as defaultFormatError,
print as printGraphql,
} from 'graphql'
import { extendedFormatError } from '../../graphql/utils/extendedFormatError'
import { $$pgClient } from '../../postgres/inventory/pgClientFromContext'
import renderGraphiQL from './renderGraphiQL'
import debugPgClient from './debugPgClient'
Expand Down Expand Up @@ -78,8 +79,10 @@ export default function createPostGraphQLHttpRequestHandler (options) {
// Formats an error using the default GraphQL `formatError` function, and
// custom formatting using some other options.
const formatError = error => {
// Get the default formatted error object.
const formattedError = defaultFormatError(error)
// Get the appropriate formatted error object, including any extended error
// fields if the user wants them.
const formattedError = options.extendedErrors && options.extendedErrors.length ?
extendedFormatError(error, options.extendedErrors) : defaultFormatError(error)

// If the user wants to see the error’s stack, let’s add it to the
// formatted error.
Expand Down
1 change: 1 addition & 0 deletions src/postgraphql/postgraphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type PostGraphQLOptions = {
jwtPgTypeIdentifier?: string,
watchPg?: boolean,
showErrorStack?: boolean,
extendedErrors?: Array<string>,
disableQueryLog?: boolean,
disableDefaultMutations?: boolean,
enableCors?: boolean,
Expand Down

0 comments on commit e29380f

Please sign in to comment.