mirror of
https://github.com/lukevella/rallly.git
synced 2025-08-01 23:48:53 +02:00
♻️ Replace eslint and prettier with biome (#1697)
This commit is contained in:
parent
1577a0c5df
commit
a34da49486
158 changed files with 450 additions and 2718 deletions
|
@ -1,2 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config} */
|
||||
module.exports = require("@rallly/eslint-config/preset")(__dirname);
|
|
@ -10,8 +10,7 @@
|
|||
"checkout-expiry": "dotenv -e ../../.env -- tsx ./src/scripts/checkout-expiry.ts",
|
||||
"subscription-data-sync": "dotenv -e ../../.env -- tsx ./src/scripts/subscription-data-sync.ts",
|
||||
"sync-payment-methods": "dotenv -e ../../.env -- tsx ./src/scripts/sync-payment-methods.ts",
|
||||
"type-check": "tsc --pretty --noEmit",
|
||||
"lint": "eslint ./src"
|
||||
"type-check": "tsc --pretty --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-radio-group": "^1.2.3",
|
||||
|
@ -20,7 +19,6 @@
|
|||
"stripe": "^13.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rallly/eslint-config": "workspace:*",
|
||||
"@rallly/tsconfig": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config} */
|
||||
module.exports = {
|
||||
...require("@rallly/eslint-config")(__dirname),
|
||||
};
|
|
@ -8,6 +8,7 @@ const prismaClientSingleton = () => {
|
|||
|
||||
export type ExtendedPrismaClient = ReturnType<typeof prismaClientSingleton>;
|
||||
|
||||
// biome-ignore lint/suspicious/noShadowRestrictedNames: Fix this later
|
||||
declare const globalThis: {
|
||||
prismaGlobal: ExtendedPrismaClient;
|
||||
} & typeof global;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@rallly/eslint-config": "workspace:*",
|
||||
"@rallly/tsconfig": "workspace:*",
|
||||
"@types/node": "^18.19.41",
|
||||
"prisma": "^6.4.1",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { faker } from "@faker-js/faker";
|
||||
import type { User } from "@prisma/client";
|
||||
import { VoteType } from "@prisma/client";
|
||||
import dayjs from "dayjs";
|
||||
import type { VoteType } from "@prisma/client";
|
||||
import { prisma } from "@rallly/database";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { randInt } from "./utils";
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { ScheduledEventInviteStatus } from "@prisma/client";
|
||||
import { Prisma, ScheduledEventStatus } from "@prisma/client"; // Ensure Prisma is imported
|
||||
import dayjs from "dayjs";
|
||||
import { faker } from "@faker-js/faker";
|
||||
import type { ScheduledEventInviteStatus } from "@prisma/client";
|
||||
import { type Prisma, ScheduledEventStatus } from "@prisma/client"; // Ensure Prisma is imported
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { prisma } from "@rallly/database";
|
||||
import { randInt } from "./utils";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import dayjs from "dayjs";
|
||||
import { prisma } from "@rallly/database";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export async function seedUsers() {
|
||||
console.info("Seeding users...");
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config} */
|
||||
module.exports = require("@rallly/eslint-config/preset")(__dirname);
|
|
@ -4,7 +4,6 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "email dev --port 3333 --dir ./src/previews",
|
||||
"lint": "eslint ./src",
|
||||
"type-check": "tsc --pretty --noEmit",
|
||||
"i18n:scan": "i18next-scanner --config i18next-scanner.config.js"
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
import { Trans } from "react-i18next/TransWithoutContext";
|
||||
|
||||
import type { EmailContext } from "../types";
|
||||
import { darkTextColor, fontFamily, Link, Text } from "./styled-components";
|
||||
import { Link, Text, darkTextColor, fontFamily } from "./styled-components";
|
||||
|
||||
export interface EmailLayoutProps {
|
||||
preview: string;
|
||||
|
|
|
@ -97,7 +97,7 @@ export class EmailClient {
|
|||
const subject = Template.getSubject?.(options.props, ctx);
|
||||
const component = (
|
||||
<Template
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Fix this later
|
||||
{...(options.props as any)}
|
||||
ctx={ctx}
|
||||
/>
|
||||
|
@ -134,7 +134,7 @@ export class EmailClient {
|
|||
}
|
||||
|
||||
async sendEmail(options: Mail.Options) {
|
||||
if (!process.env["SUPPORT_EMAIL"]) {
|
||||
if (!process.env.SUPPORT_EMAIL) {
|
||||
console.info("ℹ SUPPORT_EMAIL not configured - skipping email send");
|
||||
return;
|
||||
}
|
||||
|
@ -170,21 +170,21 @@ export class EmailClient {
|
|||
break;
|
||||
}
|
||||
case "smtp": {
|
||||
const hasAuth = process.env["SMTP_USER"] || process.env["SMTP_PWD"];
|
||||
const hasAuth = process.env.SMTP_USER || process.env.SMTP_PWD;
|
||||
this.cachedTransport = createTransport({
|
||||
host: process.env["SMTP_HOST"],
|
||||
port: process.env["SMTP_PORT"]
|
||||
? parseInt(process.env["SMTP_PORT"])
|
||||
host: process.env.SMTP_HOST,
|
||||
port: process.env.SMTP_PORT
|
||||
? Number.parseInt(process.env.SMTP_PORT)
|
||||
: undefined,
|
||||
secure: process.env["SMTP_SECURE"] === "true",
|
||||
secure: process.env.SMTP_SECURE === "true",
|
||||
auth: hasAuth
|
||||
? {
|
||||
user: process.env["SMTP_USER"],
|
||||
pass: process.env["SMTP_PWD"],
|
||||
user: process.env.SMTP_USER,
|
||||
pass: process.env.SMTP_PWD,
|
||||
}
|
||||
: undefined,
|
||||
tls: {
|
||||
rejectUnauthorized: process.env["SMTP_TLS_ENABLED"] === "true",
|
||||
rejectUnauthorized: process.env.SMTP_TLS_ENABLED === "true",
|
||||
},
|
||||
});
|
||||
break;
|
||||
|
|
|
@ -133,14 +133,11 @@ AbandonedCheckoutEmail.getSubject = (
|
|||
props: AbandonedCheckoutEmailProps,
|
||||
ctx: EmailContext,
|
||||
) => {
|
||||
return (
|
||||
"🎉 " +
|
||||
ctx.t("abandoned_checkout_subject", {
|
||||
defaultValue: "Get {{discount}}% off your first year of Rallly Pro",
|
||||
discount: props.discount,
|
||||
ns: "emails",
|
||||
})
|
||||
);
|
||||
return `🎉 ${ctx.t("abandoned_checkout_subject", {
|
||||
defaultValue: "Get {{discount}}% off your first year of Rallly Pro",
|
||||
discount: props.discount,
|
||||
ns: "emails",
|
||||
})}`;
|
||||
};
|
||||
|
||||
export default AbandonedCheckoutEmail;
|
||||
|
|
|
@ -3,10 +3,10 @@ import { Trans } from "react-i18next/TransWithoutContext";
|
|||
|
||||
import { EmailLayout } from "../components/email-layout";
|
||||
import {
|
||||
borderColor,
|
||||
Button,
|
||||
Heading,
|
||||
Text,
|
||||
borderColor,
|
||||
} from "../components/styled-components";
|
||||
import type { EmailContext } from "../types";
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ import { Trans } from "react-i18next/TransWithoutContext";
|
|||
|
||||
import { EmailLayout } from "../components/email-layout";
|
||||
import {
|
||||
borderColor,
|
||||
Button,
|
||||
Heading,
|
||||
Text,
|
||||
borderColor,
|
||||
} from "../components/styled-components";
|
||||
import type { EmailContext } from "../types";
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config} */
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: ["turbo"],
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
const preset = require("./preset");
|
||||
|
||||
/** @return {import("eslint").Linter.Config} */
|
||||
module.exports = function (workspaceDirPath) {
|
||||
const baseConfig = preset(workspaceDirPath);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
extends: [...baseConfig.extends, "next"],
|
||||
};
|
||||
};
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"name": "@rallly/eslint-config",
|
||||
"version": "0.0.0",
|
||||
"exports": {
|
||||
"./*": "./*.js"
|
||||
},
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
||||
"@typescript-eslint/parser": "^8.28.0",
|
||||
"eslint-config-next": "^14.0.1",
|
||||
"eslint-config-turbo": "^2.0.3",
|
||||
"eslint-import-resolver-typescript": "^2.7.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-react": "^7.23.2",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0"
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/** @return {import("eslint").Linter.Config} */
|
||||
module.exports = function (workspaceDirPath) {
|
||||
return {
|
||||
root: true,
|
||||
extends: ["turbo"],
|
||||
plugins: [
|
||||
"eslint-plugin-import",
|
||||
"simple-import-sort",
|
||||
"@typescript-eslint",
|
||||
],
|
||||
env: {
|
||||
es6: true,
|
||||
},
|
||||
ignorePatterns: ["dist/", "playwright-report/"],
|
||||
globals: {
|
||||
React: true,
|
||||
JSX: true,
|
||||
},
|
||||
parserOptions: {
|
||||
tsconfigRootDir: workspaceDirPath,
|
||||
project: workspaceDirPath + "/tsconfig.json",
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/*.ts", "**/*.tsx"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
extends: ["plugin:@typescript-eslint/recommended"],
|
||||
rules: {
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/consistent-type-imports": [
|
||||
"error",
|
||||
{
|
||||
prefer: "type-imports",
|
||||
fixStyle: "separate-type-imports",
|
||||
disallowTypeAnnotations: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
"import/first": "error",
|
||||
"import/newline-after-import": "error",
|
||||
"import/no-duplicates": "error",
|
||||
"no-console": ["error", { allow: ["warn", "error", "info"] }],
|
||||
"no-unused-vars": "error",
|
||||
},
|
||||
};
|
||||
};
|
20
packages/eslint-config/react.js
vendored
20
packages/eslint-config/react.js
vendored
|
@ -1,20 +0,0 @@
|
|||
const preset = require("./preset");
|
||||
|
||||
/** @return {import("eslint").Linter.Config} */
|
||||
module.exports = function (workspaceDirPath) {
|
||||
const baseConfig = preset(workspaceDirPath);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
extends: [
|
||||
...baseConfig.extends,
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
import languages, { defaultLocale } from "./index";
|
||||
import Negotiator from "negotiator";
|
||||
import { match } from "@formatjs/intl-localematcher";
|
||||
import Negotiator from "negotiator";
|
||||
import languages, { defaultLocale } from "./index";
|
||||
|
||||
const locales = Object.keys(languages);
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config} */
|
||||
module.exports = require("@rallly/eslint-config/preset")(__dirname);
|
|
@ -8,7 +8,6 @@
|
|||
"./utils": "./src/utils.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint ./src",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -17,7 +16,6 @@
|
|||
"posthog-node": "^4.10.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rallly/eslint-config": "workspace:*",
|
||||
"@rallly/tsconfig": "workspace:*",
|
||||
"@types/js-cookie": "^3.0.1"
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config} */
|
||||
module.exports = require("@rallly/eslint-config/preset")(__dirname);
|
|
@ -6,7 +6,6 @@
|
|||
"types": "src/index.ts",
|
||||
"scripts": {
|
||||
"ui:add": "npx shadcn-ui@latest add",
|
||||
"lint": "eslint .",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"exports": {
|
||||
|
@ -46,7 +45,6 @@
|
|||
"tailwind-merge": "^1.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rallly/eslint-config": "workspace:*",
|
||||
"@rallly/tsconfig": "workspace:*",
|
||||
"@types/react": "^18.2.0",
|
||||
"@types/react-dom": "^18.2.0"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { type VariantProps, cva } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "./lib/utils";
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ const BreadcrumbPage = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<span
|
||||
ref={ref}
|
||||
role="link"
|
||||
aria-disabled="true"
|
||||
aria-current="page"
|
||||
className={cn("text-foreground font-normal", className)}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type React from "react";
|
||||
|
||||
type ComponentPropsAs<
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Fix this later
|
||||
C extends React.ElementType<any>,
|
||||
T extends React.ComponentPropsWithoutRef<C>["as"],
|
||||
> = Omit<
|
||||
|
|
|
@ -91,6 +91,7 @@ export const reducer = (state: State, action: Action): State => {
|
|||
if (toastId) {
|
||||
addToRemoveQueue(toastId);
|
||||
} else {
|
||||
// biome-ignore lint/complexity/noForEach: Fix this later
|
||||
state.toasts.forEach((toast) => {
|
||||
addToRemoveQueue(toast.id);
|
||||
});
|
||||
|
@ -128,6 +129,7 @@ let memoryState: State = { toasts: [] };
|
|||
|
||||
function dispatch(action: Action) {
|
||||
memoryState = reducer(memoryState, action);
|
||||
// biome-ignore lint/complexity/noForEach: Fix this later
|
||||
listeners.forEach((listener) => {
|
||||
listener(memoryState);
|
||||
});
|
||||
|
@ -167,6 +169,7 @@ function toast({ ...props }: Toast) {
|
|||
function useToast() {
|
||||
const [state, setState] = React.useState<State>(memoryState);
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: I think this needs to be here
|
||||
React.useEffect(() => {
|
||||
listeners.push(setState);
|
||||
return () => {
|
||||
|
|
|
@ -102,7 +102,7 @@ const SidebarProvider = React.forwardRef<
|
|||
return isMobile
|
||||
? setOpenMobile((open) => !open)
|
||||
: setOpen((open) => !open);
|
||||
}, [isMobile, setOpen, setOpenMobile]);
|
||||
}, [isMobile, setOpen]);
|
||||
|
||||
// Adds a keyboard shortcut to toggle the sidebar.
|
||||
React.useEffect(() => {
|
||||
|
@ -134,15 +134,7 @@ const SidebarProvider = React.forwardRef<
|
|||
setOpenMobile,
|
||||
toggleSidebar,
|
||||
}),
|
||||
[
|
||||
state,
|
||||
open,
|
||||
setOpen,
|
||||
isMobile,
|
||||
openMobile,
|
||||
setOpenMobile,
|
||||
toggleSidebar,
|
||||
],
|
||||
[state, open, setOpen, isMobile, openMobile, toggleSidebar],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { cn } from "./lib/utils"
|
||||
import { cn } from "./lib/utils";
|
||||
|
||||
function Skeleton({
|
||||
className,
|
||||
|
@ -9,7 +9,7 @@ function Skeleton({
|
|||
className={cn("animate-pulse rounded-md bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { Skeleton }
|
||||
export { Skeleton };
|
||||
|
|
|
@ -14,20 +14,16 @@ export function Toaster() {
|
|||
|
||||
return (
|
||||
<ToastProvider duration={2000}>
|
||||
{toasts.map(function ({ id, title, description, action, ...props }) {
|
||||
return (
|
||||
<Toast key={id} {...props}>
|
||||
<div className="grid gap-1">
|
||||
{title && <ToastTitle>{title}</ToastTitle>}
|
||||
{description && (
|
||||
<ToastDescription>{description}</ToastDescription>
|
||||
)}
|
||||
</div>
|
||||
{action}
|
||||
<ToastClose />
|
||||
</Toast>
|
||||
);
|
||||
})}
|
||||
{toasts.map(({ id, title, description, action, ...props }) => (
|
||||
<Toast key={id} {...props}>
|
||||
<div className="grid gap-1">
|
||||
{title && <ToastTitle>{title}</ToastTitle>}
|
||||
{description && <ToastDescription>{description}</ToastDescription>}
|
||||
</div>
|
||||
{action}
|
||||
<ToastClose />
|
||||
</Toast>
|
||||
))}
|
||||
<ToastViewport />
|
||||
</ToastProvider>
|
||||
);
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/** @type {import("eslint").Linter.Config} */
|
||||
module.exports = require("@rallly/eslint-config/preset")(__dirname);
|
|
@ -4,7 +4,6 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"test:unit": "vitest run",
|
||||
"lint": "eslint ./src",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"exports": {
|
||||
|
|
|
@ -7,6 +7,7 @@ describe("absoluteUrl", () => {
|
|||
});
|
||||
|
||||
afterAll(() => {
|
||||
// biome-ignore lint/performance/noDelete: Setting to undefined doesn't work
|
||||
delete process.env.NEXT_PUBLIC_BASE_URL;
|
||||
});
|
||||
|
||||
|
@ -37,10 +38,6 @@ describe("absoluteUrl", () => {
|
|||
process.env.NEXT_PUBLIC_VERCEL_URL = "example.vercel.com";
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
delete process.env.NEXT_PUBLIC_VERCEL_URL;
|
||||
});
|
||||
|
||||
it("should return the correct absolute URL with a subpath and query params", () => {
|
||||
expect(absoluteUrl("/test", { test: "test" })).toBe(
|
||||
"https://example.vercel.com/test?test=test",
|
||||
|
|
|
@ -23,6 +23,7 @@ export function absoluteUrl(subpath = "", query: Record<string, string> = {}) {
|
|||
|
||||
const url = new URL(subpath, baseUrl);
|
||||
|
||||
// biome-ignore lint/complexity/noForEach: Fix this later
|
||||
Object.entries(query).forEach(([key, value]) => {
|
||||
url.searchParams.set(key, value);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import path from "path";
|
||||
import path from "node:path";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue