-
-
Notifications
You must be signed in to change notification settings - Fork 575
Plugin: replacing PG GraphQL types
Matt Bretl edited this page Oct 2, 2018
·
3 revisions
Postgraphile will replace certain types with custom types. Often times you might want to provide an alternate type of your own. This plugin allows you to hook into any Postgres Type by Type Code (pg_type
's oid
column).
Thanks to @dwelch2344
https://gitter.im/graphile/postgraphile?at=5aca78ff2b9dfdbc3a6c0c10
// helper function to delegate to a type if a mapped value is provided
const curryOriginal = (original, mapping) => {
return (typeId, typeModifier) => {
if (mapping[typeId]) {
let gqlType = mapping[typeId]
gqlType = gqlType instanceof Function ? gqlType() : gqlType
return gqlType
}
return original(typeId, typeModifier)
}
}
/**
* mapping[typeId] = GraphQL Type
*
* To see all typeIds => SELECT pt.oid, pt.typname, pt.typcategory FROM pg_type pt ORDER BY pt.oid
*/
export const PgTypeReplacerPlugin = mapping => {
const fn = function PgTypeReplacer(builder) {
builder.hook('build', build =>
Object.assign({}, build, {
pgGetGqlTypeByTypeIdAndModifier: curryOriginal(
build.pgGetGqlTypeByTypeIdAndModifier,
mapping
),
pgGetGqlInputTypeByTypeIdAndModifier: curryOriginal(
build.pgGetGqlInputTypeByTypeIdAndModifier,
mapping
)
})
)
}
fn.displayName = `PgTypeReplacerPlugin`
return fn
}
export const SplicePgTypeReplacer = (
originalPlugins,
mapping,
options = {}
) => {
let plugins = [...originalPlugins]
const idx = plugins.findIndex(e => e.name === 'PgTypesPlugin')
if (idx < 0) {
throw new Error('Could not find PgTypesPlugin')
}
const part = plugins.splice(0, idx + 1)
plugins = [...part, ...[PgTypeReplacerPlugin(mapping)], ...plugins]
if (options.debug) {
plugins.forEach((e, i) => {
console.warn(`${i} ${e.name}`)
})
}
return plugins
}
With usage as:
const {
createPostGraphileSchema,
withPostGraphileContext
} = require('postgraphile')
const { defaultPlugins: corePlugins } = require('graphile-build')
const { defaultPlugins: pgPlugins } = require('graphile-build-pg')
const { GraphQLInt, GraphQLFloat } = require('graphql')
const { SplicePgTypeReplacer } = require('./graphile/plugins/PgTypeReplacer')
//...
const initializeQuery = async ({
db,
schema: schemaName,
jwtSecret,
defaultRole,
jwtType
}) => {
const mapping = {
'20': GraphQLInt,
'1700': GraphQLFloat
}
const plugins = SplicePgTypeReplacer([...corePlugins, ...pgPlugins], mapping)
const graphileSchema = await createPostGraphileSchema(db, schemaName, {
pgDefaultRole: defaultRole,
jwtSecret,
jwtPgTypeIdentifier: jwtType,
replaceAllPlugins: plugins
})
//... use schema with `withPostGraphileContext`
or middleware usage as:
const express = require("express");
const { postgraphile } = require("postgraphile");
const { defaultPlugins: corePlugins } = require('graphile-build');
const { defaultPlugins: pgPlugins } = require('graphile-build-pg');
const { GraphQLInt, GraphQLFloat } = require('graphql');
const { SplicePgTypeReplacer } = require('./graphile/plugins/PgTypeReplacer');
const mapping = {
'20': GraphQLInt,
'1700': GraphQLFloat
};
const plugins = SplicePgTypeReplacer([...corePlugins, ...pgPlugins], mapping);
const app = express();
app.use(
postgraphile(pgConfig, [schemaName], {
replaceAllPlugins: plugins,
})
);
app.listen(5000);