Cleanup and apply pr suggestions

This commit is contained in:
Chi Vinh Le
2017-09-07 15:38:39 +07:00
parent b1b3db51a6
commit 43b7326db4
6 changed files with 85 additions and 94 deletions
-1
View File
@@ -42,4 +42,3 @@ plugins/*
!plugins/talk-plugin-toxic-comments
**/node_modules/*
story.html
+6 -22
View File
@@ -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) => {
+3 -31
View File
@@ -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 = {
+25 -35
View File
@@ -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);
}
};
+46
View File
@@ -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,
};
@@ -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) {