diff --git a/.gitignore b/.gitignore index 4bae06f..5bf6015 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ yarn-error\.log *.log \.next/ coverage/ -packages/*/lib \ No newline at end of file +packages/*/lib +*/tsconfig.tsbuildinfo +.pnp \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index dde3429..f043730 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:11.14 AS builder +FROM node:12 AS builder WORKDIR /src COPY . /src # we double yarn here to strip off dev-only packages that are needed at build time. @@ -6,7 +6,7 @@ RUN yarn --frozen-lockfile &&\ yarn build &&\ yarn --prod --frozen-lockfile -FROM node:11.14-alpine +FROM node:12-alpine ENV NODE_ENV production WORKDIR /dist COPY --from=builder /src /dist diff --git a/package.json b/package.json index f1df003..4aac496 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,6 @@ "dev:backend": "babel-node packages/roleypoly-server/index.js", "dev:bot": "babel-node packages/roleypoly-bot/index.js", "build": "lerna run build", - "flow:install": "flow-mono install-types", - "flow": "flow", "remotedebug": "remotedebug_ios_webkit_adapter --port=9000 > /dev/null", "test": "jest --color --coverage", "lint": "lerna run lint-staged", @@ -29,30 +27,21 @@ } }, "devDependencies": { - "@babel/cli": "^7.4.4", - "@babel/core": "^7.4.4", - "@babel/node": "^7.2.2", - "@babel/plugin-proposal-class-properties": "^7.4.4", - "@babel/plugin-proposal-optional-chaining": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/core": "^7.4.5", "@babel/plugin-transform-runtime": "^7.4.4", - "@babel/preset-env": "^7.4.4", - "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", - "@types/enzyme": "^3.9.2", - "@types/sinon": "^7.0.11", + "@types/enzyme": "^3.9.3", + "@types/sinon": "^7.0.12", "@types/webpack-env": "^1.13.9", "await-outside": "^2.1.2", - "babel-eslint": "^10.0.1", "babel-jest": "^24.8.0", "babel-loader": "^8.0.6", - "babel-plugin-macros": "^2.5.1", "babel-plugin-styled-components": "^1.10.0", - "chokidar": "^2.1.5", + "chokidar": "^3.0.0", "enzyme": "^3.9.0", "enzyme-adapter-react-16": "^1.13.1", "enzyme-to-json": "^3.3.5", - "husky": "^1.3.1", + "husky": "^2.3.0", "jest": "^24.8.0", "jest-styled-components": "^6.3.1", "lerna": "^3.14.1", @@ -70,9 +59,9 @@ "stylelint-config-styled-components": "^0.1.1", "stylelint-processor-styled-components": "^1.7.0", "ts-jest": "^24.0.2", - "tslint": "^5.16.0", - "typescript": "^3.4.5", - "typescript-tslint-plugin": "^0.3.1" + "tslint": "^5.17.0", + "typescript": "^3.5.1", + "typescript-tslint-plugin": "^0.4.0" }, "lint-staged": { "*.{ts,tsx}": [ diff --git a/packages/roleypoly-bot/.lintstagedrc.yml b/packages/roleypoly-bot/.lintstagedrc.yml new file mode 100644 index 0000000..2a83f89 --- /dev/null +++ b/packages/roleypoly-bot/.lintstagedrc.yml @@ -0,0 +1,14 @@ +linters: + lib/*.{js,jsx}: + - standard --fix + - git add + lib/*.d.ts: + - tslint --fix + - git add + src/*.{ts,tsx}: + - tslint --fix + - stylelint --fix + - jest --bail --findRelatedTests + - git add + + \ No newline at end of file diff --git a/packages/roleypoly-bot/package.json b/packages/roleypoly-bot/package.json index 328e6fe..4c607d4 100644 --- a/packages/roleypoly-bot/package.json +++ b/packages/roleypoly-bot/package.json @@ -3,15 +3,19 @@ "name": "@roleypoly/bot", "version": "2.0.0", "scripts": { - "build": "babel --delete-dir-on-start -d lib .", + "build": "tsc", + "precommit": "lint-staged", "dev": "yarn build --watch" }, "dependencies": { "async-retry": "^1.2.3", - "dotenv": "^7.0.0", + "dotenv": "^8.0.0", "eris": "^0.9.0" }, "devDependencies": { - "@babel/cli": "^7.4.3" + "@types/async-retry": "^1.4.1", + "lint-staged": "^8.1.7", + "tslint": "^5.17.0", + "typescript": "^3.5.1" } } diff --git a/packages/roleypoly-bot/Bot.js b/packages/roleypoly-bot/src/Bot.ts similarity index 78% rename from packages/roleypoly-bot/Bot.js rename to packages/roleypoly-bot/src/Bot.ts index 461e91b..e96fa1a 100644 --- a/packages/roleypoly-bot/Bot.js +++ b/packages/roleypoly-bot/src/Bot.ts @@ -1,23 +1,24 @@ -// @flow -import Eris, { type Message, type TextChannel, type Guild } from 'eris' -import RPCClient from '@roleypoly/rpc-client' +// tslint:disable: no-floating-promises + +import Eris, { Message, TextChannel, Guild } from 'eris' +// import RPCClient from '@roleypoly/rpc-client' import randomEmoji from './random-emoji' import DMCommands from './commands/dm' import TextCommands from './commands/text' import RootCommands from './commands/root' -import type { Command } from './commands/_types' +import { Command } from './commands/_types' import retry from 'async-retry' import logger from './logger' const log = logger(__filename) -export type BotConfig = $Shape<{ +export type BotConfig = { sharedSecret: string, botToken: string, rootUsers: Set, appUrl: string, logChannel: string -}> +} export default class Bot { config: BotConfig = { @@ -28,23 +29,21 @@ export default class Bot { logChannel: process.env.LOG_CHANNEL || '' } - client: Eris + client: Eris.Client - $RPC: RPCClient + // $RPC: RPCClient - rpc: * + // rpc: typeof RPCClient - commandCheck: RegExp + commandCheck: RegExp = new RegExp(`^<@!?${process.env.DISCORD_CLIENT_ID}>`) - constructor (config: BotConfig = {}) { - if (config != null) { - this.config = { - ...this.config, - ...config - } + constructor (config: Partial = {}) { + this.config = { + ...this.config, + ...config } - this.client = new Eris(this.config.botToken, { + this.client = new Eris.Client(this.config.botToken, { disableEveryone: true, maxShards: 'auto', messageLimit: 10, @@ -64,8 +63,8 @@ export default class Bot { } }) - this.$RPC = new RPCClient({ forceDev: false, retry: true }) - this.rpc = this.$RPC.withBotAuth(this.config.sharedSecret) + // this.$RPC = new RPCClient({ forceDev: false, retry: true }) + // this.rpc = this.$RPC.withBotAuth(this.config.sharedSecret) this.botPing() if (this.config.sharedSecret === '') { @@ -85,17 +84,16 @@ export default class Bot { } sendErrorLog (msg: Message, err: Error) { - if (this.config.logChannel === '') return + if (this.config.logChannel === '') { + return + } - this.client.createMessage( - this.config.logChannel, - `❌ **Command errored:**\nUser > <@${msg.author.id}> (${msg.author.username}#${msg.author.discriminator}) \nChannel > <#${msg.channel.id}> in ${(msg.channel: any)?.guild?.name || 'DM'}\nInput > \`${msg.content}\`\nTrace > \`\`\`${err.stack}\`\`\`` - ) + this.client.createMessage(this.config.logChannel, `command errored.`) } botPing = async () => { try { - await this.rpc.botPing() + // await this.rpc.botPing() } catch (e) { log.fatal('bot failed to connect to RPC server.', e) } @@ -116,15 +114,15 @@ export default class Bot { name: `${author.username}#${author.discriminator}` }, channel: { - id: channel.id, - name: channel.name || '' + id: channel.id + // name: channel.name || '' }, guild: {} } try { if (type === 0) { - const { id, name } = ((msg.channel: any): TextChannel).guild + const { id, name } = (msg.channel as TextChannel).guild o.guild = { id, name @@ -138,28 +136,30 @@ export default class Bot { } // this is a very silly O(n) matcher. i bet we can do better later. - findCmdIn (text: string, set: Set): ?{cmd: Command, matches: string[]} { - for (const cmd of set) { + findCmdIn (text: string, items: Set): { cmd: Command, matches: string[] } | undefined { + for (const cmd of items) { const matches = text.match(cmd.regex) - if (matches != null) { + if (matches !== null) { return { cmd, matches } } } + + return undefined } async tryCommand (msg: Message, text: string, startTime: number, ...sets: Array | null>): Promise { for (const set of sets) { - if (set == null) { + if (set === null) { continue } for (const cmd of set) { const matches = text.match(cmd.regex) - if (matches != null) { + if (matches !== null) { // handle! try { const result = await cmd.handler(this, msg, matches.slice(1)) - if (result != null) { + if (result !== undefined) { await msg.channel.createMessage(result) } } catch (e) { @@ -182,7 +182,7 @@ export default class Bot { // only react if there's a mention of myself. const check = msg.mentions.find(v => v.id === this.client.user.id) - if (check == null) { + if (check === undefined) { return } @@ -206,7 +206,7 @@ export default class Bot { } } - const channel: TextChannel = (msg.channel: any) + const channel: TextChannel = msg.channel as TextChannel channel.createMessage(`${randomEmoji()} Assign your roles here! ${this.config.appUrl}/s/${channel.guild.id}`) } @@ -227,10 +227,12 @@ export default class Bot { case 1: // dm channel return this.handleDMMessage(msg) } + + return } async syncGuild (type: string, guild: Guild) { - await this.rpc.syncGuild(type, guild.id) + // await this.rpc.syncGuild(type, guild.id) } async start () { diff --git a/packages/roleypoly-bot/commands/_types.js.flow b/packages/roleypoly-bot/src/commands/_types.ts similarity index 74% rename from packages/roleypoly-bot/commands/_types.js.flow rename to packages/roleypoly-bot/src/commands/_types.ts index d80a1d4..9552f6c 100644 --- a/packages/roleypoly-bot/commands/_types.js.flow +++ b/packages/roleypoly-bot/src/commands/_types.ts @@ -1,6 +1,5 @@ -// @flow -import type { Message } from 'eris' -import type Bot from '../Bot' +import { Message } from 'eris' +import Bot from '../Bot' export type Command = { regex: RegExp, diff --git a/packages/roleypoly-bot/commands/dm.js b/packages/roleypoly-bot/src/commands/dm.ts similarity index 100% rename from packages/roleypoly-bot/commands/dm.js rename to packages/roleypoly-bot/src/commands/dm.ts diff --git a/packages/roleypoly-bot/commands/root.js b/packages/roleypoly-bot/src/commands/root.ts similarity index 100% rename from packages/roleypoly-bot/commands/root.js rename to packages/roleypoly-bot/src/commands/root.ts diff --git a/packages/roleypoly-bot/commands/text.js b/packages/roleypoly-bot/src/commands/text.ts similarity index 100% rename from packages/roleypoly-bot/commands/text.js rename to packages/roleypoly-bot/src/commands/text.ts diff --git a/packages/roleypoly-bot/index.js b/packages/roleypoly-bot/src/index.ts similarity index 81% rename from packages/roleypoly-bot/index.js rename to packages/roleypoly-bot/src/index.ts index a63d9b3..acc3597 100644 --- a/packages/roleypoly-bot/index.js +++ b/packages/roleypoly-bot/src/index.ts @@ -3,4 +3,4 @@ import 'dotenv/config' import Bot from './Bot' const B = new Bot() -B.start() +B.start().catch() diff --git a/packages/roleypoly-bot/logger.js b/packages/roleypoly-bot/src/logger.ts similarity index 100% rename from packages/roleypoly-bot/logger.js rename to packages/roleypoly-bot/src/logger.ts diff --git a/packages/roleypoly-bot/random-emoji.js b/packages/roleypoly-bot/src/random-emoji.ts similarity index 97% rename from packages/roleypoly-bot/random-emoji.js rename to packages/roleypoly-bot/src/random-emoji.ts index a14ce77..9bb64b4 100644 --- a/packages/roleypoly-bot/random-emoji.js +++ b/packages/roleypoly-bot/src/random-emoji.ts @@ -1,4 +1,3 @@ -// @flow export const emojis = [ ':beginner:', ':beginner:', diff --git a/packages/roleypoly-bot/utils.js b/packages/roleypoly-bot/src/utils.ts similarity index 60% rename from packages/roleypoly-bot/utils.js rename to packages/roleypoly-bot/src/utils.ts index 9cfca2d..d68d956 100644 --- a/packages/roleypoly-bot/utils.js +++ b/packages/roleypoly-bot/src/utils.ts @@ -1,8 +1,8 @@ // @flow -import type Bot from './Bot' -import type { Message } from 'eris' +import Bot from './Bot' +import { Message } from 'eris' export const withTyping = (fn: Function) => async (bot: Bot, msg: Message, ...args: any[]) => { - msg.channel.sendTyping() + await msg.channel.sendTyping() return fn(bot, msg, ...args) } diff --git a/packages/roleypoly-bot/tsconfig.json b/packages/roleypoly-bot/tsconfig.json new file mode 100644 index 0000000..fdfdb95 --- /dev/null +++ b/packages/roleypoly-bot/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./lib" + }, + "include": [ + "./src" + ] +} \ No newline at end of file diff --git a/packages/roleypoly-bot/tslint.json b/packages/roleypoly-bot/tslint.json new file mode 100644 index 0000000..7967051 --- /dev/null +++ b/packages/roleypoly-bot/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "tslint-config-standard" +} \ No newline at end of file diff --git a/packages/roleypoly-design/.babelrc b/packages/roleypoly-design/.babelrc index 74fc32e..215f77b 100644 --- a/packages/roleypoly-design/.babelrc +++ b/packages/roleypoly-design/.babelrc @@ -1,11 +1,9 @@ { "presets": [ "next/babel", - "@babel/preset-typescript", + "@zeit/next-typescript/babel" ], "plugins": [ - "@babel/plugin-syntax-dynamic-import", - "@babel/plugin-proposal-class-properties", [ "@babel/plugin-transform-runtime", { @@ -18,8 +16,6 @@ "ssr": true } ], - "@babel/plugin-proposal-optional-chaining", - "macros" ], "env": { "test": { @@ -32,10 +28,6 @@ } } ] - ], - "plugins": [ - "require-context-hook", - "macros" ] } } diff --git a/packages/roleypoly-design/.lintstagedrc.yml b/packages/roleypoly-design/.lintstagedrc.yml index 39e386b..2a83f89 100644 --- a/packages/roleypoly-design/.lintstagedrc.yml +++ b/packages/roleypoly-design/.lintstagedrc.yml @@ -4,8 +4,11 @@ linters: - git add lib/*.d.ts: - tslint --fix + - git add src/*.{ts,tsx}: - tslint --fix - stylelint --fix - jest --bail --findRelatedTests - - git add \ No newline at end of file + - git add + + \ No newline at end of file diff --git a/packages/roleypoly-design/.storybook/preview-head.html b/packages/roleypoly-design/.storybook/preview-head.html index 5a0ba1d..bc33ae0 100644 --- a/packages/roleypoly-design/.storybook/preview-head.html +++ b/packages/roleypoly-design/.storybook/preview-head.html @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/packages/roleypoly-design/package.json b/packages/roleypoly-design/package.json index b03242d..ab2d736 100644 --- a/packages/roleypoly-design/package.json +++ b/packages/roleypoly-design/package.json @@ -11,6 +11,7 @@ "files": [ "lib" ], + "types": "./lib/index.d.ts", "devDependencies": { "@babel/core": "^7.4.4", "@babel/preset-typescript": "^7.3.3", @@ -25,7 +26,7 @@ "@types/enzyme-adapter-react-16": "^1.0.5", "@types/jest": "^24.0.13", "@types/node": "^12.0.2", - "@types/react": "^16.8.17", + "@types/react": "^16.8.19", "@types/react-dom": "^16.8.4", "@types/react-test-renderer": "^16.8.1", "@types/storybook__addon-actions": "^3.4.2", @@ -36,16 +37,14 @@ "@types/styled-components": "4.1.8", "awesome-typescript-loader": "^5.2.1", "babel-loader": "^8.0.6", - "babel-plugin-macros": "^2.5.1", - "babel-plugin-require-context-hook": "^1.0.0", + "lint-staged": "^8.1.7", "react-docgen-typescript-loader": "^3.1.0", "react-test-renderer": "^16.8.6", - "require-context.macro": "^1.0.4", "sinon": "^7.3.2", "stylelint": "^10.0.1", - "tslint": "^5.16.0", + "tslint": "^5.17.0", "tslint-config-standard": "^8.0.1", - "typescript": "^3.4.5" + "typescript": "^3.5.1" }, "scripts": { "storybook": "start-storybook -p 6006", diff --git a/packages/roleypoly-design/src/__test__/__snapshots__/storyshots.test.ts.snap b/packages/roleypoly-design/src/__test__/__snapshots__/storyshots.test.ts.snap index 7102ac1..2508728 100644 --- a/packages/roleypoly-design/src/__test__/__snapshots__/storyshots.test.ts.snap +++ b/packages/roleypoly-design/src/__test__/__snapshots__/storyshots.test.ts.snap @@ -45,25 +45,155 @@ exports[`Storyshots Button Disabled 1`] = ` `; exports[`Storyshots Button Loading 1`] = ` - Example - + `; exports[`Storyshots Button Primary 1`] = ` diff --git a/packages/roleypoly-design/src/button/Button.story.tsx b/packages/roleypoly-design/src/button/Button.story.tsx index 809d716..a2d4cd2 100644 --- a/packages/roleypoly-design/src/button/Button.story.tsx +++ b/packages/roleypoly-design/src/button/Button.story.tsx @@ -1,10 +1,16 @@ import * as React from 'react' import { storiesOf } from '@storybook/react' import { action } from '@storybook/addon-actions' +import { number, withKnobs } from '@storybook/addon-knobs' -import Button, { PrimaryButton, SecondaryButton } from './Button' +import Button, { + PrimaryButton, + SecondaryButton, + LoadingButton +} from './Button' const s = storiesOf('Button', module) +s.addDecorator(withKnobs) const pressed = action('button pressed!') @@ -12,4 +18,4 @@ s.add('Default', () => ) s.add('Disabled', () => ) s.add('Primary', () => Example) s.add('Secondary', () => Example) -s.add('Loading', () => ) +s.add('Loading', () => Example) diff --git a/packages/roleypoly-design/src/button/Button.test.tsx b/packages/roleypoly-design/src/button/Button.test.tsx index 3932aca..b0ac6c3 100644 --- a/packages/roleypoly-design/src/button/Button.test.tsx +++ b/packages/roleypoly-design/src/button/Button.test.tsx @@ -1,8 +1,11 @@ import * as React from 'react' import { shallow } from 'enzyme' import * as sinon from 'sinon' +import 'jest-styled-components' import Button from './Button' +// import { StyledLoadingButton } from './styled' +// import { ButtonProps } from './types' describe('