From 43b7326db4e50f59a4511cab539e3d03b25917bb Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 7 Sep 2017 15:38:39 +0700 Subject: [PATCH] Cleanup and apply pr suggestions --- .gitignore | 1 - graph/errorHandler.js | 28 ++------- graph/hooks.js | 34 +---------- graph/resolvers/root_mutation.js | 60 ++++++++----------- graph/utils.js | 46 ++++++++++++++ .../server/perspective.js | 10 ++-- 6 files changed, 85 insertions(+), 94 deletions(-) create mode 100644 graph/utils.js diff --git a/.gitignore b/.gitignore index c3c17fac3..405a0248a 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,3 @@ plugins/* !plugins/talk-plugin-toxic-comments **/node_modules/* -story.html diff --git a/graph/errorHandler.js b/graph/errorHandler.js index 066ae3319..d7176f16a 100644 --- a/graph/errorHandler.js +++ b/graph/errorHandler.js @@ -1,28 +1,8 @@ -const { - GraphQLObjectType, - GraphQLInterfaceType -} = require('graphql'); +const {forEachField} = require('./utils'); const {maskErrors} = require('graphql-errors'); const errors = require('../errors'); const {Error: {ValidationError}} = require('mongoose'); -// This function is pretty much copied verbatim from the graphql-tools repo: -// https://github.com/apollographql/graphql-tools/blob/b12973c86e00be209d04af0184780998056051c4/src/schemaGenerator.ts#L180-L194 -const forEachField = (schema, fn) => { - const typeMap = schema.getTypeMap(); - Object.keys(typeMap).forEach((typeName) => { - const type = typeMap[typeName]; - - if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) { - const fields = type.getFields(); - Object.keys(fields).forEach((fieldName) => { - const field = fields[fieldName]; - fn(field, typeName, fieldName); - }); - } - }); -}; - // If an APIError happens in a mutation, then respond with `{errors: Array}` // according to the schema. const decorateWithMutationErrorHandler = (field) => { @@ -47,7 +27,11 @@ const decorateWithMutationErrorHandler = (field) => { }; }; -// Masks errors during production and handle mutation errors inside the schema. +/** + * Masks errors during production and handle mutation errors inside the schema. + * @param {GraphQLSchema} schema the schema to decorate + * @return {void} + */ const decorateWithErrorHandler = (schema) => { forEachField(schema, (field, typeName) => { diff --git a/graph/hooks.js b/graph/hooks.js index 7f6be7feb..3a34be0bb 100644 --- a/graph/hooks.js +++ b/graph/hooks.js @@ -1,7 +1,4 @@ -const { - GraphQLObjectType, - GraphQLInterfaceType -} = require('graphql'); +const {forEachField} = require('./utils'); const debug = require('debug')('talk:graph:schema'); const Joi = require('joi'); @@ -26,33 +23,6 @@ const defaultResolveFn = (source, args, context, {fieldName}) => { } }; -// This function is pretty much copied verbatim from the graphql-tools repo: -// https://github.com/apollographql/graphql-tools/blob/b12973c86e00be209d04af0184780998056051c4/src/schemaGenerator.ts#L180-L194 -// With the small alteration that we look for the `resolveType` function on the -// schema so we can wrap post hooks around it to provide additional resolve -// points. -const forEachField = (schema, fn) => { - const typeMap = schema.getTypeMap(); - Object.keys(typeMap).forEach((typeName) => { - const type = typeMap[typeName]; - - if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) { - - // Here we capture the change to extract the resolve type. We pass this - // with the `isResolveType = true` to introduce the specific beheviour. - if ('resolveType' in type) { - fn(type, typeName, '__resolveType', true); - } - - const fields = type.getFields(); - Object.keys(fields).forEach((fieldName) => { - const field = fields[fieldName]; - fn(field, typeName, fieldName); - }); - } - }); -}; - /** * Decorates the field with the post resolvers (if available) and attaches a * default type in the form of `Default${typeName}`. @@ -239,6 +209,8 @@ const decorateWithHooks = (schema, hooks) => forEachField(schema, (field, typeNa return result; }, result); }; +}, { + includeResolveType: true, }); module.exports = { diff --git a/graph/resolvers/root_mutation.js b/graph/resolvers/root_mutation.js index 437d2ab5b..21e6c4787 100644 --- a/graph/resolvers/root_mutation.js +++ b/graph/resolvers/root_mutation.js @@ -1,43 +1,35 @@ const RootMutation = { - async createComment(_, {input}, {mutators: {Comment}}) { - return { - comment: await Comment.create(input), - }; - }, - async editComment(_, {id, asset_id, edit: {body}}, {mutators: {Comment}}) { - return { - comment: await Comment.edit({id, asset_id, edit: {body}}), - }; - }, - async createFlag(_, {flag: {item_id, item_type, reason, message}}, {mutators: {Action}}) { - return { - flag: Action.create({item_id, item_type, action_type: 'FLAG', group_id: reason, metadata: {message}}), - }; - }, - async createDontAgree(_, {dontagree: {item_id, item_type, reason, message}}, {mutators: {Action}}) { - return { - dontagree: await Action.create({item_id, item_type, action_type: 'DONTAGREE', group_id: reason, metadata: {message}}), - }; - }, - async deleteAction(_, {id}, {mutators: {Action}}) { + createComment: async (_, {input}, {mutators: {Comment}}) => ({ + comment: await Comment.create(input), + }), + editComment: async (_, {id, asset_id, edit: {body}}, {mutators: {Comment}}) => ({ + comment: await Comment.edit({id, asset_id, edit: {body}}), + }), + createFlag: async (_, {flag: {item_id, item_type, reason, message}}, {mutators: {Action}}) => ({ + flag: Action.create({item_id, item_type, action_type: 'FLAG', group_id: reason, metadata: {message}}), + }), + createDontAgree: async (_, {dontagree: {item_id, item_type, reason, message}}, {mutators: {Action}}) => ({ + dontagree: await Action.create({item_id, item_type, action_type: 'DONTAGREE', group_id: reason, metadata: {message}}), + }), + deleteAction: async (_, {id}, {mutators: {Action}}) => { await Action.delete({id}); }, - async setUserStatus(_, {id, status}, {mutators: {User}}) { + setUserStatus: async (_, {id, status}, {mutators: {User}}) => { await User.setUserStatus({id, status}); }, - async suspendUser(_, {input: {id, message, until}}, {mutators: {User}}) { + suspendUser: async (_, {input: {id, message, until}}, {mutators: {User}}) => { await User.suspendUser({id, message, until}); }, - async rejectUsername(_, {input: {id, message}}, {mutators: {User}}) { + rejectUsername: async (_, {input: {id, message}}, {mutators: {User}}) => { await User.rejectUsername({id, message}); }, - async ignoreUser(_, {id}, {mutators: {User}}) { + ignoreUser: async (_, {id}, {mutators: {User}}) => { await User.ignoreUser({id}); }, - async stopIgnoringUser(_, {id}, {mutators: {User}}) { + stopIgnoringUser: async (_, {id}, {mutators: {User}}) => { await User.stopIgnoringUser({id}); }, - async setCommentStatus(_, {id, status}, {mutators: {Comment}, pubsub}) { + setCommentStatus: async (_, {id, status}, {mutators: {Comment}, pubsub}) => { const comment = await Comment.setStatus({id, status}); if (status === 'ACCEPTED') { @@ -49,18 +41,16 @@ const RootMutation = { pubsub.publish('commentRejected', comment); } }, - async addTag(_, {tag}, {mutators: {Tag}}) { + addTag: async (_, {tag}, {mutators: {Tag}}) => { await Tag.add(tag); }, - async removeTag(_, {tag}, {mutators: {Tag}}) { + removeTag: async (_, {tag}, {mutators: {Tag}}) => { await Tag.remove(tag); }, - async createToken(_, {input}, {mutators: {Token}}) { - return { - token: await Token.create(input), - }; - }, - async revokeToken(_, {input}, {mutators: {Token}}) { + createToken: async (_, {input}, {mutators: {Token}}) => ({ + token: await Token.create(input), + }), + revokeToken: async (_, {input}, {mutators: {Token}}) => { await Token.revoke(input); } }; diff --git a/graph/utils.js b/graph/utils.js new file mode 100644 index 000000000..d170a2d83 --- /dev/null +++ b/graph/utils.js @@ -0,0 +1,46 @@ +const { + GraphQLObjectType, + GraphQLInterfaceType +} = require('graphql'); + +/** + * Iterates over each field in a schema. + * This function is pretty much copied verbatim from the graphql-tools repo: + * https://github.com/apollographql/graphql-tools/blob/b12973c86e00be209d04af0184780998056051c4/src/schemaGenerator.ts#L180-L194 + * With the small alteration that we look for the `resolveType` function on the + * schema so we can wrap post hooks around it to provide additional resolve + * points. (Only when `options.includeResolveType` is set to true). + * + * @param {GraphQLSchema} schema the schema to iterate over + * @param {function} fn callback to call on each field + * @param {object} [options] options + * @param {boolean} [options.includeResolveType] include resolveType during iteration + * @return {void} + */ +const forEachField = (schema, fn, options = {}) => { + const {includeResolveType = false} = options; + + const typeMap = schema.getTypeMap(); + Object.keys(typeMap).forEach((typeName) => { + const type = typeMap[typeName]; + + if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) { + + // Here we capture the change to extract the resolve type. We pass this + // with the `isResolveType = true` to introduce the specific beheviour. + if (includeResolveType && 'resolveType' in type) { + fn(type, typeName, '__resolveType', true); + } + + const fields = type.getFields(); + Object.keys(fields).forEach((fieldName) => { + const field = fields[fieldName]; + fn(field, typeName, fieldName); + }); + } + }); +}; + +module.exports = { + forEachField, +}; diff --git a/plugins/talk-plugin-toxic-comments/server/perspective.js b/plugins/talk-plugin-toxic-comments/server/perspective.js index 5db5a5334..0b5cd6b05 100644 --- a/plugins/talk-plugin-toxic-comments/server/perspective.js +++ b/plugins/talk-plugin-toxic-comments/server/perspective.js @@ -3,8 +3,8 @@ const {API_ENDPOINT, API_KEY, TOXICITY_THRESHOLD} = require ('./config'); /** * Get scores from the perspective api - * @param {string} text to be anaylized - * @return {object} object containing toxicity scores + * @param {string} text text to be anaylized + * @return {object} object containing toxicity scores */ async function getScores(text) { const response = await fetch(`${API_ENDPOINT}/comments:analyze?key=${API_KEY}`, { @@ -38,8 +38,8 @@ async function getScores(text) { /** * Get toxicity probability - * @param {object} scores as returned by `getScores` - * @return {number} toxicity probability from 0 - 1.0 + * @param {object} scores scores as returned by `getScores` + * @return {number} toxicity probability from 0 - 1.0 */ function getProbability(scores) { return scores.SEVERE_TOXICITY.summaryScore; @@ -47,7 +47,7 @@ function getProbability(scores) { /** * isToxic determines if given probabilty or scores meets the toxicity threshold. - * @param {object|number} scores or probability + * @param {object|number} scoresOrProbability scores or probability * @return {boolean} */ function isToxic(scoresOrProbability) {