Skip to content

Instantly share code, notes, and snippets.

@giautm
Last active April 23, 2018 16:47
Show Gist options
  • Save giautm/c9e298a21e1efa45523965e10bc310ae to your computer and use it in GitHub Desktop.
Save giautm/c9e298a21e1efa45523965e10bc310ae to your computer and use it in GitHub Desktop.
directive @relayID(
type: String,
) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
type User {
id: ID! @relayID
email: String!
name: String!
}
const {
defaultFieldResolver,
GraphQLList,
GraphQLNonNull,
GraphQLScalarType,
} = require('graphql');
const { SchemaDirectiveVisitor } = require('graphql-tools');
const {
fromGlobalId,
toGlobalId,
} = require('graphql-relay');
class RelayIdDirective extends SchemaDirectiveVisitor {
visitInputFieldDefinition(field, details) {
if (!this.args.type) {
throw new Error('Argument "type" is required for the Input field on '
+ '"' + details.objectType + '"');
}
field.type = this.wrapType(field.type,
this.args.type);
}
visitArgumentDefinition(arg, details) {
if (!this.args.type) {
throw new Error('Argument "type" is required for the argument "'
+ arg.name + '" on "' + details.field.name + '"');
}
arg.type = this.wrapType(arg.type,
this.args.type);
}
visitFieldDefinition(field, details) {
field.type = this.wrapType(field.type,
this.args.type || details.objectType);
}
wrapType(base, typeName) {
if (base instanceof GraphQLNonNull) {
return new GraphQLNonNull(
this.wrapType(base.ofType, typeName));
} else if (base instanceof GraphQLList) {
return new GraphQLList(
this.wrapType(base.ofType, typeName));
} else if (base instanceof GraphQLScalarType) {
return new GraphQLGlobalID(base, typeName);
}
throw new Error(`Not a scalar type: ${base}`);
}
}
class GraphQLGlobalID extends GraphQLScalarType {
constructor(base, typeName) {
super({
name: `GraphQLGlobalID`,
serialize(value) {
value = base.serialize(value);
return toGlobalId(typeName, value);
},
parseValue(value) {
const { type, id } = fromGlobalId(value);
if (type !== typeName) {
throw new Error(`RelayID: Invalid type ${type}, expected: ${typeName}`);
}
return base.parseValue(id);
},
parseLiteral(ast) {
const { type, id } = fromGlobalId(ast.value);
if (type !== typeName) {
throw new Error(`RelayID: Invalid type ${type}, expected: ${typeName}`);
}
return id;
}
});
}
}
module.exports = { RelayIdDirective };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment