BOD-14 Backend server work + sending of messages WIP for front end

This commit is contained in:
Patrick Fic
2020-03-25 15:50:46 -07:00
parent 5b5ffe21cd
commit 84a5820d8d
32 changed files with 892 additions and 274 deletions

View File

@@ -43,10 +43,8 @@
"redux-persist": "^6.0.0",
"redux-saga": "^1.1.3",
"reselect": "^4.0.0",
"styled-components": "^5.0.1",
"subscriptions-transport-ws": "^0.9.16",
"twilio": "^3.41.1"
"subscriptions-transport-ws": "^0.9.16"
},
"scripts": {
"analyze": "source-map-explorer 'build/static/js/*.js'",

View File

@@ -0,0 +1,37 @@
import { Button } from "antd";
import React from "react";
import { connect } from "react-redux";
import { closeConversation, sendMessage, toggleConversationVisible } from "../../redux/messaging/messaging.actions";
import PhoneFormatter from "../../utils/PhoneFormatter";
const mapDispatchToProps = dispatch => ({
toggleConversationVisible: conversationId =>
dispatch(toggleConversationVisible(conversationId)),
closeConversation: phone => dispatch(closeConversation(phone)),
sendMessage: message => dispatch(sendMessage(message))
});
function ChatConversationClosedComponent({
conversation,
toggleConversationVisible,
closeConversation
}) {
return (
<div style={{ display: "flex" }}>
<div onClick={() => toggleConversationVisible(conversation.phone)}>
<PhoneFormatter>{conversation.phone}</PhoneFormatter>
</div>
<Button
type='dashed'
shape='circle-outline'
onClick={() => closeConversation(conversation.phone)}>
X
</Button>
</div>
);
}
export default connect(
null,
mapDispatchToProps
)(ChatConversationClosedComponent);

View File

@@ -1,22 +1,16 @@
import { Button, Card, Input } from "antd";
import Icon from '@ant-design/icons';
import React, { useEffect, useState } from "react";
import { Button, Card } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import twilio from "twilio";
import {
closeConversation,
sendMessage,
toggleConversationVisible
} from "../../redux/messaging/messaging.actions";
import PhoneFormatter from "../../utils/PhoneFormatter";
import ChatConversationOpenComponent from "./chat-conversation.open.component";
import "./chat-conversation.styles.scss"; //https://bootsnipp.com/snippets/exR5v
import { MdSend } from "react-icons/md";
import { useTranslation } from "react-i18next";
const client = twilio(
"ACf1b1aaf0e04740828b49b6e58467d787",
"0bea5e29a6d77593183ab1caa01d23de"
);
import ChatConversationClosedComponent from "./chat-conversation.closed.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -24,35 +18,17 @@ const mapStateToProps = createStructuredSelector({
const mapDispatchToProps = dispatch => ({
toggleConversationVisible: conversationId =>
dispatch(toggleConversationVisible(conversationId)),
closeConversation: phone => dispatch(closeConversation(phone))
closeConversation: phone => dispatch(closeConversation(phone)),
sendMessage: message => dispatch(sendMessage(message))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(function ChatConversationComponent({
export function ChatConversationComponent({
conversation,
toggleConversationVisible,
closeConversation
}) {
const { t } = useTranslation();
const messages = [];
const [messages, setMessages] = useState([]);
useEffect(() => {
client.messages.list({ limit: 20 }, (error, items) => {
setMessages(
items.reduce((acc, value) => {
acc.push({
sid: value.sid,
direction: value.direction,
body: value.body
});
return acc;
}, [])
);
});
return () => {};
}, [setMessages]);
return (
<div>
<Card
@@ -60,15 +36,13 @@ export default connect(
conversation.open ? (
<div style={{ display: "flex" }}>
<div
onClick={() => toggleConversationVisible(conversation.phone)}
>
onClick={() => toggleConversationVisible(conversation.phone)}>
<PhoneFormatter>{conversation.phone}</PhoneFormatter>
</div>
<Button
type="danger"
shape="circle-outline"
onClick={() => closeConversation(conversation.phone)}
>
type='danger'
shape='circle-outline'
onClick={() => closeConversation(conversation.phone)}>
X
</Button>
</div>
@@ -78,44 +52,18 @@ export default connect(
width: conversation.open ? "400px" : "175px",
margin: "0px 10px"
}}
size="small"
>
size='small'>
{conversation.open ? (
<div>
<div className="messages" style={{ height: "400px" }}>
<ul>
{messages.map(item => (
<li
key={item.sid}
className={`${
item.direction === "inbound" ? "sent" : "replies"
}`}
>
<p> {item.body}</p>
</li>
))}
</ul>
</div>
<Input.Search
placeholder={t("messaging.labels.typeamessage")}
enterButton={<Icon component={MdSend} />}
/>
</div>
<ChatConversationOpenComponent messages={messages} />
) : (
<div style={{ display: "flex" }}>
<div onClick={() => toggleConversationVisible(conversation.phone)}>
<PhoneFormatter>{conversation.phone}</PhoneFormatter>
</div>
<Button
type="dashed"
shape="circle-outline"
onClick={() => closeConversation(conversation.phone)}
>
X
</Button>
</div>
<ChatConversationClosedComponent conversation={conversation} />
)}
</Card>
</div>
);
});
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ChatConversationComponent);

View File

@@ -0,0 +1,27 @@
import React from "react";
import ChatSendMessage from "../chat-send-message/chat-send-message.component";
export default function ChatConversationOpenComponent({
conversation,
messages
}) {
if (!!!messages) return <div>No Messages</div>;
return (
<div>
<div className='messages' style={{ height: "400px" }}>
<ul>
{messages.map(item => (
<li
key={item.sid}
className={`${
item.direction === "inbound" ? "sent" : "replies"
}`}>
<p> {item.body}</p>
</li>
))}
</ul>
</div>
<ChatSendMessage conversation={conversation} />
</div>
);
}

View File

@@ -0,0 +1,48 @@
import { Input } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { sendMessage } from "../../redux/messaging/messaging.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
});
const mapDispatchToProps = dispatch => ({
sendMessage: message => dispatch(sendMessage(message))
});
function ChatSendMessageComponent({ conversation, bodyshop, sendMessage }) {
const [message, setMessage] = useState("");
const { t } = useTranslation();
console.log("message", message);
const handleEnter = () => {
console.log("Sending that message ");
sendMessage({
to: conversation.phone,
body: message,
messagingServiceSid: bodyshop.messagingservicesid
});
};
return (
<div style={{ display: "flex " }}>
<Input.TextArea
allowClear
autoSize={{ minRows: 1, maxRows: 4 }}
placeholder={t("messaging.labels.typeamessage")}
// enterButton={}
onChange={e => setMessage(e.target.value)}
onPressEnter={event => {
if (!!!event.shiftKey) handleEnter();
}}
/>
</div>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ChatSendMessageComponent);

View File

@@ -22,6 +22,7 @@ export const QUERY_BODYSHOP = gql`
zip_post
region_config
md_responsibility_centers
messagingservicesid
employees {
id
first_name

View File

@@ -5,20 +5,24 @@ import AlertComponent from "../../components/alert/alert.component";
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
import { setBodyshop } from "../../redux/user/user.actions";
import ManagePage from "./manage.page.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import { useTranslation } from "react-i18next";
const mapDispatchToProps = dispatch => ({
setBodyshop: bs => dispatch(setBodyshop(bs))
});
function ManagePageContainer({ match, setBodyshop }) {
const { error, data } = useQuery(QUERY_BODYSHOP, {
const { loading, error, data } = useQuery(QUERY_BODYSHOP, {
fetchPolicy: "network-only"
});
const { t } = useTranslation();
useEffect(() => {
if (data) setBodyshop(data.bodyshops[0]);
}, [data, setBodyshop]);
if (loading)
return <LoadingSpinner message={t("general.labels.loadingshop")} />;
if (error) return <AlertComponent message={error.message} type='error' />;
return <ManagePage match={match} />;
}

View File

@@ -19,3 +19,13 @@ export const closeConversation = phone => ({
type: MessagingActionTypes.CLOSE_CONVERSATION,
payload: phone
});
export const sendMessage = message => ({
type: MessagingActionTypes.SEND_MESSAGE,
payload: message
});
export const sendMessageFailure = error => ({
type: MessagingActionTypes.SEND_MESSAGE_FAILURE,
payload: error
});

View File

@@ -3,8 +3,16 @@ import MessagingActionTypes from "./messaging.types";
const INITIAL_STATE = {
visible: false,
conversations: [
{ phone: "6049992002", open: false },
{ phone: "6049992991", open: false }
{
phone: "6049992002",
id: "519ba10d-6467-4fa5-9c22-59ae891edeb6",
open: false
},
{
phone: "6049992991",
id: "ab57deba-eeb9-40db-b5ae-23f3ce8d7c7b",
open: false
}
]
};

View File

@@ -1,5 +1,23 @@
import { all } from "redux-saga/effects";
import { all, call, put, takeLatest } from "redux-saga/effects";
import { sendMessageFailure } from "./messaging.actions";
import MessagingActionTypes from "./messaging.types";
import axios from "axios";
export function* onSendMessage() {
yield takeLatest(MessagingActionTypes.SEND_MESSAGE, sendMessage);
}
export function* sendMessage(payload) {
try {
console.log("Message Contents", payload);
axios.post("/sms/send", payload).then(response => {
console.log(JSON.stringify(response));
});
} catch (error) {
console.log("Error in sendMessage saga.");
yield put(sendMessageFailure(error));
}
}
export function* messagingSagas() {
yield all([]);
yield all([call(onSendMessage)]);
}

View File

@@ -4,6 +4,7 @@ const MessagingActionTypes = {
OPEN_CONVERSATION: "OPEN_CONVERSATION",
CLOSE_CONVERSATION: "CLOSE_CONVERSATION",
TOGGLE_CONVERSATION_VISIBLE: "TOGGLE_CONVERSATION_VISIBLE",
SEND_MESSAGE: "SEND_MESSAGE"
SEND_MESSAGE: "SEND_MESSAGE",
SEND_MESSAGE_FAILURE: "SEND_MESSAGE_FAILURE"
};
export default MessagingActionTypes;

View File

@@ -2145,14 +2145,6 @@
dependencies:
"@babel/types" "^7.3.0"
"@types/body-parser@*":
version "1.19.0"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
dependencies:
"@types/connect" "*"
"@types/node" "*"
"@types/bytebuffer@^5.0.40":
version "5.0.40"
resolved "https://registry.yarnpkg.com/@types/bytebuffer/-/bytebuffer-5.0.40.tgz#d6faac40dcfb09cd856cdc4c01d3690ba536d3ee"
@@ -2166,13 +2158,6 @@
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
"@types/connect@*":
version "3.4.33"
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==
dependencies:
"@types/node" "*"
"@types/eslint-visitor-keys@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
@@ -2183,23 +2168,6 @@
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
"@types/express-serve-static-core@*":
version "4.17.2"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz#f6f41fa35d42e79dbf6610eccbb2637e6008a0cf"
integrity sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg==
dependencies:
"@types/node" "*"
"@types/range-parser" "*"
"@types/express@^4.17.3":
version "4.17.3"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9"
integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "*"
"@types/serve-static" "*"
"@types/glob@^7.1.1":
version "7.1.1"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
@@ -2244,11 +2212,6 @@
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
"@types/mime@*":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -2279,11 +2242,6 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
"@types/range-parser@*":
version "1.2.3"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
"@types/react@^16.9.11":
version "16.9.23"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c"
@@ -2292,14 +2250,6 @@
"@types/prop-types" "*"
csstype "^2.2.0"
"@types/serve-static@*":
version "1.13.3"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==
dependencies:
"@types/express-serve-static-core" "*"
"@types/mime" "*"
"@types/stack-utils@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -3055,7 +3005,7 @@ arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
asap@^2.0.0, asap@^2.0.3, asap@~2.0.3, asap@~2.0.6:
asap@^2.0.3, asap@~2.0.3, asap@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
@@ -3621,11 +3571,6 @@ btoa@^1.2.1:
resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73"
integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@@ -4796,11 +4741,6 @@ date-arithmetic@^4.0.1:
resolved "https://registry.yarnpkg.com/date-arithmetic/-/date-arithmetic-4.1.0.tgz#e5d6434e9deb71f79760a37b729e4a515e730ddf"
integrity sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg==
dayjs@^1.8.21:
version "1.8.23"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.23.tgz#07b5a8e759c4d75ae07bdd0ad6977f851c01e510"
integrity sha512-NmYHMFONftoZbeOhVz6jfiXI4zSiPN6NoVWJgC0aZQfYVwzy/ZpESPHuCcI0B8BUMpSJQ08zenHDbofOLKq8hQ==
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -5177,13 +5117,6 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
ecdsa-sig-formatter@1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
dependencies:
safe-buffer "^5.0.1"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -8046,22 +7979,6 @@ jsonify@~0.0.0:
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
jsonwebtoken@^8.5.1:
version "8.5.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
dependencies:
jws "^3.2.2"
lodash.includes "^4.3.0"
lodash.isboolean "^3.0.3"
lodash.isinteger "^4.0.4"
lodash.isnumber "^3.0.3"
lodash.isplainobject "^4.0.6"
lodash.isstring "^4.0.1"
lodash.once "^4.0.0"
ms "^2.1.1"
semver "^5.6.0"
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -8080,23 +7997,6 @@ jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3:
array-includes "^3.0.3"
object.assign "^4.1.0"
jwa@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
dependencies:
buffer-equal-constant-time "1.0.1"
ecdsa-sig-formatter "1.0.11"
safe-buffer "^5.0.1"
jws@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
dependencies:
jwa "^1.4.1"
safe-buffer "^5.0.1"
killable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@@ -8320,47 +8220,22 @@ lodash.get@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.includes@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
lodash.isboolean@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
lodash.isequal@^4.0.0, lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.isinteger@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
lodash.isnumber@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
lodash.isstring@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
lodash.once@^4.0.0, lodash.once@^4.1.1:
lodash.once@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
@@ -9852,11 +9727,6 @@ pnp-webpack-plugin@1.6.4:
dependencies:
ts-pnp "^1.1.6"
pop-iterate@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/pop-iterate/-/pop-iterate-1.0.1.tgz#ceacfdab4abf353d7a0f2aaa2c1fc7b3f9413ba3"
integrity sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=
popper.js@^1.15.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
@@ -10744,15 +10614,6 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
q@2.0.x:
version "2.0.3"
resolved "https://registry.yarnpkg.com/q/-/q-2.0.3.tgz#75b8db0255a1a5af82f58c3f3aaa1efec7d0d134"
integrity sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=
dependencies:
asap "^2.0.0"
pop-iterate "^1.0.1"
weak-map "^1.0.5"
q@^1.1.2:
version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
@@ -10763,11 +10624,6 @@ qs@6.7.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
qs@^6.9.1:
version "6.9.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.2.tgz#a27b695006544a04bf0e6c6a7e8120778926d5bd"
integrity sha512-2eQ6zajpK7HwqrY1rRtGw5IZvjgtELXzJECaEDuzDFo2jjnIXpJSimzd4qflWZq6bLLi+Zgfj5eDrAzl/lptyg==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
@@ -12116,11 +11972,6 @@ rmc-feedback@^2.0.0:
babel-runtime "6.x"
classnames "^2.2.5"
rootpath@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/rootpath/-/rootpath-0.1.2.tgz#5b379a87dca906e9b91d690a599439bef267ea6b"
integrity sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms=
rst-selector-parser@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91"
@@ -12284,11 +12135,6 @@ schema-utils@^2.6.5:
ajv "^6.12.0"
ajv-keywords "^3.4.1"
scmp@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/scmp/-/scmp-2.1.0.tgz#37b8e197c425bdeb570ab91cc356b311a11f9c9a"
integrity sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==
screenfull@^5.0.0:
version "5.0.2"
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.0.2.tgz#b9acdcf1ec676a948674df5cd0ff66b902b0bed7"
@@ -13449,23 +13295,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
twilio@^3.41.1:
version "3.41.1"
resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.41.1.tgz#653f2daccad7fe3ac0362acd1a1347e690dd9795"
integrity sha512-YOAuQtb3xELQJDcL+G6ffDRrZeJSlFRph5peudFYcEa9Or5R0x+r8lShXlYl7yP8w7atCWxETSeySLuStEpvhg==
dependencies:
"@types/express" "^4.17.3"
axios "^0.19.2"
dayjs "^1.8.21"
jsonwebtoken "^8.5.1"
lodash "^4.17.15"
q "2.0.x"
qs "^6.9.1"
rootpath "^0.1.2"
scmp "^2.1.0"
url-parse "^1.4.7"
xmlbuilder "^13.0.2"
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -13646,7 +13475,7 @@ url-loader@2.3.0:
mime "^2.4.4"
schema-utils "^2.5.0"
url-parse@^1.4.3, url-parse@^1.4.7:
url-parse@^1.4.3:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
@@ -13812,11 +13641,6 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
weak-map@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.5.tgz#79691584d98607f5070bd3b70a40e6bb22e401eb"
integrity sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=
webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@@ -14245,11 +14069,6 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xmlbuilder@^13.0.2:
version "13.0.2"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-13.0.2.tgz#02ae33614b6a047d1c32b5389c1fdacb2bce47a7"
integrity sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==
xmlchars@^2.1.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"

View File

@@ -0,0 +1,5 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."messages" DROP COLUMN "isoutbound";
type: run_sql

View File

@@ -0,0 +1,6 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."messages" ADD COLUMN "isoutbound" boolean NOT NULL
DEFAULT false;
type: run_sql

View File

@@ -0,0 +1,38 @@
- args:
role: user
table:
name: messages
schema: public
type: drop_insert_permission
- args:
permission:
check:
conversation:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- id
- created_at
- updated_at
- msid
- conversationid
- text
- image
- image_path
- sent
- delivered
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: messages
schema: public
type: create_insert_permission

View File

@@ -0,0 +1,39 @@
- args:
role: user
table:
name: messages
schema: public
type: drop_insert_permission
- args:
permission:
check:
conversation:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- id
- created_at
- updated_at
- msid
- conversationid
- text
- image
- image_path
- sent
- delivered
- isoutbound
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: messages
schema: public
type: create_insert_permission

View File

@@ -0,0 +1,36 @@
- args:
role: user
table:
name: messages
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- delivered
- image
- sent
- image_path
- msid
- text
- created_at
- updated_at
- conversationid
- id
computed_fields: []
filter:
conversation:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
role: user
table:
name: messages
schema: public
type: create_select_permission

View File

@@ -0,0 +1,37 @@
- args:
role: user
table:
name: messages
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- delivered
- image
- isoutbound
- sent
- image_path
- msid
- text
- created_at
- updated_at
- conversationid
- id
computed_fields: []
filter:
conversation:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
role: user
table:
name: messages
schema: public
type: create_select_permission

View File

@@ -0,0 +1,38 @@
- args:
role: user
table:
name: messages
schema: public
type: drop_update_permission
- args:
permission:
columns:
- delivered
- image
- sent
- image_path
- msid
- text
- created_at
- updated_at
- conversationid
- id
filter:
conversation:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: messages
schema: public
type: create_update_permission

View File

@@ -0,0 +1,39 @@
- args:
role: user
table:
name: messages
schema: public
type: drop_update_permission
- args:
permission:
columns:
- delivered
- image
- isoutbound
- sent
- image_path
- msid
- text
- created_at
- updated_at
- conversationid
- id
filter:
conversation:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
localPresets:
- key: ""
value: ""
set: {}
role: user
table:
name: messages
schema: public
type: create_update_permission

View File

@@ -0,0 +1,5 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "messagingservicesid";
type: run_sql

View File

@@ -0,0 +1,6 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "messagingservicesid" text NULL
UNIQUE;
type: run_sql

View File

@@ -0,0 +1,42 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- id
- shopname
- created_at
- updated_at
- address1
- address2
- city
- state
- zip_post
- country
- email
- federal_tax_id
- insurance_vendor_id
- state_tax_id
- logo_img_path
- md_ro_statuses
- region_config
- md_order_statuses
- md_responsibility_centers
computed_fields: []
filter:
associations:
bodyshop:
associations:
user:
authid:
_eq: X-Hasura-User-Id
role: user
table:
name: bodyshops
schema: public
type: create_select_permission

View File

@@ -0,0 +1,43 @@
- args:
role: user
table:
name: bodyshops
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- id
- shopname
- created_at
- updated_at
- address1
- address2
- city
- state
- zip_post
- country
- email
- federal_tax_id
- insurance_vendor_id
- state_tax_id
- logo_img_path
- md_ro_statuses
- region_config
- md_order_statuses
- md_responsibility_centers
- messagingservicesid
computed_fields: []
filter:
associations:
bodyshop:
associations:
user:
authid:
_eq: X-Hasura-User-Id
role: user
table:
name: bodyshops
schema: public
type: create_select_permission

View File

@@ -25,8 +25,11 @@
"express": "^4.16.4",
"express-sslify": "^1.2.0",
"firebase-tools": "^7.14.0",
"graphql-request": "^1.8.2",
"nodemailer": "^6.4.4",
"source-map-explorer": "^2.3.1"
"phone": "^2.4.8",
"source-map-explorer": "^2.3.1",
"twilio": "^3.41.1"
},
"devDependencies": {
"concurrently": "^5.1.0",

View File

@@ -3,6 +3,7 @@ const cors = require("cors");
const bodyParser = require("body-parser");
const path = require("path");
const compression = require("compression");
const twilio = require("twilio");
var enforce = require("express-sslify");
if (process.env.NODE_ENV !== "production") require("dotenv").config();
@@ -25,9 +26,21 @@ app.post("/delete_s3", s3upload.delete_s3);
var sendEmail = require("./sendemail.js");
app.post("/sendemail", sendEmail.sendEmail);
// app.get("/test", function(req, res) {
// res.json({ success: true });
// });
app.get("/test", function(req, res) {
res.json({ success: true });
});
var smsReceive = require("./server/sms/receive");
app.post(
"/sms/receive",
twilio.webhook({ validate: process.env.NODE_ENV === "PRODUCTION" }),
smsReceive.receive
);
var smsSend = require("./server/sms/send");
app.post("/sms/send", smsSend.send);
var smsStatus = require("./server/sms/status");
app.post("/sms/status", smsStatus.status);
var downloadImages = require("./download-images");
app.get("/downloadImages", downloadImages.downloadImages);

View File

@@ -0,0 +1,9 @@
const GraphQLClient = require("graphql-request").GraphQLClient;
require("dotenv").config();
//TODO May need to use a different client that includes caching of resources.
exports.client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
headers: {
"x-hasura-admin-secret": process.env.HASURA_ADMIN_SECRET
}
});

View File

@@ -0,0 +1,23 @@
exports.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID = `
query FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID(
$mssid: String!
$phone: String!
) {
bodyshops(where: { messagingservicesid: { _eq: $mssid } }) {
id
conversations(where: { phone_num: { _eq: $phone } }) {
id
}
}
}
`;
exports.INSERT_MESSAGE = `
mutation INSERT_MESSAGE($msg: [messages_insert_input!]!) {
insert_messages(objects: $msg) {
returning {
id
}
}
}
`;

82
server/sms/receive.js Normal file
View File

@@ -0,0 +1,82 @@
require("dotenv").config();
const client = require("../graphql-client/graphql-client").client;
const queries = require("../graphql-client/queries");
const phone = require("phone");
exports.receive = (req, res) => {
//Perform request validation
if (!req.body || !req.body.MessagingServiceSid || !req.body.SmsMessageSid) {
res.sendStatus(400);
} else {
client
.request(queries.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, {
mssid: req.body.MessagingServiceSid,
phone: phone(req.body.From)[0]
})
.then(response => {
//TODO Add logic for handling MMS.
let newMessage = { msid: req.body.SmsMessageSid, text: req.body.Body };
if (response.bodyshops[0]) {
//Found a bodyshop - should always happen.
if (response.bodyshops[0].conversations.length === 0) {
//No conversation Found, create one.
console.log("[SMS Receive] No conversation found. Creating one.");
newMessage.conversation = {
data: {
bodyshopid: response.bodyshops[0].id,
phone_num: phone(req.body.From)[0]
}
};
} else if (response.bodyshops[0].conversations.length === 1) {
//Just add it to the conversation
console.log("[SMS Receive] Conversation found. Added ID.");
newMessage.conversationid =
response.bodyshops[0].conversations[0].id;
} else {
//We should never get here.
console.log(
"Massive Error: Duplicate Phone Numbers for MSSID: " +
req.body.MessagingServiceSid
);
}
client
.request(queries.INSERT_MESSAGE, { msg: newMessage })
.then(r2 => {
res.sendStatus(200);
})
.catch(e2 => {
console.log("e2", e2);
res.json(e2);
});
}
})
.catch(e1 => {
console.log("e1", e1);
res.json(e1);
});
}
};
// const sampleMessage: {
// "ToCountry": "CA",
// "ToState": "BC",
// "SmsMessageSid": "SMad7bddaf3454c0904999d6018b1e8f49",
// "NumMedia": "0",
// "ToCity": "Vancouver",
// "FromZip": "",
// "SmsSid": "SMad7bddaf3454c0904999d6018b1e8f49",
// "FromState": "BC",
// "SmsStatus": "received",
// "FromCity": "VANCOUVER",
// "Body": "Hi",
// "FromCountry": "CA",
// "To": "+16043301606",
// "MessagingServiceSid": "MG6e259e2add04ffa0d0aa355038670ee1",
// "ToZip": "",
// "NumSegments": "1",
// "MessageSid": "SMad7bddaf3454c0904999d6018b1e8f49",
// "AccountSid": "AC6c09d337d6b9c68ab6488c2052bd457c",
// "From": "+16049992002",
// "ApiVersion": "2010-04-01"
// }

41
server/sms/send.js Normal file
View File

@@ -0,0 +1,41 @@
require("dotenv").config();
const twilio = require("twilio");
const phone = require("phone");
const client = twilio(
process.env.TWILIO_AUTH_TOKEN,
process.env.TWILIO_AUTH_KEY
);
exports.send = (req, res) => {
console.log("Sending an SMS!");
const { to, messagingServiceSid, body, conversationid } = req.body;
if (!!to && !!messagingServiceSid && !!body && !!conversationid) {
client.messages
.create({
body: body,
messagingServiceSid: messagingServiceSid,
to: phone(to)[0]
})
.then(message => {
let newMessage = {
msid: message.sid,
text: body,
conversationid,
isoutbound: true
};
client
.request(queries.INSERT_MESSAGE, { msg: newMessage })
.then(r2 => {
res.sendStatus(200);
})
.catch(e2 => {
res.json({ success: false, message: e2 });
});
})
.catch(error => res.json({ success: false, message: error }));
} else {
res.json({ success: false, message: "Missing required parameter(s)." });
}
};

23
server/sms/status.js Normal file
View File

@@ -0,0 +1,23 @@
require("dotenv").config();
const client = require("../graphql-client/graphql-client").client;
const queries = require("../graphql-client/queries");
const phone = require("phone");
exports.status = (req, res) => {
//Perform request validation
console.log("Inbound Status Update: ", JSON.stringify(req.body));
res.sendStatus(200);
};
// Inbound Sample
// {
// "SmsSid": "SM5205ea340e06437799d9345e7283457c",
// "SmsStatus": "queued",
// "MessageStatus": "queued",
// "To": "+16049992002",
// "MessagingServiceSid": "MG6e259e2add04ffa0d0aa355038670ee1",
// "MessageSid": "SM5205ea340e06437799d9345e7283457c",
// "AccountSid": "AC6c09d337d6b9c68ab6488c2052bd457c",
// "From": "+16043301606",
// "ApiVersion": "2010-04-01"
// }

173
yarn.lock
View File

@@ -136,11 +136,26 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-1.2.0.tgz#63ce3638cb85231f3704164c90a18ef816da3fb7"
integrity sha512-mwhXGkRV5dlvQc4EgPDxDxO6WuMBVymGFd1CA+2Y+z5dG9MNspoQ+AWjl/Ld1MnpCL8AKbosZlDVohqcIwuWsw==
"@types/body-parser@*":
version "1.19.0"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
dependencies:
"@types/connect" "*"
"@types/node" "*"
"@types/color-name@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
"@types/connect@*":
version "3.4.33"
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==
dependencies:
"@types/node" "*"
"@types/duplexify@^3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8"
@@ -148,11 +163,33 @@
dependencies:
"@types/node" "*"
"@types/express-serve-static-core@*":
version "4.17.3"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.3.tgz#dc8068ee3e354d7fba69feb86b3dfeee49b10f09"
integrity sha512-sHEsvEzjqN+zLbqP+8OXTipc10yH1QLR+hnr5uw29gi9AhCAAAdri8ClNV7iMdrJrIzXIQtlkPvq8tJGhj3QJQ==
dependencies:
"@types/node" "*"
"@types/range-parser" "*"
"@types/express@^4.17.3":
version "4.17.3"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9"
integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "*"
"@types/serve-static" "*"
"@types/long@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.0.tgz#719551d2352d301ac8b81db732acb6bdc28dbdef"
integrity sha512-1w52Nyx4Gq47uuu0EVcsHBxZFJgurQ+rTKS3qMHxR1GY2T8c2AJYd6vZoZ9q1rupaDjU0yT+Jc2XTyXkjeMA+Q==
"@types/mime@*":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==
"@types/node@*":
version "12.12.17"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.17.tgz#191b71e7f4c325ee0fb23bc4a996477d92b8c39b"
@@ -163,6 +200,19 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.9.tgz#4f251a1ed77ac7ef09d456247d67fc8173f6b9da"
integrity sha512-+6VygF9LbG7Gaqeog2G7u1+RUcmo0q1rI+2ZxdIg2fAUngk5Vz9fOCHXdloNUOHEPd1EuuOpL5O0CdgN9Fx5UQ==
"@types/range-parser@*":
version "1.2.3"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
"@types/serve-static@*":
version "1.13.3"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==
dependencies:
"@types/express-serve-static-core" "*"
"@types/mime" "*"
JSONStream@^1.2.1:
version "1.3.5"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
@@ -355,6 +405,11 @@ as-array@^2.0.0:
resolved "https://registry.yarnpkg.com/as-array/-/as-array-2.0.0.tgz#4f04805d87f8fce8e511bc2108f8e5e3a287d547"
integrity sha1-TwSAXYf4/OjlEbwhCPjl46KH1Uc=
asap@^2.0.0:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
@@ -440,6 +495,13 @@ axios@^0.19.0:
follow-redirects "1.5.10"
is-buffer "^2.0.2"
axios@^0.19.2:
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
dependencies:
follow-redirects "1.5.10"
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -993,6 +1055,14 @@ cross-env@^5.1.3:
dependencies:
cross-spawn "^6.0.5"
cross-fetch@2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.2.tgz#a47ff4f7fc712daba8f6a695a11c948440d45723"
integrity sha1-pH/09/xxLauo9qaVoRyUhEDUVyM=
dependencies:
node-fetch "2.1.2"
whatwg-fetch "2.0.4"
cross-spawn@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
@@ -1058,6 +1128,11 @@ date-fns@^2.0.1:
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.10.0.tgz#abd10604d8bafb0bcbd2ba2e9b0563b922ae4b6b"
integrity sha512-EhfEKevYGWhWlZbNeplfhIU/+N+x0iCIx7VzKlXma2EdQyznVlZhCptXUY+BegNpPW2kjdx15Rvq503YcXXrcA==
dayjs@^1.8.21:
version "1.8.23"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.23.tgz#07b5a8e759c4d75ae07bdd0ad6977f851c01e510"
integrity sha512-NmYHMFONftoZbeOhVz6jfiXI4zSiPN6NoVWJgC0aZQfYVwzy/ZpESPHuCcI0B8BUMpSJQ08zenHDbofOLKq8hQ==
debug@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -1971,6 +2046,13 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9,
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
graphql-request@^1.8.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-1.8.2.tgz#398d10ae15c585676741bde3fc01d5ca948f8fbe"
integrity sha512-dDX2M+VMsxXFCmUX0Vo0TopIZIX4ggzOtiCsThgtrKR4niiaagsGTDIHj3fsOMFETpa064vzovI+4YV4QnMbcg==
dependencies:
cross-fetch "2.2.2"
gtoken@^2.3.0:
version "2.3.3"
resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-2.3.3.tgz#8a7fe155c5ce0c4b71c886cfb282a9060d94a641"
@@ -2459,7 +2541,7 @@ jsonschema@^1.0.2:
resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.5.tgz#bab69d97fa28946aec0a56a9cc266d23fe80ae61"
integrity sha512-kVTF+08x25PQ0CjuVc0gRM9EUPb0Fe9Ln/utFOgcdxEIOHuU7ooBk/UPTd7t1M91pP35m0MU1T8M5P7vP1bRRw==
jsonwebtoken@^8.2.1:
jsonwebtoken@^8.2.1, jsonwebtoken@^8.5.1:
version "8.5.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
@@ -2927,6 +3009,11 @@ node-emoji@^1.4.1:
dependencies:
lodash.toarray "^4.4.0"
node-fetch@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5"
integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=
node-fetch@^2.3.0, node-fetch@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
@@ -3189,6 +3276,11 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
phone@^2.4.8:
version "2.4.8"
resolved "https://registry.yarnpkg.com/phone/-/phone-2.4.8.tgz#4da4c046b4a90ca65ea04f86e99094b50ed518df"
integrity sha512-8RO0PfJPzjsWKhbU9W79f7exxkEgjrjbkHqG3psV3SI2q+SJqDEC7We3Ylxivk8XNdoZ8jDs4TPHnqCVs8TwNA==
picomatch@^2.0.4:
version "2.1.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
@@ -3218,6 +3310,11 @@ plist@^3.0.1:
xmlbuilder "^9.0.7"
xmldom "0.1.x"
pop-iterate@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/pop-iterate/-/pop-iterate-1.0.1.tgz#ceacfdab4abf353d7a0f2aaa2c1fc7b3f9413ba3"
integrity sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=
portfinder@^1.0.23:
version "1.0.25"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
@@ -3304,11 +3401,25 @@ punycode@^2.1.0:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
q@2.0.x:
version "2.0.3"
resolved "https://registry.yarnpkg.com/q/-/q-2.0.3.tgz#75b8db0255a1a5af82f58c3f3aaa1efec7d0d134"
integrity sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=
dependencies:
asap "^2.0.0"
pop-iterate "^1.0.1"
weak-map "^1.0.5"
qs@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
qs@^6.9.1:
version "6.9.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.2.tgz#a27b695006544a04bf0e6c6a7e8120778926d5bd"
integrity sha512-2eQ6zajpK7HwqrY1rRtGw5IZvjgtELXzJECaEDuzDFo2jjnIXpJSimzd4qflWZq6bLLi+Zgfj5eDrAzl/lptyg==
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
@@ -3324,6 +3435,11 @@ querystring@0.2.0:
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
querystringify@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
@@ -3462,6 +3578,11 @@ require-main-filename@^2.0.0:
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
requires-port@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@@ -3524,6 +3645,11 @@ rimraf@^3.0.0:
dependencies:
glob "^7.1.3"
rootpath@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/rootpath/-/rootpath-0.1.2.tgz#5b379a87dca906e9b91d690a599439bef267ea6b"
integrity sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms=
router@^1.3.1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/router/-/router-1.3.3.tgz#c142f6b5ea4d6b3359022ca95b6580bd217f89cf"
@@ -3581,6 +3707,11 @@ sax@>=0.6.0:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
scmp@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/scmp/-/scmp-2.1.0.tgz#37b8e197c425bdeb570ab91cc356b311a11f9c9a"
integrity sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==
semver-diff@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
@@ -4092,6 +4223,23 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
twilio@^3.41.1:
version "3.41.1"
resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.41.1.tgz#653f2daccad7fe3ac0362acd1a1347e690dd9795"
integrity sha512-YOAuQtb3xELQJDcL+G6ffDRrZeJSlFRph5peudFYcEa9Or5R0x+r8lShXlYl7yP8w7atCWxETSeySLuStEpvhg==
dependencies:
"@types/express" "^4.17.3"
axios "^0.19.2"
dayjs "^1.8.21"
jsonwebtoken "^8.5.1"
lodash "^4.17.15"
q "2.0.x"
qs "^6.9.1"
rootpath "^0.1.2"
scmp "^2.1.0"
url-parse "^1.4.7"
xmlbuilder "^13.0.2"
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -4199,6 +4347,14 @@ url-parse-lax@^1.0.0:
dependencies:
prepend-http "^1.0.1"
url-parse@^1.4.7:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"
url@0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64"
@@ -4276,6 +4432,16 @@ wcwidth@^1.0.1:
dependencies:
defaults "^1.0.3"
weak-map@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.5.tgz#79691584d98607f5070bd3b70a40e6bb22e401eb"
integrity sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=
whatwg-fetch@2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f"
integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
@@ -4381,6 +4547,11 @@ xml2js@0.4.19:
sax ">=0.6.0"
xmlbuilder "~9.0.1"
xmlbuilder@^13.0.2:
version "13.0.2"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-13.0.2.tgz#02ae33614b6a047d1c32b5389c1fdacb2bce47a7"
integrity sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==
xmlbuilder@^9.0.7, xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"