Skip to content

Commit cd2979c

Browse files
committed
Convert to TypeScript.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
1 parent 2f03074 commit cd2979c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+916
-474
lines changed

.github/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ the **zulipbot wiki**.
2727

2828
## Usage
2929

30-
If you're using the [Zulip project configuration](../config/config-example.js)
31-
(`./config/config-example.js`), see zulipbot's [usage
30+
If you're using the [Zulip project configuration](../config/config-example.ts)
31+
(`./config/config-example.ts`), see zulipbot's [usage
3232
instructions](https://zulip.readthedocs.io/en/latest/contributing/zulipbot-usage.html)
3333
on the Zulip documentation.
3434

35-
If you're using your own custom configuration (`./config/config.js` is different
35+
If you're using your own custom configuration (`./config/config.ts` is different
3636
from the Zulip project configuration), please visit the
3737
[Commands](https://github.com/zulip/zulipbot/wiki/Commands) page on the
3838
**zulipbot wiki**.

.github/workflows/node.js.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
with:
2626
node-version: ${{ matrix.node-version }}
2727
cache: pnpm
28-
- run: ln -s config-example.js config/config.js
28+
- run: ln -s config-example.ts config/config.ts
2929
- run: pnpm install --frozen-lockfile
3030
- run: pnpm test
3131
- uses: codecov/codecov-action@v5

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
.tap
22
node_modules
3-
/config/config.js
3+
/config/config.ts
44
/config/secrets.json

.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.tap
2-
/config/config.js
2+
/config/config.ts
33
/config/secrets.json
44
/pnpm-lock.yaml
55
/pnpm-workspace.yaml
Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@
55
* explanations on each option.
66
*/
77

8+
import { safeCastTo } from "ts-extras";
9+
810
// Default authentication specified by environment variables
9-
export const auth = {
10-
oAuthToken: process.env.OAUTH_TOKEN,
11-
webhookSecret: process.env.WEBHOOK_SECRET,
11+
export const auth: {
12+
oAuthToken: string | undefined;
13+
webhookSecret: string | undefined;
14+
username?: string;
15+
} = {
16+
oAuthToken: process.env["OAUTH_TOKEN"],
17+
webhookSecret: process.env["WEBHOOK_SECRET"],
1218
};
1319

1420
/**
@@ -20,27 +26,27 @@ export const auth = {
2026
export const issues = {
2127
commands: {
2228
assign: {
23-
claim: [],
24-
abandon: [],
29+
claim: new Array<string>(),
30+
abandon: new Array<string>(),
2531
limit: Number.POSITIVE_INFINITY,
2632
newContributors: {
27-
permission: null,
33+
permission: safeCastTo<string | null>(null),
2834
restricted: Number.POSITIVE_INFINITY,
2935
},
3036
warn: {
31-
labels: [],
37+
labels: new Array<string>(),
3238
presence: false,
3339
force: true,
3440
},
3541
},
3642
label: {
37-
add: [],
38-
remove: [],
39-
self: false,
43+
add: new Array<string>(),
44+
remove: new Array<string>(),
45+
self: safeCastTo<boolean | { users: string[] }>(false),
4046
},
4147
},
4248
area: {
43-
labels: null,
49+
labels: safeCastTo<Map<string, string> | null>(null),
4450
references: false,
4551
},
4652
};
@@ -56,18 +62,22 @@ export const pulls = {
5662
status: {
5763
mergeConflicts: {
5864
branch: "main",
59-
label: null,
65+
label: safeCastTo<string | null>(null),
6066
comment: false,
6167
},
62-
wip: null,
68+
wip: safeCastTo<string | null>(null),
6369
size: {
64-
labels: null,
65-
exclude: [],
70+
labels: safeCastTo<Map<string, number> | null>(null),
71+
exclude: new Array<string>(),
6672
},
6773
},
6874
references: {
6975
required: false,
70-
labels: false,
76+
labels: safeCastTo<
77+
| { include: string[]; exclude?: never }
78+
| { include?: never; exclude: string[] }
79+
| false
80+
>(false),
7181
},
7282
};
7383

@@ -79,25 +89,25 @@ export const pulls = {
7989
*/
8090

8191
export const activity = {
82-
inactive: null,
92+
inactive: safeCastTo<string | null>(null),
8393
check: {
84-
repositories: [],
85-
interval: null,
86-
reminder: null,
87-
limit: null,
94+
repositories: new Array<string>(),
95+
interval: safeCastTo<number | null>(null),
96+
reminder: safeCastTo<number | null>(null),
97+
limit: safeCastTo<number | null>(null),
8898
},
8999
issues: {
90-
inProgress: null,
100+
inProgress: safeCastTo<string | undefined>(undefined),
91101
clearClosed: false,
92102
},
93103
pulls: {
94104
autoUpdate: true,
95105
reviewed: {
96-
label: null,
97-
assignee: null,
106+
label: safeCastTo<string | null>(null),
107+
assignee: safeCastTo<boolean | null>(null),
98108
},
99109
needsReview: {
100-
label: null,
110+
label: safeCastTo<string | null>(null),
101111
ignore: false,
102112
},
103113
},

eslint.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export default defineConfig(
2626
},
2727
rules: {
2828
"@stylistic/curly-newline": "off", // https://github.com/prettier/eslint-config-prettier/issues/351
29+
"@typescript-eslint/naming-convention": "off",
30+
"@typescript-eslint/no-restricted-types": "off",
2931
"arrow-body-style": "error",
3032
"capitalized-comments": "off",
3133
curly: ["error", "multi-line", "consistent"],
@@ -50,6 +52,7 @@ export default defineConfig(
5052
strict: "error",
5153
"unicorn/no-null": "off",
5254
"unicorn/no-process-exit": "off",
55+
"unicorn/no-useless-undefined": "off",
5356
"unicorn/numeric-separators-style": "off",
5457
"unicorn/prefer-node-protocol": "off",
5558
"unicorn/prefer-ternary": "off",

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"description": "GitHub workflow-optimizing bot",
55
"type": "module",
66
"scripts": {
7-
"start": "node ./src/index.js",
8-
"pretest": "eslint . && prettier --check . '!**/*.js' '!**/*.ts'",
7+
"start": "node ./src/index.ts",
8+
"pretest": "tsc && eslint . && prettier --check . '!**/*.js' '!**/*.ts'",
99
"test": "tap --coverage-report=lcovonly"
1010
},
1111
"packageManager": "pnpm@10.26.2+sha512.0e308ff2005fc7410366f154f625f6631ab2b16b1d2e70238444dd6ae9d630a8482d92a451144debc492416896ed16f7b114a86ec68b8404b2443869e68ffda6",

src/client.js renamed to src/client.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,51 @@ import { retry } from "@octokit/plugin-retry";
44
import { throttling } from "@octokit/plugin-throttling";
55
import { Octokit } from "@octokit/rest";
66
import _ from "lodash";
7+
import { assertDefined } from "ts-extras";
8+
import type { Writable } from "type-fest";
79

8-
import * as custom from "../config/config.js";
9-
import * as defaults from "../config/default.js";
10+
import * as custom from "../config/config.ts";
11+
import * as defaults from "../config/default.ts";
1012

11-
import commands from "./commands/index.js";
12-
import Template from "./structures/template.js";
13+
import commands, {
14+
type CommandAliases,
15+
type CommandPayload,
16+
} from "./commands/index.ts";
17+
import Template from "./structures/template.ts";
18+
19+
const MyOctokit: typeof Octokit &
20+
(new (
21+
...args: any[]
22+
) => ReturnType<typeof retry> & ReturnType<typeof throttling>) =
23+
Octokit.plugin(retry, throttling);
24+
25+
export class Client extends MyOctokit {
26+
cfg: Writable<typeof defaults>;
27+
commands: Map<
28+
string,
29+
{
30+
run: (
31+
this: Client,
32+
payload: CommandPayload,
33+
commenter: string,
34+
args: string,
35+
) => Promise<unknown>;
36+
aliasPath: (commands: CommandAliases) => string[];
37+
}
38+
>;
39+
40+
invites: Map<string, number>;
41+
templates: Map<string, Template>;
1342

14-
export class Client extends Octokit.plugin(retry, throttling) {
1543
constructor() {
16-
const cfg = _.merge({}, defaults, custom);
44+
const cfg: Writable<typeof defaults> = _.merge({}, defaults, custom);
1745
super({
1846
auth: cfg.auth.oAuthToken,
1947
retry: {
20-
enabled: process.env.NODE_ENV !== "test",
48+
enabled: process.env["NODE_ENV"] !== "test",
2149
},
2250
throttle: {
23-
enabled: process.env.NODE_ENV !== "test",
51+
enabled: process.env["NODE_ENV"] !== "test",
2452
onRateLimit: (retryAfter, { method, url }, _octokit, retryCount) => {
2553
if (retryCount < 3) {
2654
this.log.warn(
@@ -36,8 +64,9 @@ export class Client extends Octokit.plugin(retry, throttling) {
3664
retryCount + 1
3765
} times for ${method} ${url}; aborting`,
3866
);
67+
return; // eslint-disable-line no-useless-return
3968
},
40-
onSecondaryRateLimit: (retryAfter, { method, url }) => {
69+
onSecondaryRateLimit: (_retryAfter, { method, url }) => {
4170
this.log.warn(
4271
`Secondary rate limit detected for ${method} ${url}; aborting`,
4372
);
@@ -62,6 +91,7 @@ export class Client extends Octokit.plugin(retry, throttling) {
6291
);
6392
for (const file of templates) {
6493
const [name] = file.split(".md");
94+
assertDefined(name);
6595
const content = fs.readFileSync(
6696
new URL(`../config/templates/${file}`, import.meta.url),
6797
"utf8",
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
export const run = function (payload, commenter) {
1+
import type { Client } from "../client.ts";
2+
3+
import type { CommandAliases, CommandPayload } from "./index.ts";
4+
5+
export const run = async function (
6+
this: Client,
7+
payload: CommandPayload,
8+
commenter: string,
9+
) {
210
const repoOwner = payload.repository.owner.login;
311
const repoName = payload.repository.name;
412
const number = payload.issue.number;
5-
const assignees = payload.issue.assignees.map((assignee) => assignee.login);
13+
const assignees = payload.issue.assignees.map((assignee) => assignee?.login);
614

715
if (!assignees.includes(commenter)) {
816
const error = "**ERROR:** You have not claimed this issue to work on yet.";
@@ -22,4 +30,4 @@ export const run = function (payload, commenter) {
2230
});
2331
};
2432

25-
export const aliasPath = (commands) => commands.assign.abandon;
33+
export const aliasPath = (commands: CommandAliases) => commands.assign.abandon;

0 commit comments

Comments
 (0)