diff --git a/Dockerfile.onbuild b/Dockerfile.onbuild index 20d34ffb9..dab06f336 100644 --- a/Dockerfile.onbuild +++ b/Dockerfile.onbuild @@ -5,6 +5,7 @@ ONBUILD ARG TALK_THREADING_LEVEL=3 ONBUILD ARG TALK_DEFAULT_STREAM_TAB=all ONBUILD ARG TALK_DEFAULT_LANG=en ONBUILD ARG TALK_PLUGINS_JSON +ONBUILD ARG TALK_WEBPACK_SOURCE_MAP # Bundle app source ONBUILD COPY . /usr/src/app diff --git a/bin/cli-assets b/bin/cli-assets index d14df320b..78229d91b 100755 --- a/bin/cli-assets +++ b/bin/cli-assets @@ -14,6 +14,7 @@ const AssetsService = require('../services/assets'); const mongoose = require('../services/mongoose'); const scraper = require('../services/scraper'); const inquirer = require('inquirer'); +const { URL } = require('url'); // Register the shutdown criteria. util.onshutdown([() => mongoose.disconnect()]); @@ -125,6 +126,70 @@ async function merge(srcID, dstID) { } } +async function rewrite(search, replace, options) { + try { + search = new RegExp(search); + + const assets = await AssetModel.find({ + url: { $regex: search }, + }); + if (assets.length === 0) { + console.log(`No assets found with the pattern: ${search}`); + return util.shutdown(0); + } + + let opts = []; + assets.forEach(({ id, url: oldURL }) => { + // Replace the url. + const newURL = oldURL.replace(search, replace); + + // Try to validate that the new url is valid. + try { + new URL(newURL); + } catch (err) { + throw new Error( + `Rewrite would have replaced the valid URL ${oldURL} with an invalid one ${newURL}` + ); + } + + opts.push({ + find: { id }, + updateOne: { $set: { url: newURL } }, + id, + oldURL, + newURL, + }); + }); + + if (opts.length > 0) { + if (options.dryRun) { + const table = new Table({ head: ['ID', 'Old URL', 'New URL'] }); + + opts.forEach(({ id, oldURL, newURL }) => { + table.push([id, oldURL, newURL]); + }); + + console.log(table.toString()); + } else { + const bulk = AssetModel.collection.initializeUnorderedBulkOp(); + opts.forEach(({ find, updateOne, oldURL, newURL }) => { + // If the url was updated with the operation, then queue up the update op. + if (newURL !== oldURL) { + bulk.find(find).updateOne(updateOne); + } + }); + await bulk.execute(); + console.log(`${opts.length} assets had their url's updated`); + } + } + + util.shutdown(0); + } catch (err) { + console.error(err); + util.shutdown(1); + } +} + //============================================================================== // Setting up the program command line arguments. //============================================================================== @@ -151,6 +216,14 @@ program ) .action(merge); +program + .command('rewrite ') + .option('-d, --dry-run', 'enables dry run of the replacement') + .description( + "rewrites asset url's using the provided regex replacement pattern" + ) + .action(rewrite); + program.parse(process.argv); // If there is no command listed, output help. diff --git a/circle.yml b/circle.yml index cc8ea5725..d45828540 100644 --- a/circle.yml +++ b/circle.yml @@ -19,6 +19,13 @@ machine: # - sudo apt-get install -y mongodb-org # - sudo service mongod restart + # Force sync the time. + - date + - sudo service ntp stop + - sudo ntpdate -s time.nist.gov + - sudo service ntp start + - date + # Install chromium for e2e and remove old google-chrome - sudo rm -rf /opt/google/chrome - sudo rm -f /usr/bin/google-chrome* diff --git a/client/coral-admin/src/components/CommentAnimatedEdit.js b/client/coral-admin/src/components/CommentAnimatedEdit.js index 43fbf9fbf..12280b204 100644 --- a/client/coral-admin/src/components/CommentAnimatedEdit.js +++ b/client/coral-admin/src/components/CommentAnimatedEdit.js @@ -4,7 +4,7 @@ import { CSSTransitionGroup } from 'react-transition-group'; import styles from './CommentAnimatedEdit.css'; import PropTypes from 'prop-types'; -const CommentBodyHighlighter = ({ children, body }) => { +const CommentAnimatedEdit = ({ children, body }) => { return ( { ); }; -CommentBodyHighlighter.propTypes = { +CommentAnimatedEdit.propTypes = { children: PropTypes.node, body: PropTypes.string, }; -export default CommentBodyHighlighter; +export default CommentAnimatedEdit; diff --git a/client/coral-admin/src/components/CommentBodyHighlighter.js b/client/coral-admin/src/components/CommentFormatter.js similarity index 63% rename from client/coral-admin/src/components/CommentBodyHighlighter.js rename to client/coral-admin/src/components/CommentFormatter.js index 9e381bf0b..8874d123f 100644 --- a/client/coral-admin/src/components/CommentBodyHighlighter.js +++ b/client/coral-admin/src/components/CommentFormatter.js @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { matchLinks } from '../utils'; import memoize from 'lodash/memoize'; @@ -62,16 +63,47 @@ function markLinks(body) { return content; } -export default ({ suspectWords, bannedWords, body, ...rest }) => { - // First highlight links. - const content = markLinks(body).map((element, index) => { - // Keep highlighted links. - if (typeof element !== 'string') { - return element; - } +const CommentFormatter = ({ + body, + suspectWords, + bannedWords, + className = 'comment', + ...rest +}) => { + // Breaking the body by line break + const textbreaks = body.split('\n'); - // Highlight suspect and banned phrase inside this part of text. - return markPhrases(element, suspectWords, bannedWords, index); - }); - return
{content}
; + return ( + + {textbreaks.map((line, i) => { + const content = markLinks(line).map((element, index) => { + // Keep highlighted links. + if (typeof element !== 'string') { + return element; + } + + // Highlight suspect and banned phrase inside this part of text. + return markPhrases(element, suspectWords, bannedWords, index); + }); + + return ( + + {content} + {i !== textbreaks.length - 1 && ( +
+ )} +
+ ); + })} +
+ ); }; + +CommentFormatter.propTypes = { + className: PropTypes.string, + bannedWords: PropTypes.array, + suspectWords: PropTypes.array, + body: PropTypes.string, +}; + +export default CommentFormatter; diff --git a/client/coral-admin/src/components/UserDetailComment.js b/client/coral-admin/src/components/UserDetailComment.js index b1cc486ec..2d98edcb3 100644 --- a/client/coral-admin/src/components/UserDetailComment.js +++ b/client/coral-admin/src/components/UserDetailComment.js @@ -5,7 +5,7 @@ import { Link } from 'react-router'; import { Icon } from 'coral-ui'; import CommentDetails from './CommentDetails'; import styles from './UserDetailComment.css'; -import CommentBodyHighlighter from 'coral-admin/src/components/CommentBodyHighlighter'; +import CommentFormatter from 'coral-admin/src/components/CommentFormatter'; import IfHasLink from 'coral-admin/src/components/IfHasLink'; import cn from 'classnames'; import CommentAnimatedEdit from './CommentAnimatedEdit'; @@ -78,11 +78,12 @@ class UserDetailComment extends React.Component {
- {' '} + className="talk-admin-user-detail-comment" + />
- {' '} + /> this.props.updateAssetStatus(this.props.asset.id, { closedAt: null }); - closeAsset = () => - this.props.updateAssetStatus(this.props.asset.id, { - closedAt: new Date().toISOString(), - }); + closeAsset = () => this.props.closeAsset(this.props.asset.id); render() { return ( @@ -29,6 +29,7 @@ class AssetStatusInfoContainer extends React.Component { AssetStatusInfoContainer.propTypes = { asset: PropTypes.object.isRequired, updateAssetStatus: PropTypes.func.isRequired, + closeAsset: PropTypes.func.isRequired, }; const withAssetStatusInfoFragments = withFragments({ @@ -41,6 +42,10 @@ const withAssetStatusInfoFragments = withFragments({ `, }); -const enhance = compose(withAssetStatusInfoFragments, withUpdateAssetStatus); +const enhance = compose( + withAssetStatusInfoFragments, + withUpdateAssetStatus, + withCloseAsset +); export default enhance(AssetStatusInfoContainer); diff --git a/client/coral-framework/graphql/fragments.js b/client/coral-framework/graphql/fragments.js index 2ec92ea6b..a62fd6d92 100644 --- a/client/coral-framework/graphql/fragments.js +++ b/client/coral-framework/graphql/fragments.js @@ -3,27 +3,28 @@ import { createDefaultResponseFragments } from '../utils'; // fragments defined here are automatically registered. export default { ...createDefaultResponseFragments( - 'SetUserRoleResponse', - 'ChangeUsernameResponse', - 'SetUsernameResponse', 'BanUsersResponse', - 'UnbanUserResponse', - 'SetUserSuspensionStatusResponse', - 'SetCommentStatusResponse', - 'SetUsernameStatusResponse', - 'UnsuspendUserResponse', - 'SuspendUserResponse', + 'ChangeUsernameResponse', + 'CloseAssetResponse', 'CreateCommentResponse', - 'CreateFlagResponse', - 'EditCommentResponse', - 'PostFlagResponse', 'CreateDontAgreeResponse', + 'CreateFlagResponse', 'DeleteActionResponse', - 'ModifyTagResponse', + 'EditCommentResponse', 'IgnoreUserResponse', + 'ModifyTagResponse', + 'PostFlagResponse', + 'SetCommentStatusResponse', + 'SetUsernameResponse', + 'SetUsernameStatusResponse', + 'SetUserRoleResponse', + 'SetUserSuspensionStatusResponse', 'StopIgnoringUserResponse', - 'UpdateSettingsResponse', + 'SuspendUserResponse', + 'UnbanUserResponse', + 'UnsuspendUserResponse', 'UpdateAssetSettingsResponse', - 'UpdateAssetStatusResponse' + 'UpdateAssetStatusResponse', + 'UpdateSettingsResponse' ), }; diff --git a/client/coral-framework/graphql/mutations.js b/client/coral-framework/graphql/mutations.js index e5f0bb60e..f34a2cc88 100644 --- a/client/coral-framework/graphql/mutations.js +++ b/client/coral-framework/graphql/mutations.js @@ -665,3 +665,46 @@ export const withUpdateAssetStatus = withMutation( }), } ); + +export const withCloseAsset = withMutation( + gql` + mutation CloseAsset($id: ID!) { + closeAsset(id: $id) { + ...CloseAssetResponse + } + } + `, + { + props: ({ mutate }) => ({ + closeAsset: id => { + return mutate({ + variables: { + id, + }, + optimisticResponse: { + closeAsset: { + __typename: 'CloseAssetResponse', + errors: null, + }, + }, + update: proxy => { + const fragment = gql` + fragment Talk_CloseAssetResponse on Asset { + closedAt + isClosed + } + `; + + const fragmentId = `Asset_${id}`; + const data = { + __typename: 'Asset', + closedAt: new Date(), + isClosed: true, + }; + proxy.writeFragment({ fragment, id: fragmentId, data }); + }, + }); + }, + }), + } +); diff --git a/client/coral-framework/services/i18n.js b/client/coral-framework/services/i18n.js index 6c4aa00a9..91f8560cc 100644 --- a/client/coral-framework/services/i18n.js +++ b/client/coral-framework/services/i18n.js @@ -9,6 +9,8 @@ import 'moment/locale/es'; import 'moment/locale/fr'; import 'moment/locale/pt-br'; +import { createStorage } from 'coral-framework/services/storage'; + import daTA from 'timeago.js/locales/da'; import esTA from 'timeago.js/locales/es'; import frTA from 'timeago.js/locales/fr'; @@ -38,25 +40,35 @@ const translations = { let lang; let timeagoInstance; -function setLocale(locale) { +function setLocale(storage, locale) { try { - localStorage.setItem('locale', locale); + if (storage) { + storage.setItem('locale', locale); + } } catch (err) { console.error(err); } } -function getLocale() { - return ( - localStorage.getItem('locale') || - navigator.language || - defaultLanguage - ).split('-')[0]; +function getLocale(storage) { + try { + return ( + (storage && storage.getItem('locale')) || + navigator.language || + defaultLanguage + ).split('-')[0]; + } catch (err) { + console.error(err); + return null; + } } -function init() { - const locale = getLocale(); - setLocale(locale); +export function setupTranslations() { + // Setup the translation framework with the storage. + const storage = createStorage(); + + const locale = getLocale(storage); + setLocale(storage, locale); // Setting moment moment.locale(locale); @@ -114,4 +126,5 @@ export function t(key, ...replacements) { export default t; -init(); +// Setup the translations globally as soon as this module runs. +setupTranslations(); diff --git a/errors.js b/errors.js index 868be0488..a19afe3c6 100644 --- a/errors.js +++ b/errors.js @@ -265,6 +265,15 @@ const ErrCannotIgnoreStaff = new APIError('Cannot ignore staff members.', { status: 400, }); +// ErrParentDoesNotVisible is returned when the user tries to reply to a comment +// that isn't visible. +const ErrParentDoesNotVisible = new APIError( + 'Cannot reply to a comment that is not visible', + { + translation_key: 'COMMENT_PARENT_NOT_VISIBLE', + } +); + module.exports = { APIError, ErrAlreadyExists, @@ -276,24 +285,25 @@ module.exports = { ErrContainsProfanity, ErrEditWindowHasEnded, ErrEmailTaken, + ErrEmailVerificationToken, ErrInstallLock, ErrInvalidAssetURL, ErrLoginAttemptMaximumExceeded, ErrMaxRateLimit, ErrMissingEmail, ErrMissingPassword, - ErrEmailVerificationToken, - ErrPasswordResetToken, ErrMissingUsername, ErrNotAuthorized, ErrNotFound, ErrNotVerified, + ErrParentDoesNotVisible, + ErrPasswordResetToken, ErrPasswordTooShort, ErrPermissionUpdateUsername, + ErrSameUsernameProvided, ErrSettingsInit, ErrSettingsNotInit, ErrSpecialChars, ErrUsernameTaken, - ErrSameUsernameProvided, ExtendableError, }; diff --git a/graph/mutators/asset.js b/graph/mutators/asset.js index 171c711f0..6524331e1 100644 --- a/graph/mutators/asset.js +++ b/graph/mutators/asset.js @@ -38,11 +38,30 @@ const updateStatus = async (ctx, id, { closedAt, closedMessage }) => } ); +/** + * closeNow will close an asset for commenting. + * + * @param {Object} ctx graphql context + * @param {String} id the asset's id to close + */ +const closeNow = async (ctx, id) => + AssetModel.update( + { + id, + }, + { + $set: { + closedAt: new Date(), + }, + } + ); + module.exports = ctx => { let mutators = { Asset: { updateSettings: () => Promise.reject(errors.ErrNotAuthorized), updateStatus: () => Promise.reject(errors.ErrNotAuthorized), + closeNow: () => Promise.reject(errors.ErrNotAuthorized), }, }; @@ -55,6 +74,7 @@ module.exports = ctx => { if (ctx.user.can(UPDATE_ASSET_STATUS)) { mutators.Asset.updateStatus = (id, status) => updateStatus(ctx, id, status); + mutators.Asset.closeNow = id => closeNow(ctx, id); } } diff --git a/graph/resolvers/root_mutation.js b/graph/resolvers/root_mutation.js index e99a8bd4b..3a646b3d8 100644 --- a/graph/resolvers/root_mutation.js +++ b/graph/resolvers/root_mutation.js @@ -94,6 +94,9 @@ const RootMutation = { ) => { await Asset.updateStatus(id, status); }, + closeAsset: async (_, { id }, { mutators: { Asset } }) => { + await Asset.closeNow(id); + }, setUserRole: async (_, { id, role }, { mutators: { User } }) => { await User.setRole(id, role); }, diff --git a/graph/typeDefs.graphql b/graph/typeDefs.graphql index 375d1edc0..79d1c5b0f 100644 --- a/graph/typeDefs.graphql +++ b/graph/typeDefs.graphql @@ -1111,6 +1111,14 @@ type UpdateAssetStatusResponse implements Response { errors: [UserError!] } +# CloseAssetResponse is the response returned with possibly some errors +# relating to the update status attempt. +type CloseAssetResponse implements Response { + + # An array of errors relating to the mutation that occurred. + errors: [UserError!] +} + # UpdateAssetSettingsResponse is the response returned with possibly some errors # relating to the update settings attempt. type UpdateAssetSettingsResponse implements Response { @@ -1446,6 +1454,9 @@ type RootMutation { # Mutation is restricted. updateAssetStatus(id: ID!, input: UpdateAssetStatusInput!): UpdateAssetStatusResponse + # closeAsset will close the asset for commenting based on server time. + closeAsset(id: ID!): CloseAssetResponse + # updateSettings will update the global settings. # Mutation is restricted. updateSettings(input: UpdateSettingsInput!): UpdateSettingsResponse diff --git a/locales/en.yml b/locales/en.yml index 0bc9ab6fb..1ba2544f7 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -203,6 +203,7 @@ en: embedlink: copy: "Copy to Clipboard" error: + COMMENT_PARENT_NOT_VISIBLE: "The comment that you're replying to has been removed or doesn't exist." EMAIL_VERIFICATION_TOKEN_INVALID: "Email verification token is invalid." PASSWORD_RESET_TOKEN_INVALID: "Your password reset link is invalid." COMMENT_TOO_SHORT: "Comments should be more than one character, please revise your comment and try again." diff --git a/locales/es.yml b/locales/es.yml index 584e83f7b..010119728 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -182,6 +182,7 @@ es: embedlink: copy: "Copiar al portapapeles" error: + COMMENT_PARENT_NOT_VISIBLE: "El comentario a la que estás contestando ha sido eliminado o no existe." COMMENT_TOO_SHORT: "Tu comentario debe tener algo escrito" COMMENTING_CLOSED: "Los comentarios ya estan cerrados" confirm_password: "Las contraseñas no coinciden. Inténtelo nuevamente" diff --git a/models/action.js b/models/action.js index 5e2dc1128..f3414f3ea 100644 --- a/models/action.js +++ b/models/action.js @@ -37,6 +37,17 @@ const ActionSchema = new Schema( } ); +// Create an index on the `item_id` field so that queries looking for +// actions based on the item id can resolve faster. +ActionSchema.index( + { + item_id: 1, + }, + { + background: true, + } +); + const Action = mongoose.model('Action', ActionSchema); module.exports = Action; diff --git a/models/asset.js b/models/asset.js index 1f565a110..68ca08bbf 100644 --- a/models/asset.js +++ b/models/asset.js @@ -41,7 +41,7 @@ const AssetSchema = new Schema( publication_date: Date, modified_date: Date, - // This object is used exclusivly for storing settings that are to override + // This object is used exclusively for storing settings that are to override // the base settings from the base Settings object. This is to be accessed // always after running `rectifySettings` against it. settings: { diff --git a/package.json b/package.json index 9234e4ef7..92dcd7f51 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "start:development": "NODE_ENV=development ./bin/cli-serve -j -w", "start": "NODE_ENV=production ./bin/cli-serve -j -w", "prebuild": "npm-run-all clean generate-introspection", - "build": "NODE_ENV=production webpack -p --bail", + "build": "NODE_ENV=production parallel-webpack --bail", "lint:yaml": "yamllint locales/*.yml", "lint:js": "eslint bin/* .", "lint": "npm-run-all lint:*", @@ -138,6 +138,7 @@ "node-fetch": "^1.7.2", "nodemailer": "^2.6.4", "npm-run-all": "^4.1.2", + "parallel-webpack": "^2.2.0", "passport": "^0.4.0", "passport-jwt": "^3.0.0", "passport-local": "^1.0.0", @@ -178,11 +179,12 @@ "timeago.js": "^2.0.3", "timekeeper": "^1.0.0", "tlds": "^1.196.0", + "uglifyjs-webpack-plugin": "^1.1.6", "url-join": "^2.0.2", "url-loader": "^0.6.0", "url-search-params": "^0.9.0", "uuid": "^3.1.0", - "webpack": "2.4.1", + "webpack": "^3.10.0", "webpack-sources": "^1.0.1", "yaml-loader": "^0.4.0", "yamljs": "^0.2.10" diff --git a/scripts/docker.sh b/scripts/docker.sh index e1e3f9725..06f0cb279 100755 --- a/scripts/docker.sh +++ b/scripts/docker.sh @@ -68,17 +68,16 @@ then docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS fi - if [ "$CIRCLE_BRANCH" = "master" ] + # deploy based on the env + if [ -n "$CIRCLE_TAG" ] then - - # deploy based on the env - if [ -n "$CIRCLE_TAG" ] - then - deploy_tag - else - deploy_latest - fi + deploy_tag else - deploy_branch + if [ "$CIRCLE_BRANCH" = "master" ] + then + deploy_latest + else + deploy_branch + fi fi fi \ No newline at end of file diff --git a/services/comments.js b/services/comments.js index 344115054..e18e04970 100644 --- a/services/comments.js +++ b/services/comments.js @@ -7,24 +7,31 @@ const SettingsService = require('./settings'); const cloneDeep = require('lodash/cloneDeep'); const errors = require('../errors'); const events = require('./events'); +const merge = require('lodash/merge'); const { COMMENTS_NEW, COMMENTS_EDIT } = require('./events/constants'); module.exports = class CommentsService { /** * Creates a new Comment that came from a public source. - * @param {Mixed} comment either a single comment or an array of comments. + * @param {Object} input either a single comment or an array of comments. * @return {Promise} */ - static async publicCreate(comment) { - // Check to see if this is an array of comments, if so map it out. - if (Array.isArray(comment)) { - return Promise.all(comment.map(CommentsService.publicCreate)); + static async publicCreate(input) { + // Extract the parent_id from the comment, if there is one. + const { status = 'NONE', parent_id = null } = input; + + // Check to see if we are replying to a comment, and if that comment is + // visible. + if (parent_id !== null) { + const parent = await CommentModel.findOne({ id: parent_id }); + if (parent === null || !parent.visible) { + throw errors.ErrParentDoesNotVisible; + } } - const { status = 'NONE' } = comment; - - const commentModel = new CommentModel( - Object.assign( + // Create the comment in the database. + const comment = await CommentModel.create( + merge( { status_history: status ? [ @@ -36,21 +43,19 @@ module.exports = class CommentsService { : [], body_history: [ { - body: comment.body, + body: input.body, created_at: new Date(), }, ], }, - comment + input ) ); - const savedCommentModel = await commentModel.save(); - // Emit that the comment was created! - await events.emitAsync(COMMENTS_NEW, savedCommentModel); + await events.emitAsync(COMMENTS_NEW, comment); - return savedCommentModel; + return comment; } /** diff --git a/test/.eslintrc.json b/test/.eslintrc.json index 027872c7d..36b8a3078 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -7,6 +7,6 @@ ], "extends": "../.eslintrc.json", "rules": { - "mocha/no-exclusive-tests": "warn" + "mocha/no-exclusive-tests": "error" } } diff --git a/test/e2e/specs/03_embedStream.js b/test/e2e/specs/03_embedStream.js index 15fb299e4..f45c467e8 100644 --- a/test/e2e/specs/03_embedStream.js +++ b/test/e2e/specs/03_embedStream.js @@ -121,6 +121,9 @@ module.exports = { embedStream.goToConfigSection().closeStream(); + // Pause to give time for action to succeed. + client.pause(1000); + embedStream .goToCommentsSection() .waitForElementVisible('@firstComment') diff --git a/test/server/graph/mutations/createComment.js b/test/server/graph/mutations/createComment.js index 88ca3415a..8a5a98aa1 100644 --- a/test/server/graph/mutations/createComment.js +++ b/test/server/graph/mutations/createComment.js @@ -116,6 +116,8 @@ describe('graph.mutations.createComment', () => { } expect(data.createComment).to.have.property('errors').null; expect(data.createComment).to.have.property('comment').not.null; + expect(data.createComment.comment).to.have.property('id').not + .null; } } ); diff --git a/test/server/graph/queries/asset.js b/test/server/graph/queries/asset.js index af19e4f69..f976bd37d 100644 --- a/test/server/graph/queries/asset.js +++ b/test/server/graph/queries/asset.js @@ -34,12 +34,14 @@ describe('graph.queries.asset', () => { username: 'usernameC', }, ]); - comments = await CommentsService.publicCreate( - [0, 0, 1, 1].map(idx => ({ - author_id: users[idx].id, - asset_id: assets[idx].id, - body: `hello there! ${String(Math.random()).slice(2)}`, - })) + comments = await Promise.all( + [0, 0, 1, 1].map(idx => + CommentsService.publicCreate({ + author_id: users[idx].id, + asset_id: assets[idx].id, + body: `hello there! ${String(Math.random()).slice(2)}`, + }) + ) ); }); diff --git a/test/server/services/assets.js b/test/server/services/assets.js index c071b5634..923f28751 100644 --- a/test/server/services/assets.js +++ b/test/server/services/assets.js @@ -176,28 +176,30 @@ describe('services.AssetsService', () => { ); // Create some comments on both assets. - await CommentsService.publicCreate([ - { - asset_id: '1', - body: 'This is a comment!', - status: 'ACCEPTED', - }, - { - asset_id: '1', - body: 'This is a comment!', - status: 'ACCEPTED', - }, - { - asset_id: '2', - body: 'This is a comment!', - status: 'ACCEPTED', - }, - { - asset_id: '2', - body: 'This is a comment!', - status: 'ACCEPTED', - }, - ]); + await Promise.all( + [ + { + asset_id: '1', + body: 'This is a comment!', + status: 'ACCEPTED', + }, + { + asset_id: '1', + body: 'This is a comment!', + status: 'ACCEPTED', + }, + { + asset_id: '2', + body: 'This is a comment!', + status: 'ACCEPTED', + }, + { + asset_id: '2', + body: 'This is a comment!', + status: 'ACCEPTED', + }, + ].map(comment => CommentsService.publicCreate(comment)) + ); // Merge all the comments from asset 1 into asset 2, followed by deleting // asset 1. diff --git a/test/server/services/comments.js b/test/server/services/comments.js index c9ec1315d..2d0b37163 100644 --- a/test/server/services/comments.js +++ b/test/server/services/comments.js @@ -131,6 +131,64 @@ describe('services.CommentsService', () => { }); describe('#publicCreate()', () => { + describe('does not allow replies to comments that are not visible', () => { + it('parent not found', async () => { + try { + await CommentsService.publicCreate({ + body: 'This is a comment!', + status: 'ACCEPTED', + parent_id: 'does not exist', + }); + throw new Error('comment should not have been created'); + } catch (err) { + expect(err).to.have.property( + 'translation_key', + 'COMMENT_PARENT_NOT_VISIBLE' + ); + } + }); + + it('parent REJECTED', async () => { + try { + const parent = await CommentsService.publicCreate({ + body: 'This is a comment!', + status: 'REJECTED', + }); + await CommentsService.publicCreate({ + body: 'This is a comment!', + status: 'ACCEPTED', + parent_id: parent.id, + }); + throw new Error('comment should not have been created'); + } catch (err) { + expect(err).to.have.property( + 'translation_key', + 'COMMENT_PARENT_NOT_VISIBLE' + ); + } + }); + + it('parent SYSTEM_WITHHELD', async () => { + try { + const parent = await CommentsService.publicCreate({ + body: 'This is a comment!', + status: 'SYSTEM_WITHHELD', + }); + await CommentsService.publicCreate({ + body: 'This is a comment!', + status: 'ACCEPTED', + parent_id: parent.id, + }); + throw new Error('comment should not have been created'); + } catch (err) { + expect(err).to.have.property( + 'translation_key', + 'COMMENT_PARENT_NOT_VISIBLE' + ); + } + }); + }); + it('creates a new comment', async () => { const c = await CommentsService.publicCreate({ body: 'This is a comment!', @@ -142,31 +200,6 @@ describe('services.CommentsService', () => { expect(c.id).to.be.uuid; expect(c.status).to.be.equal('ACCEPTED'); }); - - it('creates many new comments', async () => { - const [c1, c2, c3] = await CommentsService.publicCreate([ - { - body: 'This is a comment!', - status: 'ACCEPTED', - }, - { - body: 'This is another comment!', - }, - { - body: 'This is a rejected comment!', - status: 'REJECTED', - }, - ]); - - expect(c1).to.not.be.null; - expect(c1.status).to.be.equal('ACCEPTED'); - - expect(c2).to.not.be.null; - expect(c2.status).to.be.equal('NONE'); - - expect(c3).to.not.be.null; - expect(c3.status).to.be.equal('REJECTED'); - }); }); describe('#edit', () => { diff --git a/webpack.config.js b/webpack.config.js index cb3327fe7..d46c2cb7d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,6 +7,7 @@ const precss = require('precss'); const _ = require('lodash'); const Copy = require('copy-webpack-plugin'); const webpack = require('webpack'); +const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); const debug = require('debug')('talk:webpack'); // Possibly load the config from the .env file (if there is one). @@ -22,12 +23,30 @@ const buildTargets = ['coral-admin', 'coral-docs']; const buildEmbeds = ['stream']; +// In production, default turn off source maps. In development, default use +// 'cheap-module-source-map'. +const DEFAULT_WEBPACK_SOURCE_MAP = + process.env.NODE_ENV === 'production' ? 'none' : 'cheap-module-source-map'; + +// TALK_WEBPACK_SOURCE_MAP is sourced from the environment, defaulting based on +// the environment. +const TALK_WEBPACK_SOURCE_MAP = _.get( + process.env, + 'TALK_WEBPACK_SOURCE_MAP', + DEFAULT_WEBPACK_SOURCE_MAP +); + +// Set the devtool based on the source map selection, 'none' just means turn off +// source maps. +const devtool = + TALK_WEBPACK_SOURCE_MAP === 'none' ? false : TALK_WEBPACK_SOURCE_MAP; + //============================================================================== // Base Webpack Config //============================================================================== const config = { - devtool: 'cheap-module-source-map', + devtool, target: 'web', output: { path: path.join(__dirname, 'dist'), @@ -99,6 +118,7 @@ const config = { new webpack.DefinePlugin({ 'process.env': { VERSION: `"${require('./package.json').version}"`, + NODE_ENV: `${JSON.stringify(process.env.NODE_ENV)}`, }, }), new webpack.EnvironmentPlugin({ @@ -153,6 +173,44 @@ const config = { if (process.env.NODE_ENV === 'production') { config.plugins.push( + // Pulled from https://slack.engineering/keep-webpack-fast-a-field-guide-for-better-build-performance-f56a5995e8f1 + new UglifyJsPlugin({ + uglifyOptions: { + compress: { + arrows: false, + booleans: false, + collapse_vars: false, + comparisons: false, + computed_props: false, + hoist_funs: false, + hoist_props: false, + hoist_vars: false, + if_return: false, + inline: false, + join_vars: false, + keep_infinity: true, + loops: false, + negate_iife: false, + properties: false, + reduce_funcs: false, + reduce_vars: false, + sequences: false, + side_effects: false, + switches: false, + top_retain: false, + toplevel: false, + typeofs: false, + unused: false, + + // Switch off all types of compression except those needed to convince + // react-devtools that we're using a production build + conditionals: true, + dead_code: true, + evaluate: true, + }, + mangle: true, + }, + }), new CompressionPlugin({ algorithm: 'gzip', asset: '[path].gz[query]', diff --git a/yarn.lock b/yarn.lock index 53de65471..5df93e694 100644 --- a/yarn.lock +++ b/yarn.lock @@ -153,8 +153,8 @@ acorn@^4.0.3, acorn@^4.0.4, acorn@~4.0.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" acorn@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" + version "5.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" acorn@^5.2.1: version "5.2.1" @@ -171,15 +171,11 @@ agent-base@2: extend "~3.0.0" semver "~5.0.1" -ajv-keywords@^1.1.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - -ajv-keywords@^2.1.0: +ajv-keywords@^2.0.0, ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" -ajv@^4.7.0, ajv@^4.9.1: +ajv@^4.9.1, ajv@^4.9.2: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: @@ -195,7 +191,7 @@ ajv@^5.0.0: json-schema-traverse "^0.3.0" json-stable-stringify "^1.0.1" -ajv@^5.1.0, ajv@^5.2.3, ajv@^5.3.0: +ajv@^5.1.0, ajv@^5.1.5, ajv@^5.2.3, ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: @@ -456,8 +452,8 @@ asap@^2.0.0, asap@~2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" asn1.js@^4.0.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.1.tgz#48ba240b45a9280e94748990ba597d216617fd40" + version "4.9.2" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a" dependencies: bn.js "^4.0.0" inherits "^2.0.1" @@ -511,7 +507,7 @@ async@2.1.4: dependencies: lodash "^4.14.0" -async@2.4.1, async@^2.1.2: +async@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7" dependencies: @@ -521,7 +517,7 @@ async@^1.4.0, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.1.4, async@~2.6.0: +async@^2.1.2, async@^2.1.4, async@~2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" dependencies: @@ -1261,7 +1257,7 @@ bluebird@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" -bluebird@3.5.1, bluebird@^3.3.4, bluebird@^3.4.6, bluebird@^3.5.0: +bluebird@3.5.1, bluebird@^3.0.6, bluebird@^3.3.4, bluebird@^3.4.6, bluebird@^3.5.0: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -1368,8 +1364,8 @@ browser-stdout@1.3.0: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.0.tgz#1d2ad62a8b479f23f0ab631c1be86a82dbccbe48" + version "1.1.1" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f" dependencies: buffer-xor "^1.0.3" cipher-base "^1.0.0" @@ -1413,11 +1409,11 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" dependencies: - pako "~0.2.0" + pako "~1.0.5" browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: version "1.7.7" @@ -1959,6 +1955,10 @@ commander@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" +commander@~2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + common-tags@^1.4.0: version "1.5.1" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.5.1.tgz#e2e39931a013cd02253defeed89a1ad615a27f07" @@ -2228,8 +2228,8 @@ cryptiles@3.x.x: boom "5.x.x" crypto-browserify@^3.11.0: - version "3.11.1" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.1.tgz#948945efc6757a400d6e5e5af47194d10064279f" + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" dependencies: browserify-cipher "^1.0.0" browserify-sign "^4.0.0" @@ -2241,6 +2241,7 @@ crypto-browserify@^3.11.0: pbkdf2 "^3.0.3" public-encrypt "^4.0.0" randombytes "^2.0.0" + randomfill "^1.0.3" crypto-random-string@^1.0.0: version "1.0.0" @@ -2393,6 +2394,12 @@ d3-helpers@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/d3-helpers/-/d3-helpers-0.3.0.tgz#4b31dce4a2121a77336384574d893fbed5fb293d" +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -2691,6 +2698,10 @@ duplexify@^3.1.2, duplexify@^3.4.2: readable-stream "^2.0.0" stream-shift "^1.0.0" +easy-stack@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/easy-stack/-/easy-stack-1.0.0.tgz#12c91b3085a37f0baa336e9486eac4bf94e3e788" + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -2748,7 +2759,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^3.0.0: +enhanced-resolve@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" dependencies: @@ -2814,7 +2825,13 @@ enzyme@^3.0.0: raf "^3.4.0" rst-selector-parser "^2.2.3" -errno@^0.1.3, errno@^0.1.4: +errno@^0.1.3: + version "0.1.6" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026" + dependencies: + prr "~1.0.1" + +errno@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" dependencies: @@ -2854,6 +2871,32 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" +es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.38" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.38.tgz#fa7d40d65bbc9bb8a67e1d3f9cc656a00530eed3" + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + es6-promise@3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4" @@ -2862,6 +2905,32 @@ es6-promise@^4.0.5: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a" +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-weak-map@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + dependencies: + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2885,6 +2954,15 @@ escodegen@1.x.x, escodegen@^1.6.1: optionalDependencies: source-map "~0.5.6" +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-config-prettier@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" @@ -3018,6 +3096,17 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + dependencies: + d "1" + es5-ext "~0.10.14" + +event-pubsub@4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/event-pubsub/-/event-pubsub-4.3.0.tgz#f68d816bc29f1ec02c539dc58c8dd40ce72cb36e" + event-stream@~3.3.0: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" @@ -4198,9 +4287,9 @@ httpreq@>=0.4.22: version "0.4.24" resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.4.24.tgz#4335ffd82cd969668a39465c929ac61d6393627f" -https-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" https-proxy-agent@1, https-proxy-agent@^1.0.0: version "1.0.0" @@ -4405,7 +4494,7 @@ inquirer@3.3.0, inquirer@^3.0.6, inquirer@^3.2.2: strip-ansi "^4.0.0" through "^2.3.6" -interpret@^1.0.0: +interpret@^1.0.0, interpret@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" @@ -5072,6 +5161,16 @@ js-base64@^2.1.9: version "2.3.2" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf" +js-message@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/js-message/-/js-message-1.0.5.tgz#2300d24b1af08e89dd095bc1a4c9c9cfcb892d15" + +js-queue@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/js-queue/-/js-queue-2.0.0.tgz#362213cf860f468f0125fc6c96abc1742531f948" + dependencies: + easy-stack "^1.0.0" + js-stringify@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" @@ -5428,7 +5527,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@^0.2.15, loader-utils@^0.2.16: +loader-utils@^0.2.15: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" dependencies: @@ -5437,7 +5536,7 @@ loader-utils@^0.2.15, loader-utils@^0.2.16: json5 "^0.5.0" object-assign "^4.0.1" -loader-utils@^1.0.2: +loader-utils@^1.0.2, loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" dependencies: @@ -5514,7 +5613,7 @@ lodash._stack@^4.0.0: version "4.1.3" resolved "https://registry.yarnpkg.com/lodash._stack/-/lodash._stack-4.1.3.tgz#751aa76c1b964b047e76d14fc72a093fcb5e2dd0" -lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.1.0, lodash.assign@^4.2.0: +lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.0.8, lodash.assign@^4.1.0, lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" @@ -5569,7 +5668,11 @@ lodash.difference@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" -lodash.flatten@^4.4.0: +lodash.endswith@^4.0.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" + +lodash.flatten@^4.2.0, lodash.flatten@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" @@ -6268,29 +6371,37 @@ node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" +node-ipc@^9.1.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/node-ipc/-/node-ipc-9.1.1.tgz#4e245ed6938e65100e595ebc5dc34b16e8dd5d69" + dependencies: + event-pubsub "4.3.0" + js-message "1.0.5" + js-queue "2.0.0" + node-libs-browser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646" + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" dependencies: assert "^1.1.1" - browserify-zlib "^0.1.4" + browserify-zlib "^0.2.0" buffer "^4.3.0" console-browserify "^1.1.0" constants-browserify "^1.0.0" crypto-browserify "^3.11.0" domain-browser "^1.1.1" events "^1.0.0" - https-browserify "0.0.1" - os-browserify "^0.2.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" path-browserify "0.0.0" - process "^0.11.0" + process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" - readable-stream "^2.0.5" + readable-stream "^2.3.3" stream-browserify "^2.0.1" - stream-http "^2.3.1" - string_decoder "^0.10.25" - timers-browserify "^2.0.2" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" tty-browserify "0.0.0" url "^0.11.0" util "^0.10.3" @@ -6595,9 +6706,9 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -os-browserify@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" @@ -6687,9 +6798,9 @@ package-json@^4.0.0: registry-url "^3.0.3" semver "^5.1.0" -pako@~0.2.0: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" +pako@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" parallel-transform@^1.1.0: version "1.1.0" @@ -6699,6 +6810,23 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" +parallel-webpack@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parallel-webpack/-/parallel-webpack-2.2.0.tgz#7171440b684444610ba890d32439a33666ab46cb" + dependencies: + ajv "^4.9.2" + bluebird "^3.0.6" + chalk "^1.1.1" + interpret "^1.0.1" + lodash.assign "^4.0.8" + lodash.endswith "^4.0.1" + lodash.flatten "^4.2.0" + minimist "^1.2.0" + node-ipc "^9.1.0" + pluralize "^1.2.1" + supports-color "^3.1.2" + worker-farm "^1.3.1" + parse-asn1@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" @@ -6918,6 +7046,10 @@ pluralize@7.0.0, pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + pop-iterate@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/pop-iterate/-/pop-iterate-1.0.1.tgz#ceacfdab4abf353d7a0f2aaa2c1fc7b3f9413ba3" @@ -7435,7 +7567,7 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -process@^0.11.0: +process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -7499,6 +7631,10 @@ prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + ps-tree@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" @@ -7732,12 +7868,19 @@ randomatic@^1.1.3: is-number "^3.0.0" kind-of "^4.0.0" -randombytes@^2.0.0, randombytes@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79" +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" dependencies: safe-buffer "^5.1.0" +randomfill@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -7751,7 +7894,7 @@ raw-body@2, raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" -rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: +rc@^1.0.1, rc@^1.1.6: version "1.2.2" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077" dependencies: @@ -7760,6 +7903,15 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +rc@^1.1.7: + version "1.2.4" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.4.tgz#a0f606caae2a3b862bbd0ef85482c0125b315fa3" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-addons-create-fragment@^15.0.0: version "15.6.2" resolved "https://registry.yarnpkg.com/react-addons-create-fragment/-/react-addons-create-fragment-15.6.2.tgz#a394de7c2c7becd6b5475ba1b97ac472ce7c74f8" @@ -7956,7 +8108,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -7986,7 +8138,7 @@ readable-stream@1.1.x: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@2.2.7, readable-stream@^2.0.1, readable-stream@^2.2.6: +readable-stream@2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1" dependencies: @@ -8449,6 +8601,13 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" +schema-utils@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.3.tgz#e2a594d3395834d5e15da22b48be13517859458e" + dependencies: + ajv "^5.0.0" + ajv-keywords "^2.1.0" + secure-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/secure-keys/-/secure-keys-1.0.0.tgz#f0c82d98a3b139a8776a8808050b824431087fca" @@ -8485,7 +8644,11 @@ semver-regex@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9" -"semver@2 || 3 || 4 || 5", semver@5.4.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1: +"semver@2 || 3 || 4 || 5", semver@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +semver@5.4.1, semver@^5.0.3, semver@^5.1.0, semver@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -8757,10 +8920,6 @@ sort-keys@^1.0.0: dependencies: is-plain-obj "^1.0.0" -source-list-map@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1" - source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" @@ -8789,7 +8948,7 @@ source-map@0.4.x, source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6: +source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -8877,13 +9036,13 @@ stream-each@^1.1.0: end-of-stream "^1.1.0" stream-shift "^1.0.0" -stream-http@^2.3.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" +stream-http@^2.7.2: + version "2.8.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.1" - readable-stream "^2.2.6" + readable-stream "^2.3.3" to-arraybuffer "^1.0.0" xtend "^4.0.0" @@ -8935,16 +9094,16 @@ string.prototype.padend@^3.0.0: es-abstract "^1.4.3" function-bind "^1.0.2" -string_decoder@^0.10.25, string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.0.0, string_decoder@~1.0.3: +string_decoder@^1.0.0, string_decoder@~1.0.0, string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" dependencies: safe-buffer "~5.1.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + stringstream@~0.0.4, stringstream@~0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -9048,13 +9207,13 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3: +supports-color@^3.1.2, supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: has-flag "^1.0.0" -supports-color@^4, supports-color@^4.0.0, supports-color@^4.4.0: +supports-color@^4, supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" dependencies: @@ -9095,7 +9254,7 @@ table@^4.0.1: slice-ansi "1.0.0" string-width "^2.1.1" -tapable@^0.2.7, tapable@~0.2.5: +tapable@^0.2.7: version "0.2.8" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22" @@ -9209,7 +9368,7 @@ timekeeper@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-1.0.0.tgz#2f38aee1e94b11dd66d8580ff1aa9dcc6a2ba0d8" -timers-browserify@^2.0.2: +timers-browserify@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6" dependencies: @@ -9379,11 +9538,18 @@ uc.micro@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" +uglify-es@^3.3.4: + version "3.3.7" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.7.tgz#d1249af668666aba7cb1163e277455be9eb393cf" + dependencies: + commander "~2.13.0" + source-map "~0.6.1" + uglify-js@1.x: version "1.3.5" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-1.3.5.tgz#4b5bfff9186effbaa888e4c9e94bd9fc4c94929d" -uglify-js@^2.6, uglify-js@^2.6.1, uglify-js@^2.8.5: +uglify-js@^2.6, uglify-js@^2.6.1, uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: @@ -9396,6 +9562,27 @@ uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" +uglifyjs-webpack-plugin@^0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz#b951f4abb6bd617e66f63eb891498e391763e309" + dependencies: + source-map "^0.5.6" + uglify-js "^2.8.29" + webpack-sources "^1.0.1" + +uglifyjs-webpack-plugin@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.1.6.tgz#f4ba8449edcf17835c18ba6ae99b9d610857fb19" + dependencies: + cacache "^10.0.1" + find-cache-dir "^1.0.0" + schema-utils "^0.4.2" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + uglify-es "^3.3.4" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" + uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -9537,7 +9724,11 @@ uuid@^2.0.1, uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" -uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: +uuid@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + +uuid@^3.0.1, uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" @@ -9608,7 +9799,7 @@ watch@~0.18.0: exec-sh "^0.2.0" minimist "^1.2.0" -watchpack@^1.3.1: +watchpack@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac" dependencies: @@ -9632,45 +9823,39 @@ webidl-conversions@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" -webpack-sources@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb" - dependencies: - source-list-map "^1.1.1" - source-map "~0.5.3" - -webpack-sources@^1.0.1, webpack-sources@^1.0.2: +webpack-sources@^1.0.1, webpack-sources@^1.0.2, webpack-sources@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54" dependencies: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.4.1.tgz#15a91dbe34966d8a4b99c7d656efd92a2e5a6f6a" +webpack@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.10.0.tgz#5291b875078cf2abf42bdd23afe3f8f96c17d725" dependencies: acorn "^5.0.0" acorn-dynamic-import "^2.0.0" - ajv "^4.7.0" - ajv-keywords "^1.1.1" + ajv "^5.1.5" + ajv-keywords "^2.0.0" async "^2.1.2" - enhanced-resolve "^3.0.0" + enhanced-resolve "^3.4.0" + escope "^3.6.0" interpret "^1.0.0" json-loader "^0.5.4" json5 "^0.5.1" loader-runner "^2.3.0" - loader-utils "^0.2.16" + loader-utils "^1.1.0" memory-fs "~0.4.1" mkdirp "~0.5.0" node-libs-browser "^2.0.0" source-map "^0.5.3" - supports-color "^3.1.0" - tapable "~0.2.5" - uglify-js "^2.8.5" - watchpack "^1.3.1" - webpack-sources "^0.2.3" - yargs "^6.0.0" + supports-color "^4.2.1" + tapable "^0.2.7" + uglifyjs-webpack-plugin "^0.4.6" + watchpack "^1.4.0" + webpack-sources "^1.0.1" + yargs "^8.0.2" whatwg-encoding@^1.0.1: version "1.0.1" @@ -9782,6 +9967,13 @@ worker-farm@^1.3.1: errno "^0.1.4" xtend "^4.0.1" +worker-farm@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.2.tgz#32b312e5dc3d5d45d79ef44acc2587491cd729ae" + dependencies: + errno "^0.1.4" + xtend "^4.0.1" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -9890,12 +10082,6 @@ yargs-parser@^3.2.0: camelcase "^3.0.0" lodash.assign "^4.1.0" -yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - dependencies: - camelcase "^3.0.0" - yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" @@ -9952,23 +10138,23 @@ yargs@^5.0.0: y18n "^3.2.1" yargs-parser "^3.2.0" -yargs@^6.0.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" +yargs@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" dependencies: - camelcase "^3.0.0" + camelcase "^4.1.0" cliui "^3.2.0" decamelize "^1.1.1" get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" + string-width "^2.0.0" + which-module "^2.0.0" y18n "^3.2.1" - yargs-parser "^4.2.0" + yargs-parser "^7.0.0" yargs@^9.0.0: version "9.0.1"