diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7d3f32d1..67b78f2e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: - uses: ./.github/actions/pnpm-install - name: Check linting rules - run: pnpm lint + run: pnpm turbo check unit-tests: name: Unit tests diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 43603229a..000000000 --- a/.prettierrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "plugins": ["prettier-plugin-tailwindcss"], - "semi": true, - "tabWidth": 2, - "useTabs": false, - "trailingComma": "all", - "singleQuote": false, - "arrowParens": "always" -} diff --git a/.vscode/settings.json b/.vscode/settings.json index d2276158e..5a2f464f9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,9 @@ "editor.codeActionsOnSave": { "source.fixAll": "explicit" }, + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, "typescript.tsdk": "node_modules/typescript/lib", "typescript.preferences.importModuleSpecifier": "shortest", "cSpell.words": ["Rallly", "Vella"], diff --git a/apps/docs/.eslintrc.js b/apps/docs/.eslintrc.js deleted file mode 100644 index 3d9be6e61..000000000 --- a/apps/docs/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - ...require("@rallly/eslint-config")(__dirname), -}; diff --git a/apps/landing/.eslintrc.js b/apps/landing/.eslintrc.js deleted file mode 100644 index c3b985290..000000000 --- a/apps/landing/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - ...require("@rallly/eslint-config/next")(__dirname), -}; diff --git a/apps/landing/package.json b/apps/landing/package.json index 81782847e..92fd9c65e 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -7,7 +7,6 @@ "build": "next build", "analyze": "cross-env ANALYZE=true next build", "start": "next start", - "lint": "eslint .", "type-check": "tsc --pretty --noEmit", "i18n:scan": "i18next-scanner --config i18next-scanner.config.js" }, @@ -41,7 +40,6 @@ }, "devDependencies": { "@next/bundle-analyzer": "^14.2.25", - "@rallly/eslint-config": "workspace:*", "@rallly/tsconfig": "workspace:*", "@types/color-hash": "^1.0.2", "@types/lodash": "^4.14.178", diff --git a/apps/landing/src/app/[locale]/blog/[slug]/page.tsx b/apps/landing/src/app/[locale]/blog/[slug]/page.tsx index 273bd7207..e174861b2 100644 --- a/apps/landing/src/app/[locale]/blog/[slug]/page.tsx +++ b/apps/landing/src/app/[locale]/blog/[slug]/page.tsx @@ -1,8 +1,8 @@ import { absoluteUrl } from "@rallly/utils/absolute-url"; import { ArrowLeftIcon } from "lucide-react"; +import { MDXRemote } from "next-mdx-remote/rsc"; import Image from "next/image"; import Link from "next/link"; -import { MDXRemote } from "next-mdx-remote/rsc"; import PostHeader from "@/components/blog/post-header"; import { getAllPosts, getPostBySlug } from "@/lib/api"; diff --git a/apps/landing/src/app/[locale]/footer.tsx b/apps/landing/src/app/[locale]/footer.tsx index 450ee6bc0..a4e84d14b 100644 --- a/apps/landing/src/app/[locale]/footer.tsx +++ b/apps/landing/src/app/[locale]/footer.tsx @@ -13,7 +13,7 @@ import { LanguagesIcon } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; import { usePathname, useRouter } from "next/navigation"; -import * as React from "react"; +import type * as React from "react"; import DiscordIcon from "@/assets/discord.svg"; import GithubIcon from "@/assets/github.svg"; @@ -301,6 +301,7 @@ export const Footer: React.FunctionComponent = () => { target="_blank" href="https://vercel.com?utm_source=rallly&utm_campaign=oss" className="inline-block text-white" + rel="noreferrer" > { target="_blank" className="inline-block" href="/partners/digitalocean" + rel="noreferrer" > { target="_blank" className="inline-block" href="https://sentry.io" + rel="noreferrer" > -
-
-
- Rallly -
- Blog -
+
+
+
+
+ Rallly +
+ Blog
-

- {title} -

- {excerpt ? ( -

{excerpt}

- ) : null}
+

+ {title} +

+ {excerpt ? ( +

{excerpt}

+ ) : null}
- ), +
, { width: 1200, height: 630, diff --git a/apps/landing/src/components/blog/post-body.tsx b/apps/landing/src/components/blog/post-body.tsx index c913e7772..4c4d43339 100644 --- a/apps/landing/src/components/blog/post-body.tsx +++ b/apps/landing/src/components/blog/post-body.tsx @@ -7,7 +7,8 @@ type Props = { const PostBody = ({ content }: Props) => { return (
); diff --git a/apps/landing/src/components/error-page.tsx b/apps/landing/src/components/error-page.tsx index 86ad294f2..f8ccb7559 100644 --- a/apps/landing/src/components/error-page.tsx +++ b/apps/landing/src/components/error-page.tsx @@ -3,7 +3,7 @@ import { Button } from "@rallly/ui/button"; import { FileSearchIcon } from "lucide-react"; import Link from "next/link"; -import * as React from "react"; +import type * as React from "react"; import { useTranslation } from "@/i18n/client/use-translation"; diff --git a/apps/landing/src/components/marketing.tsx b/apps/landing/src/components/marketing.tsx index ac843bea7..1f7ac8cac 100644 --- a/apps/landing/src/components/marketing.tsx +++ b/apps/landing/src/components/marketing.tsx @@ -3,7 +3,7 @@ import { ArrowUpRight } from "lucide-react"; import * as m from "motion/react-m"; import Image from "next/image"; import Link from "next/link"; -import React from "react"; +import type React from "react"; import { Trans } from "@/i18n/client/trans"; diff --git a/apps/landing/src/i18n/client/i18n-provider.tsx b/apps/landing/src/i18n/client/i18n-provider.tsx index b60784e30..be14e9d54 100644 --- a/apps/landing/src/i18n/client/i18n-provider.tsx +++ b/apps/landing/src/i18n/client/i18n-provider.tsx @@ -2,7 +2,7 @@ import i18next from "i18next"; import ICU from "i18next-icu"; import resourcesToBackend from "i18next-resources-to-backend"; -import React from "react"; +import type React from "react"; import { I18nextProvider, initReactI18next } from "react-i18next"; import { useAsync } from "react-use"; diff --git a/apps/landing/src/lib/api.ts b/apps/landing/src/lib/api.ts index cc43534a2..acf8fdaad 100644 --- a/apps/landing/src/lib/api.ts +++ b/apps/landing/src/lib/api.ts @@ -1,6 +1,6 @@ -import fs from "fs"; +import fs from "node:fs"; +import { join } from "node:path"; import matter from "gray-matter"; -import { join } from "path"; const postsDirectory = join(process.cwd(), "src", "posts"); @@ -21,6 +21,7 @@ export function getPostBySlug(slug: string, fields: string[] = []) { const items: Items = {}; // Ensure only the minimal needed data is exposed + // biome-ignore lint/complexity/noForEach: Fix this later fields.forEach((field) => { if (field === "slug") { items[field] = realSlug; diff --git a/apps/web/.eslintrc.js b/apps/web/.eslintrc.js deleted file mode 100644 index c3b985290..000000000 --- a/apps/web/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("eslint").Linter.Config} */ -module.exports = { - ...require("@rallly/eslint-config/next")(__dirname), -}; diff --git a/apps/web/declarations/next-auth.d.ts b/apps/web/declarations/next-auth.d.ts index facea5619..366f2fe83 100644 --- a/apps/web/declarations/next-auth.d.ts +++ b/apps/web/declarations/next-auth.d.ts @@ -1,10 +1,9 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ import type { TimeFormat } from "@rallly/database"; -import type { NextRequest } from "next/server"; import type { DefaultSession, DefaultUser } from "next-auth"; import NextAuth from "next-auth"; import type { DefaultJWT } from "next-auth/jwt"; import { JWT } from "next-auth/jwt"; +import type { NextRequest } from "next/server"; declare module "next-auth" { /** diff --git a/apps/web/next-i18next.config.js b/apps/web/next-i18next.config.js index 8423aef44..46c9b0c51 100644 --- a/apps/web/next-i18next.config.js +++ b/apps/web/next-i18next.config.js @@ -1,5 +1,5 @@ const ICU = require("i18next-icu/i18nextICU.js"); -const path = require("path"); +const path = require("node:path"); const i18n = require("./i18n.config.js"); module.exports = { diff --git a/apps/web/next.config.js b/apps/web/next.config.js index f9475605b..2af869c62 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -28,9 +28,6 @@ const nextConfig = { return config; }, - eslint: { - ignoreDuringBuilds: true, - }, typescript: { ignoreBuildErrors: true, }, diff --git a/apps/web/package.json b/apps/web/package.json index 684669cd3..afdf919fa 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -8,7 +8,6 @@ "build:test": "NODE_ENV=test next build", "analyze": "cross-env ANALYZE=true next build", "start": "next start", - "lint": "eslint .", "type-check": "tsc --pretty --noEmit", "i18n:scan": "i18next-scanner --config i18next-scanner.config.js", "test:integration": "NODE_ENV=test playwright test", @@ -96,7 +95,6 @@ "devDependencies": { "@babel/core": "^7.26.10", "@playwright/test": "^1.49.1", - "@rallly/eslint-config": "workspace:*", "@rallly/tsconfig": "workspace:*", "@types/color-hash": "^1.0.2", "@types/js-cookie": "^3.0.1", diff --git a/apps/web/src/app/[locale]/(auth)/layout.tsx b/apps/web/src/app/[locale]/(auth)/layout.tsx index 940d6702d..989ae6acb 100644 --- a/apps/web/src/app/[locale]/(auth)/layout.tsx +++ b/apps/web/src/app/[locale]/(auth)/layout.tsx @@ -2,9 +2,9 @@ import { cn } from "@rallly/ui"; import { DotPattern } from "@rallly/ui/dot-pattern"; import { - isQuickCreateEnabled, QuickCreateButton, QuickCreateWidget, + isQuickCreateEnabled, } from "@/features/quick-create"; export default async function Layout({ diff --git a/apps/web/src/app/[locale]/(auth)/login/components/login-email-form.tsx b/apps/web/src/app/[locale]/(auth)/login/components/login-email-form.tsx index 5c8a26920..3a41369fe 100644 --- a/apps/web/src/app/[locale]/(auth)/login/components/login-email-form.tsx +++ b/apps/web/src/app/[locale]/(auth)/login/components/login-email-form.tsx @@ -10,8 +10,8 @@ import { FormMessage, } from "@rallly/ui/form"; import { Input } from "@rallly/ui/input"; -import { useRouter, useSearchParams } from "next/navigation"; import { signIn } from "next-auth/react"; +import { useRouter, useSearchParams } from "next/navigation"; import React from "react"; import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; diff --git a/apps/web/src/app/[locale]/(auth)/login/components/sso-provider.tsx b/apps/web/src/app/[locale]/(auth)/login/components/sso-provider.tsx index 7c7c3e84c..8c7b841fb 100644 --- a/apps/web/src/app/[locale]/(auth)/login/components/sso-provider.tsx +++ b/apps/web/src/app/[locale]/(auth)/login/components/sso-provider.tsx @@ -2,8 +2,8 @@ import { Button } from "@rallly/ui/button"; import { Icon } from "@rallly/ui/icon"; import { UserIcon } from "lucide-react"; -import Image from "next/image"; import { signIn } from "next-auth/react"; +import Image from "next/image"; import { Trans } from "@/components/trans"; import { useTranslation } from "@/i18n/client"; diff --git a/apps/web/src/app/[locale]/(auth)/register/verify/components/otp-form.tsx b/apps/web/src/app/[locale]/(auth)/register/verify/components/otp-form.tsx index eec3725a9..a6f326b7b 100644 --- a/apps/web/src/app/[locale]/(auth)/register/verify/components/otp-form.tsx +++ b/apps/web/src/app/[locale]/(auth)/register/verify/components/otp-form.tsx @@ -10,8 +10,8 @@ import { FormItem, FormMessage, } from "@rallly/ui/form"; -import { useSearchParams } from "next/navigation"; import { signIn } from "next-auth/react"; +import { useSearchParams } from "next/navigation"; import { useForm } from "react-hook-form"; import { z } from "zod"; diff --git a/apps/web/src/app/[locale]/(space)/app-card.tsx b/apps/web/src/app/[locale]/(space)/app-card.tsx index ad754bc54..89c62cc7e 100644 --- a/apps/web/src/app/[locale]/(space)/app-card.tsx +++ b/apps/web/src/app/[locale]/(space)/app-card.tsx @@ -1,6 +1,6 @@ import { cn } from "@rallly/ui"; import { BarChart2Icon } from "lucide-react"; -import React from "react"; +import type React from "react"; export function AppCard({ children, diff --git a/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar.tsx b/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar.tsx index 3dddf7a04..89fc84139 100644 --- a/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar.tsx +++ b/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar.tsx @@ -18,7 +18,7 @@ import { SparklesIcon, } from "lucide-react"; import Link from "next/link"; -import * as React from "react"; +import type * as React from "react"; import { LogoLink } from "@/app/components/logo-link"; import { Trans } from "@/components/trans"; diff --git a/apps/web/src/app/[locale]/(space)/events/events-tabbed-view.tsx b/apps/web/src/app/[locale]/(space)/events/events-tabbed-view.tsx index 65a7cc4e4..24cb4014f 100644 --- a/apps/web/src/app/[locale]/(space)/events/events-tabbed-view.tsx +++ b/apps/web/src/app/[locale]/(space)/events/events-tabbed-view.tsx @@ -19,7 +19,7 @@ export function EventsTabbedView({ children }: { children: React.ReactNode }) { const newUrl = `?${params.toString()}`; router.replace(newUrl, { scroll: false }); }, - [name, router, searchParams], + [router, searchParams], ); const value = searchParams.get(name) ?? "upcoming"; diff --git a/apps/web/src/app/[locale]/(space)/polls/page.tsx b/apps/web/src/app/[locale]/(space)/polls/page.tsx index 70846990a..000e3d745 100644 --- a/apps/web/src/app/[locale]/(space)/polls/page.tsx +++ b/apps/web/src/app/[locale]/(space)/polls/page.tsx @@ -37,8 +37,8 @@ const pageSchema = z .nullish() .transform((val) => { if (!val) return 1; - const parsed = parseInt(val, 10); - return isNaN(parsed) || parsed < 1 ? 1 : parsed; + const parsed = Number.parseInt(val, 10); + return Number.isNaN(parsed) || parsed < 1 ? 1 : parsed; }); const querySchema = z @@ -56,8 +56,8 @@ const pageSizeSchema = z .nullish() .transform((val) => { if (!val) return DEFAULT_PAGE_SIZE; - const parsed = parseInt(val, 10); - return isNaN(parsed) || parsed < 1 + const parsed = Number.parseInt(val, 10); + return Number.isNaN(parsed) || parsed < 1 ? DEFAULT_PAGE_SIZE : Math.min(parsed, 100); }); diff --git a/apps/web/src/app/[locale]/(space)/polls/polls-tabbed-view.tsx b/apps/web/src/app/[locale]/(space)/polls/polls-tabbed-view.tsx index 761c74a09..1dcd52944 100644 --- a/apps/web/src/app/[locale]/(space)/polls/polls-tabbed-view.tsx +++ b/apps/web/src/app/[locale]/(space)/polls/polls-tabbed-view.tsx @@ -19,7 +19,7 @@ export function PollsTabbedView({ children }: { children: React.ReactNode }) { const newUrl = `?${params.toString()}`; router.replace(newUrl, { scroll: false }); }, - [name, router, searchParams], + [router, searchParams], ); const value = searchParams.get(name) ?? "live"; diff --git a/apps/web/src/app/[locale]/(space)/settings/layout.tsx b/apps/web/src/app/[locale]/(space)/settings/layout.tsx index db6c56f2c..3dd669049 100644 --- a/apps/web/src/app/[locale]/(space)/settings/layout.tsx +++ b/apps/web/src/app/[locale]/(space)/settings/layout.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import type React from "react"; import { SettingsPageIcon } from "@/app/components/page-icons"; import { diff --git a/apps/web/src/app/[locale]/(space)/settings/preferences/components/date-time-preferences.tsx b/apps/web/src/app/[locale]/(space)/settings/preferences/components/date-time-preferences.tsx index 8f57269cf..6ee376f69 100644 --- a/apps/web/src/app/[locale]/(space)/settings/preferences/components/date-time-preferences.tsx +++ b/apps/web/src/app/[locale]/(space)/settings/preferences/components/date-time-preferences.tsx @@ -96,7 +96,7 @@ const DateTimePreferencesForm = () => {