Skip to content

Commit

Permalink
refac(slaq): to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
renatorib committed Feb 5, 2020
1 parent b842d85 commit 6be5954
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 132 deletions.
1 change: 1 addition & 0 deletions packages/slaq/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("../../babel.config");
11 changes: 9 additions & 2 deletions packages/slaq/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
{
"name": "slaq",
"version": "0.3.0",
"main": "src/index.js",
"scripts": {},
"main": "lib/index.js",
"scripts": {
"clean": "rm -rf ./lib",
"build": "yarn clean && babel src -d lib -x '.js,.ts' --ignore '**/*.test.ts' && tsc",
"watch": "watch -p 'src/**/*.{ts,js}' -c 'yarn build'",
"test:unit": "jest"
},
"dependencies": {
"@types/express": "^4.17.2",
"@types/node-fetch": "^2.5.4",
"crypto": "^1.0.1",
"express": "^4.17.1",
"node-fetch": "^2.6.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
const fetch = require("node-fetch");
const debug = require("debug")("slaq");
import fetch, { Response, BodyInit, HeadersInit } from "node-fetch";
import _debug from "debug";

const debugErrorMiddleware = method => res => {
const debug = _debug("slaq");

const debugErrorMiddleware = (method: string) => (res: Response) => {
if (res.ok === false) {
debug(`Method ${method} result in an error`);
debug(res);
}
return res;
};

module.exports = ({ token }) => {
const fetcher = async (url, options = {}) => {
type FetcherOptions = {
headers?: HeadersInit;
body?: BodyInit;
};

export type Client = {
web: {
(method: string, body: Object): Promise<Object>;
form(method: string, body: Object): Promise<Object>;
};
hook: (url: string, body: Object) => Promise<Object>;
fetcher: (url: string, options?: FetcherOptions) => Promise<Object>;
};

export const createClient = ({ token }: { token: string }): Client => {
const fetcher = async (url: string, options: FetcherOptions = {}) => {
const res = await fetch(url, {
method: "POST",
...options,
Expand All @@ -30,7 +46,7 @@ module.exports = ({ token }) => {
}
};

const web = (method, body) => {
const web = (method: string, body: Object) => {
if (!token)
throw new Error("Must specify App token config to use slack Web API.");

Expand All @@ -39,14 +55,14 @@ module.exports = ({ token }) => {
}).then(debugErrorMiddleware(method));
};

const searchParams = params =>
const searchParams = (params: Object) =>
Object.keys(params)
.map(key => {
return encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
})
.join("&");

web.form = (method, body) => {
web.form = (method: string, body: Object) => {
return fetcher(`https://slack.com/api/${method}`, {
body: searchParams(body),
headers: {
Expand All @@ -55,7 +71,8 @@ module.exports = ({ token }) => {
}).then(debugErrorMiddleware(method));
};

const hook = (url, body) => fetcher(url, { body: JSON.stringify(body) });
const hook = (url: string, body: Object) =>
fetcher(url, { body: JSON.stringify(body) });

return {
web,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const handleUrlVerification = app => {
import { Module } from "../index";

export const handleUrlVerification: Module = app => {
app.use((req, res, next) => {
if (req.body.type === "url_verification") {
res.ack(req.body.challenge);
Expand All @@ -8,5 +10,3 @@ const handleUrlVerification = app => {
next();
});
};

module.exports = handleUrlVerification;
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
const rawBody = require("raw-body");
const qs = require("querystring");
const infer = require("../helpers/infer");
declare global {
namespace Express {
interface Request {
type: string;
user: string;
channel?: string;
}
}
}

const parseRequestBody = app => {
import rawBody from "raw-body";
import qs from "querystring";
import { infer } from "../helpers/infer";
import { Module } from "../index";

export const parseRequestBody: Module = app => {
app.use(async (req, res, next) => {
const stringBody =
(req.rawBody && req.rawBody.toString()) ||
(await rawBody(req)).toString();
const stringBody = (await rawBody(req)).toString();
const contentType = req.headers["content-type"];

const getBody = () => {
Expand Down Expand Up @@ -40,5 +49,3 @@ const parseRequestBody = app => {
next();
});
};

module.exports = parseRequestBody;
Original file line number Diff line number Diff line change
@@ -1,37 +1,54 @@
const infer = require("../helpers/infer");
const debug = require("debug")("slaq");
import _debug from "debug";
import { infer } from "../helpers/infer";
import { Module } from "../index";

const parseResponseHelpers = app => {
type Message = string | object;

declare global {
namespace Express {
interface Response {
say: (message: Message) => Promise<any>;
pm: (message: Message) => Promise<any>;
whisper: (message: Message) => Promise<any>;
ack: (message: Message) => void;
respond: (message: Message) => Promise<any> | void;
}
}
}

const debug = _debug("slaq");

export const useResponseHelpers: Module = app => {
app.use((req, res, next) => {
const { channel, user } = infer(req);

const say = message => {
const say: Express.Response["say"] = message => {
return app.client.web("chat.postMessage", {
channel,
...(typeof message === "string" ? { text: message } : { ...message })
});
};

const pm = message => {
const pm: Express.Response["pm"] = message => {
return app.client.web("chat.postMessage", {
channel: user,
...(typeof message === "string" ? { text: message } : { ...message })
});
};

const whisper = message => {
const whisper: Express.Response["whisper"] = message => {
return app.client.web("chat.postEphemeral", {
channel,
user,
...(typeof message === "string" ? { text: message } : { ...message })
});
};

const ack = message => {
const ack: Express.Response["ack"] = message => {
res.status(200).send(message);
};

const respond = message => {
const respond: Express.Response["respond"] = message => {
if (req.body.response_url) {
return app.client.hook(req.body.response_url, {
...(typeof message === "string" ? { text: message } : { ...message })
Expand All @@ -50,5 +67,3 @@ const parseResponseHelpers = app => {
next();
});
};

module.exports = parseResponseHelpers;
7 changes: 0 additions & 7 deletions packages/slaq/src/core/useSlackClient.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
const crypto = require("crypto");
const tsscmp = require("tsscmp");

const verify = (body, secret, signature, timestamp) => {
import { Module } from "../index";
import crypto from "crypto";
import tsscmp from "tsscmp";

const verify = (
body: string,
secret: string,
signature: string,
timestamp: number
) => {
const fiveMinutesAgo = Math.floor(Date.now() / 1000) - 60 * 5;

if (timestamp < fiveMinutesAgo) {
Expand All @@ -23,13 +29,14 @@ const verify = (body, secret, signature, timestamp) => {
return true;
};

const verifySigningSecret = app => {
export const verifySigningSecret: Module = app => {
const secret = app.slaq.signingSecret;

app.use((req, res, next) => {
const body = req.stringBody;
const signature = req.headers["x-slack-signature"];
const timestamp = parseInt(req.headers["x-slack-request-timestamp"]);
const signature = req.headers["x-slack-signature"] as string;
const requestTimestamp = req.headers["x-slack-request-timestamp"] as string;
const timestamp = parseInt(requestTimestamp);

try {
verify(body, secret, signature, timestamp);
Expand All @@ -39,5 +46,3 @@ const verifySigningSecret = app => {
}
});
};

module.exports = verifySigningSecret;
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
// Infer metadata like type and channel based on parsed requests
import { Request } from "express";

const infer = req => {
export type Inferred = {
type?: "event" | "command" | "options" | "action";
channel?: string;
user?: string;
};

export const infer = (req: Request): Inferred => {
const body = req.body || {};

if (body.event !== undefined) {
Expand Down Expand Up @@ -50,5 +57,3 @@ const infer = req => {

return {};
};

module.exports = infer;
80 changes: 0 additions & 80 deletions packages/slaq/src/index.js

This file was deleted.

Loading

0 comments on commit 6be5954

Please sign in to comment.