From 50b5e334a3720c7a6631ca7a5cb36a212e3e276a Mon Sep 17 00:00:00 2001 From: Kata Date: Thu, 4 Apr 2019 11:13:34 -0500 Subject: [PATCH] [bot] break out RPC and shared packages for bot service breakout --- .env.example | 5 +- .gitignore | 1 + package.json | 7 +- packages/roleypoly-bot/.babelrc | 14 ++++ packages/roleypoly-bot/Bot.js | 0 packages/roleypoly-bot/index.js | 5 ++ packages/roleypoly-bot/logger.js | 70 +++++++++++++++++++ packages/roleypoly-bot/package.json | 17 +++++ packages/roleypoly-rpc-client/.babelrc | 14 ++++ packages/roleypoly-rpc-client/error.js | 21 ++++++ .../rpc => roleypoly-rpc-client}/index.js | 22 ++++-- packages/roleypoly-rpc-client/package.json | 16 +++++ packages/roleypoly-server/Roleypoly.js | 6 +- packages/roleypoly-server/bot/index.js | 13 ---- packages/roleypoly-server/package.json | 1 - packages/roleypoly-server/rpc/_error.js | 15 ---- packages/roleypoly-server/rpc/_security.js | 25 ++++++- packages/roleypoly-server/rpc/index.js | 3 +- packages/roleypoly-server/rpc/servers.js | 2 +- packages/roleypoly-server/rpc/user.js | 3 +- packages/roleypoly-server/services/auth.js | 5 ++ packages/roleypoly-server/services/discord.js | 45 +++--------- .../services/discord/botFetcher.js | 22 ------ packages/roleypoly-ui/config/rpc.js | 2 +- packages/roleypoly-ui/package.json | 1 + packages/roleypoly-ui/pages/_app.js | 1 + .../roleypoly-ui/pages/_internal/_server.js | 2 +- packages/roleypoly-ui/pages/auth/login.js | 2 +- packages/roleypoly-ui/pages/index.js | 2 +- .../roleypoly-ui/{lib => util}/redirect.js | 0 yarn.lock | 2 +- 31 files changed, 233 insertions(+), 111 deletions(-) create mode 100644 packages/roleypoly-bot/.babelrc create mode 100644 packages/roleypoly-bot/Bot.js create mode 100644 packages/roleypoly-bot/index.js create mode 100644 packages/roleypoly-bot/logger.js create mode 100644 packages/roleypoly-bot/package.json create mode 100644 packages/roleypoly-rpc-client/.babelrc create mode 100644 packages/roleypoly-rpc-client/error.js rename packages/{roleypoly-ui/rpc => roleypoly-rpc-client}/index.js (88%) create mode 100644 packages/roleypoly-rpc-client/package.json delete mode 100644 packages/roleypoly-server/bot/index.js delete mode 100644 packages/roleypoly-server/services/discord/botFetcher.js rename packages/roleypoly-ui/{lib => util}/redirect.js (100%) diff --git a/.env.example b/.env.example index a6d03ce..a8a3a7f 100644 --- a/.env.example +++ b/.env.example @@ -22,9 +22,8 @@ APP_URL=http://localhost:6769 # CHANGE THIS ALWAYS. BUT EXACTLY ONCE. # signing key for sessions. changing this will invalidate all sessions. APP_KEY=PJoayPGqi8vfYVFYBDgSeJSDYUpzBX - -# does this instance start a bot? -IS_BOT=true +# shared secret for bot authenticated requests. +SHARED_SECRET=EJ1LongZLRJgHBhkSROsGh8MeaE0YvMo # your and your friend's user ID for using admin tools. ROOT_USERS=62601275618889721 diff --git a/.gitignore b/.gitignore index d8ce8e0..4bae06f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ yarn-error\.log *.log \.next/ coverage/ +packages/*/lib \ No newline at end of file diff --git a/package.json b/package.json index 3711678..49817ad 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "scripts": { "lerna": "lerna", "start": "node packages/roleypoly-server/dist/index.js", - "dev": "babel-node packages/roleypoly-server/index.js", + "dev": "run-p dev:*", + "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", @@ -77,7 +79,8 @@ "$Call" ], "ignore": [ - "flow-typed/*" + "flow-typed/*", + "packages/*/lib/*" ] } } diff --git a/packages/roleypoly-bot/.babelrc b/packages/roleypoly-bot/.babelrc new file mode 100644 index 0000000..5073193 --- /dev/null +++ b/packages/roleypoly-bot/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ ["@babel/preset-env", { + "targets": { + "node": true + } + }], "@babel/preset-flow" ], + "plugins": [ + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-proposal-class-properties", + "@babel/plugin-proposal-optional-chaining", + ["@babel/plugin-transform-runtime", + { "helpers": false }] + ] +} diff --git a/packages/roleypoly-bot/Bot.js b/packages/roleypoly-bot/Bot.js new file mode 100644 index 0000000..e69de29 diff --git a/packages/roleypoly-bot/index.js b/packages/roleypoly-bot/index.js new file mode 100644 index 0000000..15fb82c --- /dev/null +++ b/packages/roleypoly-bot/index.js @@ -0,0 +1,5 @@ +// @flow +import Bot from './Bot' + +const B = new Bot() +B.start() diff --git a/packages/roleypoly-bot/logger.js b/packages/roleypoly-bot/logger.js new file mode 100644 index 0000000..ccb7beb --- /dev/null +++ b/packages/roleypoly-bot/logger.js @@ -0,0 +1,70 @@ +// @flow +import chalk from 'chalk' + +export class Logger { + debugOn: boolean + name: string + quietSql: boolean + + constructor (name: string, debugOverride: boolean = false) { + this.name = name + this.debugOn = (process.env.DEBUG === 'true' || process.env.DEBUG === '*') || debugOverride + this.quietSql = (process.env.DEBUG_SQL !== 'true') + } + + fatal (text: string, ...data: any) { + this.error(text, data) + + if (typeof data[data.length - 1] === 'number') { + process.exit(data[data.length - 1]) + } else { + process.exit(1) + } + } + + error (text: string, ...data: any) { + console.error(chalk.red.bold(`ERR ${this.name}:`) + `\n ${text}`, data) + } + + warn (text: string, ...data: any) { + console.warn(chalk.yellow.bold(`WARN ${this.name}:`) + `\n ${text}`, data) + } + + notice (text: string, ...data: any) { + console.log(chalk.cyan.bold(`NOTICE ${this.name}:`) + `\n ${text}`, data) + } + + info (text: string, ...data: any) { + console.info(chalk.blue.bold(`INFO ${this.name}:`) + `\n ${text}`, data) + } + + bot (text: string, ...data: any) { + console.log(chalk.yellowBright.bold(`BOT CMD:`) + `\n ${text}`, data) + } + + deprecated (text: string, ...data: any) { + console.warn(chalk.yellowBright(`DEPRECATED ${this.name}:`) + `\n ${text}`, data) + console.trace() + } + + request (text: string, ...data: any) { + console.info(chalk.green.bold(`HTTP ${this.name}:`) + `\n ${text}`) + } + + debug (text: string, ...data: any) { + if (this.debugOn) { + console.log(chalk.gray.bold(`DEBUG ${this.name}:`) + `\n ${text}`, data) + } + } + + sql (logger: Logger, ...data: any) { + if (logger.debugOn && !logger.quietSql) { + console.log(chalk.bold('DEBUG SQL:\n '), data) + } + } +} + +export default (pathname: string) => { + const name = pathname.replace(__dirname, '').replace('.js', '') + return new Logger(name) +} diff --git a/packages/roleypoly-bot/package.json b/packages/roleypoly-bot/package.json new file mode 100644 index 0000000..e8d3ad0 --- /dev/null +++ b/packages/roleypoly-bot/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "@roleypoly/bot", + "version": "2.0.0", + "scripts": { + "build": "babel --delete-dir-on-start -d lib .", + "dev": "yarn build --watch" + }, + "main": "./lib/Bot.js", + "dependencies": { + "eris": "^0.9.0", + "@roleypoly/rpc-client": "2.0.0" + }, + "devDependencies": { + "@babel/cli": "^7.4.3" + } +} \ No newline at end of file diff --git a/packages/roleypoly-rpc-client/.babelrc b/packages/roleypoly-rpc-client/.babelrc new file mode 100644 index 0000000..5073193 --- /dev/null +++ b/packages/roleypoly-rpc-client/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ ["@babel/preset-env", { + "targets": { + "node": true + } + }], "@babel/preset-flow" ], + "plugins": [ + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-proposal-class-properties", + "@babel/plugin-proposal-optional-chaining", + ["@babel/plugin-transform-runtime", + { "helpers": false }] + ] +} diff --git a/packages/roleypoly-rpc-client/error.js b/packages/roleypoly-rpc-client/error.js new file mode 100644 index 0000000..35cce10 --- /dev/null +++ b/packages/roleypoly-rpc-client/error.js @@ -0,0 +1,21 @@ +// @flow +import type { RPCResponse } from './index' + +class RPCError extends Error { + code: ?number + extra: any[] + remoteStack: ?string + constructor (msg: string, code?: number, ...extra: any[]) { + super(msg) + this.code = code + this.extra = extra + } + + static fromResponse (body: RPCResponse, status: number) { + const e = new RPCError(body.msg, status) + e.remoteStack = body.trace + return e + } +} + +module.exports = RPCError diff --git a/packages/roleypoly-ui/rpc/index.js b/packages/roleypoly-rpc-client/index.js similarity index 88% rename from packages/roleypoly-ui/rpc/index.js rename to packages/roleypoly-rpc-client/index.js index b5104f4..86b4e1b 100644 --- a/packages/roleypoly-ui/rpc/index.js +++ b/packages/roleypoly-rpc-client/index.js @@ -1,6 +1,6 @@ // @flow import superagent from 'superagent' -import RPCError from '@roleypoly/server/rpc/_error' +import RPCError from './error' export type RPCResponse = { response?: mixed, @@ -8,7 +8,7 @@ export type RPCResponse = { // error stuff error?: boolean, - msg?: string, + msg: string, trace?: string } @@ -24,6 +24,10 @@ export default class RPCClient { recentHash: string cookieHeader: string + headerMixins: { + [x:string]: string + } = {} + rpc: { [fn: string]: (...args: any[]) => Promise } = {} @@ -55,7 +59,12 @@ export default class RPCClient { } withCookies = (h: string) => { - this.cookieHeader = h + this.headerMixins['Set-Cookie'] = h + return this.rpc + } + + withBotAuth = (h: string) => { + this.headerMixins['Authorization'] = `Bot ${h}` return this.rpc } @@ -85,12 +94,11 @@ export default class RPCClient { async call (fn: string, ...args: any[]): mixed { const req: RPCRequest = { fn, args } - const rq = superagent.post(this.baseUrl) - if (this.cookieHeader != null) { - rq.cookies = this.cookieHeader - } + const rq = superagent.post(this.baseUrl).set({ ...this.headerMixins }) + const rsp = await rq.send(req).ok(() => true) const body: RPCResponse = rsp.body + // console.log(body) if (body.error === true) { console.error(body) diff --git a/packages/roleypoly-rpc-client/package.json b/packages/roleypoly-rpc-client/package.json new file mode 100644 index 0000000..a9eb359 --- /dev/null +++ b/packages/roleypoly-rpc-client/package.json @@ -0,0 +1,16 @@ +{ + "private": true, + "name": "@roleypoly/rpc-client", + "version": "2.0.0", + "scripts": { + "postinstall": "yarn build", + "build": "babel --delete-dir-on-start -d lib ." + }, + "main": "./lib/index.js", + "dependencies": { + "superagent":"^5.0.2" + }, + "devDependencies": { + "@babel/cli": "^7.4.3" + } +} \ No newline at end of file diff --git a/packages/roleypoly-server/Roleypoly.js b/packages/roleypoly-server/Roleypoly.js index 274aa49..26fe937 100644 --- a/packages/roleypoly-server/Roleypoly.js +++ b/packages/roleypoly-server/Roleypoly.js @@ -34,7 +34,8 @@ export type AppContext = { config: { appUrl: string, dev: boolean, - hotReload: boolean + hotReload: boolean, + sharedSecret: string }, ui: Next, uiHandler: Next.Handler, @@ -85,7 +86,8 @@ class Roleypoly { config: { appUrl, dev, - hotReload: process.env.NO_HOT_RELOAD !== '1' + hotReload: process.env.NO_HOT_RELOAD !== '1', + sharedSecret: process.env.SHARED_SECRET }, io, ui, diff --git a/packages/roleypoly-server/bot/index.js b/packages/roleypoly-server/bot/index.js deleted file mode 100644 index fb6a35e..0000000 --- a/packages/roleypoly-server/bot/index.js +++ /dev/null @@ -1,13 +0,0 @@ -// @flow -import type DiscordService from '../services/discord' -import logger from '../logger' -const log = logger(__filename) - -export default class Bot { - svc: DiscordService - log: typeof log - constructor (DS: DiscordService) { - this.svc = DS - this.log = log - } -} diff --git a/packages/roleypoly-server/package.json b/packages/roleypoly-server/package.json index 922b223..e9c278b 100644 --- a/packages/roleypoly-server/package.json +++ b/packages/roleypoly-server/package.json @@ -3,7 +3,6 @@ "private": true, "version": "2.0.0", "scripts": { - "dev": "babel-node index.js", "start": "NODE_ENV=production node dist/index.js", "pretest": "standard --fix", "build": "NODE_ENV=production babel --delete-dir-on-start -d dist ." diff --git a/packages/roleypoly-server/rpc/_error.js b/packages/roleypoly-server/rpc/_error.js index f3faceb..e69de29 100644 --- a/packages/roleypoly-server/rpc/_error.js +++ b/packages/roleypoly-server/rpc/_error.js @@ -1,15 +0,0 @@ -class RPCError extends Error { - constructor (msg, code, ...extra) { - super(msg) - this.code = code - this.extra = extra - } - - static fromResponse (body, status) { - const e = new RPCError(body.msg, status) - e.remoteStack = body.trace - return e - } -} - -module.exports = RPCError diff --git a/packages/roleypoly-server/rpc/_security.js b/packages/roleypoly-server/rpc/_security.js index 7cdc365..9ed88ab 100644 --- a/packages/roleypoly-server/rpc/_security.js +++ b/packages/roleypoly-server/rpc/_security.js @@ -1,7 +1,7 @@ // @flow import { type AppContext } from '../Roleypoly' import { type Context } from 'koa' -import RPCError from './_error' +import RPCError from '@roleypoly/rpc-client/error' import logger from '../logger' const log = logger(__filename) @@ -122,6 +122,29 @@ export const any = ( silent: boolean = false ) => (...args: any) => fn(...args) +export const bot = ( + $: AppContext, + fn: (ctx: Context, ...args: any[]) => any, + silent: boolean = false +) => ( + ctx: Context, + ...args: any +) => { + const authToken: ?string = ctx.request.headers['Authorization'] + + if (authToken != null && authToken.startsWith('Bot ')) { + if (authToken === `Bot ${$.config.sharedSecret}`) { + return fn(ctx, ...args) + } + } + + if (!silent) { + log.info('RPC bot check failed', logFacts(ctx)) + } + + throw PermissionError +} + type Handler = (ctx: Context, ...args: any[]) => any type Strategy = ( $: AppContext, diff --git a/packages/roleypoly-server/rpc/index.js b/packages/roleypoly-server/rpc/index.js index b5a5a97..25b2301 100644 --- a/packages/roleypoly-server/rpc/index.js +++ b/packages/roleypoly-server/rpc/index.js @@ -1,7 +1,7 @@ // @flow import fnv from 'fnv-plus' import autoloader from './_autoloader' -import RPCError from './_error' +import RPCError from '@roleypoly/rpc-client/error' import type Roleypoly, { Router } from '../Roleypoly' import type { Context } from 'koa' // import logger from '../logger' @@ -121,7 +121,6 @@ export default class RPCServer { if (err instanceof RPCError || err.constructor.name === 'RPCError') { // $FlowFixMe ctx.status = err.code - console.log(err.code) } } diff --git a/packages/roleypoly-server/rpc/servers.js b/packages/roleypoly-server/rpc/servers.js index 2187e2c..9f93325 100644 --- a/packages/roleypoly-server/rpc/servers.js +++ b/packages/roleypoly-server/rpc/servers.js @@ -3,7 +3,7 @@ import { type AppContext } from '../Roleypoly' import { type Context } from 'koa' import { type Guild } from 'eris' import * as secureAs from './_security' -import RPCError from './_error' +import RPCError from '@roleypoly/rpc-client/error' export default ($: AppContext) => ({ diff --git a/packages/roleypoly-server/rpc/user.js b/packages/roleypoly-server/rpc/user.js index 467d870..b34efe0 100644 --- a/packages/roleypoly-server/rpc/user.js +++ b/packages/roleypoly-server/rpc/user.js @@ -6,7 +6,8 @@ import * as secureAs from './_security' export default ($: AppContext) => ({ getCurrentUser: secureAs.authed($, async (ctx: Context) => { - return $.discord.getUserPartial(ctx.session.userId) + const u = await $.discord.getUserPartial(ctx.session.userId) + return u }), isRoot: secureAs.root($, () => { diff --git a/packages/roleypoly-server/services/auth.js b/packages/roleypoly-server/services/auth.js index 6983a4c..ca3b0e4 100644 --- a/packages/roleypoly-server/services/auth.js +++ b/packages/roleypoly-server/services/auth.js @@ -31,20 +31,25 @@ export default class AuthService extends Service { async isLoggedIn (ctx: Context, { refresh = false }: { refresh: boolean } = {}) { const { userId, expiresAt, authType } = ctx.session if (userId == null) { + this.log.debug('isLoggedIn failed, no userId', ctx.session) return false } if (expiresAt < Date.now()) { + this.log.debug('session has expired.', expiresAt, Date.now()) if (refresh && authType === 'oauth') { + this.log.debug('was oauth and we can refresh') const tokens = await this.ctx.discord.refreshOAuth(ctx.session) this.injectSessionFromOAuth(ctx, tokens, userId) return true } + this.log.debug('was not oauth, we are destroying the session') ctx.session = null // reset session as well return false } + this.log.debug('this user is logged in', userId) return true } diff --git a/packages/roleypoly-server/services/discord.js b/packages/roleypoly-server/services/discord.js index 03eadfe..e41f597 100644 --- a/packages/roleypoly-server/services/discord.js +++ b/packages/roleypoly-server/services/discord.js @@ -1,7 +1,6 @@ // @flow import Service from './Service' import type { AppContext } from '../Roleypoly' -import Bot from '../bot' import Eris, { type Member, Role, type Guild, type Permission as ErisPermission } from 'eris' import LRU from 'lru-cache' // $FlowFixMe @@ -9,13 +8,13 @@ import { OrderedSet } from 'immutable' import superagent from 'superagent' import type { AuthTokens } from './auth' import type { IFetcher } from './discord/types' +import RestFetcher from './discord/restFetcher' type DiscordServiceConfig = { token: string, clientId: string, clientSecret: string, - rootUsers: Set, - isBot: boolean + rootUsers: Set } export type Permissions = { @@ -56,7 +55,6 @@ export type MemberExt = Member & { export default class DiscordService extends Service { ctx: AppContext - bot: Bot client: Eris cfg: DiscordServiceConfig @@ -77,8 +75,7 @@ export default class DiscordService extends Service { rootUsers: new Set((process.env.ROOT_USERS || '').split(',')), token: process.env.DISCORD_BOT_TOKEN || '', clientId: process.env.DISCORD_CLIENT_ID || '', - clientSecret: process.env.DISCORD_CLIENT_SECRET || '', - isBot: process.env.IS_BOT === 'true' + clientSecret: process.env.DISCORD_CLIENT_SECRET || '' } this.oauthCallback = `${ctx.config.appUrl}/api/oauth/callback` @@ -86,36 +83,11 @@ export default class DiscordService extends Service { this.ownRoleCache = new LRU() this.topRoleCache = new LRU() - if (this.cfg.isBot) { - this.client = new Eris(this.cfg.token, { - disableEveryone: true, - maxShards: 'auto', - messageLimit: 10, - disableEvents: { - CHANNEL_PINS_UPDATE: true, - USER_SETTINGS_UPDATE: true, - USER_NOTE_UPDATE: true, - RELATIONSHIP_ADD: true, - RELATIONSHIP_REMOVE: true, - GUILD_BAN_ADD: true, - GUILD_BAN_REMOVE: true, - TYPING_START: true, - MESSAGE_UPDATE: true, - MESSAGE_DELETE: true, - MESSAGE_DELETE_BULK: true, - VOICE_STATE_UPDATE: true - } - }) - this.bot = new Bot(this) - const BotFetcher = require('./discord/botFetcher').default - this.fetcher = new BotFetcher(this) - } else { - this.client = new Eris(`Bot ${this.cfg.token}`, { - restMode: true - }) - const RestFetcher = require('./discord/restFetcher').default - this.fetcher = new RestFetcher(this) - } + this.client = new Eris(`Bot ${this.cfg.token}`, { + restMode: true + }) + + this.fetcher = new RestFetcher(this) } isRoot (id: string): boolean { @@ -272,6 +244,7 @@ export default class DiscordService extends Service { async getUserPartial (userId: string): Promise { const u = await this.fetcher.getUser(userId) if (u == null) { + this.log.debug('userPartial got a null user', userId, u) return null } diff --git a/packages/roleypoly-server/services/discord/botFetcher.js b/packages/roleypoly-server/services/discord/botFetcher.js deleted file mode 100644 index 0aae271..0000000 --- a/packages/roleypoly-server/services/discord/botFetcher.js +++ /dev/null @@ -1,22 +0,0 @@ -// @flow -import type { IFetcher } from './types' -import type DiscordSvc from '../discord' -import type ErisClient, { User, Member, Guild } from 'eris' - -export default class BotFetcher implements IFetcher { - ctx: DiscordSvc - client: ErisClient - constructor (ctx: DiscordSvc) { - this.ctx = ctx - this.client = ctx.client - } - - getUser = async (id: string): Promise => - this.client.users.get(id) - - getMember = async (server: string, user: string): Promise => - this.client.guilds.get(server)?.members.get(user) - - getGuild = async (server: string): Promise => - this.client.guilds.get(server) -} diff --git a/packages/roleypoly-ui/config/rpc.js b/packages/roleypoly-ui/config/rpc.js index f7eb7ca..b40943a 100644 --- a/packages/roleypoly-ui/config/rpc.js +++ b/packages/roleypoly-ui/config/rpc.js @@ -1,5 +1,5 @@ // @flow -import RPCClient from '../rpc' +import RPCClient from '@roleypoly/rpc-client' const client = new RPCClient({ forceDev: false }) diff --git a/packages/roleypoly-ui/package.json b/packages/roleypoly-ui/package.json index 0a72497..6a2adae 100644 --- a/packages/roleypoly-ui/package.json +++ b/packages/roleypoly-ui/package.json @@ -7,6 +7,7 @@ }, "dependencies": { "@roleypoly/types": "^2.0.0", + "@roleypoly/rpc-client": "^2.0.0", "color": "^3.1.0", "eventemitter3": "^3.1.0", "fast-redux": "^0.7.1", diff --git a/packages/roleypoly-ui/pages/_app.js b/packages/roleypoly-ui/pages/_app.js index de063b7..b904ed6 100644 --- a/packages/roleypoly-ui/pages/_app.js +++ b/packages/roleypoly-ui/pages/_app.js @@ -42,6 +42,7 @@ class RoleypolyApp extends App { ctx.user = user } catch (e) { if (e.code === 403) { + console.error('user not found') ctx.user = null } else { console.error(e) diff --git a/packages/roleypoly-ui/pages/_internal/_server.js b/packages/roleypoly-ui/pages/_internal/_server.js index b125e60..eb42a53 100644 --- a/packages/roleypoly-ui/pages/_internal/_server.js +++ b/packages/roleypoly-ui/pages/_internal/_server.js @@ -3,7 +3,7 @@ import * as React from 'react' import Head from 'next/head' import type { PageProps } from '../../types' import SocialCards from '../../components/social-cards' -import redirect from '../../lib/redirect' +import redirect from '../../util/redirect' import { connect } from 'react-redux' import { fetchServerIfNeed, getCurrentServerState, type ServerState } from '../../stores/currentServer' import { renderRoles, getCategoryViewState, toggleRole, type ViewState } from '../../stores/roles' diff --git a/packages/roleypoly-ui/pages/auth/login.js b/packages/roleypoly-ui/pages/auth/login.js index d585ca5..8eb9d4d 100644 --- a/packages/roleypoly-ui/pages/auth/login.js +++ b/packages/roleypoly-ui/pages/auth/login.js @@ -4,7 +4,7 @@ import styled from 'styled-components' import { md } from '../../kit/media' import DiscordButton from '../../components/discord-button' import RPC from '../../config/rpc' -import redirect from '../../lib/redirect' +import redirect from '../../util/redirect' import dynamic from 'next/dynamic' import type { PageProps } from '../../types' import type { ServerSlug } from '@roleypoly/types' diff --git a/packages/roleypoly-ui/pages/index.js b/packages/roleypoly-ui/pages/index.js index 9e13353..1f8bf0d 100644 --- a/packages/roleypoly-ui/pages/index.js +++ b/packages/roleypoly-ui/pages/index.js @@ -1,5 +1,5 @@ import * as React from 'react' -import redirect from '../lib/redirect' +import redirect from '../util/redirect' // import Link from 'next/link' // import Head from '../components/head' // import Nav from '../components/nav' diff --git a/packages/roleypoly-ui/lib/redirect.js b/packages/roleypoly-ui/util/redirect.js similarity index 100% rename from packages/roleypoly-ui/lib/redirect.js rename to packages/roleypoly-ui/util/redirect.js diff --git a/yarn.lock b/yarn.lock index b42a51f..914311d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10769,7 +10769,7 @@ standard-engine@~9.0.0: minimist "^1.1.0" pkg-conf "^2.0.0" -standard@12.0.1: +standard@12.0.1, standard@^12.0.1: version "12.0.1" resolved "https://registry.yarnpkg.com/standard/-/standard-12.0.1.tgz#0fc5a8aa6c34c546c5562aae644242b24dae2e61" integrity sha512-UqdHjh87OG2gUrNCSM4QRLF5n9h3TFPwrCNyVlkqu31Hej0L/rc8hzKqVvkb2W3x0WMq7PzZdkLfEcBhVOR6lg==