Last active
June 1, 2018 11:56
-
-
Save miraris/23d05a7ba4d0cd7215d711f61db19a45 to your computer and use it in GitHub Desktop.
A poor man’s Postgraphile args validator plugin implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The pagination args validator | |
* @param {number} opts | |
*/ | |
function validator (opts) { | |
const options = opts || {} | |
const min = options.min || 1 | |
const max = options.max || 100 | |
return (args) => { | |
if (!args.first && !args.last) { | |
throw new Error('Must specify a `first` or `last` range') | |
} | |
// Validate conflicting args are not present | |
if (args.first && args.last) { | |
throw new Error('Can not use both `first` and `last` together') | |
} | |
if (args.before && args.after) { | |
throw new Error('Can not use both `before` and `after` together') | |
} | |
// Validate requested limits do not exceed allowable range | |
if (args.first > max || args.last > max) { | |
throw new Error(`Can not request more than ${max} records at a time`) | |
} | |
if (args.first < min || args.last < min) { | |
throw new Error(`Can not request less than ${min} records at a time`) | |
} | |
} | |
} | |
/** | |
* The pagination args validator plugin | |
* @param builder | |
*/ | |
module.exports = function PageArgsValidator (builder) { | |
builder.hook( | |
'GraphQLObjectType:fields:field', ( | |
field, { | |
pgSql: sql | |
}, { | |
scope: { | |
isPgFieldConnection, | |
isPgFieldSimpleCollection, | |
pgIntrospection: table, | |
pgFieldIntrospection, // smart comments | |
fieldName | |
} | |
} | |
) => { | |
if ( | |
!(isPgFieldConnection || isPgFieldSimpleCollection) | |
) { | |
return field | |
} | |
const defaultResolver = obj => obj[fieldName] | |
const { | |
resolve: oldResolve = defaultResolver, | |
...rest | |
} = field | |
return { | |
...rest, | |
// resolver which wraps the old resolver | |
async resolve (...resolveParams) { | |
const RESOLVE_ARGS_INDEX = 1 | |
const validate = validator({ | |
min: 1, | |
max: pgFieldIntrospection.tags.paginationCap || 20 | |
}) | |
// validate the args on the connection field | |
validate(resolveParams[RESOLVE_ARGS_INDEX]) | |
// call and return the old resolver | |
return oldResolve(...resolveParams) | |
} | |
} | |
} | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment