mirror of
https://github.com/wassname/talk.git
synced 2026-06-30 01:58:00 +08:00
Merge branch 'master' into optional-google-fonts
This commit is contained in:
+2
-1
@@ -3,4 +3,5 @@ client/lib
|
||||
**/*.html
|
||||
plugins/*
|
||||
!plugins/coral-plugin-facebook-auth
|
||||
node_modules
|
||||
!plugins/coral-plugin-respect
|
||||
node_modules
|
||||
|
||||
+2
-1
@@ -16,4 +16,5 @@ coverage/
|
||||
|
||||
plugins.json
|
||||
plugins/*
|
||||
!plugins/coral-plugin-facebook-auth
|
||||
!plugins/coral-plugin-facebook-auth
|
||||
!plugins/coral-plugin-respect
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"verbose": true,
|
||||
"ignore": ["test/*", "client/*", "dist/*"],
|
||||
"ignore": ["test/*", "client/*", "dist/*", "plugins/*/client"],
|
||||
"ext": "js,json,graphql"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {render} from 'react-dom';
|
||||
import {GraphQLDocs} from 'graphql-docs';
|
||||
|
||||
import fetcher from './services/fetcher';
|
||||
|
||||
// Render the application into the DOM
|
||||
ReactDOM.render(<GraphQLDocs fetcher={fetcher} />, document.querySelector('#root'));
|
||||
render(<GraphQLDocs fetcher={fetcher} />, document.querySelector('#root'));
|
||||
|
||||
@@ -19,6 +19,7 @@ import FlagComment from 'coral-plugin-flags/FlagComment';
|
||||
import LikeButton from 'coral-plugin-likes/LikeButton';
|
||||
import {BestButton, IfUserCanModifyBest, BEST_TAG, commentIsBest, BestIndicator} from 'coral-plugin-best/BestButton';
|
||||
import LoadMore from 'coral-embed-stream/src/LoadMore';
|
||||
import {Slot} from 'coral-framework';
|
||||
|
||||
import styles from './Comment.css';
|
||||
|
||||
@@ -157,6 +158,7 @@ class Comment extends React.Component {
|
||||
? <TagLabel><BestIndicator /></TagLabel>
|
||||
: null }
|
||||
<PubDate created_at={comment.created_at} />
|
||||
<Slot fill="commentInfoBar" commentId={comment.id} />
|
||||
|
||||
<Content body={comment.body} />
|
||||
<div className="commentActionsLeft comment__action-container">
|
||||
@@ -187,6 +189,7 @@ class Comment extends React.Component {
|
||||
removeBest={removeBestTag} />
|
||||
</IfUserCanModifyBest>
|
||||
</ActionButton>
|
||||
<Slot fill="commentDetail" commentId={comment.id} />
|
||||
</div>
|
||||
<div className="commentActionsRight comment__action-container">
|
||||
<ActionButton>
|
||||
@@ -241,7 +244,8 @@ class Comment extends React.Component {
|
||||
showSignInDialog={showSignInDialog}
|
||||
reactKey={reply.id}
|
||||
key={reply.id}
|
||||
comment={reply} />;
|
||||
comment={reply}
|
||||
/>;
|
||||
})
|
||||
}
|
||||
{
|
||||
|
||||
@@ -313,5 +313,5 @@ export default compose(
|
||||
addCommentTag,
|
||||
removeCommentTag,
|
||||
deleteAction,
|
||||
queryStream
|
||||
queryStream,
|
||||
)(Embed);
|
||||
|
||||
@@ -41,7 +41,8 @@ class Stream extends React.Component {
|
||||
deleteAction,
|
||||
showSignInDialog,
|
||||
addCommentTag,
|
||||
removeCommentTag
|
||||
removeCommentTag,
|
||||
pluginProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@@ -67,7 +68,9 @@ class Stream extends React.Component {
|
||||
showSignInDialog={showSignInDialog}
|
||||
key={comment.id}
|
||||
reactKey={comment.id}
|
||||
comment={comment} />
|
||||
comment={comment}
|
||||
pluginProps={pluginProps}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -255,13 +255,13 @@ hr {
|
||||
.commentActionsRight, .replyActionsRight {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 50%;
|
||||
width: 30%;
|
||||
}
|
||||
.commentActionsLeft, .replyActionsLeft {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
float: left;
|
||||
width: 50%;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.comment__action-container .material-icons {
|
||||
|
||||
@@ -3,7 +3,7 @@ import coralApi from '../helpers/response';
|
||||
import {addNotification} from '../actions/notification';
|
||||
import {pym} from 'coral-framework';
|
||||
|
||||
import I18n from '../../coral-framework/modules/i18n/i18n';
|
||||
import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from './../translations';
|
||||
const lang = new I18n(translations);
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import {gql} from 'react-apollo';
|
||||
import client from 'coral-framework/services/client';
|
||||
import I18n from '../../coral-framework/modules/i18n/i18n';
|
||||
import translations from './../translations';
|
||||
const lang = new I18n(translations);
|
||||
@@ -5,6 +7,20 @@ import * as actions from '../constants/auth';
|
||||
import coralApi, {base} from '../helpers/response';
|
||||
import {pym} from 'coral-framework';
|
||||
|
||||
const ME_QUERY = gql`
|
||||
query Me {
|
||||
me {
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
function fetchMe() {
|
||||
return client.query({
|
||||
fetchPolicy: 'network-only',
|
||||
query: ME_QUERY});
|
||||
}
|
||||
|
||||
// Dialog Actions
|
||||
export const showSignInDialog = (offset = 0) => ({type: actions.SHOW_SIGNIN_DIALOG, offset});
|
||||
export const hideSignInDialog = () => ({type: actions.HIDE_SIGNIN_DIALOG});
|
||||
@@ -52,6 +68,7 @@ export const fetchSignIn = (formData) => (dispatch) => {
|
||||
const isAdmin = !!user && !!user.roles.filter(i => i === 'ADMIN').length;
|
||||
dispatch(signInSuccess(user, isAdmin));
|
||||
dispatch(hideSignInDialog());
|
||||
fetchMe();
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.metadata) {
|
||||
@@ -104,6 +121,7 @@ export const facebookCallback = (err, data) => dispatch => {
|
||||
dispatch(signInFacebookSuccess(user));
|
||||
dispatch(hideSignInDialog());
|
||||
dispatch(showCreateUsernameDialog());
|
||||
fetchMe();
|
||||
} catch (err) {
|
||||
dispatch(signInFacebookFailure(err));
|
||||
return;
|
||||
@@ -151,7 +169,10 @@ const logOutFailure = () => ({type: actions.LOGOUT_FAILURE});
|
||||
export const logout = () => dispatch => {
|
||||
dispatch(logOutRequest());
|
||||
return coralApi('/auth', {method: 'DELETE'})
|
||||
.then(() => dispatch(logOutSuccess()))
|
||||
.then(() => {
|
||||
dispatch(logOutSuccess());
|
||||
fetchMe();
|
||||
})
|
||||
.catch(error => dispatch(logOutFailure(error)));
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import * as authActions from './auth';
|
||||
import * as assetActions from './asset';
|
||||
import * as notificationActions from './notification';
|
||||
|
||||
export default {
|
||||
authActions,
|
||||
assetActions,
|
||||
notificationActions,
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import React, {Component} from 'react';
|
||||
import {getSlotElements} from 'coral-framework/helpers/plugins';
|
||||
|
||||
class Slot extends Component {
|
||||
render() {
|
||||
const {fill, ...rest} = this.props;
|
||||
return (
|
||||
<div>
|
||||
{getSlotElements(fill, rest)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Slot.propTypes = {
|
||||
fill: React.PropTypes.string
|
||||
};
|
||||
|
||||
export default Slot;
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import merge from 'lodash/merge';
|
||||
import flatten from 'lodash/flatten';
|
||||
import plugins from 'pluginsConfig';
|
||||
|
||||
export const pluginReducers = merge(
|
||||
...plugins
|
||||
.filter(o => o.module.reducer)
|
||||
.map(o => ({...o.module.reducer}))
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns React Elements for given slot.
|
||||
*/
|
||||
export function getSlotElements(slot, props = {}) {
|
||||
const components = flatten(plugins
|
||||
.filter(o => o.module.slots[slot])
|
||||
.map(o => o.module.slots[slot]));
|
||||
return components
|
||||
.map((component, i) => React.createElement(component, {...props, key: i}));
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
import store from './services/store';
|
||||
import pym from './services/PymConnection';
|
||||
import I18n from './modules/i18n/i18n';
|
||||
import * as authActions from './actions/auth';
|
||||
import * as assetActions from './actions/asset';
|
||||
import * as notificationActions from './actions/notification';
|
||||
import actions from './actions';
|
||||
import Slot from './components/Slot';
|
||||
|
||||
export {
|
||||
// TODO (bc): Deprecate old actions. Spreading actions is now needed.
|
||||
|
||||
export default {
|
||||
pym,
|
||||
Slot,
|
||||
I18n,
|
||||
store,
|
||||
authActions,
|
||||
assetActions,
|
||||
notificationActions
|
||||
actions,
|
||||
...actions
|
||||
};
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Executes `source` to retrieve plugins configuration
|
||||
* and loads the `index.js` of specified plugins.
|
||||
*
|
||||
* Outputs a module that looks like the following:
|
||||
*
|
||||
* module.exports = [{plugin: string, module: object}, ...]
|
||||
*
|
||||
*/
|
||||
const {stripIndent} = require('common-tags');
|
||||
|
||||
function getPluginList(config) {
|
||||
if (config && config.client) {
|
||||
return config.client.map(x => typeof x === 'string' ? x : Object.keys(x)[0]);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
module.exports = function(source) {
|
||||
this.cacheable();
|
||||
const config = this.exec(source, this.resourcePath);
|
||||
const plugins = getPluginList(config).map((plugin) => `{
|
||||
module: require('${plugin}/client'),
|
||||
plugin: '${plugin}'
|
||||
}`);
|
||||
|
||||
return stripIndent`
|
||||
module.exports = [
|
||||
${plugins.join(',')}
|
||||
];
|
||||
`;
|
||||
};
|
||||
@@ -1,9 +1,11 @@
|
||||
import auth from './auth';
|
||||
import user from './user';
|
||||
import asset from './asset';
|
||||
import {pluginReducers} from '../helpers/plugins';
|
||||
|
||||
export default {
|
||||
auth,
|
||||
user,
|
||||
asset,
|
||||
...pluginReducers
|
||||
};
|
||||
|
||||
@@ -6,9 +6,11 @@ export const client = new ApolloClient({
|
||||
queryTransformer: addTypename,
|
||||
dataIdFromObject: (result) => {
|
||||
if (result.id && result.__typename) { // eslint-disable-line no-underscore-dangle
|
||||
return result.__typename + result.id; // eslint-disable-line no-underscore-dangle
|
||||
return `${result.__typename}_${result.id}`; // eslint-disable-line no-underscore-dangle
|
||||
}
|
||||
return null;
|
||||
},
|
||||
networkInterface: getNetworkInterface()
|
||||
});
|
||||
|
||||
export default client;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* getActionSummary
|
||||
* retrieves the action summary based on the type and the comment
|
||||
*/
|
||||
|
||||
export const getActionSummary = (type, comment) =>
|
||||
comment.action_summaries.filter(a => a.__typename === type)[0];
|
||||
@@ -0,0 +1,31 @@
|
||||
const errors = require('../../errors');
|
||||
const {Error: {ValidationError}} = require('mongoose');
|
||||
|
||||
/**
|
||||
* Wraps up a promise to return an object with the resolution of the promise
|
||||
* keyed at `key` or an error caught at `errors`.
|
||||
*/
|
||||
|
||||
const wrapResponse = (key) => (promise) => {
|
||||
return promise.then((value) => {
|
||||
let res = {};
|
||||
if (key) {
|
||||
res[key] = value;
|
||||
}
|
||||
return res;
|
||||
}).catch((err) => {
|
||||
if (err instanceof errors.APIError) {
|
||||
return {
|
||||
errors: [err]
|
||||
};
|
||||
} else if (err instanceof ValidationError) {
|
||||
|
||||
// TODO: wrap this with one of our internal errors.
|
||||
throw err;
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = wrapResponse;
|
||||
+75
-3
@@ -1,4 +1,7 @@
|
||||
const {forEachField} = require('graphql-tools');
|
||||
const {
|
||||
GraphQLObjectType,
|
||||
GraphQLInterfaceType
|
||||
} = require('graphql');
|
||||
const debug = require('debug')('talk:graph:schema');
|
||||
|
||||
/**
|
||||
@@ -22,6 +25,33 @@ 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 schema with pre and post hooks as provided by the Plugin
|
||||
* Manager.
|
||||
@@ -29,7 +59,7 @@ const defaultResolveFn = (source, args, context, {fieldName}) => {
|
||||
* @param {Array} hooks hooks to apply to the schema
|
||||
* @return {void}
|
||||
*/
|
||||
const decorateWithHooks = (schema, hooks) => forEachField(schema, (field, typeName, fieldName) => {
|
||||
const decorateWithHooks = (schema, hooks) => forEachField(schema, (field, typeName, fieldName, isResolveType = false) => {
|
||||
|
||||
// Pull out the pre/post hooks from the available hooks.
|
||||
const {
|
||||
@@ -85,6 +115,48 @@ const decorateWithHooks = (schema, hooks) => forEachField(schema, (field, typeNa
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a resolve type, we need to do some specific things to handle
|
||||
// this type of field.
|
||||
if (isResolveType) {
|
||||
|
||||
// Warn if we have any pre hooks.
|
||||
if (pre.length !== 0) {
|
||||
throw new Error(`invalid pre hooks were found for ${typeName}.${fieldName}, only post hooks are supported on the __resolveType hook`);
|
||||
}
|
||||
|
||||
// This only needs to do something if post hooks are defined.
|
||||
if (post.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache the original resolverType function.
|
||||
let resolveType = field.resolveType;
|
||||
|
||||
// Return the function to handle the resolveType hooks.
|
||||
field.resolveType = (obj, context, info) => {
|
||||
let type = resolveType(obj, context, info);
|
||||
|
||||
// Only if a previous resolver was unable to resolve the field type do we
|
||||
// progress to the hooks (in order!) to resolve the field name until we
|
||||
// have resolved it.
|
||||
if (typeof type !== 'undefined' && type != null) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// We will walk through the post hooks until we find the right one. This
|
||||
// follows what redux does to combine existing reducers.
|
||||
for (let i = 0; i < post.length; i++) {
|
||||
let resolveType = post[i];
|
||||
type = resolveType(obj, context, info);
|
||||
if (typeof type !== 'undefined' && type != null) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache the original resolve function, this emulates the beheviour found in
|
||||
// graphql-tools: https://github.com/apollographql/graphql-tools/blob/6e9cc124b10d673448386041e6c3d058bc205a02/src/schemaGenerator.ts#L423-L425
|
||||
let resolve = field.resolve;
|
||||
@@ -102,7 +174,7 @@ const decorateWithHooks = (schema, hooks) => forEachField(schema, (field, typeNa
|
||||
await Promise.all(pre.map((pre) => pre(obj, args, context, info)));
|
||||
|
||||
// Resolve the field.
|
||||
let result = resolve(obj, args, context, info);
|
||||
let result = await resolve(obj, args, context, info);
|
||||
|
||||
// Insure all post hooks after we've resolved the field with the result
|
||||
// passed in as the fifth argument.
|
||||
|
||||
@@ -1,33 +1,6 @@
|
||||
const {Error: {ValidationError}} = require('mongoose');
|
||||
const errors = require('../../errors');
|
||||
const wrapResponse = require('../helpers/response');
|
||||
const CommentsService = require('../../services/comments');
|
||||
|
||||
/**
|
||||
* Wraps up a promise to return an object with the resolution of the promise
|
||||
* keyed at `key` or an error caught at `errors`.
|
||||
*/
|
||||
const wrapResponse = (key) => (promise) => {
|
||||
return promise.then((value) => {
|
||||
let res = {};
|
||||
if (key) {
|
||||
res[key] = value;
|
||||
}
|
||||
return res;
|
||||
}).catch((err) => {
|
||||
if (err instanceof errors.APIError) {
|
||||
return {
|
||||
errors: [err]
|
||||
};
|
||||
} else if (err instanceof ValidationError) {
|
||||
|
||||
// TODO: wrap this with one of our internal errors.
|
||||
throw err;
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
|
||||
const RootMutation = {
|
||||
createComment(_, {asset_id, parent_id, body}, {mutators: {Comment}}) {
|
||||
return wrapResponse('comment')(Comment.create({asset_id, parent_id, body}));
|
||||
|
||||
+7
-3
@@ -7,7 +7,7 @@
|
||||
"postinstall": "./bin/cli plugins reconcile --skip-remote",
|
||||
"start": "./bin/cli serve --jobs",
|
||||
"dev-start": "nodemon --config .nodemon.json --exec \"./bin/cli -c .env serve --jobs\"",
|
||||
"build": "NODE_ENV=production webpack --progress -p --config webpack.config.js --bail",
|
||||
"build": "NODE_ENV=production webpack -p --config webpack.config.js --bail",
|
||||
"build-watch": "NODE_ENV=development webpack --progress --config webpack.config.js --watch",
|
||||
"lint": "eslint bin/* .",
|
||||
"lint-fix": "eslint bin/* . --fix",
|
||||
@@ -74,6 +74,7 @@
|
||||
"graphql-tools": "^0.9.0",
|
||||
"helmet": "^3.5.0",
|
||||
"inquirer": "^3.0.6",
|
||||
"joi": "^10.4.1",
|
||||
"jsonwebtoken": "^7.3.0",
|
||||
"kue": "^0.11.5",
|
||||
"linkify-it": "^2.0.3",
|
||||
@@ -90,7 +91,7 @@
|
||||
"parse-duration": "^0.1.1",
|
||||
"passport": "^0.3.2",
|
||||
"passport-local": "^1.0.0",
|
||||
"react-apollo": "^0.10.0",
|
||||
"react-apollo": "^1.0.0",
|
||||
"react-recaptcha": "^2.2.6",
|
||||
"redis": "^2.7.1",
|
||||
"resolve": "^1.3.2",
|
||||
@@ -99,8 +100,9 @@
|
||||
"uuid": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"apollo-client": "^0.8.3",
|
||||
"apollo-client": "^1.0.0",
|
||||
"autoprefixer": "^6.5.2",
|
||||
"babel-cli": "^6.24.0",
|
||||
"babel-core": "^6.24.0",
|
||||
"babel-eslint": "^7.2.1",
|
||||
"babel-jest": "^19.0.0",
|
||||
@@ -114,10 +116,12 @@
|
||||
"babel-plugin-transform-react-jsx": "^6.23.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-es2015": "^6.24.0",
|
||||
"babel-preset-react": "^6.23.0",
|
||||
"babel-preset-stage-0": "^6.16.0",
|
||||
"chai": "^3.5.0",
|
||||
"chai-as-promised": "^6.0.0",
|
||||
"chai-http": "^3.0.0",
|
||||
"common-tags": "^1.4.0",
|
||||
"copy-webpack-plugin": "^4.0.0",
|
||||
"css-loader": "^0.27.3",
|
||||
"dialog-polyfill": "^0.4.4",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
{
|
||||
"server": [
|
||||
"coral-plugin-respect",
|
||||
"coral-plugin-facebook-auth"
|
||||
],
|
||||
"client": [
|
||||
"coral-plugin-respect"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = JSON.parse(process.env.TALK_PLUGINS_JSON);
|
||||
+46
-6
@@ -2,9 +2,11 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const resolve = require('resolve');
|
||||
const debug = require('debug')('talk:plugins');
|
||||
const Joi = require('joi');
|
||||
const amp = require('app-module-path');
|
||||
|
||||
// Add support for require rewriting.
|
||||
require('app-module-path').addPath(__dirname);
|
||||
// Add the current path to the module root.
|
||||
amp.addPath(__dirname);
|
||||
|
||||
let plugins = {};
|
||||
|
||||
@@ -12,13 +14,13 @@ let plugins = {};
|
||||
// file isn't loaded, but continuing. Else, like a parsing error, throw it and
|
||||
// crash the program.
|
||||
try {
|
||||
let defaultPlugins = path.join(__dirname, 'plugins.default.json');
|
||||
let envPlugins = path.join(__dirname, 'plugins.env.js');
|
||||
let customPlugins = path.join(__dirname, 'plugins.json');
|
||||
let envPluginJSON = process.env.TALK_PLUGINS_JSON;
|
||||
let defaultPlugins = path.join(__dirname, 'plugins.default.json');
|
||||
|
||||
if (envPluginJSON && envPluginJSON.length > 0) {
|
||||
if (process.env.TALK_PLUGINS_JSON && process.env.TALK_PLUGINS_JSON.length > 0) {
|
||||
debug('Now using TALK_PLUGINS_JSON environment variable for plugins');
|
||||
plugins = JSON.parse(envPluginJSON);
|
||||
plugins = require(envPlugins);
|
||||
} else if (fs.existsSync(customPlugins)) {
|
||||
debug(`Now using ${customPlugins} for plugins`);
|
||||
plugins = JSON.parse(fs.readFileSync(customPlugins, 'utf8'));
|
||||
@@ -34,6 +36,23 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All the hooks from plugins must match the schema defined here.
|
||||
*/
|
||||
const hookSchemas = {
|
||||
passport: Joi.func().arity(1),
|
||||
router: Joi.func().arity(1),
|
||||
context: Joi.object().pattern(/\w/, Joi.func().maxArity(1)),
|
||||
hooks: Joi.object().pattern(/\w/, Joi.object().pattern(/(?:__resolveType|\w+)/, Joi.object({
|
||||
pre: Joi.func(),
|
||||
post: Joi.func()
|
||||
}))),
|
||||
loaders: Joi.object().pattern(/\w/, Joi.object().pattern(/\w/, Joi.func())),
|
||||
mutators: Joi.object().pattern(/\w/, Joi.object().pattern(/\w/, Joi.func())),
|
||||
resolvers: Joi.object().pattern(/\w/, Joi.object().pattern(/(?:__resolveType|\w+)/, Joi.func())),
|
||||
typeDefs: Joi.string()
|
||||
};
|
||||
|
||||
/**
|
||||
* isInternal checks to see if a given plugin is internal, and returns true
|
||||
* if it is.
|
||||
@@ -67,6 +86,12 @@ function pluginPath(name) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Itterates over the plugins and gets the plugin path's, version, and name.
|
||||
*
|
||||
* @param {Array<Object|String>} plugins
|
||||
* @returns {Array<Object>}
|
||||
*/
|
||||
function itteratePlugins(plugins) {
|
||||
return plugins.map((p) => {
|
||||
let plugin = {};
|
||||
@@ -96,6 +121,12 @@ function itteratePlugins(plugins) {
|
||||
});
|
||||
}
|
||||
|
||||
// Add each plugin folder to the allowed import path so that they can import our
|
||||
// internal dependancies.
|
||||
Object.keys(plugins).forEach((type) => itteratePlugins(plugins[type]).forEach((plugin) => {
|
||||
amp.enableForDir(path.dirname(plugin.path));
|
||||
}));
|
||||
|
||||
/**
|
||||
* Stores a reference to a section for a section of Plugins.
|
||||
*/
|
||||
@@ -135,6 +166,15 @@ class PluginSection {
|
||||
hook(hook) {
|
||||
return this.plugins
|
||||
.filter(({module}) => hook in module)
|
||||
.filter((plugin) => {
|
||||
|
||||
// Validate the hook.
|
||||
if (hook in hookSchemas) {
|
||||
Joi.assert(plugin.module[hook], hookSchemas[hook], `Plugin '${plugin.name}' failed validation for the '${hook}' hook`);
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.map((plugin) => ({
|
||||
plugin,
|
||||
[hook]: plugin.module[hook]
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015"
|
||||
],
|
||||
"plugins": [
|
||||
"add-module-exports",
|
||||
"transform-class-properties",
|
||||
"transform-decorators-legacy",
|
||||
"transform-object-assign",
|
||||
"transform-object-rest-spread",
|
||||
"transform-async-to-generator",
|
||||
"transform-react-jsx"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true,
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"rules": {
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
|
||||
export default ({className}) => (
|
||||
<i className={cn('fa', 'fa-handshake-o', className)} aria-hidden="true"/>
|
||||
);
|
||||
@@ -0,0 +1,67 @@
|
||||
import React, {Component} from 'react';
|
||||
import styles from './style.css';
|
||||
import Icon from './Icon';
|
||||
|
||||
import {I18n} from 'coral-framework';
|
||||
import cn from 'classnames';
|
||||
import translations from '../translations.json';
|
||||
|
||||
const lang = new I18n(translations);
|
||||
|
||||
class RespectButton extends Component {
|
||||
|
||||
handleClick = () => {
|
||||
const {postRespect, showSignInDialog, deleteAction, commentId} = this.props;
|
||||
const {me, comment} = this.props.data;
|
||||
|
||||
const respect = comment.action_summaries[0];
|
||||
const respected = (respect && respect.current_user);
|
||||
|
||||
// If the current user does not exist, trigger sign in dialog.
|
||||
if (!me) {
|
||||
const offset = document.getElementById(`c_${commentId}`).getBoundingClientRect().top - 75;
|
||||
showSignInDialog(offset);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the current user is banned, do nothing.
|
||||
if (me.status === 'BANNED') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!respected) {
|
||||
postRespect({
|
||||
item_id: commentId,
|
||||
item_type: 'COMMENTS'
|
||||
});
|
||||
} else {
|
||||
deleteAction(respect.current_user.id);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {comment} = this.props.data;
|
||||
const respect = comment && comment.action_summaries && comment.action_summaries[0];
|
||||
const respected = respect && respect.current_user;
|
||||
let count = respect ? respect.count : 0;
|
||||
|
||||
return (
|
||||
<div className={styles.respect}>
|
||||
<button
|
||||
className={cn(styles.button, {[styles.respected]: respected})}
|
||||
onClick={this.handleClick} >
|
||||
<span>{lang.t(respected ? 'respected' : 'respect')}</span>
|
||||
<Icon className={cn(styles.icon, {[styles.respected]: respected})} />
|
||||
{count > 0 && count}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
RespectButton.propTypes = {
|
||||
data: React.PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default RespectButton;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
.respect {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.button {
|
||||
color: #2a2a2a;
|
||||
margin: 5px 10px 5px 0px;
|
||||
background: none;
|
||||
padding: 0px;
|
||||
border: none;
|
||||
font-size: inherit;
|
||||
|
||||
&:hover {
|
||||
color: #767676;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.respected {
|
||||
color: #c98211;
|
||||
|
||||
&:hover {
|
||||
color: #e59614;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
padding: 0 5px;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
import {compose, gql, graphql} from 'react-apollo';
|
||||
import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import {showSignInDialog} from 'coral-framework/actions/auth';
|
||||
import RespectButton from '../components/RespectButton';
|
||||
|
||||
// TODO: use `update` instead of `updateQueries` for optimistic mutations.
|
||||
// See https://dev-blog.apollodata.com/apollo-clients-new-imperative-store-api-6cb69318a1e3
|
||||
// and https://github.com/apollographql/apollo-client/issues/1224
|
||||
|
||||
export const RESPECT_QUERY = gql`
|
||||
query RespectQuery($commentId: ID!) {
|
||||
comment(id: $commentId) {
|
||||
id
|
||||
action_summaries {
|
||||
... on RespectActionSummary {
|
||||
count
|
||||
current_user {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
me {
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const withQuery = graphql(RESPECT_QUERY);
|
||||
|
||||
const withDeleteAction = graphql(gql`
|
||||
mutation deleteAction($id: ID!) {
|
||||
deleteAction(id:$id) {
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
}
|
||||
`, {
|
||||
props: ({mutate}) => ({
|
||||
deleteAction: (id) => {
|
||||
return mutate({
|
||||
variables: {id},
|
||||
optimisticResponse: {
|
||||
deleteAction: {
|
||||
__typename: 'DeleteActionResponse',
|
||||
errors: null,
|
||||
}
|
||||
},
|
||||
updateQueries: {
|
||||
RespectQuery: (prev) => {
|
||||
if (get(prev, 'comment.action_summaries.0.current_user.id') !== id) {
|
||||
return prev;
|
||||
}
|
||||
const next = {
|
||||
...prev,
|
||||
comment: {
|
||||
...prev.comment,
|
||||
action_summaries: [{
|
||||
__typename: 'RespectActionSummary',
|
||||
count: prev.comment.action_summaries[0].count - 1,
|
||||
current_user: null,
|
||||
}],
|
||||
}
|
||||
};
|
||||
return next;
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const withPostRespect = graphql(gql`
|
||||
mutation createRespect($respect: CreateRespectInput!) {
|
||||
createRespect(respect: $respect) {
|
||||
respect {
|
||||
id
|
||||
}
|
||||
errors {
|
||||
translation_key
|
||||
}
|
||||
}
|
||||
}
|
||||
`, {
|
||||
props: ({mutate}) => ({
|
||||
postRespect: (respect) => {
|
||||
return mutate({
|
||||
variables: {respect},
|
||||
optimisticResponse: {
|
||||
createRespect: {
|
||||
__typename: 'CreateRespectResponse',
|
||||
errors: null,
|
||||
respect: {
|
||||
__typename: 'RespectAction',
|
||||
id: 'pending',
|
||||
},
|
||||
}
|
||||
},
|
||||
updateQueries: {
|
||||
RespectQuery: (prev, {mutationResult, queryVariables}) => {
|
||||
if (queryVariables.commentId !== respect.item_id) {
|
||||
return prev;
|
||||
}
|
||||
const respectAction = mutationResult.data.createRespect.respect;
|
||||
const count = prev.action_summaries ? prev.action_summaries.count : 0;
|
||||
const next = {
|
||||
...prev,
|
||||
comment: {
|
||||
...prev.comment,
|
||||
action_summaries: [{
|
||||
__typename: 'RespectActionSummary',
|
||||
count: count + 1,
|
||||
current_user: respectAction,
|
||||
}],
|
||||
}
|
||||
};
|
||||
return next;
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators({showSignInDialog}, dispatch);
|
||||
|
||||
const enhance = compose(
|
||||
connect(null, mapDispatchToProps),
|
||||
withDeleteAction,
|
||||
withPostRespect,
|
||||
withQuery,
|
||||
);
|
||||
|
||||
export default enhance(RespectButton);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import RespectButton from './containers/RespectButton';
|
||||
export default {
|
||||
slots: {
|
||||
commentDetail: [RespectButton],
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"en": {
|
||||
"respect": "Respect",
|
||||
"respected": "Respected"
|
||||
},
|
||||
"es": {
|
||||
"respect": "Respeto",
|
||||
"respected": "Respetado"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
const {readFileSync} = require('fs');
|
||||
const path = require('path');
|
||||
const wrapResponse = require('../../graph/helpers/response');
|
||||
|
||||
module.exports = {
|
||||
typeDefs: readFileSync(path.join(__dirname, 'server/typeDefs.graphql'), 'utf8'),
|
||||
resolvers: {
|
||||
RootMutation: {
|
||||
createRespect(_, {respect: {item_id, item_type}}, {mutators: {Action}}) {
|
||||
return wrapResponse('respect')(Action.create({item_id, item_type, action_type: 'RESPECT'}));
|
||||
}
|
||||
}
|
||||
},
|
||||
hooks: {
|
||||
Action: {
|
||||
__resolveType: {
|
||||
post({action_type}) {
|
||||
switch (action_type) {
|
||||
case 'RESPECT':
|
||||
return 'RespectAction';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ActionSummary: {
|
||||
__resolveType: {
|
||||
post({action_type}) {
|
||||
switch (action_type) {
|
||||
case 'RESPECT':
|
||||
return 'RespectActionSummary';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
enum ACTION_TYPE {
|
||||
|
||||
# Represents a Respect.
|
||||
RESPECT
|
||||
}
|
||||
|
||||
input CreateRespectInput {
|
||||
|
||||
# The item's id for which we are to create a respect.
|
||||
item_id: ID!
|
||||
|
||||
# The type of the item for which we are to create the respect.
|
||||
item_type: ACTION_ITEM_TYPE!
|
||||
}
|
||||
|
||||
# RespectAction is used by users who "respect" a specific entity.
|
||||
type RespectAction 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
|
||||
}
|
||||
|
||||
type RespectActionSummary implements ActionSummary {
|
||||
|
||||
# The count of actions with this group.
|
||||
count: Int
|
||||
|
||||
# The current user's action.
|
||||
current_user: RespectAction
|
||||
}
|
||||
|
||||
type CreateRespectResponse implements Response {
|
||||
|
||||
# The respect that was created.
|
||||
respect: RespectAction
|
||||
|
||||
# An array of errors relating to the mutation that occurred.
|
||||
errors: [UserError]
|
||||
}
|
||||
|
||||
type RootMutation {
|
||||
|
||||
# Creates a respect on an entity.
|
||||
createRespect(respect: CreateRespectInput!): CreateRespectResponse
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"extends": "../../client/.babelrc"
|
||||
"extends": "../../.babelrc"
|
||||
}
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
test/helpers/*.js
|
||||
test
|
||||
|
||||
test/e2e
|
||||
test/server
|
||||
--compilers js:babel-core/register
|
||||
--require ignore-styles
|
||||
--recursive
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const expect = require('chai').expect;
|
||||
|
||||
const User = require('../../models/user');
|
||||
const Context = require('../../graph/context');
|
||||
const errors = require('../../errors');
|
||||
const User = require('../../../models/user');
|
||||
const Context = require('../../../graph/context');
|
||||
const errors = require('../../../errors');
|
||||
|
||||
describe('graph.Context', () => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const {expect} = require('chai');
|
||||
const {graphql} = require('graphql');
|
||||
|
||||
const schema = require('../../../graph/schema');
|
||||
const Context = require('../../../graph/context');
|
||||
const UserModel = require('../../../models/user');
|
||||
const AssetModel = require('../../../models/asset');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
const ActionModel = require('../../../models/action');
|
||||
const CommentModel = require('../../../models/comment');
|
||||
const schema = require('../../../../graph/schema');
|
||||
const Context = require('../../../../graph/context');
|
||||
const UserModel = require('../../../../models/user');
|
||||
const AssetModel = require('../../../../models/asset');
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const ActionModel = require('../../../../models/action');
|
||||
const CommentModel = require('../../../../models/comment');
|
||||
|
||||
describe('graph.loaders.Metrics', () => {
|
||||
beforeEach(() => SettingsService.init());
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
const expect = require('chai').expect;
|
||||
const {graphql} = require('graphql');
|
||||
|
||||
const schema = require('../../../graph/schema');
|
||||
const Context = require('../../../graph/context');
|
||||
const UserModel = require('../../../models/user');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
const CommentsService = require('../../../services/comments');
|
||||
const schema = require('../../../../graph/schema');
|
||||
const Context = require('../../../../graph/context');
|
||||
const UserModel = require('../../../../models/user');
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const CommentsService = require('../../../../services/comments');
|
||||
|
||||
describe('graph.mutations.addCommentTag', () => {
|
||||
let comment;
|
||||
+6
-6
@@ -1,12 +1,12 @@
|
||||
const expect = require('chai').expect;
|
||||
const {graphql} = require('graphql');
|
||||
|
||||
const schema = require('../../../graph/schema');
|
||||
const Context = require('../../../graph/context');
|
||||
const UserModel = require('../../../models/user');
|
||||
const AssetModel = require('../../../models/asset');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
const ActionModel = require('../../../models/action');
|
||||
const schema = require('../../../../graph/schema');
|
||||
const Context = require('../../../../graph/context');
|
||||
const UserModel = require('../../../../models/user');
|
||||
const AssetModel = require('../../../../models/asset');
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const ActionModel = require('../../../../models/action');
|
||||
|
||||
describe('graph.mutations.createComment', () => {
|
||||
beforeEach(() => SettingsService.init());
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
const expect = require('chai').expect;
|
||||
const {graphql} = require('graphql');
|
||||
|
||||
const schema = require('../../../graph/schema');
|
||||
const Context = require('../../../graph/context');
|
||||
const UserModel = require('../../../models/user');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
const CommentsService = require('../../../services/comments');
|
||||
const schema = require('../../../../graph/schema');
|
||||
const Context = require('../../../../graph/context');
|
||||
const UserModel = require('../../../../models/user');
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const CommentsService = require('../../../../services/comments');
|
||||
|
||||
describe('graph.mutations.removeCommentTag', () => {
|
||||
let comment;
|
||||
@@ -1,4 +1,4 @@
|
||||
const kue = require('../services/kue');
|
||||
const kue = require('../../services/kue');
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const mongoose = require('./helpers/mongoose');
|
||||
const mongoose = require('../helpers/mongoose');
|
||||
|
||||
before(function(done) {
|
||||
this.timeout(30000);
|
||||
@@ -1,4 +1,4 @@
|
||||
const authorization = require('../middleware/authorization');
|
||||
const authorization = require('../../middleware/authorization');
|
||||
|
||||
// Add the passport middleware here before it's setup.
|
||||
authorization.middleware.push((req, res, next) => {
|
||||
@@ -1,17 +1,17 @@
|
||||
const passport = require('../../../passport');
|
||||
|
||||
const app = require('../../../../app');
|
||||
const app = require('../../../../../app');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const SettingsService = require('../../../../../services/settings');
|
||||
const settings = {id: '1', moderation: 'PRE', wordlist: {banned: ['bad words'], suspect: ['suspect words']}};
|
||||
|
||||
// Setup chai.
|
||||
chai.should();
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
const UsersService = require('../../../../services/users');
|
||||
const UsersService = require('../../../../../services/users');
|
||||
|
||||
describe('/api/v1/account/username', () => {
|
||||
let mockUser;
|
||||
@@ -1,6 +1,6 @@
|
||||
const passport = require('../../../passport');
|
||||
|
||||
const app = require('../../../../app');
|
||||
const app = require('../../../../../app');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
|
||||
@@ -8,9 +8,9 @@ const expect = chai.expect;
|
||||
chai.should();
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
const AssetModel = require('../../../../models/asset');
|
||||
const AssetsService = require('../../../../services/assets');
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const AssetModel = require('../../../../../models/asset');
|
||||
const AssetsService = require('../../../../../services/assets');
|
||||
const SettingsService = require('../../../../../services/settings');
|
||||
|
||||
describe('/api/v1/assets', () => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const app = require('../../../../app');
|
||||
const app = require('../../../../../app');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
const UsersService = require('../../../../services/users');
|
||||
const UsersService = require('../../../../../services/users');
|
||||
|
||||
describe('/api/v1/auth', () => {
|
||||
describe('#get', () => {
|
||||
@@ -19,7 +19,7 @@ describe('/api/v1/auth', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const SettingsService = require('../../../../../services/settings');
|
||||
|
||||
describe('/api/v1/auth/local', () => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const passport = require('../../../passport');
|
||||
|
||||
const app = require('../../../../app');
|
||||
const app = require('../../../../../app');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
|
||||
chai.should();
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const SettingsService = require('../../../../../services/settings');
|
||||
const defaults = {id: '1', moderation: 'PRE'};
|
||||
|
||||
describe('/api/v1/settings', () => {
|
||||
@@ -1,18 +1,18 @@
|
||||
const passport = require('../../../passport');
|
||||
|
||||
const app = require('../../../../app');
|
||||
const mailer = require('../../../../services/mailer');
|
||||
const app = require('../../../../../app');
|
||||
const mailer = require('../../../../../services/mailer');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const SettingsService = require('../../../../../services/settings');
|
||||
const settings = {id: '1', moderation: 'PRE', wordlist: {banned: ['bad words'], suspect: ['suspect words']}};
|
||||
|
||||
// Setup chai.
|
||||
chai.should();
|
||||
chai.use(require('chai-http'));
|
||||
|
||||
const UsersService = require('../../../../services/users');
|
||||
const UsersService = require('../../../../../services/users');
|
||||
|
||||
describe('/api/v1/users/:user_id/email/confirm', () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const ActionModel = require('../../models/action');
|
||||
const ActionsService = require('../../services/actions');
|
||||
const ActionModel = require('../../../models/action');
|
||||
const ActionsService = require('../../../services/actions');
|
||||
|
||||
const expect = require('chai').expect;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const AssetModel = require('../../models/asset');
|
||||
const AssetsService = require('../../services/assets');
|
||||
const SettingsService = require('../../services/settings');
|
||||
const AssetModel = require('../../../models/asset');
|
||||
const AssetsService = require('../../../services/assets');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
@@ -1,10 +1,10 @@
|
||||
const CommentModel = require('../../models/comment');
|
||||
const ActionModel = require('../../models/action');
|
||||
const CommentModel = require('../../../models/comment');
|
||||
const ActionModel = require('../../../models/action');
|
||||
|
||||
const ActionsService = require('../../services/actions');
|
||||
const UsersService = require('../../services/users');
|
||||
const SettingsService = require('../../services/settings');
|
||||
const CommentsService = require('../../services/comments');
|
||||
const ActionsService = require('../../../services/actions');
|
||||
const UsersService = require('../../../services/users');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
const CommentsService = require('../../../services/comments');
|
||||
|
||||
const settings = {id: '1', moderation: 'PRE', wordlist: {banned: ['bad words'], suspect: ['suspect words']}};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const expect = require('chai').expect;
|
||||
const Domainlist = require('../../services/domainlist');
|
||||
const SettingsService = require('../../services/settings');
|
||||
const Domainlist = require('../../../services/domainlist');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
|
||||
describe('services.Domainlist', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const SettingsService = require('../../services/settings');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('services.SettingsService', () => {
|
||||
@@ -1,5 +1,5 @@
|
||||
const UsersService = require('../../services/users');
|
||||
const SettingsService = require('../../services/settings');
|
||||
const UsersService = require('../../../services/users');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
|
||||
const expect = require('chai').expect;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const Errors = require('../../errors');
|
||||
const Wordlist = require('../../services/wordlist');
|
||||
const SettingsService = require('../../services/settings');
|
||||
const Errors = require('../../../errors');
|
||||
const Wordlist = require('../../../services/wordlist');
|
||||
const SettingsService = require('../../../services/settings');
|
||||
|
||||
describe('services.Wordlist', () => {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<meta property="csrf" content="<%= csrfToken %>">
|
||||
<link rel="stylesheet" type="text/css" href="/client/embed/stream/default.css">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<% if (locals.customCssUrl) { %>
|
||||
<link href="<%= customCssUrl %>" rel="stylesheet" type="text/css">
|
||||
<% } %>
|
||||
|
||||
+37
-1
@@ -1,10 +1,30 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const precss = require('precss');
|
||||
const Copy = require('copy-webpack-plugin');
|
||||
const LicenseWebpackPlugin = require('license-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
|
||||
// Possibly load the config from the .env file (if there is one).
|
||||
require('dotenv').config();
|
||||
|
||||
let pluginsConfigPath;
|
||||
|
||||
let envPlugins = path.join(__dirname, 'plugins.env.js');
|
||||
let customPlugins = path.join(__dirname, 'plugins.json');
|
||||
let defaultPlugins = path.join(__dirname, 'plugins.default.json');
|
||||
|
||||
if (process.env.TALK_PLUGINS_JSON && process.env.TALK_PLUGINS_JSON.length > 0) {
|
||||
pluginsConfigPath = envPlugins;
|
||||
} else if (fs.existsSync(customPlugins)) {
|
||||
pluginsConfigPath = customPlugins;
|
||||
} else {
|
||||
pluginsConfigPath = defaultPlugins;
|
||||
}
|
||||
|
||||
console.log(`Using ${pluginsConfigPath} as the plugin configuration path`);
|
||||
|
||||
// Edit the build targets and embeds below.
|
||||
|
||||
const buildTargets = [
|
||||
@@ -53,6 +73,11 @@ module.exports = {
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
loader: 'plugins-loader',
|
||||
test: /\.(json|js)$/,
|
||||
include: pluginsConfigPath
|
||||
},
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
@@ -115,12 +140,23 @@ module.exports = {
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'VERSION': `"${require('./package.json').version}"`
|
||||
'VERSION': `"${require('./package.json').version}"`,
|
||||
}
|
||||
}),
|
||||
new webpack.EnvironmentPlugin({
|
||||
'TALK_PLUGINS_JSON': '{}'
|
||||
})
|
||||
],
|
||||
resolveLoader: {
|
||||
modules: ['node_modules', path.resolve(__dirname, 'client/coral-framework/loaders')],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
plugins: path.resolve(__dirname, 'plugins/'),
|
||||
pluginsConfig: pluginsConfigPath
|
||||
},
|
||||
modules: [
|
||||
path.resolve(__dirname, 'plugins'),
|
||||
path.resolve(__dirname, 'client'),
|
||||
...buildTargets.map(target => path.join(__dirname, 'client', target, 'src')),
|
||||
...buildEmbeds.map(embed => path.join(__dirname, 'client', `coral-embed-${embed}`, 'src')),
|
||||
|
||||
@@ -26,13 +26,17 @@
|
||||
"@types/express-serve-static-core" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/graphql@^0.8.0", "@types/graphql@^0.8.5", "@types/graphql@^0.8.6":
|
||||
"@types/graphql@^0.8.5", "@types/graphql@^0.8.6":
|
||||
version "0.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.8.6.tgz#b34fb880493ba835b0c067024ee70130d6f9bb68"
|
||||
|
||||
"@types/isomorphic-fetch@0.0.30":
|
||||
version "0.0.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.30.tgz#a21717624cde9a48c2db53a4e500fc5c32a99bbc"
|
||||
"@types/graphql@^0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.0.tgz#fccf859f0d2817687f210737dc3be48a18b1d754"
|
||||
|
||||
"@types/isomorphic-fetch@0.0.33":
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.33.tgz#3ea1b86f8b73e6a7430d01d4dbd5b1f63fd72718"
|
||||
|
||||
"@types/mime@*":
|
||||
version "0.0.29"
|
||||
@@ -175,19 +179,20 @@ anymatch@^1.3.0:
|
||||
arrify "^1.0.0"
|
||||
micromatch "^2.1.5"
|
||||
|
||||
apollo-client@^0.8.3:
|
||||
version "0.8.6"
|
||||
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-0.8.6.tgz#9aa18b03ec338f0a3804122df7f77493a10b72a0"
|
||||
apollo-client@^1.0.0, apollo-client@^1.0.0-rc.9:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.0.2.tgz#4355bd49d53a1489bc91d9f56d5b3d0ffe33fb3c"
|
||||
dependencies:
|
||||
graphql-anywhere "^2.1.0"
|
||||
graphql-tag "^1.1.1"
|
||||
graphql "^0.9.1"
|
||||
graphql-anywhere "^3.0.1"
|
||||
graphql-tag "^2.0.0"
|
||||
redux "^3.4.0"
|
||||
symbol-observable "^1.0.2"
|
||||
whatwg-fetch "^2.0.0"
|
||||
optionalDependencies:
|
||||
"@types/async" "^2.0.31"
|
||||
"@types/graphql" "^0.8.0"
|
||||
"@types/isomorphic-fetch" "0.0.30"
|
||||
"@types/graphql" "^0.9.0"
|
||||
"@types/isomorphic-fetch" "0.0.33"
|
||||
|
||||
app-module-path@^2.2.0:
|
||||
version "2.2.0"
|
||||
@@ -360,6 +365,27 @@ aws4@^1.2.1:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755"
|
||||
|
||||
babel-cli@^6.24.0:
|
||||
version "6.24.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.24.0.tgz#a05ffd210dca0c288a26d5319c5ac8669a265ad0"
|
||||
dependencies:
|
||||
babel-core "^6.24.0"
|
||||
babel-polyfill "^6.23.0"
|
||||
babel-register "^6.24.0"
|
||||
babel-runtime "^6.22.0"
|
||||
commander "^2.8.1"
|
||||
convert-source-map "^1.1.0"
|
||||
fs-readdir-recursive "^1.0.0"
|
||||
glob "^7.0.0"
|
||||
lodash "^4.2.0"
|
||||
output-file-sync "^1.1.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
slash "^1.0.0"
|
||||
source-map "^0.5.0"
|
||||
v8flags "^2.0.10"
|
||||
optionalDependencies:
|
||||
chokidar "^1.6.1"
|
||||
|
||||
babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
|
||||
@@ -622,11 +648,15 @@ babel-plugin-syntax-export-extensions@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721"
|
||||
|
||||
babel-plugin-syntax-flow@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
|
||||
|
||||
babel-plugin-syntax-function-bind@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46"
|
||||
|
||||
babel-plugin-syntax-jsx@^6.8.0:
|
||||
babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
|
||||
|
||||
@@ -879,6 +909,13 @@ babel-plugin-transform-export-extensions@^6.22.0:
|
||||
babel-plugin-syntax-export-extensions "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-flow-strip-types@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf"
|
||||
dependencies:
|
||||
babel-plugin-syntax-flow "^6.18.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-function-bind@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97"
|
||||
@@ -899,6 +936,26 @@ babel-plugin-transform-object-rest-spread@^6.22.0, babel-plugin-transform-object
|
||||
babel-plugin-syntax-object-rest-spread "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-react-display-name@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-react-jsx-self@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e"
|
||||
dependencies:
|
||||
babel-plugin-syntax-jsx "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-react-jsx-source@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6"
|
||||
dependencies:
|
||||
babel-plugin-syntax-jsx "^6.8.0"
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-transform-react-jsx@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.23.0.tgz#23e892f7f2e759678eb5e4446a8f8e94e81b3470"
|
||||
@@ -957,12 +1014,29 @@ babel-preset-es2015@^6.24.0:
|
||||
babel-plugin-transform-es2015-unicode-regex "^6.22.0"
|
||||
babel-plugin-transform-regenerator "^6.22.0"
|
||||
|
||||
babel-preset-flow@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d"
|
||||
dependencies:
|
||||
babel-plugin-transform-flow-strip-types "^6.22.0"
|
||||
|
||||
babel-preset-jest@^19.0.0:
|
||||
version "19.0.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-19.0.0.tgz#22d67201d02324a195811288eb38294bb3cac396"
|
||||
dependencies:
|
||||
babel-plugin-jest-hoist "^19.0.0"
|
||||
|
||||
babel-preset-react@^6.23.0:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.23.0.tgz#eb7cee4de98a3f94502c28565332da9819455195"
|
||||
dependencies:
|
||||
babel-plugin-syntax-jsx "^6.3.13"
|
||||
babel-plugin-transform-react-display-name "^6.23.0"
|
||||
babel-plugin-transform-react-jsx "^6.23.0"
|
||||
babel-plugin-transform-react-jsx-self "^6.22.0"
|
||||
babel-plugin-transform-react-jsx-source "^6.22.0"
|
||||
babel-preset-flow "^6.23.0"
|
||||
|
||||
babel-preset-stage-0@^6.16.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.22.0.tgz#707eeb5b415da769eff9c42f4547f644f9296ef9"
|
||||
@@ -1483,7 +1557,7 @@ cheerio@^0.22.0:
|
||||
lodash.reject "^4.4.0"
|
||||
lodash.some "^4.4.0"
|
||||
|
||||
chokidar@^1.4.3:
|
||||
chokidar@^1.4.3, chokidar@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
|
||||
dependencies:
|
||||
@@ -1683,7 +1757,7 @@ commander@2.8.x:
|
||||
dependencies:
|
||||
graceful-readlink ">= 1.0.0"
|
||||
|
||||
commander@2.9.0, commander@^2.5.0, commander@^2.9.0:
|
||||
commander@2.9.0, commander@^2.5.0, commander@^2.8.1, commander@^2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
||||
dependencies:
|
||||
@@ -1693,6 +1767,12 @@ commander@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781"
|
||||
|
||||
common-tags@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0"
|
||||
dependencies:
|
||||
babel-runtime "^6.18.0"
|
||||
|
||||
commondir@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
@@ -3079,6 +3159,10 @@ fs-promise@^0.3.1:
|
||||
dependencies:
|
||||
any-promise "~0.1.0"
|
||||
|
||||
fs-readdir-recursive@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz#8cd1745c8b4f8a29c8caec392476921ba195f560"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@@ -3372,7 +3456,7 @@ gql-utils@^0.0.2:
|
||||
bluebird "^3.4.6"
|
||||
glob "^7.1.1"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
|
||||
version "4.1.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
|
||||
|
||||
@@ -3384,9 +3468,9 @@ graceful-fs@~2.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||
|
||||
graphql-anywhere@^2.0.0, graphql-anywhere@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-2.1.0.tgz#888c0a1718db3ff866b313070747777380560f69"
|
||||
graphql-anywhere@^3.0.0, graphql-anywhere@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.0.1.tgz#73531db861174c8f212eafb9f8e84944b38b4e5a"
|
||||
|
||||
graphql-docs@^0.2.0:
|
||||
version "0.2.0"
|
||||
@@ -3425,10 +3509,18 @@ graphql-server-module-graphiql@^0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.5.2.tgz#7e2a0c78b0267e784f8483ce5633810baf558dee"
|
||||
|
||||
graphql-tag@^1.1.1, graphql-tag@^1.2.3:
|
||||
graphql-tag@^1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-1.2.3.tgz#74c62443fbf3e693647426d7359f7e3e6ce7dace"
|
||||
|
||||
graphql-tag@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-1.3.2.tgz#7abb3a8fd9f3415d07163314ed237061c785b759"
|
||||
|
||||
graphql-tag@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.0.0.tgz#f3efe3b4d64f33bfe8479ae06a461c9d72f2a6fe"
|
||||
|
||||
graphql-tools@^0.9.0:
|
||||
version "0.9.2"
|
||||
resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-0.9.2.tgz#c3f42d0b78d2d6c57cea5ef2894863de34af9a11"
|
||||
@@ -3451,6 +3543,12 @@ graphql@^0.8.2:
|
||||
dependencies:
|
||||
iterall "1.0.2"
|
||||
|
||||
graphql@^0.9.1:
|
||||
version "0.9.2"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.9.2.tgz#2cb5c635de13f790a77c5879649cb401b1589386"
|
||||
dependencies:
|
||||
iterall "1.0.3"
|
||||
|
||||
growl@1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.8.1.tgz#4b2dec8d907e93db336624dcec0183502f8c9428"
|
||||
@@ -3567,6 +3665,10 @@ hoek@2.x.x:
|
||||
version "2.16.3"
|
||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
|
||||
|
||||
hoek@4.x.x:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.1.1.tgz#9cc573ffba2b7b408fb5e9c2a13796be94cddce9"
|
||||
|
||||
hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
|
||||
@@ -4097,6 +4199,10 @@ isemail@1.x.x:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a"
|
||||
|
||||
isemail@2.x.x:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6"
|
||||
|
||||
isexe@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
|
||||
@@ -4195,10 +4301,18 @@ istanbul@^1.1.0-alpha.1:
|
||||
which "^1.1.1"
|
||||
wordwrap "^1.0.0"
|
||||
|
||||
items@2.x.x:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198"
|
||||
|
||||
iterall@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.0.2.tgz#41a2e96ce9eda5e61c767ee5dc312373bb046e91"
|
||||
|
||||
iterall@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.0.3.tgz#e0b31958f835013c323ff0b10943829ac69aa4b7"
|
||||
|
||||
jade@0.26.3:
|
||||
version "0.26.3"
|
||||
resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c"
|
||||
@@ -4212,6 +4326,15 @@ jodid25519@^1.0.0:
|
||||
dependencies:
|
||||
jsbn "~0.1.0"
|
||||
|
||||
joi@^10.4.1:
|
||||
version "10.4.1"
|
||||
resolved "https://registry.yarnpkg.com/joi/-/joi-10.4.1.tgz#a2fca1f0d603d1b843f2c1e086b52461f6be1f36"
|
||||
dependencies:
|
||||
hoek "4.x.x"
|
||||
isemail "2.x.x"
|
||||
items "2.x.x"
|
||||
topo "2.x.x"
|
||||
|
||||
joi@^6.10.1:
|
||||
version "6.10.1"
|
||||
resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06"
|
||||
@@ -5496,6 +5619,14 @@ osenv@^0.1.0:
|
||||
os-homedir "^1.0.0"
|
||||
os-tmpdir "^1.0.0"
|
||||
|
||||
output-file-sync@^1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76"
|
||||
dependencies:
|
||||
graceful-fs "^4.1.4"
|
||||
mkdirp "^0.5.1"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
p-limit@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
|
||||
@@ -6482,11 +6613,13 @@ react-addons-test-utils@^15.4.2:
|
||||
fbjs "^0.8.4"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
react-apollo@^0.10.0:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-0.10.1.tgz#97fd50855f8575672aa68330b9c64a201cd13343"
|
||||
react-apollo@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-1.0.0.tgz#7fcc14adcc7aa4ca4d9e04ddedf50b8fb74daa91"
|
||||
dependencies:
|
||||
graphql-anywhere "^2.0.0"
|
||||
apollo-client "^1.0.0-rc.9"
|
||||
graphql-anywhere "^3.0.0"
|
||||
graphql-tag "^1.3.1"
|
||||
hoist-non-react-statics "^1.2.0"
|
||||
invariant "^2.2.1"
|
||||
lodash.flatten "^4.2.0"
|
||||
@@ -7658,6 +7791,12 @@ topo@1.x.x:
|
||||
dependencies:
|
||||
hoek "2.x.x"
|
||||
|
||||
topo@2.x.x:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182"
|
||||
dependencies:
|
||||
hoek "4.x.x"
|
||||
|
||||
touch@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de"
|
||||
@@ -7816,6 +7955,10 @@ url@^0.11.0:
|
||||
punycode "1.3.2"
|
||||
querystring "0.2.0"
|
||||
|
||||
user-home@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
|
||||
|
||||
user-home@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
|
||||
@@ -7844,6 +7987,12 @@ uuid@^3.0.0, uuid@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
|
||||
|
||||
v8flags@^2.0.10:
|
||||
version "2.0.11"
|
||||
resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881"
|
||||
dependencies:
|
||||
user-home "^1.1.1"
|
||||
|
||||
validate-commit-msg@2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/validate-commit-msg/-/validate-commit-msg-2.5.0.tgz#a7d0a68aa3917171b560664689a2ac59c25908b6"
|
||||
|
||||
Reference in New Issue
Block a user