Skip to content

Commit

Permalink
Helpers refactor + added tests + setup CI (#8)
Browse files Browse the repository at this point in the history
* Refactor of the functions using helpers

* Monorepo started (added helpers within this repo)

* Added tests for functions

* Added CI
  • Loading branch information
GPaoloni authored May 28, 2020
1 parent 015bea1 commit d5c4d3e
Show file tree
Hide file tree
Showing 34 changed files with 22,789 additions and 9,391 deletions.
4 changes: 2 additions & 2 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
functions/*.js
utils/*.js
**/*.js
tech-matters-serverless-helpers-lib/
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
'plugin:prettier/recommended',
],
parserOptions: {
project: './tsconfig.json',
project: './tsconfig.eslint.json',
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
},
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/serverless-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: serverless-ci

on: [push]

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [10.x]

steps:
- name: Checkout Branch
uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install Packages
run: npm install
- name: Run Lint
run: npm run lint --if-present
- name: Run Tests
run: npm run test
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ dist
.yarn/build-state.yml
.pnp.*

# serverless toolkit generated .js files
functions/*.js
utils/*.js
tech-matters-serverless-helpers/node_modules/
tech-matters-serverless-helpers/lib/


utils/params.json
.twilio-functions
3 changes: 0 additions & 3 deletions .twilio-functions

This file was deleted.

13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[![Actions Status](https://github.com/tech-matters/serverless/workflows/serverless-ci/badge.svg)](https://github.com/tech-matters/serverless/actions)

# serverless
Repository for serverless functions living on the Twilio Serverless Toolkit

Expand Down Expand Up @@ -32,3 +34,14 @@ Explanation
"and_valid_Token": finally append to the uri "Token=<valid_token>"

Token generator util is a work in progress

## tech-matters-serverless-helpers
This are helpers and functions reused across the various serverless functions.
They are packed as npm package because it's the easiest way to reuse the code within a Twilio Serverless Toolkit Project and preserve the typing information TS provides.

It's currenty deployed with Gian's npm account, [contact him](https://github.com/GPaoloni) to deploy new versions!

To deploy:
once inside the project folder (`cd tech-matters-serverless-helpers`)
1- `npm run build`
2- `npm publish` (must be logged in npm cli)
3 changes: 3 additions & 0 deletions __mocks__/twilio-flex-token-validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
functionValidator: e => e, // returns identity to bypass token validation
};
2 changes: 1 addition & 1 deletion assets/translations/es/messages.private.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"GoodbyeMsg": "El consejero abandonó el chat. Gracias por contactarnos. Por favor contáctenos nuevamente si necesita más ayuda.",
"GoodbyeMsg": "El consejero abandonó el chat. Gracias por contactarnos. Por favor contáctenos nuevamente si necesita más ayuda."
}
48 changes: 15 additions & 33 deletions functions/getMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,39 @@ import {
Context,
ServerlessCallback,
ServerlessFunctionSignature,
TwilioResponse,
} from '@twilio-labs/serverless-runtime-types/types';
import {
responseWithCors,
bindResolve,
error400,
error500,
success,
} from 'tech-matters-serverless-helpers';

const TokenValidator = require('twilio-flex-token-validator').functionValidator;

// TODO: Factor out into lib
const send = (statusCode: number) => (body: string | object) => (callback: ServerlessCallback) => (
response: TwilioResponse,
) => {
response.setStatusCode(statusCode);
response.setBody(body);
callback(null, response);
};

// TODO: Factor out into lib
const responseWithCors = () => {
const response = new Twilio.Response();

response.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
'Access-Control-Allow-Headers': 'Content-Type',
'Content-Type': 'application/json',
});

return response;
};

type Body = {
export type Body = {
language?: string;
};

export const handler: ServerlessFunctionSignature = TokenValidator(
async (context: Context, event: {}, callback: ServerlessCallback) => {
async (context: Context, event: Body, callback: ServerlessCallback) => {
const response = responseWithCors();
const resolve = bindResolve(callback)(response);

try {
const body = event as Body;
const { language } = body;
const { language } = event;

try {
if (language === undefined) {
const err = { message: 'Error: language parameter not provided', status: 400 };
send(400)(err)(callback)(response);
resolve(error400('language'));
return;
}

const translation = Runtime.getAssets()[`/translations/${language}/messages.json`].open();

send(200)(translation)(callback)(response);
resolve(success(translation));
} catch (err) {
send(500)(err)(callback)(response);
resolve(error500(err));
}
},
);
48 changes: 15 additions & 33 deletions functions/getTranslation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,39 @@ import {
Context,
ServerlessCallback,
ServerlessFunctionSignature,
TwilioResponse,
} from '@twilio-labs/serverless-runtime-types/types';
import {
responseWithCors,
bindResolve,
error400,
error500,
success,
} from 'tech-matters-serverless-helpers';

const TokenValidator = require('twilio-flex-token-validator').functionValidator;

// TODO: Factor out into lib
const send = (statusCode: number) => (body: string | object) => (callback: ServerlessCallback) => (
response: TwilioResponse,
) => {
response.setStatusCode(statusCode);
response.setBody(body);
callback(null, response);
};

// TODO: Factor out into lib
const responseWithCors = () => {
const response = new Twilio.Response();

response.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
'Access-Control-Allow-Headers': 'Content-Type',
'Content-Type': 'application/json',
});

return response;
};

type Body = {
export type Body = {
language?: string;
};

export const handler: ServerlessFunctionSignature = TokenValidator(
async (context: Context, event: {}, callback: ServerlessCallback) => {
async (context: Context, event: Body, callback: ServerlessCallback) => {
const response = responseWithCors();
const resolve = bindResolve(callback)(response);

try {
const body = event as Body;
const { language } = body;
const { language } = event;

try {
if (language === undefined) {
const err = { message: 'Error: language parameter not provided', status: 400 };
send(400)(err)(callback)(response);
resolve(error400('language'));
return;
}

const translation = Runtime.getAssets()[`/translations/${language}/flexUI.json`].open();

send(200)(translation)(callback)(response);
resolve(success(translation));
} catch (err) {
send(500)(err)(callback)(response);
resolve(error500(err));
}
},
);
50 changes: 16 additions & 34 deletions functions/populateCounselors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,32 @@ import {
Context,
ServerlessCallback,
ServerlessFunctionSignature,
TwilioResponse,
} from '@twilio-labs/serverless-runtime-types/types';
import {
responseWithCors,
bindResolve,
error400,
error500,
success,
} from 'tech-matters-serverless-helpers';

const TokenValidator = require('twilio-flex-token-validator').functionValidator;

// TODO: Factor out into lib
const send = (statusCode: number) => (body: string | object) => (callback: ServerlessCallback) => (
response: TwilioResponse,
) => {
response.setStatusCode(statusCode);
response.setBody(body);
callback(null, response);
};

// TODO: Factor out into lib
const responseWithCors = () => {
const response = new Twilio.Response();

response.setHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
'Access-Control-Allow-Headers': 'Content-Type',
'Content-Type': 'application/json',
});

return response;
};

type Body = {
export type Body = {
workspaceSID?: string;
helpline?: string;
};

export const handler: ServerlessFunctionSignature = TokenValidator(
async (context: Context, event: {}, callback: ServerlessCallback) => {
async (context: Context, event: Body, callback: ServerlessCallback) => {
const response = responseWithCors();
const resolve = bindResolve(callback)(response);

try {
const body = event as Body;
const { workspaceSID, helpline } = body;
const { workspaceSID, helpline } = event;

try {
if (workspaceSID === undefined) {
const err = { message: 'Error: WorkspaceSID parameter not provided', status: 400 };
send(400)(err)(callback)(response);
resolve(error400('WorkspaceSID'));
return;
}

Expand Down Expand Up @@ -83,15 +65,15 @@ export const handler: ServerlessFunctionSignature = TokenValidator(
);
const workerSummaries = filtered.map(({ fullName, sid }) => ({ fullName, sid }));

send(200)({ workerSummaries })(callback)(response);
resolve(success({ workerSummaries }));
return;
}

const workerSummaries = withHelpline.map(({ fullName, sid }) => ({ fullName, sid }));

send(200)({ workerSummaries })(callback)(response);
resolve(success({ workerSummaries }));
} catch (err) {
send(500)(err)(callback)(response);
resolve(error500(err));
}
},
);
Loading

0 comments on commit d5c4d3e

Please sign in to comment.