Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to react-router@7, eslint@9, version bump the rest #101

Merged
merged 18 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .eslintignore

This file was deleted.

22 changes: 0 additions & 22 deletions .eslintrc.js

This file was deleted.

3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ yarn.lock
*.log
k8s-context
*.sqlite3
/cypress/screenshots
/cypress/videos
tsconfig.tsbuildinfo
.react-router
2 changes: 0 additions & 2 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run validate
2 changes: 1 addition & 1 deletion .lintstagedrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
"**/*.[tj]s?(x)": ["eslint --fix --max-warnings=0", "prettier --check"],
"migrations/*.[tj]s": [
"npm run start:migrate",
Expand Down
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
FROM node:20-alpine as build

Check warning on line 1 in Dockerfile

View workflow job for this annotation

GitHub Actions / build

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm install

COPY remix.config.js tailwind.config.js kysely.config.ts tsconfig.json .eslint* .prettierignore ./
COPY vite.config.ts tailwind.config.js kysely.config.ts tsconfig.json .eslint* .prettierignore ./
COPY app ./app

RUN npm run build
Expand All @@ -20,7 +20,6 @@
RUN npm prune --production

COPY --from=build /app/build ./build
COPY --from=build /app/public ./public

COPY kysely.config.ts ./
COPY migrations ./migrations
Expand Down
11 changes: 6 additions & 5 deletions app/commands/convene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const handler = async (
staff,
extra: "✅ Restricted",
}),
applyRestriction(message.member!),
applyRestriction(message.member),
message.reply(
"After a vote by the mods, this member has had restrictions applied to them",
),
Expand All @@ -96,7 +96,7 @@ export const handler = async (
staff,
extra: "✅ Kicked",
}),
kick(message.member!),
kick(message.member),
message.reply(
"After a vote by the mods, this member has been kicked from the server to cool off",
),
Expand All @@ -110,13 +110,13 @@ export const handler = async (
staff,
extra: "✅ Banned",
}),
ban(message.member!),
ban(message.member),
message.reply(
"After a vote by the mods, this member has been permanently banned",
),
]);
return;
case resolutions.nudge:
case resolutions.nudge: {
const [thread] = await Promise.all([
originalChannel.threads.create({
name: message.author.username,
Expand Down Expand Up @@ -145,6 +145,7 @@ This isn't a formal warning, but your message concerned the moderators enough th

${quoteAndEscape(message.content)}`);
return;
}
case resolutions.warning:
reportUser({
reason: ReportReasons.mod,
Expand Down Expand Up @@ -172,7 +173,7 @@ This isn't a formal warning, but your message concerned the moderators enough th
staff,
extra: "✅ Timed out overnight",
});
timeout(message.member!);
timeout(message.member);

return;
}
Expand Down
4 changes: 2 additions & 2 deletions app/commands/reacord/ModResponse.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UserInfo } from "reacord";
import type { ComponentEventUser } from "reacord";
import { Button } from "reacord";

import type { Resolution } from "~/helpers/modResponse";
Expand All @@ -17,7 +17,7 @@ export const ModResponse = ({
modRoleId,
}: {
votesRequired?: number;
onVote: (result: { vote: Resolution; user: UserInfo }) => void;
onVote: (result: { vote: Resolution; user: ComponentEventUser }) => void;
onResolve: (result: Resolution) => Promise<void>;
modRoleId: string;
}) => {
Expand Down
4 changes: 2 additions & 2 deletions app/commands/setupTickets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { REST } from "@discordjs/rest";
import { Routes, TextInputStyle } from "discord-api-types/v10";

import { discordToken } from "~/helpers/env";
import { discordToken } from "~/helpers/env.server";
import { SETTINGS, fetchSettings } from "~/models/guilds.server";
import { format } from "date-fns";
import type {
Expand Down Expand Up @@ -114,7 +114,7 @@ export default [
await thread.send({
content: "When you’ve finished, please close the ticket.",
components: [
// @ts-ignore
// @ts-expect-error Types for this are super busted
new ActionRowBuilder().addComponents(
new ButtonBuilder()
.setCustomId(`close-ticket||${user.id}`)
Expand Down
4 changes: 2 additions & 2 deletions app/components/login.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Form } from "@remix-run/react";
import { Form } from "react-router";
import type { ButtonHTMLAttributes } from "react";

interface LoginProps extends ButtonHTMLAttributes<Element> {
Expand All @@ -8,7 +8,7 @@ interface LoginProps extends ButtonHTMLAttributes<Element> {

export function Login({
children = "Log in with Discord",
errors,
// errors,
redirectTo,
...props
}: LoginProps) {
Expand Down
14 changes: 3 additions & 11 deletions app/components/logout.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import { Form } from "@remix-run/react";
import { Form } from "react-router";
import type { ButtonHTMLAttributes } from "react";

interface LoginProps extends ButtonHTMLAttributes<Element> {
errors?: { [k: string]: string };
redirectTo?: string;
}
type LoginProps = ButtonHTMLAttributes<Element>;

export function Logout({
children = "Log out",
errors,
redirectTo,
...props
}: LoginProps) {
export function Logout({ children = "Log out", ...props }: LoginProps) {
return (
<Form method="post" action="/logout" className="space-y-6">
<button
Expand Down
7 changes: 4 additions & 3 deletions app/db.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { ColumnType } from "kysely";

export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;
export type Generated<T> =
T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;

export interface Guilds {
id: string | null;
Expand Down
2 changes: 1 addition & 1 deletion app/db.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SQLite from "better-sqlite3";
import { Kysely, ParseJSONResultsPlugin, SqliteDialect } from "kysely";
import type { DB } from "./db";
import { databaseUrl } from "./helpers/env";
import { databaseUrl } from "./helpers/env.server";

export { SqliteError } from "better-sqlite3";

Expand Down
9 changes: 6 additions & 3 deletions app/discord/activityTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ export async function startActivityTracking(client: Client) {
client.on(Events.MessageCreate, async (msg) => {
const info = await getMessageStats(msg);
if (!info) return;
if (!msg.author || !msg.guildId) {
throw Error("Missing author or guild info when tracking message stats");
}
await db
.insertInto("message_stats")
.values({
...info,
message_id: msg.id,
author_id: msg.author!.id,
guild_id: msg.guildId!,
author_id: msg.author.id,
guild_id: msg.guildId,
channel_id: msg.channelId,
recipient_id: msg.mentions?.repliedUser?.id ?? null,
channel_category: (await getOrFetchChannel(msg))?.parent?.name,
Expand Down Expand Up @@ -92,5 +95,5 @@ export async function reportByGuild(guildId: string) {
.where("guild_id", "=", guildId)
.groupBy("author_id")
.execute();
return result
return result;
}
2 changes: 1 addition & 1 deletion app/discord/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { REST } from "discord.js";
import { discordToken } from "~/helpers/env";
import { discordToken } from "~/helpers/env.server";

export const rest = new REST({ version: "10" }).setToken(discordToken);
2 changes: 1 addition & 1 deletion app/discord/client.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GatewayIntentBits, Client, Partials, ActivityType } from "discord.js";
import { ReacordDiscordJs } from "reacord";
import { discordToken } from "~/helpers/env";
import { discordToken } from "~/helpers/env.server";

export const client = new Client({
intents: [
Expand Down
16 changes: 13 additions & 3 deletions app/discord/deployCommands.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {
APIApplicationCommand,
Client,
ContextMenuCommandBuilder,
OAuth2Guild,
SlashCommandBuilder,
} from "discord.js";
import { InteractionType, Routes } from "discord.js";
Expand All @@ -15,7 +16,7 @@ import {
isSlashCommand,
isUserContextCommand,
} from "~/helpers/discord";
import { applicationId, isProd } from "~/helpers/env";
import { applicationId, isProd } from "~/helpers/env.server";
import { calculateChangedCommands } from "~/helpers/discordCommands";

/**
Expand Down Expand Up @@ -71,12 +72,14 @@ export const deployCommands = async (client: Client) => {
) {
config.handler(interaction);
}
return;
}
case InteractionType.ModalSubmit: {
const config = matchCommand(interaction.customId);
if (isModalCommand(config) && interaction.isModalSubmit()) {
config.handler(interaction);
}
return;
}
}
});
Expand Down Expand Up @@ -111,9 +114,16 @@ export const deployProdCommands = async (
// This should only one once as a migration, but maybe stuff will get into
// weird states.
const guilds = await client.guilds.fetch();
const randomGuild = guilds.at(Math.floor(Math.random() * guilds.size));
const randomGuild = ((): OAuth2Guild => {
let g: OAuth2Guild | undefined;
// This is really just to appease TS
while (!g) {
g = guilds.at(Math.floor(Math.random() * guilds.size));
}
return g;
})();
const randomGuildCommands = (await rest.get(
Routes.applicationGuildCommands(applicationId, randomGuild!.id),
Routes.applicationGuildCommands(applicationId, randomGuild.id),
)) as APIApplicationCommand[];
if (randomGuildCommands.length > 0) {
await Promise.allSettled(
Expand Down
6 changes: 3 additions & 3 deletions app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RemixBrowser } from "@remix-run/react";
import { hydrate } from "react-dom";
import { HydratedRouter } from "react-router/dom";
import { hydrateRoot } from "react-dom/client";

hydrate(<RemixBrowser />, document);
hydrateRoot(document, <HydratedRouter />);
22 changes: 0 additions & 22 deletions app/entry.server.tsx

This file was deleted.

21 changes: 10 additions & 11 deletions app/helpers/discordCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ export const compareCommands = (
return result;
}
if (json.type === ApplicationCommandType.ChatInput || !json.type) {
const hasRemoteOptions =
"options" in remoteCommand && remoteCommand.options!.length > 0;
const hasLocalOptions = "options" in json && json.options!.length > 0;
const remoteOptions = remoteCommand.options;
const localOptions = json.options;

const typeMatches = !json.type || json.type === remoteCommand.type;
if (!typeMatches) {
Expand All @@ -44,29 +43,29 @@ export const compareCommands = (
if (!descriptionMatches) {
return false;
}
const remoteOptionsMatch = hasRemoteOptions
? remoteCommand.options!.every((o) =>
const remoteOptionsMatch = !remoteOptions
? true
: remoteOptions.every((o) =>
json.options?.some(
(o2) =>
o.name === o2.name &&
o.description === o2.description &&
o.type === o2.type,
),
)
: true;
);
if (!remoteOptionsMatch) {
return false;
}
const localOptionsMatch = hasLocalOptions
? json.options!.every((o) =>
const localOptionsMatch = !localOptions
? true
: localOptions.every((o) =>
remoteCommand.options?.some(
(o2) =>
o.name === o2.name &&
o.description === o2.description &&
o.type === o2.type,
),
)
: true;
);
if (!localOptionsMatch) {
return false;
}
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions app/helpers/modResponse.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { uniq } from "lodash";
import { uniq } from "lodash-es";
import { useCallback, useMemo, useState } from "react";

export const resolutions = {
Expand All @@ -19,7 +19,7 @@ export const humanReadableResolutions = {
[resolutions.kick]: "Kick",
[resolutions.ban]: "Ban",
} as const;
export type Resolution = typeof resolutions[keyof typeof resolutions];
export type Resolution = (typeof resolutions)[keyof typeof resolutions];

export const useVotes = () => {
const [votes, setVotes] = useState({} as Record<Resolution, string[]>);
Expand Down
Loading
Loading