merge with master after huge coral-embed-stream refactor

This commit is contained in:
Benjamin Goering
2017-05-03 19:19:03 -07:00
120 changed files with 3708 additions and 2551 deletions
+8 -1
View File
@@ -1,5 +1,6 @@
const loaders = require('./loaders');
const mutators = require('./mutators');
const uuid = require('uuid');
const plugins = require('../services/plugins');
const debug = require('debug')('talk:graph:context');
@@ -31,7 +32,10 @@ const decorateContextPlugins = (context, contextPlugins) => contextPlugins.reduc
* Stores the request context.
*/
class Context {
constructor({user = null}) {
constructor({user = null}, pubsub) {
// Generate a new context id for the request.
this.id = uuid.v4();
// Load the current logged in user to `user`, otherwise this'll be null.
if (user) {
@@ -46,6 +50,9 @@ class Context {
// Decorate the plugin context.
this.plugins = decorateContextPlugins(this, contextPlugins);
// Bind the publish/subscribe to the context.
this.pubsub = pubsub;
}
}
+5 -2
View File
@@ -1,5 +1,7 @@
const schema = require('./schema');
const Context = require('./context');
const pubsub = require('./pubsub');
const {createSubscriptionManager} = require('./subscriptions');
module.exports = {
createGraphOptions: (req) => ({
@@ -9,6 +11,7 @@ module.exports = {
// Load in the new context here, this'll create the loaders + mutators for
// the lifespan of this request.
context: new Context(req)
})
context: new Context(req, pubsub)
}),
createSubscriptionManager
};
+7 -1
View File
@@ -16,7 +16,7 @@ const Wordlist = require('../../services/wordlist');
* @param {String} [status='NONE'] the status of the new comment
* @return {Promise} resolves to the created comment
*/
const createComment = ({user, loaders: {Comments}}, {body, asset_id, parent_id = null, tags = []}, status = 'NONE') => {
const createComment = ({user, loaders: {Comments}, pubsub}, {body, asset_id, parent_id = null, tags = []}, status = 'NONE') => {
// Building array of tags
tags = tags.map(tag => ({name: tag}));
@@ -47,6 +47,12 @@ const createComment = ({user, loaders: {Comments}}, {body, asset_id, parent_id =
Comments.parentCountByAssetID.incr(asset_id);
}
Comments.countByAssetID.incr(asset_id);
if (pubsub) {
// Publish the newly added comment via the subscription.
pubsub.publish('commentAdded', comment);
}
}
return comment;
+5
View File
@@ -0,0 +1,5 @@
const {RedisPubSub} = require('graphql-redis-subscriptions');
const {connectionOptions} = require('../services/redis');
module.exports = new RedisPubSub(connectionOptions);
-2
View File
@@ -5,8 +5,6 @@ const Action = {
return 'DontAgreeAction';
case 'FLAG':
return 'FlagAction';
case 'LIKE':
return 'LikeAction';
}
},
-2
View File
@@ -3,8 +3,6 @@ const ActionSummary = {
switch (action_type) {
case 'FLAG':
return 'FlagActionSummary';
case 'LIKE':
return 'LikeActionSummary';
case 'DONTAGREE':
return 'DontAgreeActionSummary';
}
+4
View File
@@ -5,6 +5,10 @@ module.exports = new GraphQLScalarType({
name: 'Date',
description: 'Date represented as an ISO8601 string',
serialize(value) {
if (typeof value === 'string') {
return value;
}
return value.toISOString();
},
parseValue(value) {
+2 -2
View File
@@ -12,10 +12,10 @@ const FlagAction = require('./flag_action');
const DontAgreeAction = require('./dont_agree_action');
const DontAgreeActionSummary = require('./dont_agree_action_summary');
const GenericUserError = require('./generic_user_error');
const LikeAction = require('./like_action');
const RootMutation = require('./root_mutation');
const RootQuery = require('./root_query');
const Settings = require('./settings');
const Subscription = require('./subscription');
const UserError = require('./user_error');
const User = require('./user');
const ValidationUserError = require('./validation_user_error');
@@ -35,10 +35,10 @@ let resolvers = {
DontAgreeAction,
DontAgreeActionSummary,
GenericUserError,
LikeAction,
RootMutation,
RootQuery,
Settings,
Subscription,
UserError,
User,
ValidationUserError,
-5
View File
@@ -1,5 +0,0 @@
const LikeAction = {
};
module.exports = LikeAction;
-3
View File
@@ -8,9 +8,6 @@ const RootMutation = {
editComment(_, args, {mutators: {Comment}}) {
return wrapResponse('comment')(Comment.editComment(args));
},
createLike(_, {like: {item_id, item_type}}, {mutators: {Action}}) {
return wrapResponse('like')(Action.create({item_id, item_type, action_type: 'LIKE'}));
},
createFlag(_, {flag: {item_id, item_type, reason, message}}, {mutators: {Action}}) {
return wrapResponse('flag')(Action.create({item_id, item_type, action_type: 'FLAG', group_id: reason, metadata: {message}}));
},
+7
View File
@@ -0,0 +1,7 @@
const Subscription = {
commentAdded(comment) {
return comment;
}
};
module.exports = Subscription;
+60
View File
@@ -0,0 +1,60 @@
const {SubscriptionManager} = require('graphql-subscriptions');
const {SubscriptionServer} = require('subscriptions-transport-ws');
const _ = require('lodash');
const pubsub = require('./pubsub');
const schema = require('./schema');
const Context = require('./context');
const plugins = require('../services/plugins');
const {deserializeUser} = require('../services/subscriptions');
// Core setup functions
let setupFunctions = {
commentAdded: (options, args) => ({
commentAdded: {
filter: (comment) => comment.asset_id === args.asset_id
},
}),
};
/**
* Plugin support requires that we merge in existing setupFunctions with our new
* plugin based ones. This allows plugins to extend existing setupFunctions as well
* as provide new ones.
*/
setupFunctions = plugins.get('server', 'setupFunctions').reduce((acc, {setupFunctions}) => {
return _.merge(acc, setupFunctions);
}, setupFunctions);
/**
* This creates a new subscription manager.
*/
const createSubscriptionManager = (server) => new SubscriptionServer({
subscriptionManager: new SubscriptionManager({
schema,
pubsub,
setupFunctions,
}),
onSubscribe: (parsedMessage, baseParams, connection) => {
// Attach the context per request.
baseParams.context = () => deserializeUser(connection.upgradeReq)
.then((req) => new Context(req, pubsub))
.catch((err) => {
console.error(err);
return new Context({}, pubsub);
});
return baseParams;
}
}, {
server,
path: '/api/v1/live'
});
module.exports = {
createSubscriptionManager
};
+9 -62
View File
@@ -103,9 +103,6 @@ enum COMMENT_STATUS {
# The types of action there are as enum's.
enum ACTION_TYPE {
# Represents a LikeAction.
LIKE
# Represents a FlagAction.
FLAG
@@ -303,41 +300,6 @@ type FlagAssetActionSummary implements AssetActionSummary {
actionableItemCount: Int
}
# A summary of counts related to all the Likes on an Asset.
type LikeAssetActionSummary implements AssetActionSummary {
# Number of likes associated with actionable types on this this Asset.
actionCount: Int
# Number of unique actionable types that are referenced by the likes.
actionableItemCount: Int
}
# LikeAction is used by users who "like" a specific entity.
type LikeAction implements Action {
# The ID of the action.
id: ID!
# The author of the action.
user: User
# The time when the Action was updated.
updated_at: Date
# The time when the Action was created.
created_at: Date
}
# LikeActionSummary is counts the amount of "likes" that a specific entity has.
type LikeActionSummary implements ActionSummary {
# The count of likes against the parent entity.
count: Int!
current_user: LikeAction
}
# A FLAG action that contains flag metadata.
type FlagAction implements Action {
@@ -549,9 +511,6 @@ enum USER_STATUS {
# Metrics for the assets.
enum ASSET_METRICS_SORT {
# Represents a LikeAction.
LIKE
# Represents a FlagAction.
FLAG
@@ -637,15 +596,6 @@ enum ACTION_ITEM_TYPE {
USERS
}
input CreateLikeInput {
# The item's id for which we are to create a like.
item_id: ID!
# The type of the item for which we are to create the like.
item_type: ACTION_ITEM_TYPE!
}
enum TAG_TYPE {
STAFF
}
@@ -666,15 +616,6 @@ input CreateCommentInput {
}
type CreateLikeResponse implements Response {
# The like that was created.
like: LikeAction
# An array of errors relating to the mutation that occurred.
errors: [UserError]
}
input CreateFlagInput {
# The item's id for which we are to create a flag.
@@ -811,9 +752,6 @@ type RootMutation {
# Creates a comment on the asset.
createComment(comment: CreateCommentInput!): CreateCommentResponse
# Creates a like on an entity.
createLike(like: CreateLikeInput!): CreateLikeResponse
# Creates a flag on an entity.
createFlag(flag: CreateFlagInput!): CreateFlagResponse
@@ -848,6 +786,14 @@ type RootMutation {
stopIgnoringUser(id: ID!): StopIgnoringUserResponse
}
################################################################################
## Subscriptions
################################################################################
type Subscription {
commentAdded(asset_id: ID!): Comment
}
################################################################################
## Schema
################################################################################
@@ -855,4 +801,5 @@ type RootMutation {
schema {
query: RootQuery
mutation: RootMutation
subscription: Subscription
}