Skip to content

Commit 08a0df2

Browse files
committed
typescript strict mode
1 parent 2a1b255 commit 08a0df2

27 files changed

+337
-197
lines changed

lib/commander.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import Command from "./commands/command";
22
import { Listener } from "./listeners/listener";
33
import Looker from "./looker";
44
import LookQueryRunner from "./repliers/look_query_runner";
5-
import QueryRunner from "./repliers/query_runner";
5+
import { QueryRunner } from "./repliers/query_runner";
6+
import ReplyContext from "./reply_context";
67
import SlackService from "./services/slack_service";
78

89
export default class Commander {
@@ -13,10 +14,10 @@ export default class Commander {
1314
constructor(opts: {listeners: Array<typeof Listener>, commands: Array<typeof Command>}) {
1415
this.service = new SlackService({
1516
listeners: opts.listeners,
16-
messageHandler: (context) => {
17+
messageHandler: (context: ReplyContext) => {
1718
return this.handleMessage(context);
1819
},
19-
urlHandler: (context, url) => {
20+
urlHandler: (context: ReplyContext, url: string) => {
2021
return this.handleUrlExpansion(context, url);
2122
},
2223
});
@@ -25,7 +26,7 @@ export default class Commander {
2526
this.commands = opts.commands.map((c) => new c());
2627
}
2728

28-
private handleMessage(context) {
29+
private handleMessage(context: ReplyContext) {
2930

3031
const message = context.sourceMessage;
3132

@@ -42,7 +43,7 @@ export default class Commander {
4243

4344
}
4445

45-
private handleUrlExpansion(context, url) {
46+
private handleUrlExpansion(context: ReplyContext, url: string) {
4647
for (const looker of Looker.all) {
4748
// Starts with Looker base URL?
4849
if (url.lastIndexOf(looker.url, 0) === 0) {
@@ -54,7 +55,7 @@ export default class Commander {
5455

5556
}
5657

57-
private annotateLook(context, url) {
58+
private annotateLook(context: ReplyContext, url: string) {
5859
const matches = url.match(/\/looks\/([0-9]+)$/);
5960
if (matches) {
6061
console.log(`Expanding Look URL ${url}`);
@@ -63,7 +64,7 @@ export default class Commander {
6364
}
6465
}
6566

66-
private annotateShareUrl(context, url) {
67+
private annotateShareUrl(context: ReplyContext, url: string) {
6768
const matches = url.match(/\/x\/([A-Za-z0-9]+)$/);
6869
if (matches) {
6970
console.log(`Expanding Share URL ${url}`);

lib/commands/custom_command.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default class CustomCommand extends Command {
1010
public attempt(context: ReplyContext) {
1111
const normalizedText = context.sourceMessage.text.toLowerCase();
1212
const shortCommands = _.sortBy(_.values(Looker.customCommands), (c) => -c.name.length);
13-
const matchedCommand = __guard__(shortCommands.filter((c) => normalizedText.indexOf(c.name) === 0), (x) => x[0]);
13+
const matchedCommand = shortCommands.filter((c) => normalizedText.indexOf(c.name) === 0)[0];
1414
if (matchedCommand) {
1515

1616
const { dashboard } = matchedCommand;
@@ -19,7 +19,7 @@ export default class CustomCommand extends Command {
1919

2020
context.looker = matchedCommand.looker;
2121

22-
const filters = {};
22+
const filters: {[key: string]: string} = {};
2323
const dashboardFilters = dashboard.dashboard_filters || dashboard.filters;
2424
for (const filter of dashboardFilters) {
2525
filters[filter.name] = query;
@@ -34,7 +34,3 @@ export default class CustomCommand extends Command {
3434
}
3535

3636
}
37-
38-
function __guard__(value, transform) {
39-
return (typeof value !== "undefined" && value !== null) ? transform(value) : undefined;
40-
}

lib/listeners/data_action_listener.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,20 @@ export default class DataActionListener extends Listener {
4444

4545
if (!this.validateToken(req, res)) { return; }
4646

47-
return this.bot.api.channels.list({exclude_archived: 1}, (err, response) => {
47+
return this.bot.api.channels.list({exclude_archived: 1}, (err: any, response: any) => {
4848
if (err) {
4949
console.error(err);
5050
}
5151
if (response != null ? response.ok : undefined) {
5252

53-
let channels = response.channels.filter((c) => c.is_member && !c.is_archived);
53+
let channels = response.channels.filter((c: any) => c.is_member && !c.is_archived);
5454
channels = _.sortBy(channels, "name");
5555

5656
response = [{
5757
description: "The bot user must be a member of the channel.",
5858
label: "Slack Channel",
5959
name: "channel",
60-
options: channels.map((channel) => ({name: channel.id, label: `#${channel.name}`})),
60+
options: channels.map((channel: any) => ({name: channel.id, label: `#${channel.name}`})),
6161
required: true,
6262
type: "select",
6363
}];
@@ -74,7 +74,7 @@ export default class DataActionListener extends Listener {
7474

7575
return this.server.post("/data_actions", (req, res) => {
7676

77-
const getParam = (name) => (req.body.form_params != null ? req.body.form_params[name] : undefined) || (req.body.data != null ? req.body.data[name] : undefined);
77+
const getParam = (name: string) => (req.body.form_params != null ? req.body.form_params[name] : undefined) || (req.body.data != null ? req.body.data[name] : undefined);
7878

7979
if (!this.validateToken(req, res)) { return; }
8080

@@ -86,9 +86,7 @@ export default class DataActionListener extends Listener {
8686
return;
8787
}
8888

89-
const context = new ReplyContext(this.bot, this.bot, {
90-
channel,
91-
});
89+
const context = ReplyContext.forChannel(this.bot, channel);
9290
context.dataAction = true;
9391

9492
if (typeof(msg) === "string") {

lib/listeners/listener.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import Looker from "../looker";
33

44
export class Listener {
55

6-
protected server: express.Application;
7-
protected bot: any;
8-
protected lookers: Looker[];
9-
10-
constructor(server: express.Application, bot, lookers: Looker[]) {
6+
constructor(
7+
protected server: express.Application,
8+
protected bot: any,
9+
protected lookers: Looker[],
10+
) {
1111
this.server = server;
1212
this.bot = bot;
1313
this.lookers = lookers;
@@ -28,7 +28,7 @@ export class Listener {
2828
return true;
2929
}
3030

31-
protected validateTokenForLooker(req: express.Request, res: express.Response, looker) {
31+
protected validateTokenForLooker(req: express.Request, res: express.Response, looker: Looker) {
3232
if (!req.headers["x-looker-webhook-token"]) {
3333
this.reply(res, {looker: {success: false}, reason: "No x-looker-webhook-token token provided."});
3434
return false;
@@ -40,7 +40,7 @@ export class Listener {
4040
return value;
4141
}
4242

43-
protected reply(res: express.Response, json) {
43+
protected reply(res: express.Response, json: any) {
4444
res.json(json);
4545
console.log(`Replied to ${this.type()}.`, json);
4646
}

lib/listeners/schedule_listener.ts

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as express from "express";
22
import LookQueryRunner from "../repliers/look_query_runner";
3-
import QueryRunner from "../repliers/query_runner";
3+
import { QueryRunner } from "../repliers/query_runner";
44
import ReplyContext from "../reply_context";
55
import { Listener } from "./listener";
66

@@ -29,7 +29,8 @@ export default class ScheduleListener extends Listener {
2929
if (req.body.scheduled_plan.type === "Look") {
3030

3131
const qid = req.body.scheduled_plan.query_id;
32-
const lookId = __guard__(req.body.scheduled_plan.url.match(/\/looks\/([0-9]+)/), (x) => x[1]);
32+
const lookMatches = req.body.scheduled_plan.url.match(/\/looks\/([0-9]+)/);
33+
const lookId = lookMatches ? lookMatches[1] : undefined;
3334

3435
if (qid || lookId) {
3536

@@ -43,9 +44,7 @@ export default class ScheduleListener extends Listener {
4344
if (req.body.scheduled_plan.url.lastIndexOf(looker.url, 0) === 0) {
4445
if (this.validateTokenForLooker(req, res, looker)) {
4546

46-
const context = new ReplyContext(this.bot, this.bot, {
47-
channel: channelName,
48-
});
47+
const context = ReplyContext.forChannel(this.bot, channelName);
4948
context.looker = looker;
5049
context.scheduled = true;
5150

@@ -77,7 +76,3 @@ export default class ScheduleListener extends Listener {
7776
}
7877
}
7978
}
80-
81-
function __guard__(value, transform) {
82-
return (typeof value !== "undefined" && value !== null) ? transform(value) : undefined;
83-
}

lib/listeners/slack_action_listener.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default class SlackActionListener extends Listener {
1313

1414
this.server.post("/slack/action", async (req, res) => {
1515

16-
let payload;
16+
let payload: any;
1717
try {
1818
payload = JSON.parse(req.body.payload);
1919
} catch (e) {
@@ -70,7 +70,7 @@ export default class SlackActionListener extends Listener {
7070
if (actionResult.success) {
7171
text = `:white_check_mark: ${actionResult.message || "Done"}!`;
7272
} else if (actionResult.validation_errors) {
73-
text = actionResult.validation_errors.errors.map((e) => `:x: ${e.message}`).join("\n");
73+
text = actionResult.validation_errors.errors.map((e: any) => `:x: ${e.message}`).join("\n");
7474
} else {
7575
text = `:x: ${actionResult.message || "Something went wrong performing the action."}.`;
7676
}

lib/listeners/slack_event_listener.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ export default class SlackEventListener extends Listener {
1111

1212
return this.server.post("/slack/event", (req, res) => {
1313

14+
const fail = () => {
15+
res.status(400);
16+
return res.send("");
17+
};
18+
1419
const payload = req.body;
1520

1621
if (SlackUtils.checkToken(null, payload)) {
@@ -19,19 +24,14 @@ export default class SlackEventListener extends Listener {
1924
return console.log(`Replied to challenge ${payload.challenge}`);
2025
} else {
2126
console.log(`Unknown event type ${JSON.stringify(payload)}`);
22-
return this.fail(res);
27+
return fail();
2328
}
2429
} else {
2530
console.log(`Payload had invalid format ${JSON.stringify(payload)}`);
26-
return this.fail(res);
31+
return fail();
2732
}
2833

2934
});
3035
}
3136

32-
private fail(res) {
33-
res.status(400);
34-
return res.send("");
35-
}
36-
3737
}

lib/looker.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { IDashboard, ISpace } from "./looker_api_types";
12
import LookerAPIClient from "./looker_client";
23

34
export interface ICustomCommand {
@@ -10,6 +11,15 @@ export interface ICustomCommand {
1011
hidden: boolean;
1112
}
1213

14+
interface ILookerOptions {
15+
apiBaseUrl: string;
16+
clientId: string;
17+
clientSecret: string;
18+
customCommandSpaceId: string;
19+
url: string;
20+
webhookToken: string;
21+
}
22+
1323
export default class Looker {
1424

1525
public static all: Looker[];
@@ -20,7 +30,7 @@ export default class Looker {
2030
}
2131

2232
public static loadAll() {
23-
const configs = process.env.LOOKERS ?
33+
const configs: ILookerOptions[] = process.env.LOOKERS ?
2434
(console.log("Using Looker information specified in LOOKERS environment variable."),
2535
JSON.parse(process.env.LOOKERS))
2636
:
@@ -41,7 +51,7 @@ export default class Looker {
4151
public webhookToken: string;
4252
public client: LookerAPIClient;
4353

44-
constructor(options) {
54+
constructor(options: ILookerOptions) {
4555

4656
this.url = options.url;
4757
this.customCommandSpaceId = options.customCommandSpaceId;
@@ -64,9 +74,9 @@ export default class Looker {
6474
}
6575
console.log(`Refreshing custom commands for ${this.url}...`);
6676

67-
this.client.get(`spaces/${this.customCommandSpaceId}`, (space) => {
77+
this.client.get(`spaces/${this.customCommandSpaceId}`, (space: ISpace) => {
6878
this.addCommandsForSpace(space, "Shortcuts");
69-
this.client.get(`spaces/${this.customCommandSpaceId}/children`, (children) => {
79+
this.client.get(`spaces/${this.customCommandSpaceId}/children`, (children: ISpace[]) => {
7080
children.map((child) =>
7181
this.addCommandsForSpace(child, child.name));
7282
},
@@ -75,9 +85,9 @@ export default class Looker {
7585
console.log);
7686
}
7787

78-
private addCommandsForSpace(space, category: string) {
88+
private addCommandsForSpace(space: ISpace, category: string) {
7989
space.dashboards.forEach((partialDashboard) =>
80-
this.client.get(`dashboards/${partialDashboard.id}`, (dashboard) => {
90+
this.client.get(`dashboards/${partialDashboard.id}`, (dashboard: IDashboard) => {
8191

8292
const command: ICustomCommand = {
8393
category,
@@ -93,7 +103,7 @@ export default class Looker {
93103
command.helptext = "";
94104

95105
const dashboardFilters = dashboard.dashboard_filters || dashboard.filters;
96-
if ((dashboardFilters != null ? dashboardFilters.length : undefined) > 0) {
106+
if (dashboardFilters && dashboardFilters.length > 0) {
97107
command.helptext = `<${dashboardFilters[0].title.toLowerCase()}>`;
98108
}
99109

0 commit comments

Comments
 (0)