diff --git a/package.json b/package.json index 25df746b..79c58235 100644 --- a/package.json +++ b/package.json @@ -82,12 +82,12 @@ "eslint-import-resolver-babel-module": "^5.1.2", "express": "^4.14.0", "google-libphonenumber": "^3.2.7", - "graphql": "^0.13.2", + "graphql": "^14.6.0", "graphql-date": "^1.0.3", - "graphql-tag": "^0.1.9", + "graphql-tag": "^2.10.3", "graphql-tools": "^2.8.0", "graphql-type-datetime": "^0.2.4", - "graphql-type-json": "^0.1.4", + "graphql-type-json": "^0.3.1", "humps": "^1.1.0", "is-url": "^1.2.2", "json-loader": "^0.5.4", @@ -120,6 +120,7 @@ "yup": "^0.24.0" }, "devDependencies": { + "@apollo/react-hooks": "^3.1.3", "@babel/cli": "^7.8.4", "@babel/core": "^7.8.4", "@babel/plugin-proposal-class-properties": "^7.8.3", @@ -130,7 +131,14 @@ "@babel/register": "^7.8.3", "@sentry/browser": "^5.12.5", "aphrodite": "^2.3.1", - "apollo-client": "^1.9.2", + "apollo-boost": "^0.4.7", + "apollo-client": "^2.6.8", + "apollo-client-legacy": "npm:apollo-client@1.9.2", + "apollo-link": "^1.2.13", + "apollo-link-batch-http": "^1.2.13", + "apollo-link-error": "^1.1.12", + "apollo-link-http": "^1.5.16", + "apollo-link-retry": "^2.2.15", "babel-eslint": "^10.0.3", "babel-jest": "^25.1.0", "babel-loader": "^8.0.6", @@ -174,8 +182,8 @@ "react-router-redux": "^4.0.5", "react-sortable-hoc": "^1.11.0", "react-test-renderer": "16", - "react-virtualized-auto-sizer": "^1.0.2", "react-virtualized": "^9.21.2", + "react-virtualized-auto-sizer": "^1.0.2", "redux": "^3.7.2", "redux-thunk": "^2.1.0", "regenerator-runtime": "^0.10.5", diff --git a/src/client/apollo.js b/src/client/apollo.js new file mode 100644 index 00000000..dbd11c54 --- /dev/null +++ b/src/client/apollo.js @@ -0,0 +1,84 @@ +import { ApolloClient } from "apollo-client"; +import { InMemoryCache } from "apollo-cache-inmemory"; +import { ApolloLink } from "apollo-link"; +import { RetryLink } from "apollo-link-retry"; +import { BatchHttpLink } from "apollo-link-batch-http"; +import { onError } from "apollo-link-error"; +import * as Sentry from "@sentry/browser"; + +window.S = Sentry; + +const cache = new InMemoryCache(); + +const retryLink = new RetryLink(); +const httpLink = new BatchHttpLink({ + uri: process.env.GRAPHQL_URL || "/graphql", + credentials: "same-origin" +}); + +const errorLink = onError(({ graphQLErrors, networkError }) => { + if (graphQLErrors) { + graphQLErrors.forEach(({ message, locations, path, code }) => { + console.error(`[GraphQL error] [${code}]: ${message}`, { + locations, + path + }); + + Sentry.addBreadcrumb({ + category: "apollo-graphql-error", + message: `Apollo GraphQL error: ${message}`, + data: { message, locations, path, code }, + level: "error" + }); + + if (code === "UNAUTHORIZED") { + window.location = `/login?nextUrl=${encodeURIComponent( + window.location.pathname + )}`; + } + + if (code === "NOT_FOUND") { + window.location = `/404`; + } + }); + } + + if (networkError) { + console.error(`[Network error]: ${networkError}`); + + Sentry.addBreadcrumb({ + category: "apollo-network-error", + message: `Apollo network error: ${networkError}`, + data: { networkError }, + level: "error" + }); + } +}); + +const breadcrumbLink = new ApolloLink((operation, forward) => { + Sentry.addBreadcrumb({ + category: "apollo-request", + message: `Apollo request - ${operation.operationName}`, + data: operation, + level: "info" + }); + + return forward(operation).map(data => { + Sentry.addBreadcrumb({ + category: "apollo-response", + message: `Apollo response - ${operation.operationName}`, + data, + level: "info" + }); + + return data; + }); +}); + +export default new ApolloClient({ + cache, + link: ApolloLink.from([retryLink, errorLink, breadcrumbLink, httpLink]), + connectToDevTools: true, + name: "spoke-client", + version: window.GIT_COMMIT_SHORT || "unknown-commit" +}); diff --git a/src/client/index.jsx b/src/client/index.jsx index 556b0021..2ea83f8d 100644 --- a/src/client/index.jsx +++ b/src/client/index.jsx @@ -4,7 +4,8 @@ import React, { Suspense } from "react"; import ReactDOM from "react-dom"; import { Router, browserHistory } from "react-router"; import { syncHistoryWithStore } from "react-router-redux"; -import { ApolloProvider } from "react-apollo"; +import { ApolloProvider as ApolloProviderLegacy } from "react-apollo"; +import { ApolloProvider } from "@apollo/react-hooks"; import MuiThemeProvider from "material-ui/styles/MuiThemeProvider"; import muiTheme from "src/styles/mui-theme"; @@ -13,6 +14,7 @@ import Store from "src/store"; import ApolloClientSingleton from "src/network/apollo-client-singleton"; import LoadingIndicator from "src/components/LoadingIndicator"; import ErrorBoundary from "src/components/ErrorBoundary"; +import client from "src/client/apollo"; import { login, logout } from "./auth-service"; import Telemetry from "./telemetry"; @@ -30,11 +32,13 @@ const history = syncHistoryWithStore(browserHistory, store.data); ReactDOM.render( - - }> - - - + + + }> + + + + , document.getElementById("mount") diff --git a/src/client/lib/error-helpers.js b/src/client/lib/error-helpers.js index 779de2db..17c7c8dc 100644 --- a/src/client/lib/error-helpers.js +++ b/src/client/lib/error-helpers.js @@ -1,5 +1,17 @@ import _ from "lodash"; +/** MODERN for new Apollo */ + +export function errorCodes(graphqlError) { + if (!graphqlError.graphQLErrors) { + return new Set(); + } + + return new Set(graphqlError.graphQLErrors.map(err => err.code)); +} + +/** LEGACY for old Apollo */ + export function getGraphQLErrors(response) { return _.get(response, "errors.graphQLErrors", []); } diff --git a/src/components/CheckReady.jsx b/src/components/CheckReady.jsx new file mode 100644 index 00000000..7a1d886f --- /dev/null +++ b/src/components/CheckReady.jsx @@ -0,0 +1,15 @@ +import React from "react"; +import LoadingIndicator from "./LoadingIndicator"; + +export default function checkReady(...results) { + // check for error + if (results.find(r => r.error)) { + return

There was an error

; + } + + if (results.find(r => r.loading)) { + return ; + } + + return null; +} diff --git a/src/components/TopNav.jsx b/src/components/TopNav.jsx index b0fca9c4..1e6a9ca8 100644 --- a/src/components/TopNav.jsx +++ b/src/components/TopNav.jsx @@ -1,13 +1,16 @@ import PropTypes from "prop-types"; import React from "react"; +import { Link } from "react-router"; +import { StyleSheet, css } from "aphrodite"; +import gql from "graphql-tag"; +import { useQuery } from "@apollo/react-hooks"; + import IconButton from "material-ui/IconButton"; import ArrowBackIcon from "material-ui/svg-icons/navigation/arrow-back"; -import { Link } from "react-router"; + import UserMenu from "../containers/UserMenu"; import theme from "../styles/theme"; -import { StyleSheet, css } from "aphrodite"; import loadData from "../containers/hoc/load-data"; -import gql from "graphql-tag"; const styles = StyleSheet.create({ container: { @@ -47,12 +50,28 @@ const styles = StyleSheet.create({ } }); -class TopNav extends React.Component { - state = { - userMenuOpen: false - }; +export default function TopNav({ backToURL, orgId, title }) { + const { loading, error, data: organizationData } = useQuery( + gql` + query getCurrentOrganization($organizationId: String!) { + organization(id: $organizationId) { + id + name + } + } + `, + { + variables: { + organizationId: orgId + }, + fetchPolicy: "network-only" + } + ); + + if (loading) return

Loading...

; + if (error) return

Error :(

; - renderBack(backToURL) { + const renderBack = () => { if (backToURL) { return ( @@ -66,51 +85,28 @@ class TopNav extends React.Component { ); } return
; - } + }; - render() { - const { backToURL, orgId, title, data } = this.props; - return ( -
-
-
{this.renderBack(backToURL)}
-
{title}
-
-
-
- {data.organization.name} -
-
-
- + return ( +
+
+
{renderBack(backToURL)}
+
{title}
+
+
+
+ {organizationData.name}
- ); - } +
+ +
+
+ ); } TopNav.propTypes = { backToURL: PropTypes.string, title: PropTypes.string.isRequired, - orgId: PropTypes.string, - data: PropTypes.object + orgId: PropTypes.string }; - -const mapQueriesToProps = ({ ownProps }) => ({ - data: { - query: gql` - query getCurrentOrganization($organizationId: String!) { - organization(id: $organizationId) { - id - name - } - } - `, - variables: { - organizationId: ownProps.orgId - }, - fetchPolicy: "network-only" - } -}); - -export default loadData(TopNav, { mapQueriesToProps }); diff --git a/src/containers/AdminLabelsList.jsx b/src/containers/AdminLabelsList.jsx index f246637c..22e6c48e 100644 --- a/src/containers/AdminLabelsList.jsx +++ b/src/containers/AdminLabelsList.jsx @@ -1,10 +1,11 @@ import types from "prop-types"; import React from "react"; -import { withRouter } from "react-router"; import _ from "lodash"; -import loadData from "./hoc/load-data"; import gql from "graphql-tag"; import DataTables from "material-ui-datatables"; +import checkReady from "src/components/CheckReady"; + +import { useQuery } from "@apollo/react-hooks"; const labelListColumns = [ { @@ -36,12 +37,37 @@ const labelListColumns = [ } ]; -function AdminLabelsList(props) { - if (!props.organizationData.organization) { - return null; +export default function AdminLabelsList(props) { + const organizationQuery = useQuery( + gql` + query getOrganization($organizationId: String!) { + organization(id: $organizationId) { + id + labels { + id + displayValue + slug + createdAt + group + } + } + } + `, + { + variables: { + organizationId: props.params.organizationId + }, + fetchPolicy: "network-only", + pollInterval: 60000 + } + ); + + const notReady = checkReady(organizationQuery); + if (notReady) { + return notReady; } - const { labels } = props.organizationData.organization; + const { labels } = organizationQuery.data.organization; return ( ({ - organizationData: { - query: gql` - query getOrganization($organizationId: String!) { - organization(id: $organizationId) { - id - labels { - id - displayValue - slug - createdAt - group - } - } - } - `, - variables: { - organizationId: ownProps.params.organizationId - }, - fetchPolicy: "network-only", - pollInterval: 60000 - } -}); - -export default loadData(AdminLabelsList, { mapQueriesToProps }); diff --git a/src/containers/AssignmentTexter/InitialMessageTexter.js b/src/containers/AssignmentTexter/InitialMessageTexter.js index 1c43e426..e1b544d5 100644 --- a/src/containers/AssignmentTexter/InitialMessageTexter.js +++ b/src/containers/AssignmentTexter/InitialMessageTexter.js @@ -1,28 +1,27 @@ import PropTypes from "prop-types"; import React, { Component } from "react"; -import { withRouter } from "react-router"; - -import loadData from "src/containers/hoc/load-data"; -import wrapMutations from "src/containers/hoc/wrap-mutations"; +import _ from "lodash"; import gql from "graphql-tag"; -import InitialMessageTexterContact from "./InitialMessageTexterContact"; -import Empty from "src/components/Empty"; import Check from "material-ui/svg-icons/action/check-circle"; import RaisedButton from "material-ui/RaisedButton"; -import _ from "lodash"; +import { useQuery, useMutation } from "@apollo/react-hooks"; + import { getTopMostParent, campaignIsBetweenTextingHours, timeUntilTextEnd } from "src/lib"; import { applyScript } from "src/lib/scripts"; -import { checkForErrorCode } from "src/client/lib/error-helpers"; +import { errorCodes } from "src/client/lib/error-helpers"; +import checkReady from "src/components/CheckReady"; +import Empty from "src/components/Empty"; import TextingClosedModal, { OUTSIDE_HOURS, CAMPAIGN_CLOSED } from "../TextingClosedModal"; -import { getGraphQLErrors } from "src/client/lib/error-helpers"; + +import InitialMessageTexterContact from "./InitialMessageTexterContact"; const contactDataFragment = ` id @@ -145,31 +144,22 @@ class InitialMessageTexter extends Component { this.isSending = true; try { - const response = await this.props.mutations.sendMessage( - messageInput, - contactId - ); - - const graphQLErrors = getGraphQLErrors(response); - const codes = graphQLErrors.map(error => error.code); - const campaignClosed = - codes.includes("CAMPAIGN_CLOSED") || - codes.includes("CAMPAIGN_CLOSED_FOR_INITIAL_SENDS"); + await this.props.mutations.sendMessage(messageInput, contactId); + } catch (e) { + const codes = errorCodes(e); - if (campaignClosed) { + if ( + codes.has("CAMPAIGN_CLOSED") || + codes.has("CAMPAIGN_CLOSED_FOR_INITIAL_SENDS") + ) { this.showClosedModal(); - } else if (codes.includes("TEXTING_HOURS")) { + } else if (codes.has("TEXTING_HOURS")) { this.showClosedModal(OUTSIDE_HOURS); - } - - // This can happen if a user has the initial message texter open in multiple windows - const dupMessage = checkForErrorCode(response, "DUPLICATE_MESSAGE"); - if (dupMessage) { + } else if (codes.has("DUPLICATE_MESSAGE")) { window.location.reload(); + } else { + this.exitTexter(); } - } catch (e) { - console.error("Error sending message", e); - this.exitTexter(); } finally { this.isSending = false; @@ -253,9 +243,9 @@ class InitialMessageTexter extends Component { }; } -const mapQueriesToProps = ({ ownProps }) => ({ - data: { - query: gql` +export default function InitialMessageTexterContainer(ownProps) { + const dataQuery = useQuery( + gql` query getContactsForInitialMessageTexter( $assignmentId: String! $contactsFilter: ContactsFilter! @@ -311,20 +301,20 @@ const mapQueriesToProps = ({ ownProps }) => ({ } } `, - variables: { - contactsFilter: { - messageStatus: "needsMessage", - isOptedOut: false, - validTimezone: true - }, - assignmentId: ownProps.params.assignmentId + { + variables: { + contactsFilter: { + messageStatus: "needsMessage", + isOptedOut: false, + validTimezone: true + }, + assignmentId: ownProps.params.assignmentId + } } - } -}); + ); -const mapMutationsToProps = ({ ownProps }) => ({ - sendMessage: (message, campaignContactId) => ({ - mutation: gql` + const [sendMessageMutation] = useMutation( + gql` mutation sendMessage( $message: MessageInput! $campaignContactId: String! @@ -339,25 +329,37 @@ const mapMutationsToProps = ({ ownProps }) => ({ } } } - `, - variables: { - message, - campaignContactId - } - }), - releaseBatch: () => ({ - mutation: gql` + ` + ); + const sendMessage = (message, campaignContactId) => + sendMessageMutation({ + variables: { message, campaignContactId } + }); + + const [releaseBatchMutation] = useMutation( + gql` mutation releaseBatch($assignmentId: String!) { releaseUnmessagedContacts(assignmentId: $assignmentId) } - `, - variables: { - assignmentId: ownProps.params.assignmentId - } - }) -}); + ` + ); + const releaseBatch = () => + releaseBatchMutation({ + variables: { + assignmentId: ownProps.params.assignmentId + } + }); -export default loadData(wrapMutations(withRouter(InitialMessageTexter)), { - mapQueriesToProps, - mapMutationsToProps -}); + const notReady = checkReady(dataQuery); + if (notReady) { + return notReady; + } + + return ( + + ); +} diff --git a/src/containers/hoc/wrap-mutations.jsx b/src/containers/hoc/wrap-mutations.jsx index 2ca95db3..6dc2c304 100644 --- a/src/containers/hoc/wrap-mutations.jsx +++ b/src/containers/hoc/wrap-mutations.jsx @@ -11,8 +11,11 @@ const wrapMutations = Component => props => { const argCopy = [...args]; // eslint-disable-next-line react/prop-types const resp = await props.mutations[key](...argCopy); + console.log("RESP", resp); const parsedError = graphQLErrorParser(resp); + console.log("PARSED ERROR", parsedError); if (parsedError) { + console.log("THROWING"); throw new GraphQLRequestError(parsedError); } return resp; diff --git a/src/network/apollo-client-singleton.js b/src/network/apollo-client-singleton.js index fc6c1961..8a3b0bef 100644 --- a/src/network/apollo-client-singleton.js +++ b/src/network/apollo-client-singleton.js @@ -1,11 +1,6 @@ -import ApolloClient from "apollo-client"; +import ApolloClient from "apollo-client-legacy"; import * as Sentry from "@sentry/browser"; -import { - getGraphQLErrors, - checkForErrorCode -} from "src/client/lib/error-helpers"; - import ResponseMiddlewareNetworkInterface from "./response-middleware-network-interface"; const responseMiddlewareNetworkInterface = new ResponseMiddlewareNetworkInterface( diff --git a/src/network/response-middleware-network-interface.js b/src/network/response-middleware-network-interface.js index 81b6d13e..71d73e23 100644 --- a/src/network/response-middleware-network-interface.js +++ b/src/network/response-middleware-network-interface.js @@ -1,4 +1,4 @@ -import { createNetworkInterface } from "apollo-client"; +import { createNetworkInterface } from "apollo-client-legacy"; class ResponseMiddlewareNetworkInterface { constructor(endpoint = "/graphql", options = {}) { diff --git a/src/server/api/lib/utils.js b/src/server/api/lib/utils.js index a11cbd98..60ebff04 100644 --- a/src/server/api/lib/utils.js +++ b/src/server/api/lib/utils.js @@ -26,8 +26,8 @@ export const capitalizeWord = word => { }; export function campaignPhoneNumbersEnabled(organization) { - return ( + return !!( organization.features && - !!JSON.parse(organization.features).campaignPhoneNumbersEnabled + JSON.parse(organization.features).campaignPhoneNumbersEnabled ); } diff --git a/src/server/api/organization.js b/src/server/api/organization.js index 6aeee4f9..eadec8c2 100644 --- a/src/server/api/organization.js +++ b/src/server/api/organization.js @@ -5,6 +5,8 @@ import { accessRequired } from "./errors"; import { getCampaigns } from "./campaign"; import { buildSortedUserOrganizationQuery } from "./user"; +import { ApolloError } from "src/server/api/errors"; + const Status = db.TwilioPhoneNumber.Status; export const resolvers = { diff --git a/src/server/index.js b/src/server/index.js index b3194081..841b459c 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -156,46 +156,53 @@ addMockFunctionsToSchema({ app.use( "/graphql", responseTimeMiddleware, - graphqlExpress(request => ({ - schema: executableSchema, - debug: !!process.env.DEBUG_APOLLO, - context: { - // TODO[matteo]: add request logger - loaders: createLoaders(), - user: request.user, - awsContext: request.awsContext || null, - awsEvent: request.awsEvent || null, - remainingMilliseconds: () => - request.awsContext && request.awsContext.getRemainingTimeInMillis - ? request.awsContext.getRemainingTimeInMillis() - : 5 * 60 * 1000 // default saying 5 min, no matter what - }, - formatError: error => { - let code = "UNKNOWN"; - if (error.originalError) { - code = error.originalError.code || "INTERNAL_SERVER_ERROR"; - } - error.code = code; - log.error({ - userId: request.user && request.user.id, - error, - msg: "GraphQL error" - }); - - if (TELEMETRY_IGNORED_ERROR_CODES.indexOf(error.code) === -1) { - telemetry.reportError(error.originalError || error, { + graphqlExpress(request => { + // if (Math.random() > 0.3) { + // throw new Error("test error"); + // } else { + // console.log("NO ERROR"); + // } + return { + schema: executableSchema, + debug: !!process.env.DEBUG_APOLLO, + context: { + // TODO[matteo]: add request logger + loaders: createLoaders(), + user: request.user, + awsContext: request.awsContext || null, + awsEvent: request.awsEvent || null, + remainingMilliseconds: () => + request.awsContext && request.awsContext.getRemainingTimeInMillis + ? request.awsContext.getRemainingTimeInMillis() + : 5 * 60 * 1000 // default saying 5 min, no matter what + }, + formatError: error => { + let code = "UNKNOWN"; + if (error.originalError) { + code = error.originalError.code || "INTERNAL_SERVER_ERROR"; + } + error.code = code; + log.error({ userId: request.user && request.user.id, - code, - awsRequestId: request.awsContext - ? request.awsContext.awsRequestId - : undefined, - awsEvent: request.awsEvent, - path: JSON.stringify(error.path) + error, + msg: "GraphQL error" }); + + if (TELEMETRY_IGNORED_ERROR_CODES.indexOf(error.code) === -1) { + telemetry.reportError(error.originalError || error, { + userId: request.user && request.user.id, + code, + awsRequestId: request.awsContext + ? request.awsContext.awsRequestId + : undefined, + awsEvent: request.awsEvent, + path: JSON.stringify(error.path) + }); + } + return error; } - return error; - } - })) + }; + }) ); app.get( diff --git a/yarn.lock b/yarn.lock index 0800d91e..25859d86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,6 +10,24 @@ d "1" es5-ext "^0.10.47" +"@apollo/react-common@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@apollo/react-common/-/react-common-3.1.3.tgz#ddc34f6403f55d47c0da147fd4756dfd7c73dac5" + integrity sha512-Q7ZjDOeqjJf/AOGxUMdGxKF+JVClRXrYBGVq+SuVFqANRpd68MxtVV2OjCWavsFAN0eqYnRqRUrl7vtUCiJqeg== + dependencies: + ts-invariant "^0.4.4" + tslib "^1.10.0" + +"@apollo/react-hooks@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@apollo/react-hooks/-/react-hooks-3.1.3.tgz#ad42c7af78e81fee0f30e53242640410d5bd0293" + integrity sha512-reIRO9xKdfi+B4gT/o/hnXuopUnm7WED/ru8VQydPw+C/KG/05Ssg1ZdxFKHa3oxwiTUIDnevtccIH35POanbA== + dependencies: + "@apollo/react-common" "^3.1.3" + "@wry/equality" "^0.1.9" + ts-invariant "^0.4.4" + tslib "^1.10.0" + "@babel/cli@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.8.4.tgz#505fb053721a98777b2b175323ea4f090b7d3c1c" @@ -1619,6 +1637,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.2.tgz#a5ccec6abb6060d5f20d256fb03ed743e9774999" integrity sha512-gojym4tX0FWeV2gsW4Xmzo5wxGjXGm550oVUII7f7G5o4BV6c7DBdiG1RRQd+y1bvqRyYtPfMK85UM95vsapqQ== +"@types/node@>=6": + version "13.7.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.7.tgz#1628e6461ba8cc9b53196dfeaeec7b07fa6eea99" + integrity sha512-Uo4chgKbnPNlxQwoFmYIwctkQVkMMmsAoGGU4JKwLuvBefF0pCq4FybNSnfkfRCpC7ZW7kttcC/TrRtAJsvGtg== + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" @@ -1654,6 +1677,11 @@ dependencies: "@types/yargs-parser" "*" +"@types/zen-observable@0.8.0", "@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" + integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -1800,7 +1828,15 @@ "@webassemblyjs/wast-parser" "1.8.5" "@xtuc/long" "4.2.2" -"@wry/equality@^0.1.2": +"@wry/context@^0.4.0": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8" + integrity sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag== + dependencies: + "@types/node" ">=6" + tslib "^1.9.3" + +"@wry/equality@^0.1.2", "@wry/equality@^0.1.9": version "0.1.9" resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.9.tgz#b13e18b7a8053c6858aa6c85b54911fb31e3a909" integrity sha512-mB6ceGjpMGz1ZTza8HYnrPGos2mC6So4NhS1PtZ8s4Qt0K7fBiIGhpSxUbQmhwcSWE3no+bYxmI2OL6KuXYmoQ== @@ -2057,6 +2093,21 @@ aphrodite@^2.3.1: inline-style-prefixer "^5.0.4" string-hash "^1.1.3" +apollo-boost@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/apollo-boost/-/apollo-boost-0.4.7.tgz#b0680ab0893e3f8b1ab1058dcfa2b00cb6440d79" + integrity sha512-jfc3aqO0vpCV+W662EOG5gq4AH94yIsvSgAUuDvS3o/Z+8Joqn4zGC9CgLCDHusK30mFgtsEgwEe0pZoedohsQ== + dependencies: + apollo-cache "^1.3.4" + apollo-cache-inmemory "^1.6.5" + apollo-client "^2.6.7" + apollo-link "^1.0.6" + apollo-link-error "^1.0.3" + apollo-link-http "^1.3.1" + graphql-tag "^2.4.2" + ts-invariant "^0.4.0" + tslib "^1.10.0" + apollo-cache-control@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.1.1.tgz#173d14ceb3eb9e7cb53de7eb8b61bee6159d4171" @@ -2064,10 +2115,29 @@ apollo-cache-control@^0.1.0: dependencies: graphql-extensions "^0.0.x" -apollo-client@^1.9.2: - version "1.9.3" - resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.9.3.tgz#37000b3c801f4571b7b089739e696a158896aeab" - integrity sha512-JABKKbqvcw8DJm3YUkEmyx1SK74i+/DesEtAtyocJi10LLmeMQYQFpg8W3BG1tZsYEQ3owEmPbsdNGTly+VOQg== +apollo-cache-inmemory@^1.6.5: + version "1.6.5" + resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.5.tgz#2ccaa3827686f6ed7fb634203dbf2b8d7015856a" + integrity sha512-koB76JUDJaycfejHmrXBbWIN9pRKM0Z9CJGQcBzIOtmte1JhEBSuzsOUu7NQgiXKYI4iGoMREcnaWffsosZynA== + dependencies: + apollo-cache "^1.3.4" + apollo-utilities "^1.3.3" + optimism "^0.10.0" + ts-invariant "^0.4.0" + tslib "^1.10.0" + +apollo-cache@1.3.4, apollo-cache@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.3.4.tgz#0c9f63c793e1cd6e34c450f7668e77aff58c9a42" + integrity sha512-7X5aGbqaOWYG+SSkCzJNHTz2ZKDcyRwtmvW4mGVLRqdQs+HxfXS4dUS2CcwrAj449se6tZ6NLUMnjko4KMt3KA== + dependencies: + apollo-utilities "^1.3.3" + tslib "^1.10.0" + +"apollo-client-legacy@npm:apollo-client@1.9.2": + version "1.9.2" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.9.2.tgz#a95b38ca846e881bba1b59b0e3fbf82abfd7f23d" + integrity sha512-1ZAw2x6AYtGFRosO9sR37+g5bNvCIyyNZ781h9M4Tm/lm8ejzINapx+BH2hdHgMxaGPuPvFpWGuD3m+sTbmWPQ== dependencies: apollo-link-core "^0.5.0" graphql "^0.10.0" @@ -2079,6 +2149,38 @@ apollo-client@^1.9.2: optionalDependencies: "@types/graphql" "0.10.2" +apollo-client@^2.6.7, apollo-client@^2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.6.8.tgz#01cebc18692abf90c6b3806414e081696b0fa537" + integrity sha512-0zvJtAcONiozpa5z5zgou83iEKkBaXhhSSXJebFHRXs100SecDojyUWKjwTtBPn9HbM6o5xrvC5mo9VQ5fgAjw== + dependencies: + "@types/zen-observable" "^0.8.0" + apollo-cache "1.3.4" + apollo-link "^1.0.0" + apollo-utilities "1.3.3" + symbol-observable "^1.0.2" + ts-invariant "^0.4.0" + tslib "^1.10.0" + zen-observable "^0.8.0" + +apollo-link-batch-http@^1.2.13: + version "1.2.13" + resolved "https://registry.yarnpkg.com/apollo-link-batch-http/-/apollo-link-batch-http-1.2.13.tgz#22b2e69e321922b4c3b0c9277811328ab6a401ba" + integrity sha512-wOuJ7M5GO1UlfWDDEIDX1rPLuy1ZR74olwDGgwOFE/PXiJpphwGg1noNHygp96PExPOwwSzfV+5J31RDVQ3ckA== + dependencies: + apollo-link "^1.2.13" + apollo-link-batch "^1.1.14" + apollo-link-http-common "^0.2.15" + tslib "^1.9.3" + +apollo-link-batch@^1.1.14: + version "1.1.14" + resolved "https://registry.yarnpkg.com/apollo-link-batch/-/apollo-link-batch-1.1.14.tgz#ee29f05a021b617f7d0f80633cc10c3b8992d930" + integrity sha512-KKQnKAVTjDzwtmLyhgTT7s64THPGGD0+4g7E9g/+XpSKURpX03clLaag7GBoiMFAI4P/BA4DtpuqcV7+9PsAfQ== + dependencies: + apollo-link "^1.2.13" + tslib "^1.9.3" + apollo-link-core@^0.5.0: version "0.5.4" resolved "https://registry.yarnpkg.com/apollo-link-core/-/apollo-link-core-0.5.4.tgz#8efd4cd747959872a32f313f0ccfc2a76b396668" @@ -2088,6 +2190,52 @@ apollo-link-core@^0.5.0: graphql-tag "^2.4.2" zen-observable-ts "^0.4.4" +apollo-link-error@^1.0.3, apollo-link-error@^1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.12.tgz#e24487bb3c30af0654047611cda87038afbacbf9" + integrity sha512-psNmHyuy3valGikt/XHJfe0pKJnRX19tLLs6P6EHRxg+6q6JMXNVLYPaQBkL0FkwdTCB0cbFJAGRYCBviG8TDA== + dependencies: + apollo-link "^1.2.13" + apollo-link-http-common "^0.2.15" + tslib "^1.9.3" + +apollo-link-http-common@^0.2.15: + version "0.2.15" + resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.15.tgz#304e67705122bf69a9abaded4351b10bc5efd6d9" + integrity sha512-+Heey4S2IPsPyTf8Ag3PugUupASJMW894iVps6hXbvwtg1aHSNMXUYO5VG7iRHkPzqpuzT4HMBanCTXPjtGzxg== + dependencies: + apollo-link "^1.2.13" + ts-invariant "^0.4.0" + tslib "^1.9.3" + +apollo-link-http@^1.3.1, apollo-link-http@^1.5.16: + version "1.5.16" + resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.16.tgz#44fe760bcc2803b8a7f57fc9269173afb00f3814" + integrity sha512-IA3xA/OcrOzINRZEECI6IdhRp/Twom5X5L9jMehfzEo2AXdeRwAMlH5LuvTZHgKD8V1MBnXdM6YXawXkTDSmJw== + dependencies: + apollo-link "^1.2.13" + apollo-link-http-common "^0.2.15" + tslib "^1.9.3" + +apollo-link-retry@^2.2.15: + version "2.2.15" + resolved "https://registry.yarnpkg.com/apollo-link-retry/-/apollo-link-retry-2.2.15.tgz#4cc3202fcb6251fed6f6b57ade99b4b1ad05c619" + integrity sha512-ltwXGxm+2NXzskrk+GTofj66LQtcc9OGCjIxAPbjlvtHanpKJn8CviWq8dIsMiYGS9T9rGG/kPPx/VdJfcFb6w== + dependencies: + "@types/zen-observable" "0.8.0" + apollo-link "^1.2.13" + tslib "^1.9.3" + +apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.13: + version "1.2.13" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.13.tgz#dff00fbf19dfcd90fddbc14b6a3f9a771acac6c4" + integrity sha512-+iBMcYeevMm1JpYgwDEIDt/y0BB7VWyvlm/7x+TIPNLHCTCMgcEgDuW5kH86iQZWo0I7mNwQiTOz+/3ShPFmBw== + dependencies: + apollo-utilities "^1.3.0" + ts-invariant "^0.4.0" + tslib "^1.9.3" + zen-observable-ts "^0.8.20" + apollo-link@^1.2.1: version "1.2.12" resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.12.tgz#014b514fba95f1945c38ad4c216f31bcfee68429" @@ -2127,6 +2275,16 @@ apollo-tracing@^0.1.0: dependencies: graphql-extensions "~0.0.9" +apollo-utilities@1.3.3, apollo-utilities@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.3.tgz#f1854715a7be80cd810bc3ac95df085815c0787c" + integrity sha512-F14aX2R/fKNYMvhuP2t9GD9fggID7zp5I96MF5QeKYWDWTrkRdHRp4+SVfXUVN+cXOaB/IebfvRtzPf25CM0zw== + dependencies: + "@wry/equality" "^0.1.2" + fast-json-stable-stringify "^2.0.0" + ts-invariant "^0.4.0" + tslib "^1.10.0" + apollo-utilities@^1.0.1, apollo-utilities@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.2.tgz#8cbdcf8b012f664cd6cb5767f6130f5aed9115c9" @@ -6293,12 +6451,7 @@ graphql-extensions@^0.0.x, graphql-extensions@~0.0.9: core-js "^2.5.3" source-map-support "^0.5.1" -graphql-tag@^0.1.9: - version "0.1.17" - resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-0.1.17.tgz#1dfd6f2310d395b309a1077bc8cdc5d6604c5e89" - integrity sha1-Hf1vIxDTlbMJoQd7yM3F1mBMXok= - -graphql-tag@^2.0.0, graphql-tag@^2.4.2: +graphql-tag@^2.0.0, graphql-tag@^2.10.3, graphql-tag@^2.4.2: version "2.10.3" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.3.tgz#ea1baba5eb8fc6339e4c4cf049dabe522b0edf03" integrity sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA== @@ -6321,10 +6474,10 @@ graphql-type-datetime@^0.2.4: dependencies: moment "^2.22.2" -graphql-type-json@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/graphql-type-json/-/graphql-type-json-0.1.4.tgz#89f13f5d32ce08c9a76c79fdf9c1968384d81a4e" - integrity sha1-ifE/XTLOCMmnbHn9+cGWg4TYGk4= +graphql-type-json@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/graphql-type-json/-/graphql-type-json-0.3.1.tgz#47fca2b1fa7adc0758d165b33580d7be7a6cf548" + integrity sha512-1lPkUXQ2L8o+ERLzVAuc3rzc/E6pGF+6HnjihCVTK0VzR0jCuUd92FqNxoHdfILXqOn2L6b4y47TBxiPyieUVA== graphql@^0.10.0, graphql@^0.10.3: version "0.10.5" @@ -6333,12 +6486,12 @@ graphql@^0.10.0, graphql@^0.10.3: dependencies: iterall "^1.1.0" -graphql@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.13.2.tgz#4c740ae3c222823e7004096f832e7b93b2108270" - integrity sha512-QZ5BL8ZO/B20VA8APauGBg3GyEgZ19eduvpLWoq5x7gMmWnHoy8rlQWPLmWgFvo1yNgjSEFMesmS4R6pPr7xog== +graphql@^14.6.0: + version "14.6.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.6.0.tgz#57822297111e874ea12f5cd4419616930cd83e49" + integrity sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg== dependencies: - iterall "^1.2.1" + iterall "^1.2.2" growly@^1.3.0: version "1.3.0" @@ -7497,12 +7650,12 @@ items@2.x.x: resolved "https://registry.yarnpkg.com/items/-/items-2.1.2.tgz#0849354595805d586dac98e7e6e85556ea838558" integrity sha512-kezcEqgB97BGeZZYtX/MA8AG410ptURstvnz5RAgyFZ8wQFPMxHY8GpTq+/ZHKT3frSlIthUq7EvLt9xn3TvXg== -iterall@^1.1.0: +iterall@^1.1.0, iterall@^1.2.2: version "1.3.0" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== -iterall@^1.1.3, iterall@^1.2.1: +iterall@^1.1.3: version "1.2.2" resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA== @@ -8450,9 +8603,9 @@ locate-path@^5.0.0: p-locate "^4.1.0" lodash-es@^4.2.1: - version "4.17.14" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.14.tgz#12a95a963cc5955683cee3b74e85458954f37ecc" - integrity sha512-7zchRrGa8UZXjD/4ivUWP1867jDkhzTG2c/uj739utSd7O/pFFdxspCemIFKEEjErbcqRzn8nKnGsi7mvTgRPA== + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" + integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== lodash.clonedeep@^4.5.0: version "4.5.0" @@ -8564,12 +8717,12 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.x, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.8.0: +lodash@4.17.x, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1, lodash@^4.8.0: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -"lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.2.1: +"lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.11, lodash@^4.17.12: version "4.17.14" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== @@ -9675,6 +9828,13 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" +optimism@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.10.3.tgz#163268fdc741dea2fb50f300bedda80356445fd7" + integrity sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw== + dependencies: + "@wry/context" "^0.4.0" + optionator@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" @@ -13102,13 +13262,18 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= -ts-invariant@^0.4.0: +ts-invariant@^0.4.0, ts-invariant@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86" integrity sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA== dependencies: tslib "^1.9.3" +tslib@^1.10.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + tslib@^1.9.0, tslib@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -14154,6 +14319,14 @@ zen-observable-ts@^0.8.19: tslib "^1.9.3" zen-observable "^0.8.0" +zen-observable-ts@^0.8.20: + version "0.8.20" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.20.tgz#44091e335d3fcbc97f6497e63e7f57d5b516b163" + integrity sha512-2rkjiPALhOtRaDX6pWyNqK1fnP5KkJJybYebopNSn6wDG1lxBoFs2+nwwXKoA6glHIrtwrfBBy6da0stkKtTAA== + dependencies: + tslib "^1.9.3" + zen-observable "^0.8.0" + zen-observable@^0.8.0: version "0.8.14" resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.14.tgz#d33058359d335bc0db1f0af66158b32872af3bf7"