diff --git a/README.md b/README.md index 7099c5b1b78c887d30e06463b54698871abdc115..ca0f91f81e9a6abe154cc83c6bc3f4ddef5ddb21 100644 --- a/README.md +++ b/README.md @@ -47,3 +47,9 @@ Contact us at technology@hindawi.com for help getting setup. ## Community Join [the Mattermost channel](https://mattermost.coko.foundation/coko/channels/xpub) for discussion of xpub. + + +## Migrations + +1. use folder `./packages/xpub-faraday/migrations` +2. add file named `${number}-${name}(.sql/.js)` e.g. `001-user-add-name-field.sql` diff --git a/packages/component-faraday-selectors/src/index.js b/packages/component-faraday-selectors/src/index.js index 5801110f0164d57e8d2e4cf366f20b639fed611c..0ab630ff6cb341f42ab8850b631ba4d270f26f10 100644 --- a/packages/component-faraday-selectors/src/index.js +++ b/packages/component-faraday-selectors/src/index.js @@ -1,5 +1,5 @@ -import { get, has, last, chain, some } from 'lodash' import { selectCurrentUser } from 'xpub-selectors' +import { get, has, last, chain, some } from 'lodash' export const isHEToManuscript = (state, collectionId = '') => { const { id = '', isAccepted = false } = chain(state) @@ -199,9 +199,7 @@ export const getHERecommendation = (state, collectionId, fragmentId) => { } const canMakeDecisionStatuses = ['submitted', 'pendingApproval'] -export const canMakeDecision = (state, collection = {}, fragment = {}) => { - if (get(fragment, 'id', '') !== last(get(collection, 'fragments', []))) - return false +export const canMakeDecision = (state, collection = {}) => { const status = get(collection, 'status', 'draft') const isEIC = currentUserIs(state, 'adminEiC') @@ -256,11 +254,11 @@ export const currentUserIsAuthor = (state, id) => { .includes(id) } -export const getUserPermissions = ({ currentUser }) => - get(currentUser, 'user.teams', []).map(t => ({ - objectId: t.object.id, - objectType: t.object.type, - role: t.teamType.permissions, +export const getUserPermissions = ({ teams = [] }) => + teams.map(t => ({ + objectId: get(t, 'object.id', ''), + objectType: get(t, 'object.type', ''), + role: get(t, 'teamType.permissions', ''), })) export const userNotConfirmed = ({ currentUser }) => @@ -412,18 +410,6 @@ export const getOwnSubmittedRecommendation = (state, fragmentId) => ) .value() -const canMakeRecommendationStatuses = [ - 'heAssigned', - 'underReview', - 'reviewCompleted', -] -export const canMakeRecommendation = (state, collection, fragment = {}) => { - if (fragment.id !== last(get(collection, 'fragments', []))) return false - const isHE = isHEToManuscript(state, get(collection, 'id', '')) - const status = get(collection, 'status', 'draft') - return isHE && canMakeRecommendationStatuses.includes(status) -} - export const canSubmitRevision = (state, fragment = {}) => { const userId = get(state, 'currentUser.user.id') const fragmentAuthors = chain(fragment) @@ -453,3 +439,14 @@ export const getVersionOptions = (state, collection = {}) => { .reverse() .value() } + +export const canReview = (state, collection = {}, fragment = {}) => { + const fragmentId = get(fragment, 'id', false) + + if (!fragmentId) return false + + const isReviewer = currentUserIsReviewer(state, fragmentId) + if (!isReviewer) return false + + return get(collection, 'status', 'draft') === 'underReview' +} diff --git a/packages/component-faraday-ui/src/ReviewerReportAuthor.js b/packages/component-faraday-ui/src/ReviewerReportAuthor.js index 297653497f8a77be8c9bf20135ca64c7c21a54a4..4df5745b8ce86a109bad547466f3fe5ff57f94de 100644 --- a/packages/component-faraday-ui/src/ReviewerReportAuthor.js +++ b/packages/component-faraday-ui/src/ReviewerReportAuthor.js @@ -1,16 +1,24 @@ import React, { Fragment } from 'react' import { get } from 'lodash' -import { withProps } from 'recompose' +import { withProps, compose } from 'recompose' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { DateParser } from '@pubsweet/ui' -import { Label, Item, FileItem, Row, Text } from './' +import { + Label, + Item, + FileItem, + Row, + Text, + withFilePreview, + withFileDownload, +} from './' const ReviewerReportAuthor = ({ - onPreview, - onDownload, reviewFile, + previewFile, + downloadFile, publicReport, reviewerName, reviewerIndex, @@ -45,8 +53,8 @@ const ReviewerReportAuthor = ({ <Item flex={0} mr={1}> <FileItem item={reviewFile} - onDownload={onDownload} - onPreview={onPreview} + onDownload={downloadFile} + onPreview={previewFile} /> </Item> </Row> @@ -55,20 +63,24 @@ const ReviewerReportAuthor = ({ </Root> ) -export default withProps(({ report, journal: { recommendations = [] } }) => ({ - recommendation: get( - recommendations.find(r => r.value === report.recommendation), - 'label', - ), - reviewFile: get(report, 'comments.0.files.0'), - publicReport: get(report, 'comments.0.content'), - reviewerName: `${get(report, 'reviewer.firstName', '')} ${get( - report, - 'reviewer.lastName', - '', - )}`, - reviewerIndex: get(report, 'reviewerIndex', ''), -}))(ReviewerReportAuthor) +export default compose( + withFilePreview, + withFileDownload, + withProps(({ report, journal: { recommendations = [] } }) => ({ + recommendation: get( + recommendations.find(r => r.value === report.recommendation), + 'label', + ), + reviewFile: get(report, 'comments.0.files.0'), + publicReport: get(report, 'comments.0.content'), + reviewerName: `${get(report, 'reviewer.firstName', '')} ${get( + report, + 'reviewer.lastName', + '', + )}`, + reviewerIndex: get(report, 'reviewerIndex', ''), + })), +)(ReviewerReportAuthor) // #region styles const Root = styled.div` diff --git a/packages/component-faraday-ui/src/Tag.js b/packages/component-faraday-ui/src/Tag.js index 856a69c88fb0f25ed6a64ed3368221239d961d81..fd6ce0316577b29f1ca95619cdd180a860209c54 100644 --- a/packages/component-faraday-ui/src/Tag.js +++ b/packages/component-faraday-ui/src/Tag.js @@ -1,27 +1,41 @@ -import styled, { css } from 'styled-components' +import { has } from 'lodash' import { th } from '@pubsweet/ui-toolkit' +import styled, { css } from 'styled-components' import { marginHelper } from './styledHelpers' -export const tagCSS = ({ status }) => - status - ? css` - padding: calc(${th('gridUnit')} / 4) ${th('gridUnit')}; - height: 24px; - font-family: ${th('fontHeading')}; - ` - : css` - height: 14px; - font-size: 85%; - padding: calc(${th('gridUnit')} / 4) calc(${th('gridUnit')} / 4) 0px; - margin-right: 1px; - font-family: ${th('fontInterface')}; - ` +const tagCSS = props => { + if (has(props, 'oldStatus')) { + return css` + background-color: ${th('colorFurnitureHue')}; + height: calc(${th('gridUnit')} * 3) + font-weight: ${th('tag.fontWeight')}; + padding: calc(${th('gridUnit')} / 2) ${th('gridUnit')} 0px + ${th('gridUnit')}; + ` + } + + if (has(props, `status`)) { + return css` + background-color: ${th('tag.statusBackgroundColor')}; + padding: calc(${th('gridUnit')} / 4) ${th('gridUnit')}; + height: 24px; + font-family: ${th('fontHeading')}; + ` + } + + return css` + background-color: ${th('tag.backgroundColor')}; + height: 14px; + font-size: 85%; + padding: calc(${th('gridUnit')} / 4) calc(${th('gridUnit')} / 4) 0px; + margin-right: 1px; + font-family: ${th('fontInterface')}; + ` +} /** @component */ export default styled.div` - background-color: ${({ status }) => - status ? th('tag.statusBackgroundColor') : th('tag.backgroundColor')}; border-radius: ${th('tag.borderRadius') ? th('tag.borderRadius') : th('borderRadius')}; diff --git a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js index 105b76fc04c6a4046c794398157ee770135ad538..5518b3ebfa9c3803816c871f4f8b32b717c468d3 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js +++ b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js @@ -15,7 +15,14 @@ const SubmittedReportsNumberForAuthorReviews = ({ reports }) => ( </Row> ) -const AuthorReviews = ({ invitations, journal, reports, fragment }) => +const AuthorReviews = ({ + invitations, + journal, + reports, + fragment, + token, + getSignedUrl, +}) => reports.length > 0 && ( <ContextualBox label="Reviewer Reports" @@ -24,11 +31,13 @@ const AuthorReviews = ({ invitations, journal, reports, fragment }) => <SubmittedReportsNumberForAuthorReviews reports={reports.length} /> } > - {reports.map((r, i) => ( + {reports.map(r => ( <ReviewerReportAuthor + getSignedUrl={getSignedUrl} journal={journal} key={r.id} - report={reports[i]} + report={r} + token={token} /> ))} </ContextualBox> diff --git a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js index 487d83cb1fa6c387883a108fd1f8644897711ce9..4d3d4b181d864cd2b5c829ad06902b058a3c09ec 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js +++ b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js @@ -5,8 +5,8 @@ import { ContextualBox, AuthorReply } from '../' const ResponseToRevisionRequest = ({ fragment, authorReply, - expanded, toggle, + expanded, }) => ( <ContextualBox expanded={expanded} diff --git a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js index efa929afe32fd35476948eca48e366414aaa3c15..d8a41b821abe0639bbb6f9cfbe6ffe17b9f75189 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js +++ b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js @@ -40,6 +40,7 @@ const ReviewerDetails = ({ highlight, canViewReviewersDetails, authorCanViewReportsDetails, + isLatestVersion, ...rest }) => ( <ContextualBox @@ -62,17 +63,18 @@ const ReviewerDetails = ({ > <H4>Reviewer Details</H4> </TabButton> - {canInviteReviewers && ( - <TabButton - data-test-id="reviewer-tab-suggestions" - ml={1} - mr={1} - onClick={() => changeTab(2)} - selected={selectedTab === 2} - > - <H4>Reviewer Suggestions</H4> - </TabButton> - )} + {canInviteReviewers && + isLatestVersion && ( + <TabButton + data-test-id="reviewer-tab-suggestions" + ml={1} + mr={1} + onClick={() => changeTab(2)} + selected={selectedTab === 2} + > + <H4>Reviewer Suggestions</H4> + </TabButton> + )} <TabButton data-test-id="reviewer-tab-reports" ml={1} @@ -87,12 +89,13 @@ const ReviewerDetails = ({ <TabContent> {selectedTab === 0 && ( <Fragment> - {canInviteReviewers && ( - <InviteReviewers - modalKey="invite-reviewers" - onInvite={onInviteReviewer} - /> - )} + {canInviteReviewers && + isLatestVersion && ( + <InviteReviewers + modalKey="invite-reviewers" + onInvite={onInviteReviewer} + /> + )} <ReviewersTable invitations={invitations} @@ -101,14 +104,15 @@ const ReviewerDetails = ({ /> </Fragment> )} - {selectedTab === 2 && ( - <PublonsTable - onInvite={onInvitePublonReviewer} - publonsError={fetchingError} - publonsFetching={isFetching} - reviewers={publonReviewers} - /> - )} + {selectedTab === 2 && + isLatestVersion && ( + <PublonsTable + onInvite={onInvitePublonReviewer} + publonsError={fetchingError} + publonsFetching={isFetching} + reviewers={publonReviewers} + /> + )} {selectedTab === 1 && ( <Fragment> {reports.length === 0 && ( diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js index b7e6f5389f196f87344e2b5f35a2f0630117c644..f93e6c4c396f67836c8d1142000cc05682aac647 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js @@ -23,6 +23,7 @@ const ManuscriptHeader = ({ manuscriptType = {}, editorInChief = 'Unassigned', collection: { visibleStatus = 'Draft', customId, handlingEditor }, + isLatestVersion, }) => { const { authors = [], metadata = {}, submitted = null } = fragment const { title = 'No title', journal = '', type = '' } = metadata @@ -34,9 +35,13 @@ const ManuscriptHeader = ({ justify="space-between" > <H2 mb={1}>{title}</H2> - <Tag data-test-id="fragment-status" status> - {visibleStatus} - </Tag> + {isLatestVersion ? ( + <Tag data-test-id="fragment-status" status> + {visibleStatus} + </Tag> + ) : ( + <Tag oldStatus>Viewing an Older Version</Tag> + )} </Row> {authors.length > 0 && ( <Row diff --git a/packages/component-fixture-manager/src/fixtures/collectionIDs.js b/packages/component-fixture-manager/src/fixtures/collectionIDs.js index b76d29095f8be6cef5c9076d692ca9f46f00fab0..5b0da41bf1758f75c2b1394ca7f42ef812761ccc 100644 --- a/packages/component-fixture-manager/src/fixtures/collectionIDs.js +++ b/packages/component-fixture-manager/src/fixtures/collectionIDs.js @@ -6,4 +6,5 @@ module.exports = { standardCollID: chance.guid(), collectionReviewCompletedID: chance.guid(), collectionNoInvitesID: chance.guid(), + twoVersionsCollectionId: chance.guid(), } diff --git a/packages/component-fixture-manager/src/fixtures/collections.js b/packages/component-fixture-manager/src/fixtures/collections.js index 42ad95ce500baa7a635cf2897de350c1c8908b1d..c0e6b797fa5259fffc927c1be6b11664cd6f5e59 100644 --- a/packages/component-fixture-manager/src/fixtures/collections.js +++ b/packages/component-fixture-manager/src/fixtures/collections.js @@ -10,12 +10,14 @@ const { standardCollID, collectionReviewCompletedID, collectionNoInvitesID, + twoVersionsCollectionId, } = require('./collectionIDs') const chance = new Chance() const collections = { collection: { id: standardCollID, + delete: jest.fn(), title: chance.sentence(), type: 'collection', fragments: [fragment.id], @@ -58,6 +60,7 @@ const collections = { }, collection1: { id: standardCollID, + delete: jest.fn(), title: chance.sentence(), type: 'collection', fragments: [fragment.id], @@ -142,6 +145,7 @@ const collections = { }, collectionReviewCompleted: { id: collectionReviewCompletedID, + delete: jest.fn(), type: 'collection', owners: [user.id], status: 'reviewCompleted', @@ -171,6 +175,36 @@ const collections = { }, technicalChecks: {}, }, + twoVersionsCollection: { + id: twoVersionsCollectionId, + title: chance.sentence(), + type: 'collection', + fragments: [fragment.id, reviewCompletedFragment.id], + owners: [user.id], + save: jest.fn(() => collections.collection), + invitations: [ + { + id: chance.guid(), + role: 'handlingEditor', + hasAnswer: true, + isAccepted: false, + userId: handlingEditor.id, + invitedOn: chance.timestamp(), + respondedOn: null, + }, + ], + handlingEditor: { + id: handlingEditor.id, + hasAnswer: false, + isAccepted: false, + email: handlingEditor.email, + invitedOn: chance.timestamp(), + respondedOn: null, + name: `${handlingEditor.firstName} ${handlingEditor.lastName}`, + }, + status: 'revisionRequested', + customId: chance.natural({ min: 999999, max: 9999999 }), + }, } module.exports = collections diff --git a/packages/component-fixture-manager/src/fixtures/fragments.js b/packages/component-fixture-manager/src/fixtures/fragments.js index d2321b0a8571ed9c31d94d59cd47b4db3a010fe0..9fca41e0ffba404be7fd612dd6feb483e6a23763 100644 --- a/packages/component-fixture-manager/src/fixtures/fragments.js +++ b/packages/component-fixture-manager/src/fixtures/fragments.js @@ -20,6 +20,12 @@ const chance = new Chance() const fragments = { fragment: { id: chance.guid(), + delete: jest.fn(), + files: { + manuscripts: [{ id: chance.guid() }], + coverLetter: [], + supplementary: [], + }, collectionId: standardCollID, metadata: { title: chance.sentence(), @@ -182,6 +188,12 @@ const fragments = { }, noParentFragment: { id: chance.guid(), + delete: jest.fn(), + files: { + manuscripts: [{ id: chance.guid() }], + coverLetter: [], + supplementary: [], + }, collectionId: '', metadata: { title: chance.sentence(), @@ -201,9 +213,9 @@ const fragments = { }, reviewCompletedFragment: { id: chance.guid(), + delete: jest.fn(), type: 'fragment', files: { - coverLetter: [], manuscripts: [ { id: @@ -213,6 +225,7 @@ const fragments = { originalName: 'LinkedInProfileDemystified.pdf', }, ], + coverLetter: [], supplementary: [], }, owners: [user.id], diff --git a/packages/component-fixture-manager/src/fixtures/teams.js b/packages/component-fixture-manager/src/fixtures/teams.js index 630a5f045ae2ab6a0635273f21580e5cfde7cf66..370a9c0e988c6c886454314b76173613d898bf25 100644 --- a/packages/component-fixture-manager/src/fixtures/teams.js +++ b/packages/component-fixture-manager/src/fixtures/teams.js @@ -35,6 +35,7 @@ const teams = { }, members: [handlingEditor.id], save: jest.fn(() => teams.heTeam), + delete: jest.fn(), updateProperties: jest.fn(() => teams.heTeam), id: heTeamID, }, @@ -51,6 +52,7 @@ const teams = { }, members: [reviewer.id, inactiveReviewer.id, answerReviewer.id], save: jest.fn(() => teams.revTeam), + delete: jest.fn(), updateProperties: jest.fn(() => teams.revTeam), id: revTeamID, }, @@ -67,6 +69,7 @@ const teams = { }, members: [reviewer.id, answerReviewer.id, recReviewer.id], save: jest.fn(() => teams.revRecommendationTeam), + delete: jest.fn(), updateProperties: jest.fn(() => teams.revRecommendationTeam), id: revRecommendationTeamID, }, @@ -99,6 +102,7 @@ const teams = { }, members: [submittingAuthor.id], save: jest.fn(() => teams.authorTeam), + delete: jest.fn(), updateProperties: jest.fn(() => teams.authorTeam), id: authorTeamID, }, diff --git a/packages/component-helper-service/src/services/User.js b/packages/component-helper-service/src/services/User.js index 18239d17471a296a3497b3ee2747dc370fcda20e..dbd0eb1f2bf7b6e5995a27df258efbb6a532fb3d 100644 --- a/packages/component-helper-service/src/services/User.js +++ b/packages/component-helper-service/src/services/User.js @@ -9,7 +9,14 @@ class User { async createUser({ role, body }) { const { UserModel } = this - const { email, firstName, lastName, affiliation, title, country } = body + const { + email, + firstName, + lastName, + affiliation, + title = 'Dr', + country, + } = body const username = email const password = uuid.v4() const userBody = { @@ -33,7 +40,7 @@ class User { }, }, accessTokens: { - invitation: role === 'reviewer' ? services.generateHash() : undefined, + invitation: role === 'reviewer' ? services.generateHash() : null, unsubscribe: services.generateHash(), passwordReset: services.generateHash(), }, diff --git a/packages/component-invite/src/routes/fragmentsInvitations/post.js b/packages/component-invite/src/routes/fragmentsInvitations/post.js index 2eab3d2d1642e1aed6f2a9384bbf11b9058fd993..43504b33418afb1807932ac303c275d65a291f84 100644 --- a/packages/component-invite/src/routes/fragmentsInvitations/post.js +++ b/packages/component-invite/src/routes/fragmentsInvitations/post.js @@ -1,5 +1,3 @@ -const logger = require('@pubsweet/logger') - const { Team, User, @@ -11,12 +9,22 @@ const { const emailInvitations = require('./emails/invitations') -module.exports = models => async (req, res) => { - const { email, role } = req.body +const { last } = require('lodash') - if (!services.checkForUndefinedParams(email, role)) { - res.status(400).json({ error: 'Email and role are required.' }) - logger.error('User ID and role are missing') +module.exports = models => async (req, res) => { + const { email, role, firstName, lastName, affiliation, country } = req.body + + if ( + !services.checkForUndefinedParams( + email, + role, + firstName, + lastName, + affiliation, + country, + ) + ) { + res.status(400).json({ error: 'Missing parameters.' }) return } @@ -40,6 +48,10 @@ module.exports = models => async (req, res) => { return res.status(400).json({ error: `Fragment ${fragmentId} does not match collection ${collectionId}.`, }) + if (last(collection.fragments) !== fragmentId) + return res.status(400).json({ + error: `Fragment ${fragmentId} is an older version.`, + }) fragment = await models.Fragment.find(fragmentId) } catch (e) { const notFoundError = await services.handleNotFoundError(e, 'item') @@ -124,7 +136,7 @@ module.exports = models => async (req, res) => { const userHelper = new User({ UserModel }) const userData = req.body - const { firstName = '', lastName = '', isPublons } = userData + const { firstName, lastName, isPublons } = userData if (!services.checkForUndefinedParams(firstName, lastName)) { return res .status(400) diff --git a/packages/component-invite/src/tests/fragmentsInvitations/post.test.js b/packages/component-invite/src/tests/fragmentsInvitations/post.test.js index ce8719050cf2d722720964548e817c814bf2db55..0683f0aaf927ed7e6b810bd1103aaa75b4267955 100644 --- a/packages/component-invite/src/tests/fragmentsInvitations/post.test.js +++ b/packages/component-invite/src/tests/fragmentsInvitations/post.test.js @@ -21,6 +21,7 @@ const reqBody = { title: 'Mr', affiliation: chance.company(), admin: false, + country: chance.country(), } const route = { path: '/api/collections/:collectionId/fragments/:fragmentId/invitations', @@ -49,17 +50,18 @@ describe('Post fragments invitations route handler', () => { expect(res.statusCode).toBe(400) const data = JSON.parse(res._getData()) - expect(data.error).toEqual('Email and role are required.') + expect(data.error).toEqual('Missing parameters.') }) it('should return success when a reviewer is invited', async () => { const { user, editorInChief } = testFixtures.users const { collection } = testFixtures.collections const { fragment } = testFixtures.fragments - body = { + body = Object.assign(body, { email: user.email, role: 'reviewer', - } + }) + const res = await requests.sendRequest({ body, userId: editorInChief.id, @@ -109,10 +111,12 @@ describe('Post fragments invitations route handler', () => { const { answerReviewer, handlingEditor } = testFixtures.users const { collection } = testFixtures.collections const { fragment } = testFixtures.fragments - body = { + + body = Object.assign(body, { email: answerReviewer.email, role: 'reviewer', - } + }) + const res = await requests.sendRequest({ body, userId: handlingEditor.id, @@ -155,10 +159,12 @@ describe('Post fragments invitations route handler', () => { const { inactiveUser, handlingEditor } = testFixtures.users const { collection } = testFixtures.collections const { fragment } = testFixtures.fragments - body = { + + body = Object.assign(body, { email: inactiveUser.email, role: 'reviewer', - } + }) + const res = await requests.sendRequest({ body, userId: handlingEditor.id, diff --git a/packages/component-manuscript-manager/src/routes/collections/delete.js b/packages/component-manuscript-manager/src/routes/collections/delete.js index 05b9e042f9c08c24f9367aea7f6db546e08e8b08..62ed1fc8c760f3f1c2aa0385e3a0db337dcb8be5 100644 --- a/packages/component-manuscript-manager/src/routes/collections/delete.js +++ b/packages/component-manuscript-manager/src/routes/collections/delete.js @@ -1,4 +1,4 @@ -const { get, remove, concat } = require('lodash') +const { get, remove, concat, has } = require('lodash') const config = require('config') const { @@ -19,6 +19,12 @@ module.exports = models => async (req, res) => { try { collection = await models.Collection.find(collectionId) + if (has(collection, 'status')) { + return res.status(400).json({ + error: 'You can only delete manuscripts while in draft.', + }) + } + const fragmentId = collection.fragments[0] fragment = await models.Fragment.find(fragmentId) @@ -48,17 +54,18 @@ module.exports = models => async (req, res) => { return user.save() }), ) - return team.delete() }), ) - const fileKeys = concat( + let fileKeys = concat( fragment.files.manuscripts, fragment.files.coverLetter, fragment.files.supplementary, fragmentId, - ).map(file => file.id) + ) + + fileKeys = fileKeys.map(file => file.id) if (fileKeys.length > 1) { await deleteFilesS3({ fileKeys, s3Config }) diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js index 55d54aa4274c9035da2fe92342ccab04929b6220..43206e0e19c9bb85290713f5eb829d04dd700df6 100644 --- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js @@ -1,5 +1,5 @@ const uuid = require('uuid') -const { pick, get, set, has, isEmpty } = require('lodash') +const { pick, get, set, has, isEmpty, last } = require('lodash') const config = require('config') const { v4 } = require('uuid') @@ -69,6 +69,15 @@ module.exports = models => async (req, res) => { error: 'Unauthorized.', }) + if ( + recommendationType === recommendations.type.editor && + last(collection.fragments) !== fragmentId + ) { + return res + .status(400) + .json({ error: 'Cannot make a recommendation on an older version.' }) + } + if ( recommendation === recommendations.publish && recommendationType === recommendations.type.editor && diff --git a/packages/component-manuscript-manager/src/tests/collections/delete.test.js b/packages/component-manuscript-manager/src/tests/collections/delete.test.js new file mode 100644 index 0000000000000000000000000000000000000000..cee28293a8b2143164d5697c09d49d50762200f5 --- /dev/null +++ b/packages/component-manuscript-manager/src/tests/collections/delete.test.js @@ -0,0 +1,65 @@ +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.SUPPRESS_NO_CONFIG_WARNING = true + +const { cloneDeep } = require('lodash') +const fixturesService = require('pubsweet-component-fixture-service') +const requests = require('../requests') + +const { Model, fixtures } = fixturesService + +jest.mock('pubsweet-component-mts-package/src/PackageManager', () => ({ + deleteFilesS3: jest.fn(), +})) +jest.mock('@pubsweet/component-send-email', () => ({ + send: jest.fn(), +})) + +const path = '../routes/collections/delete' +const route = { + path: '/api/collections/:collectionId/', +} +describe('Delete collections route handler', () => { + let testFixtures = {} + let models + beforeEach(() => { + testFixtures = cloneDeep(fixtures) + models = Model.build(testFixtures) + }) + + it('should return an error when deleting a collection which is not in draft', async () => { + const { admin } = testFixtures.users + const { collection } = testFixtures.collections + + const res = await requests.sendRequest({ + userId: admin.id, + route, + models, + path, + params: { + collectionId: collection.id, + }, + }) + + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toBe('You can only delete manuscripts while in draft.') + }) + + it('should return success when deleting a draft collection', async () => { + const { admin } = testFixtures.users + const { collection } = testFixtures.collections + delete collection.status + + const res = await requests.sendRequest({ + userId: admin.id, + route, + models, + path, + params: { + collectionId: collection.id, + }, + }) + + expect(res.statusCode).toBe(204) + }) +}) diff --git a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js index b090a9cb6fc1ae464488560f7032b0ff97388dea..867d1ed0d05986fd03e389da064d08e4a19dfc77 100644 --- a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js +++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/post.test.js @@ -357,4 +357,58 @@ describe('Post fragments recommendations route handler', () => { 'Cannot publish without at least one reviewer report.', ) }) + + it('should return an error when a HE makes a recommendation on an older version of a manuscript', async () => { + const { handlingEditor } = testFixtures.users + const { twoVersionsCollection } = testFixtures.collections + const { fragment } = testFixtures.fragments + body.recommendation = 'publish' + body.recommendationType = 'editorRecommendation' + + const res = await requests.sendRequest({ + body, + userId: handlingEditor.id, + models, + route, + path, + params: { + collectionId: twoVersionsCollection.id, + fragmentId: fragment.id, + }, + }) + + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + + expect(data.error).toEqual( + 'Cannot make a recommendation on an older version.', + ) + }) + + it('should return an error when an EiC makes a decision on an older version of a manuscript', async () => { + const { editorInChief } = testFixtures.users + const { twoVersionsCollection } = testFixtures.collections + const { fragment } = testFixtures.fragments + body.recommendation = 'publish' + body.recommendationType = 'editorRecommendation' + + const res = await requests.sendRequest({ + body, + userId: editorInChief.id, + models, + route, + path, + params: { + collectionId: twoVersionsCollection.id, + fragmentId: fragment.id, + }, + }) + + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + + expect(data.error).toEqual( + 'Cannot make a recommendation on an older version.', + ) + }) }) diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js index 9c39e9a6c7c722d76d281c73ebc0adb3ac8e777a..fd01d44a1b4009c558fb8900d8991e9bc47f7b04 100644 --- a/packages/component-manuscript/src/components/ManuscriptLayout.js +++ b/packages/component-manuscript/src/components/ManuscriptLayout.js @@ -50,6 +50,7 @@ const ManuscriptLayout = ({ heResponseExpanded, toggleReviewerResponse, invitationsWithReviewers, + responseToRevisionRequest, publonReviewers, reviewerResponseExpanded, pendingOwnRecommendation, @@ -64,6 +65,7 @@ const ManuscriptLayout = ({ reviewerRecommendations, toggleReviewerDetails, reviewerDetailsExpanded, + toggleResponseToRevisionRequest, editorialCommentsExpanded, toggleEditorialComments, submitRevision, @@ -72,6 +74,7 @@ const ManuscriptLayout = ({ inviteHandlingEditor, versions, + isLatestVersion, }) => ( <Root pb={30}> {!isEmpty(collection) && !isEmpty(fragment) ? ( @@ -92,6 +95,7 @@ const ManuscriptLayout = ({ handlingEditors={handlingEditors} inviteHE={toggleAssignHE} isFetching={isFetchingData.editorsFetching} + isLatestVersion={isLatestVersion} journal={journal} resendInvitation={inviteHandlingEditor.assignHE} revokeInvitation={inviteHandlingEditor.revokeHE} @@ -117,8 +121,10 @@ const ManuscriptLayout = ({ {get(currentUser, 'permissions.authorCanViewReportsDetails', false) && ( <AuthorReviews currentUser={currentUser} + getSignedUrl={getSignedUrl} journal={journal} reports={reviewerReports} + token={get(currentUser, 'token')} /> )} @@ -131,16 +137,16 @@ const ManuscriptLayout = ({ /> )} - {authorResponseToRevisonRequest.content && ( + {get(authorResponseToRevisonRequest, 'content', false) && ( <ResponseToRevisionRequest - authorReply={authorResponseToRevisonRequest.content} - expanded={responseToRevisionRequestExpanded} + authorReply={get(authorResponseToRevisonRequest, 'content', '')} + expanded={responseToRevisionRequest} fragment={fragment} - toggle={toggleResponeToRevisionRequest} + toggle={toggleResponseToRevisionRequest} /> )} - {shouldReview && ( + {get(currentUser, 'permissions.canReview', false) && ( <ReviewerReportForm changeForm={changeForm} expanded={reviewerRecommendationExpanded} @@ -200,23 +206,26 @@ const ManuscriptLayout = ({ } invitations={invitationsWithReviewers} isFetching={isFetchingData.publonsFetching} + isLatestVersion={isLatestVersion} journal={journal} mb={2} publonReviewers={publonReviewers} reviewerReports={reviewerReports} scrollIntoView toggle={toggleReviewerDetails} + token={get(currentUser, 'token')} {...inviteReviewer} /> )} - {get(currentUser, 'permissions.canSubmitRevision', false) && ( - <SubmitRevision {...submitRevision} /> - )} + {isLatestVersion && + get(currentUser, 'permissions.canSubmitRevision', false) && ( + <SubmitRevision {...submitRevision} /> + )} - {get(currentUser, 'permissions.canMakeHERecommendation', false) && - (!invitationsWithReviewers.length || - reviewerRecommendations.length > 0) && ( + {isLatestVersion && + get(currentUser, 'permissions.canMakeHERecommendation', false) && + reviewerRecommendations.length > 0 && ( <HERecommendation formValues={get(formValues, 'editorialRecommendation', {})} hasReviewerReports={reviewerRecommendations.length > 0} @@ -228,16 +237,17 @@ const ManuscriptLayout = ({ /> )} - {get(currentUser, 'permissions.canMakeDecision', false) && ( - <ManuscriptEicDecision - collection={collection} - formValues={get(formValues, 'eicDecision')} - highlight={editorialRecommendations.length > 0} - messagesLabel={messagesLabel} - mt={2} - submitDecision={recommendationHandler.createRecommendation} - /> - )} + {isLatestVersion && + get(currentUser, 'permissions.canMakeDecision', false) && ( + <ManuscriptEicDecision + collection={collection} + formValues={get(formValues, 'eicDecision')} + highlight={editorialRecommendations.length > 0} + messagesLabel={messagesLabel} + mt={2} + submitDecision={recommendationHandler.createRecommendation} + /> + )} </Fragment> ) : ( <Text>Loading...</Text> diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index f51c7f7ab0af1a3571d4cec79743232981fce08f..84d6059a9c3187ed2c5c5c648a1f4fe33af233a4 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -31,6 +31,7 @@ import { selectEditorialRecommendations, } from 'pubsweet-components-faraday/src/redux/recommendations' import { + canReview, getUserToken, currentUserIs, canViewReports, @@ -73,6 +74,7 @@ import { redirectToError, parseSearchParams, getPublonsReviewers, + isLatestVersion, } from './utils' import { @@ -93,6 +95,7 @@ export default compose( actions.getCollection({ id: match.params.project }), actions.getFragments({ id: match.params.project }), actions.getUsers(), + actions.getTeams(), ]), connect( (state, { match }) => ({ @@ -165,6 +168,7 @@ export default compose( isReviewer: currentUserIsReviewer(state, get(fragment, 'id', '')), isHEToManuscript: isHEToManuscript(state, get(collection, 'id', '')), permissions: { + canReview: canReview(state, collection, fragment), canSubmitRevision: canSubmitRevision(state, fragment), canMakeHERecommendation: canMakeHERecommendation(state, { collection, @@ -180,7 +184,7 @@ export default compose( canInviteReviewers: canInviteReviewers(state, collection), canMakeRecommendation: !isUndefined(pendingOwnRecommendation), canMakeRevision: canMakeRevision(state, collection, fragment), - canMakeDecision: canMakeDecision(state, collection, fragment), + canMakeDecision: canMakeDecision(state, collection), canEditManuscript: canEditManuscript(state, collection, fragment), canViewReviewersDetails: canViewReviewersDetails(state, collection), authorCanViewReportsDetails: authorCanViewReportsDetails( @@ -278,6 +282,10 @@ export default compose( toggleReviewerRecommendations: toggle, reviewerRecommendationExpanded: expanded, })), + fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({ + toggleResponseToRevisionRequest: toggle, + responseToRevisionRequest: expanded, + })), fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({ toggleReviewerDetails: toggle, reviewerDetailsExpanded: expanded, @@ -286,15 +294,9 @@ export default compose( toggleEditorialComments: toggle, editorialCommentsExpanded: expanded, })), - fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({ - toggleResponeToRevisionRequest: toggle, - responseToRevisionRequestExpanded: expanded, - })), - withProps(({ currentUser, collection, submittedOwnRecommendation }) => ({ + withProps(({ collection, fragment }) => ({ getSignedUrl, - shouldReview: - get(currentUser, 'isReviewer', false) && - isUndefined(submittedOwnRecommendation), + isLatestVersion: isLatestVersion(collection, fragment), })), withInviteHandlingEditor, withInviteReviewer, @@ -307,7 +309,6 @@ export default compose( history, setError, location, - shouldReview, reviewerReports, setEditorInChief, clearCustomError, @@ -315,13 +316,13 @@ export default compose( hasManuscriptFailure, fetchUpdatedCollection, editorialRecommendations, - authorResponseToRevisonRequest, + fragment, currentUser: { isEIC, isInvitedHE, isInvitedToReview, isHEToManuscript, - permissions: { canInviteReviewers, canSubmitRevision }, + permissions: { canInviteReviewers, canSubmitRevision, canReview }, }, } = this.props @@ -356,14 +357,14 @@ export default compose( this.props.toggleReviewerResponse() } - if (shouldReview && !authorResponseToRevisonRequest.content) { + if (canReview && !get(fragment, 'responseToReviewers.content', false)) { this.props.toggleReviewerRecommendations() } - if ( isHEToManuscript && !!reviewerReports.length && - editorialRecommendations.length === 0 + editorialRecommendations.length === 0 && + get(fragment, 'responseToReviewers.content', false) ) { this.props.toggleReviewerDetails() } @@ -376,8 +377,8 @@ export default compose( this.props.toggleEditorialComments() } - if (authorResponseToRevisonRequest.content) { - this.props.toggleResponeToRevisionRequest() + if (get(fragment, 'responseToReviewers.content', false)) { + this.props.toggleResponseToRevisionRequest() } }, componentDidUpdate(prevProps) { diff --git a/packages/component-manuscript/src/components/utils.js b/packages/component-manuscript/src/components/utils.js index e579d683636db3dfcb7917c961dd8d9f5a02eff8..f98db2189670e9dbb869bdc583cd6636ff3097e3 100644 --- a/packages/component-manuscript/src/components/utils.js +++ b/packages/component-manuscript/src/components/utils.js @@ -3,6 +3,7 @@ import { has, get, find, + last, omit, isEmpty, debounce, @@ -74,6 +75,9 @@ export const parseVersion = version => ({ abstract: get(version, 'metadata.abstract'), }) +export const isLatestVersion = (collection, fragment) => + get(fragment, 'id', '') === last(get(collection, 'fragments', [])) + export const parseJournalIssue = (journal, metadata) => journal.issueTypes.find(t => t.value === get(metadata, 'issue')) diff --git a/packages/component-manuscript/src/submitRevision/withSubmitRevision.js b/packages/component-manuscript/src/submitRevision/withSubmitRevision.js index 756551f82f57ab162c74915c3e47fca32701c4c5..57b8a4297065dd2efe876241e83e886a2b0eebbe 100644 --- a/packages/component-manuscript/src/submitRevision/withSubmitRevision.js +++ b/packages/component-manuscript/src/submitRevision/withSubmitRevision.js @@ -97,7 +97,7 @@ export default compose( }, deleteResponseFile: ({ setError, changeForm, setFetching }) => file => { setFetching(true) - return deleteFile(file.id, 'responseToReviewers') + return deleteFile({ fileId: file.id }, 'responseToReviewers') .then(r => { setFetching(false) changeForm('revision', 'responseToReviewers.file', null) diff --git a/packages/components-faraday/src/components/Dashboard/DashboardPage.js b/packages/components-faraday/src/components/Dashboard/DashboardPage.js index 2aadccce522ce995b4387b64b0f1b891433befe9..7f96042f9cf5d84f6625ef6a1c912aa8cbf2d51b 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardPage.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardPage.js @@ -17,7 +17,11 @@ import { Dashboard } from './' import { priorityFilter, orderFilter, withFiltersHOC } from '../Filters' export default compose( - ConnectPage(() => [actions.getCollections(), actions.getUsers()]), + ConnectPage(() => [ + actions.getCollections(), + actions.getUsers(), + actions.getTeams(), + ]), connect( state => { const { collections, conversion } = state @@ -34,6 +38,7 @@ export default compose( } }, { + getCollections: actions.getCollections, deleteCollection: actions.deleteCollection, }, ), @@ -52,15 +57,17 @@ export default compose( ({ journal, currentUser }) => ({ journal, currentUser }), ), withHandlers({ - deleteCollection: ({ setFetching, deleteCollection }) => collection => ({ - hideModal, - setModalError, - }) => { + deleteCollection: ({ + setFetching, + deleteCollection, + getCollections, + }) => collection => ({ hideModal, setModalError }) => { setFetching(true) deleteCollection(collection) .then(() => { setFetching(false) hideModal() + getCollections() }) // again, the error is not being thrown from deleteCollection action and // the catch is never run diff --git a/packages/xpub-faraday/app.js b/packages/xpub-faraday/app.js index 5eefe950911e489d094e41831dbda8fd695e2881..0675af2b27052928c4924d673750f6548a9308f2 100644 --- a/packages/xpub-faraday/app.js +++ b/packages/xpub-faraday/app.js @@ -1,5 +1,5 @@ const logger = require('@pubsweet/logger') -const startServer = require('pubsweet-server') +const { startServer } = require('pubsweet-server') require('dotenv').config() startServer().catch(err => { diff --git a/packages/xpub-faraday/config/authsome-helpers.js b/packages/xpub-faraday/config/authsome-helpers.js index de88ed38e85a7a4c68bd4c70e2c0fb0be4698d83..c43c00d912084c864261fd45e5c75fc05bd83a64 100644 --- a/packages/xpub-faraday/config/authsome-helpers.js +++ b/packages/xpub-faraday/config/authsome-helpers.js @@ -1,65 +1,11 @@ -const { omit, get, last, chain } = require('lodash') const config = require('config') const logger = require('@pubsweet/logger') +const { omit, get, last, chain } = require('lodash') const statuses = config.get('statuses') -const publicStatusesPermissions = ['author', 'reviewer'] const authorAllowedStatuses = ['revisionRequested', 'rejected', 'accepted'] -const parseAuthorsData = (coll, matchingCollPerm) => { - if (['reviewer'].includes(matchingCollPerm.permission)) { - coll.authors = coll.authors.map(a => omit(a, ['email'])) - } -} - -const setPublicStatuses = (coll, matchingCollPerm) => { - const status = get(coll, 'status', 'draft') - // coll.visibleStatus = statuses[status].public - if (publicStatusesPermissions.includes(matchingCollPerm.permission)) { - coll.visibleStatus = statuses[status].public - } -} - -const filterRefusedInvitations = (coll, user) => { - const matchingInv = coll.invitations.find(inv => inv.userId === user.id) - if (matchingInv === undefined) return null - if (matchingInv.hasAnswer === true && !matchingInv.isAccepted) return null - return coll -} - -const filterObjectData = ( - collectionsPermissions = [], - object = {}, - user = {}, -) => { - if (object.type === 'fragment') { - const matchingCollPerm = collectionsPermissions.find( - collPerm => object.id === collPerm.fragmentId, - ) - if (matchingCollPerm === undefined) return null - if (['reviewer'].includes(matchingCollPerm.permission)) { - object.files = omit(object.files, ['coverLetter']) - if (object.recommendations) - object.recommendations = object.recommendations.filter( - rec => rec.userId === user.id, - ) - } - parseAuthorsData(object, matchingCollPerm) - if (['reviewer', 'handlingEditor'].includes(matchingCollPerm.permission)) { - return filterRefusedInvitations(object, user) - } - return object - } - const matchingCollPerm = collectionsPermissions.find( - collPerm => object.id === collPerm.id, - ) - if (matchingCollPerm === undefined) return null - setPublicStatuses(object, matchingCollPerm) - - return object -} - const getTeamsByPermissions = async ( teamIds = [], permissions = [], @@ -75,12 +21,6 @@ const getTeamsByPermissions = async ( }), )).filter(Boolean) -const heIsInvitedToFragment = async ({ user, Team, collectionId }) => - (await getTeamsByPermissions(user.teams, ['handlingEditor'], Team)).some( - // user is a member of the team with access to the fragment's parent collection - t => t.members.includes(user.id) && t.object.id === collectionId, - ) - const getUserPermissions = async ({ user, Team, @@ -119,12 +59,6 @@ const isHandlingEditor = ({ user, object }) => const isInDraft = fragment => !get(fragment, 'submitted') -const hasFragmentInDraft = async ({ object, Fragment }) => { - const lastFragmentId = last(get(object, 'fragments')) - const fragment = await Fragment.find(lastFragmentId) - return isInDraft(fragment) -} - const filterAuthorRecommendations = (recommendations, status, isLast) => { const canViewRecommendations = authorAllowedStatuses.includes(status) if (canViewRecommendations || !isLast) { @@ -236,20 +170,15 @@ const getCollections = async ({ user, models }) => { collection.visibleStatus = get(statuses, `${status}.${up.role}.label`) const role = get(up, 'role', 'author') - - let visibleStatus = get(statuses, `${status}.${role}.label`) - - if (role === 'reviewer' && status !== 'reviewersInvited') { - visibleStatus = await updateReviewerVisibleStatusByInvitation({ - collection, - FragmentModel: models.Fragment, - user, - }) - } - + const parsedStatuses = await setCollectionStatus({ + role, + user, + collection, + FragmentModel: models.Fragment, + }) return { ...collection, - visibleStatus, + ...parsedStatuses, } }), )).filter(Boolean) @@ -260,55 +189,91 @@ const getCollections = async ({ user, models }) => { .value() } -async function updateReviewerVisibleStatusByInvitation({ +const reviewerActionStatuses = [ + 'underReview', + 'reviewCompleted', + 'reviewersInvited', +] +const setCollectionStatus = async ({ + role, + user, collection, FragmentModel, - user, -}) { - const fragmentId = last(collection.fragments) - const fragment = await FragmentModel.find(fragmentId) - const invitation = get(fragment, 'invitations', []).find( - inv => inv.userId === user.id, - ) - const recommendationDone = - fragment.recommendations && - fragment.recommendations.some( - rec => - rec.recommendationType === 'review' && - rec.userId === user.id && - rec.submittedOn, - ) +}) => { + const status = get(collection, 'status', 'draft') - if (recommendationDone) { - return get(statuses, `${collection.status}.reviewer.label`) + if (role !== 'reviewer') { + return { + status, + visibleStatus: get(statuses, `${status}.${role}.label`), + } } - if (!invitation) { - return get(statuses, `reviewCompleted.reviewer.label`) + if (reviewerActionStatuses.includes(status)) { + const fragmentId = last(collection.fragments) + const fragment = await FragmentModel.find(fragmentId) + + const hasPendingInvitation = !chain(fragment) + .get('invitations', []) + .find(i => i.userId === user.id && !i.hasAnswer) + .isUndefined() + .value() + + if (hasPendingInvitation) { + return { + status: 'reviewersInvited', + visibleStatus: get(statuses, 'reviewersInvited.reviewer.label'), + } + } + + const hasSubmittedReport = !chain(fragment) + .get('recommendations', []) + .find( + r => + r.userId === user.id && + r.recommendationType === 'review' && + r.submittedOn, + ) + .isUndefined() + .value() + + if (hasSubmittedReport) { + return { + status: 'reviewCompleted', + visibleStatus: get(statuses, 'reviewCompleted.reviewer.label'), + } + } + + const hasAcceptedInvitation = !chain(fragment) + .get('invitations', []) + .find(i => i.userId === user.id && i.hasAnswer && i.isAccepted) + .isUndefined() + .value() + + if (hasAcceptedInvitation) { + return { + status: 'underReview', + visibleStatus: get(statuses, 'underReview.reviewer.label'), + } + } } - return get(invitation, 'hasAnswer', false) && - get(invitation, 'isAccepted', false) - ? get(statuses, `underReview.reviewer.label`) - : get(statuses, `reviewersInvited.reviewer.label`) + return { + status, + visibleStatus: get(statuses, `${status}.reviewer.label`), + } } module.exports = { - filterObjectData, - parseAuthorsData, - setPublicStatuses, - getTeamsByPermissions, - filterRefusedInvitations, isOwner, - isHandlingEditor, - getUserPermissions, - heIsInvitedToFragment, - hasPermissionForObject, isInDraft, - hasFragmentInDraft, - stripeFragmentByRole, - getUsersList, parseUser, + getUsersList, getCollections, - updateReviewerVisibleStatusByInvitation, + isHandlingEditor, + getUserPermissions, + setCollectionStatus, + stripeFragmentByRole, + getTeamsByPermissions, + hasPermissionForObject, } diff --git a/packages/xpub-faraday/config/authsome-mode.js b/packages/xpub-faraday/config/authsome-mode.js index 2bb207ebd4264f3d3210d226bb0134e25e0b1bff..e4129023dccead41ff08fec5a1b33d2f24066e42 100644 --- a/packages/xpub-faraday/config/authsome-mode.js +++ b/packages/xpub-faraday/config/authsome-mode.js @@ -67,7 +67,6 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) { if (get(object, 'type') === 'collection') { return { filter: async collection => { - const status = get(collection, 'status', 'draft') const userPermissions = await helpers.getUserPermissions({ user, Team: context.models.Team, @@ -79,10 +78,6 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) { ) .map(up => up.objectId) - // if (collection.owners.map(o => o.id).includes(user.id)) { - // return collection - // } - // TODO: check why collPermission can be undefined const collPermission = userPermissions.find( p => p.objectId === collection.id || @@ -90,27 +85,22 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) { ) const role = get(collPermission, 'role', 'author') - let visibleStatus = get(statuses, `${status}.${role}.label`) - - if (role === 'reviewer' && status !== 'reviewersInvited') { - visibleStatus = await helpers.updateReviewerVisibleStatusByInvitation( - { - collection, - FragmentModel: context.models.Fragment, - user, - }, - ) - } + const parsedStatuses = await helpers.setCollectionStatus({ + role, + user, + collection, + FragmentModel: context.models.Fragment, + }) return { ...collection, + ...parsedStatuses, fragments: role !== 'reviewer' ? collection.fragments : collection.fragments.filter(fragId => fragmentPermissions.includes(fragId), ), - visibleStatus, } }, } @@ -168,6 +158,12 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) { models: context.models, }) } + + if (get(object, 'path', '') === '/teams') { + return { + filter: teams => teams.filter(t => user.teams.includes(t.id)), + } + } } if (operation === 'POST') { @@ -207,12 +203,12 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) { } if (operation === 'PATCH') { - if (get(object, 'type') === 'collection') { - return helpers.isOwner({ user, object }) + if (get(object.current, 'type') === 'collection') { + return helpers.isOwner({ user, object: object.current }) } - if (get(object, 'type') === 'fragment') { - return helpers.isOwner({ user, object }) + if (get(object.current, 'type') === 'fragment') { + return helpers.isOwner({ user, object: object.current }) } // allow reviewer to patch (accept/decline) his invitation diff --git a/packages/xpub-faraday/config/default.js b/packages/xpub-faraday/config/default.js index 7cd9de3dbaab836663730ca2ed9942712d2d237b..4ac021c51ead4f114dd58b376a2619050fc5687d 100644 --- a/packages/xpub-faraday/config/default.js +++ b/packages/xpub-faraday/config/default.js @@ -35,6 +35,9 @@ module.exports = { pubsweet: { components, }, + dbManager: { + migrationsPath: path.join(process.cwd(), 'migrations'), + }, 'pubsweet-server': { db: getDbConfig(), port: 3000, diff --git a/packages/xpub-faraday/config/validations.js b/packages/xpub-faraday/config/validations.js index 60cd146dec55f085d5535fc0eb934edfcfebc7da..6d1ac18d402b9baa6333ed22f7cfbe5d2f566cdf 100644 --- a/packages/xpub-faraday/config/validations.js +++ b/packages/xpub-faraday/config/validations.js @@ -166,10 +166,13 @@ module.exports = { confirmation: Joi.string().allow(''), passwordReset: Joi.string().allow(''), unsubscribe: Joi.string().allow(''), - invitation: Joi.string().allow(''), + invitation: Joi.string().allow(null), }), }, team: { + name: Joi.string(), + type: Joi.string(), group: Joi.string(), + teamType: Joi.object(), }, } diff --git a/packages/xpub-faraday/migrations/.gitkeep b/packages/xpub-faraday/migrations/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/packages/xpub-faraday/package.json b/packages/xpub-faraday/package.json index 4e30ddde8745944893f2ed9601603be229ba84e8..e426d3005c02ae80b2b97fb5e778d770d3ca164e 100644 --- a/packages/xpub-faraday/package.json +++ b/packages/xpub-faraday/package.json @@ -26,11 +26,11 @@ "moment": "^2.18.1", "nodemailer-ses-transport": "^1.5.1", "prop-types": "^15.5.10", - "pubsweet": "^2.2.1", + "pubsweet": "3.0.6", "pubsweet-client": "^4.0.4", "pubsweet-component-login": "^1.1.0", "pubsweet-component-signup": "^1.0.0", - "pubsweet-server": "2.0.3", + "pubsweet-server": "10.0.1", "react": "^16.4.2", "react-dnd": "^2.5.4", "react-dnd-html5-backend": "^2.5.4", @@ -81,8 +81,7 @@ "start": "pubsweet start", "start:services": "docker-compose up postgres", "server": "pubsweet server", - "start-now": - "echo $secret > config/local-development.json && npm run server", + "start-now": "echo $secret > config/local-development.json && npm run server", "build": "NODE_ENV=production pubsweet build", "clean": "rm -rf node_modules", "debug": "pgrep -f startup/start.js | xargs kill -sigusr1", diff --git a/packages/xpub-faraday/tests/config/authsome-helpers.test.js b/packages/xpub-faraday/tests/config/authsome-helpers.test.js index 0e51ce6aed419d58cda2bf016f2bbc09d821e8b5..a15e1f9852337441114611dcc2a0e426bf904c5c 100644 --- a/packages/xpub-faraday/tests/config/authsome-helpers.test.js +++ b/packages/xpub-faraday/tests/config/authsome-helpers.test.js @@ -195,42 +195,4 @@ describe('Authsome Helpers', () => { expect(parsedUser).toHaveProperty('email') expect(parsedUser).toHaveProperty('username') }) - describe('updateReviewerVisibleStatusByInvitation', () => { - it('should return the fragment status for reviewer when they have done the review', async () => { - const { answerReviewer } = testFixtures.users - const { collectionReviewCompleted } = testFixtures.collections - - const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({ - collection: collectionReviewCompleted, - FragmentModel: models.Fragment, - user: answerReviewer, - }) - - expect(visibleStatus).toEqual('Review Completed') - }) - it('should return the underReview status for reviewer when they have accepted the review', async () => { - const { reviewer } = testFixtures.users - const { collectionReviewCompleted } = testFixtures.collections - - const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({ - collection: collectionReviewCompleted, - FragmentModel: models.Fragment, - user: reviewer, - }) - - expect(visibleStatus).toEqual('Complete Review') - }) - it('should return the reviewersInvited status for reviewer when they have to accept the review', async () => { - const { recReviewer } = testFixtures.users - const { collectionReviewCompleted } = testFixtures.collections - - const visibleStatus = await ah.updateReviewerVisibleStatusByInvitation({ - collection: collectionReviewCompleted, - FragmentModel: models.Fragment, - user: recReviewer, - }) - - expect(visibleStatus).toEqual('Respond to Invite') - }) - }) }) diff --git a/yarn.lock b/yarn.lock index f6c36cafc8383e67e1a308f0309d904df6e8e006..708053b3d33e89331cac4388464f0a2cc6bfd570 100644 --- a/yarn.lock +++ b/yarn.lock @@ -139,17 +139,19 @@ aws-sdk "^2.185.0" nodemailer "^4.4.2" -"@pubsweet/db-manager@^1.0.10": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@pubsweet/db-manager/-/db-manager-1.0.10.tgz#88d9f935cb04943ea150ef3820810f792bb6308e" - integrity sha512-YCwBxnR4D6aZAsgWJUnP95X8ZmaKRqf375j12234Ui6iVqn2ZpS2fr3+qT/WSDTzFkVgs69waZ3Frdth63MJHg== +"@pubsweet/db-manager@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@pubsweet/db-manager/-/db-manager-2.0.6.tgz#75e5dbc3946c3211ff2146ef914884c3711bb92b" + integrity sha512-rheDnoOSVyuzlV63AfesAY/IDYHEkEMWxq1RUugtz22QzBLTeMaBQK7Sdp7xhuU7NK4t0kvoWuSo4QRvNgeUyQ== dependencies: - "@pubsweet/logger" "^0.2.2" + "@pubsweet/logger" "^0.2.7" fs-extra "^4.0.2" isomorphic-fetch "^2.2.1" - joi "^13.1.0" + joi "^13.6.0" pg "^7.4.1" - pubsweet-server "^6.1.0" + pubsweet-server "^10.0.1" + tmp "^0.0.33" + umzug "^2.1.0" "@pubsweet/default-theme@^3.0.0": version "3.0.0" @@ -161,13 +163,13 @@ typeface-noto-serif "^0.0.54" typeface-ubuntu-mono "^0.0.54" -"@pubsweet/logger@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@pubsweet/logger/-/logger-0.2.2.tgz#ef5680c766226d4b25c5915859ea259b8c688db3" - integrity sha512-BmGOXiGu8PRPdRMSCTNd6dKAPDBPL7hjlWHcsI16Y7lzlJLCUUfUPSuq1FGq4ZoinekM/oUeUDpbhIr7FFY9EQ== +"@pubsweet/logger@^0.2.7": + version "0.2.7" + resolved "https://registry.yarnpkg.com/@pubsweet/logger/-/logger-0.2.7.tgz#73e4b2a56c7d1145287da6081a0b6ede8abb4269" + integrity sha512-GSzvWWxkku12+HDJIFAfWSLM6/T342fX+ZAtUkTuXHu2cR3VVcJcgig2IxFfLXadFATDzSZAKJHanBOYjZYx4Q== dependencies: - config "^1.26.2" - joi "^13.1.0" + config "^2.0.1" + joi "^13.6.0" lodash "^4.17.4" "@pubsweet/styleguide@3.1.4": @@ -275,11 +277,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.6.tgz#d8176d864ee48753d053783e4e463aec86b8d82e" integrity sha512-CTUtLb6WqCCgp6P59QintjHWqzf4VL1uPA27bipLAPxFqrtK1gEYllePzTICGqQ8rYsCbpnsNypXjjDzGAAjEQ== -"@types/zen-observable@0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.3.tgz#91b728599544efbb7386d8b6633693a3c2e7ade5" - integrity sha512-aDvGDAHcVfUqNmd8q4//cHAP+HGxsbChbBbuk3+kMVk5TTxfWLpQWvVN3+UPjohLnwMYN7jr6BWNn2cYNqdm7g== - "@types/zen-observable@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" @@ -433,6 +430,16 @@ ajv@^6.1.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" +ajv@^6.1.1: + version "6.5.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" + integrity sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -489,6 +496,13 @@ ansi-styles@^3.2.0: dependencies: color-convert "^1.9.0" +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + ansi-styles@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" @@ -615,14 +629,13 @@ apollo-link@^1.0.0, apollo-link@^1.2.1, apollo-link@^1.2.2: apollo-utilities "^1.0.0" zen-observable-ts "^0.8.9" -apollo-link@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.1.0.tgz#9d573b16387ee0d8e147b1f319e42c8c562f18f7" - integrity sha512-8SP3GtYSMpLa6KJaGfgr3NO/wWmB7xLWASQt3Agf08SljGNx3SOt99Yv5VtM8FPs62BoQmESX73IRmtrD1exdA== +apollo-link@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.3.tgz#9bd8d5fe1d88d31dc91dae9ecc22474d451fb70d" + integrity sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw== dependencies: - "@types/zen-observable" "0.5.3" apollo-utilities "^1.0.0" - zen-observable "^0.7.0" + zen-observable-ts "^0.8.10" apollo-server-core@^1.3.2: version "1.3.2" @@ -776,6 +789,11 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-each@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= + array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -829,6 +847,11 @@ array-reduce@~0.0.0: resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= +array-slice@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -979,11 +1002,6 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" integrity sha1-ri1acpR38onWDdf5amMUoi3Wwio= -authsome@0.0.9: - version "0.0.9" - resolved "https://registry.yarnpkg.com/authsome/-/authsome-0.0.9.tgz#08b34f1797b3539e6a362f0fb11a01ae0613f928" - integrity sha512-orMHR7RqVuc0apo8reiwOiiC7ZoEOcBwZjVt6wko/uEjNK5Ti/ouvP5Huqja0CNzQxItZOn+c9XUJM27bfIJTw== - authsome@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/authsome/-/authsome-0.1.0.tgz#4152e666afcaa7f7c51ddbed94145ad7105904d9" @@ -1803,7 +1821,7 @@ babel-register@^6.26.0: mkdirp "^0.5.1" source-map-support "^0.4.15" -babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.9.2: +babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0, babel-runtime@^6.9.2: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -1857,6 +1875,11 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== +backo2@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + bail@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.2.tgz#f7d6c1731630a9f9f0d4d35ed1f962e2074a1764" @@ -1914,13 +1937,13 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bcrypt@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-1.0.3.tgz#b02ddc6c0b52ea16b8d3cf375d5a32e780dab548" - integrity sha512-pRyDdo73C8Nim3jwFJ7DWe3TZCgwDfWZ6nHS5LSdU77kWbj1frruvdndP02AOavtD4y8v6Fp2dolbHgp4SDrfg== +bcrypt@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-2.0.1.tgz#229c5afe09379789f918efe86e5e5b682e509f85" + integrity sha512-DwB7WgJPdskbR+9Y3OTJtwRq09Lmm7Na6b+4ewvXjkD0nfNRi1OozxljHm5ETlDCBq9DTy04lQz+rj+T2ztIJg== dependencies: - nan "2.6.2" - node-pre-gyp "0.6.36" + nan "2.10.0" + node-pre-gyp "0.9.1" big.js@^3.1.3: version "3.2.0" @@ -1951,6 +1974,11 @@ bluebird@2.x: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= +bluebird@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" + integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== + bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -2401,6 +2429,15 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796" @@ -2815,6 +2852,11 @@ commander@2.14.x, commander@^2.11.0, commander@^2.9.0, commander@~2.14.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" integrity sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw== +commander@^2.16.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + commander@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" @@ -2912,6 +2954,13 @@ config@^1.21.0, config@^1.26.2: json5 "0.4.0" os-homedir "1.0.2" +config@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/config/-/config-2.0.1.tgz#995ccc8175460578d646ac0a2e4018ffa44ca046" + integrity sha512-aTaviJnC8ZjQYx8kQf4u6tWqIxWolyQQ3LqXgnCLAsIb78JrUshHG0YuzIarzTaVVe1Pazms3TXImfYra8UsyQ== + dependencies: + json5 "^1.0.1" + connect-history-api-fallback@^1.3.0: version "1.5.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#b06873934bc5e344fef611a196a6faae0aee015a" @@ -3591,7 +3640,7 @@ debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6. dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.0.1, debug@^3.1.0: +debug@3.1.0, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== @@ -3768,6 +3817,11 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" @@ -4601,7 +4655,7 @@ eventemitter2@0.4.14: resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" integrity sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas= -eventemitter3@^3.0.0: +eventemitter3@^3.0.0, eventemitter3@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== @@ -4891,6 +4945,11 @@ fast-deep-equal@^1.0.0: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + fast-diff@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" @@ -5075,6 +5134,16 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + findup@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/findup/-/findup-0.1.5.tgz#8ad929a3393bac627957a7e5de4623b06b0e2ceb" @@ -5083,6 +5152,22 @@ findup@^0.1.5: colors "~0.6.0-1" commander "~2.1.0" +fined@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476" + integrity sha1-s33IRLdqL15wgeiE98CuNE8VNHY= + dependencies: + expand-tilde "^2.0.2" + is-plain-object "^2.0.3" + object.defaults "^1.1.0" + object.pick "^1.2.0" + parse-filepath "^1.0.1" + +flagged-respawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" + integrity sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c= + flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" @@ -5632,29 +5717,39 @@ graphql-extensions@^0.0.x: core-js "^2.5.3" source-map-support "^0.5.1" +graphql-postgres-subscriptions@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/graphql-postgres-subscriptions/-/graphql-postgres-subscriptions-1.0.4.tgz#a8083b03cfb93feea4ecdf088b4dde5f0481b923" + integrity sha512-2cyyIwwjzspf6406GnTPTOFgYeEeO/Se5mAkdbbVdunVWHKtWdRAF25qRLJIdHLqrXhjkQtTue+2k7OMehW+cA== + dependencies: + graphql-subscriptions "^0.5.8" + iterall "^1.2.2" + pg "^7.4.1" + pg-ipc "^1.0.4" + +graphql-subscriptions@^0.5.8: + version "0.5.8" + resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.5.8.tgz#13a6143c546bce390404657dc73ca501def30aa7" + integrity sha512-0CaZnXKBw2pwnIbvmVckby5Ge5e2ecmjofhYCdyeACbCly2j3WXDP/pl+s+Dqd2GQFC7y99NB+53jrt55CKxYQ== + dependencies: + iterall "^1.2.1" + graphql-tag@^2.7.3: version "2.9.1" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.9.1.tgz#1ab090ef7d3518b06d8c97d1393672145fe91587" integrity sha512-JBLpagu/Xbb8N6xU6hZvBeHjdvnWb/GJnA/rrnBy3iSl0bcy+pjT5N1HctAsWNmGoAgY1+ilwv6JJqu0Tk2hHQ== -graphql-tools@^2.18.0: - version "2.21.0" - resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-2.21.0.tgz#c0d0fbda6f40a87c8d267a2989ade2ae8b9a288e" - integrity sha512-AmG4WGdpL1OHwnA20ouP7BVB3KnvUOvsc7+4ULWRzEunyRFUYqxrgnEf20iZnYAha8JCb7AP4WPMwWKmGT91rg== +graphql-tools@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-4.0.0.tgz#6ea01937c6f947212f83567ba687e97c22fdd2a6" + integrity sha512-WokvjkanuZwY4BZBS3SlkDjrjCPu7WlCtLB2i9JiiXembVEkNos3Rl90zf7sJu72zSidGzTXU63iXRO2Fg3TtA== dependencies: - apollo-link "^1.1.0" + apollo-link "^1.2.3" apollo-utilities "^1.0.1" deprecated-decorator "^0.1.6" iterall "^1.1.3" uuid "^3.1.0" -graphql@^0.12.3: - version "0.12.3" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.12.3.tgz#11668458bbe28261c0dcb6e265f515ba79f6ce07" - integrity sha512-Hn9rdu4zacplKXNrLCvR8YFiTGnbM4Zw/UH8FDmzBDsH7ou40lSNH4tIlsxcYnz2TGNVJCpu1WxCM23yd6kzhA== - dependencies: - iterall "1.1.3" - graphql@^0.13.0: version "0.13.2" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.13.2.tgz#4c740ae3c222823e7004096f832e7b93b2108270" @@ -5662,6 +5757,13 @@ graphql@^0.13.0: dependencies: iterall "^1.2.1" +graphql@^14.0.2: + version "14.0.2" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.0.2.tgz#7dded337a4c3fd2d075692323384034b357f5650" + integrity sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw== + dependencies: + iterall "^1.2.2" + grid-styled@5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/grid-styled/-/grid-styled-5.0.2.tgz#1e81d7d5bde50a9b43d81cf111b81399126fe595" @@ -6272,7 +6374,7 @@ internal-ip@1.2.0: dependencies: meow "^3.3.0" -interpret@^1.0.0: +interpret@^1.0.0, interpret@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= @@ -6316,6 +6418,14 @@ is-absolute-url@^2.0.0: resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -6624,6 +6734,13 @@ is-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -6683,6 +6800,13 @@ is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" @@ -6840,17 +6964,12 @@ items@2.x.x: resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" integrity sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg= -iterall@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9" - integrity sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ== - iterall@^1.1.3: version "1.2.0" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.0.tgz#434e9f41f0b99911ab9c3d49d95f0e079176a2a2" integrity sha512-FB8k5B8otDib0rFysEP5G/oOY6aBF48Y9crLxyZ43eHsk/SfMVH1JqvzU0badSu/WR5nkk3ihp8VQlyBP3SJxg== -iterall@^1.2.1: +iterall@^1.2.1, iterall@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== @@ -7183,10 +7302,10 @@ joi@^10.0.6: items "2.x.x" topo "2.x.x" -joi@^13.1.0: - version "13.1.2" - resolved "https://registry.yarnpkg.com/joi/-/joi-13.1.2.tgz#b2db260323cc7f919fafa51e09e2275bd089a97e" - integrity sha512-bZZSQYW5lPXenOfENvgCBPb9+H6E6MeNWcMtikI04fKphj5tvFL9TOb+H2apJzbCrRw/jebjTH8z6IHLpBytGg== +joi@^13.6.0: + version "13.7.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz#cfd85ebfe67e8a1900432400b4d03bbd93fb879f" + integrity sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q== dependencies: hoek "5.x.x" isemail "3.x.x" @@ -7305,6 +7424,11 @@ json-schema-traverse@^0.3.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -7342,6 +7466,13 @@ json5@^0.5.0, json5@^0.5.1: resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + jsonfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" @@ -7506,6 +7637,28 @@ kleur@^2.0.1: resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.1.tgz#7cc64b0d188d0dcbc98bdcdfdda2cc10619ddce8" integrity sha512-Zq/jyANIJ2uX8UZjWlqLwbyhcxSXJtT/Y89lClyeZd3l++3ztL1I5SSCYrbcbwSunTjC88N3WuMk0kRDQD6gzA== +knex@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/knex/-/knex-0.15.2.tgz#6059b87489605f4cc87599a6d2a9d265709e9340" + integrity sha1-YFm4dIlgX0zIdZmm0qnSZXCek0A= + dependencies: + babel-runtime "^6.26.0" + bluebird "^3.5.1" + chalk "2.3.2" + commander "^2.16.0" + debug "3.1.0" + inherits "~2.0.3" + interpret "^1.1.0" + liftoff "2.5.0" + lodash "^4.17.10" + minimist "1.2.0" + mkdirp "^0.5.1" + pg-connection-string "2.0.0" + tarn "^1.1.4" + tildify "1.2.0" + uuid "^3.3.2" + v8flags "^3.1.1" + known-css-properties@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.5.0.tgz#6ff66943ed4a5b55657ee095779a91f4536f8084" @@ -7593,6 +7746,20 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +liftoff@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" + integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew= + dependencies: + extend "^3.0.0" + findup-sync "^2.0.0" + fined "^1.0.1" + flagged-respawn "^1.0.0" + is-plain-object "^2.0.4" + object.map "^1.0.0" + rechoir "^0.6.2" + resolve "^1.1.7" + linkify-it@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f" @@ -7908,6 +8075,11 @@ lodash@4.17.5, lodash@^4, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" integrity sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw== +lodash@^4.17.0: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + lodash@^4.17.10, lodash@^4.17.2, lodash@~4.17.10: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" @@ -8007,6 +8179,13 @@ make-dir@^1.0.0: dependencies: pify "^3.0.0" +make-iterator@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" + integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== + dependencies: + kind-of "^6.0.2" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -8014,7 +8193,7 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -map-cache@^0.2.2: +map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= @@ -8188,7 +8367,7 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.1.4: +micromatch@^3.0.4, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -8303,16 +8482,16 @@ minimist@1.1.x: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= +minimist@1.2.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + minimist@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4= -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -8460,12 +8639,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" - integrity sha1-5P805slf37WuzAjeZZb0NgWn20U= - -nan@^2.10.0, nan@^2.9.2: +nan@2.10.0, nan@^2.10.0, nan@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== @@ -8533,6 +8707,15 @@ nearley@^2.7.10: randexp "0.4.6" semver "^5.4.1" +needle@^2.2.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + needle@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" @@ -8667,20 +8850,21 @@ node-notifier@^5.2.1: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@0.6.36: - version "0.6.36" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" - integrity sha1-22BBEst04NR3VU6bUFsXq936t4Y= +node-pre-gyp@0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz#f11c07516dd92f87199dbc7e1838eab7cd56c9e0" + integrity sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA= dependencies: + detect-libc "^1.0.2" mkdirp "^0.5.1" + needle "^2.2.0" nopt "^4.0.1" + npm-packlist "^1.1.6" npmlog "^4.0.2" rc "^1.1.7" - request "^2.81.0" rimraf "^2.6.1" semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" + tar "^4" node-pre-gyp@^0.10.0: version "0.10.3" @@ -8959,6 +9143,16 @@ object.assign@^4.0.4, object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.defaults@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= + dependencies: + array-each "^1.0.1" + array-slice "^1.0.0" + for-own "^1.0.0" + isobject "^3.0.0" + object.entries@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" @@ -8977,6 +9171,14 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.2" es-abstract "^1.5.1" +object.map@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" + integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= + dependencies: + for-own "^1.0.0" + make-iterator "^1.0.0" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -8985,7 +9187,7 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" -object.pick@^1.3.0: +object.pick@^1.2.0, object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= @@ -9002,6 +9204,15 @@ object.values@^1.0.4: function-bind "^1.1.0" has "^1.0.1" +objection@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/objection/-/objection-1.3.0.tgz#2b7e41d4b44a5c1abcb40e34e7ef6347e8bb683d" + integrity sha512-LhKd9N/tSNiFNKSozydrk7C8XmQbEbYNmnF1vC7ywgdWzMZfWhehILIE95mVpdo93f26jWDVaY6SHp/bjMvEng== + dependencies: + ajv "^6.1.1" + bluebird "^3.5.1" + lodash "^4.17.4" + obuf@^1.0.0, obuf@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -9260,6 +9471,15 @@ parse-entities@^1.1.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" +parse-filepath@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + parse-github-repo-url@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" @@ -9417,6 +9637,18 @@ path-parse@^1.0.5: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" integrity sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME= +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= + dependencies: + path-root-regex "^0.1.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -9483,6 +9715,16 @@ pg-connection-string@0.1.3: resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= +pg-connection-string@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.0.0.tgz#3eefe5997e06d94821e4d502e42b6a1c73f8df82" + integrity sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I= + +pg-ipc@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/pg-ipc/-/pg-ipc-1.0.4.tgz#e018f5aae417ded8a917878e33c1fe911bcce45f" + integrity sha1-4Bj1quQX3tipF4eOM8H+kRvM5F8= + pg-pool@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.3.tgz#c022032c8949f312a4f91fb6409ce04076be3257" @@ -10074,6 +10316,7 @@ promise@^7.1.1: prompt@^1.0.0, prompt@flatiron/prompt#1c95d1d8d333b5fbc13fa5f0619f3dcf0d514f87: version "1.0.0" resolved "https://codeload.github.com/flatiron/prompt/tar.gz/1c95d1d8d333b5fbc13fa5f0619f3dcf0d514f87" + integrity sha1-jlcSPDlquYiJf7Mn/Trtw+c15P4= dependencies: colors "^1.1.2" read "1.0.x" @@ -10330,72 +10573,36 @@ pubsweet-component-signup@^1.0.0: react-router "^4.2.0" redux "^3.7.2" -pubsweet-server@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/pubsweet-server/-/pubsweet-server-2.0.3.tgz#97d36cec0e2f4f0c2955fb0b0de73206ec05fe69" - integrity sha512-AEn4aSs4GHJciqsvTZkXKLh+NcgAJ34HDIPp1ODnZ9nubohSDH+ZM6XBIjiP77BaJtnnjPzs536v/b/zFy1rkw== +pubsweet-server@10.0.1, pubsweet-server@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/pubsweet-server/-/pubsweet-server-10.0.1.tgz#ac2ccc0ae1f42f2c97b044be3f90782b11b1d0fa" + integrity sha512-hUcOfVAV6rWeohgb93NO5sn414m03cOeKKUaOKxCXqn8CNgFmZQhmogLeEXH+MVbEXsnbpYnEuV0rcuwA0boNQ== dependencies: - "@pubsweet/logger" "^0.2.2" - apollo-server-express "^1.3.2" - apollo-upload-server "^4.0.2" - authsome "0.0.9" - bcrypt "^1.0.2" - bluebird "^3.5.1" - body-parser "^1.15.2" - colors "^1.1.2" - config "^1.26.2" - cookie-parser "^1.4.3" - dotenv "^4.0.0" - express "^4.16.1" - graphql "^0.12.3" - graphql-tools "^2.18.0" - helmet "^3.8.1" - http-status-codes "^1.0.6" - joi "^13.1.0" - jsonwebtoken "^7.1.7" - lodash "^4.0.0" - minimist "^1.2.0" - morgan "^1.8.2" - multer "^1.1.0" - passport "^0.3.2" - passport-anonymous "^1.0.1" - passport-http-bearer "^1.0.1" - passport-local "^1.0.0" - pg "^7.4.1" - promise-queue "^2.2.3" - prompt "^1.0.0" - pubsweet-sse "^0.1.4" - require-relative "^0.8.7" - uuid "^3.0.1" - winston "^2.2.0" - -pubsweet-server@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/pubsweet-server/-/pubsweet-server-6.1.0.tgz#038b8fdb08717c1b701f175030546492f387303c" - integrity sha512-maPhfKtyEicoRhX9jCZkQgQ08S58P5BU1RpJ58gF+lmdswTyrCsRqbid22eVmJJHAiOW8XByDbV2ipw8PUbZ+w== - dependencies: - "@pubsweet/logger" "^0.2.2" + "@pubsweet/logger" "^0.2.7" apollo-server-express "^1.3.2" apollo-upload-server "^4.0.2" authsome "^0.1.0" - bcrypt "^1.0.2" + bcrypt "^2.0.1" bluebird "^3.5.1" body-parser "^1.15.2" colors "^1.1.2" - config "^1.26.2" + config "^2.0.1" cookie-parser "^1.4.3" dotenv "^4.0.0" express "^4.16.1" - graphql "^0.12.3" - graphql-tools "^2.18.0" + graphql "^14.0.2" + graphql-postgres-subscriptions "^1.0.4" + graphql-tools "^4.0.0" helmet "^3.8.1" http-status-codes "^1.0.6" - joi "^13.1.0" + joi "^13.6.0" jsonwebtoken "^7.1.7" + knex "^0.15.2" lodash "^4.0.0" minimist "^1.2.0" morgan "^1.8.2" multer "^1.1.0" + objection "^1.3.0" passport "^0.3.2" passport-anonymous "^1.0.1" passport-http-bearer "^1.0.1" @@ -10403,28 +10610,23 @@ pubsweet-server@^6.1.0: pg "^7.4.1" promise-queue "^2.2.3" prompt "^1.0.0" - pubsweet-sse "^1.0.0" - require-relative "^0.8.7" + pubsweet-sse "^1.0.1" + subscriptions-transport-ws "^0.9.12" uuid "^3.0.1" winston "^2.2.0" -pubsweet-sse@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/pubsweet-sse/-/pubsweet-sse-0.1.4.tgz#1ff38a230143cbd487a8d44afb28a6c4746ee464" - integrity sha512-zQlcHSgVpKvsPSoNHgoh7+8DPIPQ6kqMRRhs3e8d/icHrJAhoz0aQdovB8VK5XZfjUkoHYidCjDT2LFueDvwVA== - -pubsweet-sse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pubsweet-sse/-/pubsweet-sse-1.0.0.tgz#dd36aa378a302b518d417b545b064da65aec876a" - integrity sha512-oxCfHoH68ym4k8WNxfGIkEh7OVGGSx14p1QVaYmVQJ4XpdWdY9J4vErG/RcbWTPpaAz2hZIUJb1AsCU7E70VKA== +pubsweet-sse@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pubsweet-sse/-/pubsweet-sse-1.0.1.tgz#675f699213a7c228a448e7c9f272a5a9e7585fcf" + integrity sha512-A5aDdSI38GmrfUhXc3bjXGExqUEzuzcWdm63Km7ww9KIMFQDnHl06ovap8OAP/+BmqxXvXooxHqqeQ/rhe0l7A== -pubsweet@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/pubsweet/-/pubsweet-2.2.1.tgz#6191303105c8d531a16de7090b89aec8f451a454" - integrity sha512-7uCRpJFsBr3cxyb22ZrCpK8p4a9p+BKdR2Sg4se4U3Z+DKkEUtLZ5Nw6hm1od3bm2toihAEl91AILBQuIy8rjw== +pubsweet@3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/pubsweet/-/pubsweet-3.0.6.tgz#8f2543f8d101cea596be53edf3d559d6bd89a57f" + integrity sha512-eJIscLmMvLmZ5+DBsOh9fpMNmXDd1xYtwOHNYty8hMn5pP6+b93EOzXeI+ofoFzdCTVCeAIATWKMAJmzWutOnQ== dependencies: - "@pubsweet/db-manager" "^1.0.10" - "@pubsweet/logger" "^0.2.2" + "@pubsweet/db-manager" "^2.0.6" + "@pubsweet/logger" "^0.2.7" bluebird "^3.5.0" colors "^1.1.2" commander "^2.9.0" @@ -10433,8 +10635,7 @@ pubsweet@^2.2.1: fs-extra "^4.0.2" inflection "^1.12.0" prompt flatiron/prompt#1c95d1d8d333b5fbc13fa5f0619f3dcf0d514f87 - pubsweet-server "^6.1.0" - require-relative "^0.8.7" + pubsweet-server "^10.0.1" uuid "^3.0.1" webpack "^3.8.1" webpack-dev-middleware "^1.12.0" @@ -11115,6 +11316,13 @@ recast@^0.13.0: private "~0.1.5" source-map "~0.6.1" +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + recompose@^0.26.0: version "0.26.0" resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.26.0.tgz#9babff039cb72ba5bd17366d55d7232fbdfb2d30" @@ -11543,7 +11751,7 @@ request@2.87.0, request@^2.87.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -request@^2.81.0, request@^2.83.0: +request@^2.83.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw== @@ -11591,11 +11799,6 @@ require-main-filename@^1.0.1: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= -require-relative@^0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" - integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4= - require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -11621,7 +11824,7 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" -resolve-dir@^1.0.0: +resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= @@ -11659,6 +11862,13 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= +resolve@^1.0.0, resolve@^1.1.6, resolve@^1.1.7: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== + dependencies: + path-parse "^1.0.5" + resolve@^1.3.3, resolve@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" @@ -12732,6 +12942,17 @@ stylis@^3.5.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1" integrity sha512-pP7yXN6dwMzAR29Q0mBrabPCe0/mNO1MSr93bhay+hcZondvMMTpeGyd8nbhYJdyperNT2DRxONQuUGcJr5iPw== +subscriptions-transport-ws@^0.9.12: + version "0.9.15" + resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.15.tgz#68a8b7ba0037d8c489fb2f5a102d1494db297d0d" + integrity sha512-f9eBfWdHsePQV67QIX+VRhf++dn1adyC/PZHP6XI5AfKnZ4n0FW+v5omxwdHVpd4xq2ZijaHEcmlQrhBY79ZWQ== + dependencies: + backo2 "^1.0.2" + eventemitter3 "^3.1.0" + iterall "^1.2.1" + symbol-observable "^1.0.4" + ws "^5.2.0" + sugarss@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44" @@ -12796,6 +13017,13 @@ supports-color@^5.2.0: dependencies: has-flag "^3.0.0" +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + svg-tags@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" @@ -12904,6 +13132,11 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" +tarn@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.4.tgz#aeeb85964b1afa0bbf381359c1167df237c27b6a" + integrity sha512-j4samMCQCP5+6Il9/cxCqBd3x4vvlLeVdoyGex0KixPKl4F8LpNbDSC6NDhjianZgUngElRr9UI1ryZqJDhwGg== + temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -12973,6 +13206,13 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.2.tgz#a862e018e3fb1ea2ec3fce5d55605cf57f247371" integrity sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E= +tildify@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" + integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo= + dependencies: + os-homedir "^1.0.0" + time-stamp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357" @@ -13282,6 +13522,21 @@ ultron@~1.1.0: resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== +umzug@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/umzug/-/umzug-2.1.0.tgz#c49dd71c7c26d082a9c9d3592dc6dc92cf867761" + integrity sha512-BgT+ekpItEWaG+3JjLLj6yVTxw2wIH8Cr6JyKYIzukWAx9nzGhC6BGHb/IRMjpobMM1qtIrReATwLUjKpU2iOQ== + dependencies: + babel-runtime "^6.23.0" + bluebird "^3.4.1" + lodash "^4.17.0" + resolve "^1.0.0" + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + uncontrollable@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-4.1.0.tgz#e0358291252e1865222d90939b19f2f49f81c1a9" @@ -13456,6 +13711,13 @@ upper-case@^1.1.1: resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -13571,6 +13833,18 @@ uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA== +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +v8flags@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.1.tgz#42259a1461c08397e37fe1d4f1cfb59cad85a053" + integrity sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ== + dependencies: + homedir-polyfill "^1.0.1" + validate-npm-package-license@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" @@ -14016,6 +14290,13 @@ ws@^4.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" +ws@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== + dependencies: + async-limiter "~1.0.0" + x-is-function@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" @@ -14266,6 +14547,13 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" +zen-observable-ts@^0.8.10: + version "0.8.10" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz#18e2ce1c89fe026e9621fd83cc05168228fce829" + integrity sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ== + dependencies: + zen-observable "^0.8.0" + zen-observable-ts@^0.8.9: version "0.8.9" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.9.tgz#d3c97af08c0afdca37ebcadf7cc3ee96bda9bab1" @@ -14273,11 +14561,6 @@ zen-observable-ts@^0.8.9: dependencies: zen-observable "^0.8.0" -zen-observable@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.7.1.tgz#f84075c0ee085594d3566e1d6454207f126411b3" - integrity sha512-OI6VMSe0yeqaouIXtedC+F55Sr6r9ppS7+wTbSexkYdHbdt4ctTuPNXP/rwm7GTVI63YBc+EBT0b0tl7YnJLRg== - zen-observable@^0.8.0: version "0.8.8" resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.8.tgz#1ea93995bf098754a58215a1e0a7309e5749ec42"