diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 36f30a9c..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - root: true, - // This tells ESLint to load the config from the package `eslint-config-custom` - extends: ["custom"], - settings: { - next: { - rootDir: ["apps/*/"], - }, - }, - rules: { - eqeqeq: ["error", "smart"], - }, -}; diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 451f0854..00000000 --- a/.prettierrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "singleQuote": false, - "trailingComma": "es5", - "printWidth": 100 - } \ No newline at end of file diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index d82b78e3..00000000 --- a/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -nodejs 16.19.0 diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e400bd48..bdef8201 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,3 @@ { - "recommendations": [ - "svelte.svelte-vscode" - ] -} \ No newline at end of file + "recommendations": ["svelte.svelte-vscode"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 29519146..e63244be 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,8 +4,6 @@ "editor.defaultFormatter": "svelte.svelte-vscode" }, "[typescript][typescriptreact][typescriptangular]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "eslint.workingDirectories": ["apps", "packages"], - "prettier.enable": true + "editor.defaultFormatter": "biomejs.biome" + } } diff --git a/apps/cdn/src/index.ts b/apps/cdn/src/index.ts index c2eebb28..90e9b769 100644 --- a/apps/cdn/src/index.ts +++ b/apps/cdn/src/index.ts @@ -1,10 +1,10 @@ +import { ABBY_WINDOW_KEY, type AbbyDataResponse } from "@tryabby/core"; import { Hono } from "hono"; import { ZoneCache } from "./lib/cache"; -import { ABBY_WINDOW_KEY, AbbyDataResponse } from "@tryabby/core"; import { cors } from "hono/cors"; -import { timing } from "hono/timing"; import { logger } from "hono/logger"; +import { timing } from "hono/timing"; import { ConfigService } from "./lib/config"; const cache = new ZoneCache<{ diff --git a/apps/cdn/src/lib/cache.ts b/apps/cdn/src/lib/cache.ts index 705adfa4..085fd566 100644 --- a/apps/cdn/src/lib/cache.ts +++ b/apps/cdn/src/lib/cache.ts @@ -45,12 +45,16 @@ export class ZoneCache> { } public async get( - c: Context, + _c: Context, namespace: TName, key: string - ): Promise<[TNamespaces[TName] | undefined, "stale" | "hit" | "miss" | "error"]> { + ): Promise< + [TNamespaces[TName] | undefined, "stale" | "hit" | "miss" | "error"] + > { try { - const res = await caches.default.match(new Request(this.createCacheKey(namespace, key))); + const res = await caches.default.match( + new Request(this.createCacheKey(namespace, key)) + ); if (!res) { return [undefined, "miss"]; } @@ -76,7 +80,7 @@ export class ZoneCache> { const res = new Response(JSON.stringify(entry), { headers: { "Content-Type": "application/json", - "Cache-Control": `public, s-maxage=60`, + "Cache-Control": "public, s-maxage=60", }, }); diff --git a/apps/cdn/src/lib/config.ts b/apps/cdn/src/lib/config.ts index 06555095..3996cfb1 100644 --- a/apps/cdn/src/lib/config.ts +++ b/apps/cdn/src/lib/config.ts @@ -1,8 +1,8 @@ -import { AbbyDataResponse, HttpService } from "@tryabby/core"; +import { type AbbyDataResponse, HttpService } from "@tryabby/core"; -import type { ZoneCache } from "./cache"; -import { Context } from "hono"; +import type { Context } from "hono"; import { endTime, startTime } from "hono/timing"; +import type { ZoneCache } from "./cache"; export class ConfigService { constructor( diff --git a/apps/docs/package.json b/apps/docs/package.json index 6d4695bf..97579dea 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -5,15 +5,12 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "next start", - "lint": "next lint" + "start": "next start" }, "dependencies": { "@types/node": "^18.0.0", "@types/react": "18.0.26", "@types/react-dom": "^18.0.5", - "eslint": "8.29.0", - "eslint-config-next": "13.0.6", "next": "14.1.1", "next-plausible": "^3.11.3", "nextra": "2.13.2", @@ -23,7 +20,6 @@ "typescript": "5.5.4" }, "devDependencies": { - "eslint-config-custom": "workspace:^0.0.0", "tsconfig": "workspace:^0.0.0" } } diff --git a/apps/docs/theme.config.jsx b/apps/docs/theme.config.jsx index 4f35f11e..93ff3b39 100644 --- a/apps/docs/theme.config.jsx +++ b/apps/docs/theme.config.jsx @@ -1,4 +1,3 @@ -/* eslint-disable import/no-anonymous-default-export */ import { useRouter } from "next/router"; export default { diff --git a/apps/web/abby.config.ts b/apps/web/abby.config.ts index d0cf68ec..964949bc 100644 --- a/apps/web/abby.config.ts +++ b/apps/web/abby.config.ts @@ -1,8 +1,8 @@ -/* eslint-disable turbo/no-undeclared-env-vars */ import { defineConfig } from "@tryabby/core"; export default defineConfig( { + // biome-ignore lint/style/noNonNullAssertion:> projectId: process.env.NEXT_PUBLIC_ABBY_PROJECT_ID!, currentEnvironment: process.env.VERCEL_ENV ?? process.env.NODE_ENV, apiUrl: process.env.NEXT_PUBLIC_ABBY_API_URL, diff --git a/apps/web/emails/ContactFormularEmail.tsx b/apps/web/emails/ContactFormularEmail.tsx index dcf5845f..5975b93b 100644 --- a/apps/web/emails/ContactFormularEmail.tsx +++ b/apps/web/emails/ContactFormularEmail.tsx @@ -1,10 +1,8 @@ - import { Container } from "@react-email/container"; import { Head } from "@react-email/head"; import { Html } from "@react-email/html"; import { Preview } from "@react-email/preview"; import { Section } from "@react-email/section"; -import * as React from "react"; import { ABBY_BASE_URL } from "@tryabby/core"; export type Props = { @@ -20,7 +18,7 @@ export default function ContactFormularEmail({ name, message, }: Props) { - const baseUrl = + const _baseUrl = process.env.NODE_ENV === "development" ? "http://localhost:3000/" : ABBY_BASE_URL; @@ -60,11 +58,11 @@ const container = { width: "465px", }; -const logo = { +const _logo = { margin: "0 auto", }; -const h1 = { +const _h1 = { color: "#000", fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", @@ -75,16 +73,16 @@ const h1 = { padding: "0", }; -const avatar = { +const _avatar = { borderRadius: "100%", }; -const link = { +const _link = { color: "#067df7", textDecoration: "none", }; -const text = { +const _text = { color: "#000", fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", @@ -92,15 +90,15 @@ const text = { lineHeight: "24px", }; -const black = { +const _black = { color: "black", }; -const center = { +const _center = { verticalAlign: "middle", }; -const btn = { +const _btn = { backgroundColor: "#000", borderRadius: "5px", color: "#fff", @@ -113,6 +111,6 @@ const btn = { textAlign: "center" as const, }; -const spacing = { +const _spacing = { marginBottom: "26px", }; diff --git a/apps/web/emails/index.tsx b/apps/web/emails/index.tsx index 7976ef34..1c69ed0c 100644 --- a/apps/web/emails/index.tsx +++ b/apps/web/emails/index.tsx @@ -1,10 +1,10 @@ import { render } from "@react-email/render"; import { env } from "env/server.mjs"; import { createTransport } from "nodemailer"; -import InviteEmail, { Props as InviteEmailProps } from "./invite"; import ContactFormularEmail, { - Props as ContactMailProps, + type Props as ContactMailProps, } from "./ContactFormularEmail"; +import InviteEmail, { type Props as InviteEmailProps } from "./invite"; const transporter = createTransport({ pool: true, diff --git a/apps/web/emails/invite.tsx b/apps/web/emails/invite.tsx index 7d1bd503..1f86ff77 100644 --- a/apps/web/emails/invite.tsx +++ b/apps/web/emails/invite.tsx @@ -1,15 +1,12 @@ -import { Project } from "@prisma/client"; +import type { Project } from "@prisma/client"; import { Button } from "@react-email/button"; import { Container } from "@react-email/container"; import { Head } from "@react-email/head"; -import { Hr } from "@react-email/hr"; import { Html } from "@react-email/html"; -import { Img } from "@react-email/img"; import { Link } from "@react-email/link"; import { Preview } from "@react-email/preview"; import { Section } from "@react-email/section"; import { Text } from "@react-email/text"; -import * as React from "react"; import { ABBY_BASE_URL } from "@tryabby/core"; export type Props = { @@ -88,7 +85,7 @@ const container = { width: "465px", }; -const logo = { +const _logo = { margin: "0 auto", }; @@ -103,7 +100,7 @@ const h1 = { padding: "0", }; -const avatar = { +const _avatar = { borderRadius: "100%", }; @@ -120,11 +117,11 @@ const text = { lineHeight: "24px", }; -const black = { +const _black = { color: "black", }; -const center = { +const _center = { verticalAlign: "middle", }; @@ -141,6 +138,6 @@ const btn = { textAlign: "center" as const, }; -const spacing = { +const _spacing = { marginBottom: "26px", }; diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 2a8e79e9..80f6eb07 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -1,8 +1,8 @@ +import { remarkCodeHike } from "@code-hike/mdx"; // @ts-check import bundleAnalzyer from "@next/bundle-analyzer"; -import { withPlausibleProxy } from "next-plausible"; import mdx from "@next/mdx"; -import { remarkCodeHike } from "@code-hike/mdx"; +import { withPlausibleProxy } from "next-plausible"; import theme from "shiki/themes/poimandres.json" assert { type: "json" }; const withMDX = mdx({ diff --git a/apps/web/package.json b/apps/web/package.json index 6582524d..ba8d2ccf 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -9,7 +9,6 @@ "dev": "next dev", "postinstall": "pnpm run db:generate", "db:generate": "prisma generate", - "lint": "next lint", "start": "next start", "seed:events": "ts-node --compiler-options {\\\"module\\\":\\\"CommonJS\\\"} prisma/seedEvents.ts", "db:migrate": "prisma migrate dev", @@ -34,8 +33,6 @@ "@monaco-editor/react": "^4.5.1", "@next-auth/prisma-adapter": "1.0.5", "@next/mdx": "14.0.4", - "@planetscale/database": "^1.11.0", - "@prisma/adapter-planetscale": "5.6.0", "@prisma/client": "5.6.0", "@radix-ui/react-avatar": "^1.0.3", "@radix-ui/react-dialog": "^1.0.5", @@ -118,6 +115,7 @@ "tailwind-merge": "^1.13.1", "tailwindcss-animate": "^1.0.6", "ts-pattern": "^4.2.2", + "vite": "5.4.0", "zod": "^3.21.4", "zustand": "^4.4.1" }, @@ -133,12 +131,8 @@ "@types/prettier": "^2.7.2", "@types/react": "18.0.14", "@types/react-dom": "18.0.05", - "@typescript-eslint/eslint-plugin": "^5.58.0", - "@typescript-eslint/parser": "^5.58.0", "@vitejs/plugin-react": "4.2.1", "autoprefixer": "^10.4.14", - "eslint": "^8.38.0", - "eslint-config-next": "13.0.2", "jsdom": "^20.0.3", "postcss": "^8.4.21", "prettier": "^2.8.7", @@ -149,7 +143,7 @@ "tsconfig-paths": "^4.2.0", "typescript": "5.5.4", "vite-tsconfig-paths": "^4.3.2", - "vitest": "2.0.4" + "vitest": "2.0.5" }, "ct3aMetadata": { "initVersion": "6.11.1" diff --git a/apps/web/prettier.config.cjs b/apps/web/prettier.config.cjs deleted file mode 100644 index 58b0aee2..00000000 --- a/apps/web/prettier.config.cjs +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import("prettier").Config} */ -module.exports = { - plugins: [require.resolve("prettier-plugin-tailwindcss")], -}; diff --git a/apps/web/prisma/generateCoupons.ts b/apps/web/prisma/generateCoupons.ts index 3c487cb5..af1426aa 100644 --- a/apps/web/prisma/generateCoupons.ts +++ b/apps/web/prisma/generateCoupons.ts @@ -1,6 +1,6 @@ -import { PrismaClient } from "@prisma/client"; import fs from "node:fs/promises"; import path from "node:path"; +import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); @@ -10,9 +10,7 @@ async function main() { const fileName = path.join(__dirname, "./coupons.csv"); const items = Array.from({ length: COUPON_CODE_AMOUNT }).map(() => ({ - stripePriceId: - // eslint-disable-next-line turbo/no-undeclared-env-vars - "STARTUP_LIFETIME", + stripePriceId: "STARTUP_LIFETIME", })); const codes = await prisma.$transaction( diff --git a/apps/web/prisma/seedEvents.ts b/apps/web/prisma/seedEvents.ts index 8067be15..0213e92f 100644 --- a/apps/web/prisma/seedEvents.ts +++ b/apps/web/prisma/seedEvents.ts @@ -1,6 +1,6 @@ -import { PrismaClient, Prisma } from "@prisma/client"; +import crypto from "node:crypto"; +import { type Prisma, PrismaClient } from "@prisma/client"; import { AbbyEventType } from "@tryabby/core"; -import crypto from "crypto"; const prisma = new PrismaClient(); @@ -94,7 +94,7 @@ async function main() { testId: footerTest.id, type: AbbyEventType.PING, createdAt: randomDateFromLast30Days(), - } as Prisma.EventCreateManyInput) + }) as Prisma.EventCreateManyInput ), ...Array.from({ length: Math.floor(Math.random() * 200), @@ -105,7 +105,7 @@ async function main() { testId: footerTest.id, type: AbbyEventType.PING, createdAt: randomDateFromLast30Days(), - } as Prisma.EventCreateManyInput) + }) as Prisma.EventCreateManyInput ), ...Array.from({ length: Math.floor(Math.random() * 200), @@ -116,7 +116,7 @@ async function main() { testId: footerTest.id, type: AbbyEventType.ACT, createdAt: randomDateFromLast30Days(), - } as Prisma.EventCreateManyInput) + }) as Prisma.EventCreateManyInput ), ...Array.from({ length: Math.floor(Math.random() * 200), @@ -127,7 +127,7 @@ async function main() { testId: footerTest.id, type: AbbyEventType.ACT, createdAt: randomDateFromLast30Days(), - } as Prisma.EventCreateManyInput) + }) as Prisma.EventCreateManyInput ), ], }); diff --git a/apps/web/src/api/index.ts b/apps/web/src/api/index.ts index ba18b331..ac36ac09 100644 --- a/apps/web/src/api/index.ts +++ b/apps/web/src/api/index.ts @@ -4,8 +4,8 @@ import { Hono } from "hono"; import { cors } from "hono/cors"; import { logger } from "hono/logger"; import { makeHealthRoute } from "./routes/health"; -import { makeEventRoute } from "./routes/v1_event"; import { makeLegacyProjectDataRoute } from "./routes/legacy_project_data"; +import { makeEventRoute } from "./routes/v1_event"; export const app = new Hono() .basePath("/api") diff --git a/apps/web/src/api/routes/legacy_project_data.test.ts b/apps/web/src/api/routes/legacy_project_data.test.ts index 31e11bf7..52c8c7d8 100644 --- a/apps/web/src/api/routes/legacy_project_data.test.ts +++ b/apps/web/src/api/routes/legacy_project_data.test.ts @@ -1,8 +1,13 @@ +import type { + FeatureFlag, + FeatureFlagValue, + Option, + Test, +} from "@prisma/client"; +import type { Decimal } from "@prisma/client/runtime/library"; import { testClient } from "hono/testing"; -import { makeLegacyProjectDataRoute } from "./legacy_project_data"; import { jobManager } from "server/queue/Manager"; -import { FeatureFlag, FeatureFlagValue, Option, Test } from "@prisma/client"; -import { Decimal } from "@prisma/client/runtime/library"; +import { makeLegacyProjectDataRoute } from "./legacy_project_data"; vi.mock("../../env/server.mjs", () => ({ env: {}, @@ -28,7 +33,9 @@ vi.mock("server/db/client", () => ({ id: "", value: "true", }, - ] satisfies Array }>), + ] satisfies Array< + FeatureFlagValue & { flag: Pick } + >), }, test: { findMany: vi.fn().mockResolvedValue([ diff --git a/apps/web/src/api/routes/legacy_project_data.ts b/apps/web/src/api/routes/legacy_project_data.ts index 243b0a77..c42b2398 100644 --- a/apps/web/src/api/routes/legacy_project_data.ts +++ b/apps/web/src/api/routes/legacy_project_data.ts @@ -1,16 +1,16 @@ -import { Context, Hono } from "hono"; +import { type Context, Hono } from "hono"; import { endTime, startTime, timing } from "hono/timing"; import { zValidator } from "@hono/zod-validator"; import { cors } from "hono/cors"; import { prisma } from "server/db/client"; -import { LegacyAbbyDataResponse } from "@tryabby/core"; +import type { LegacyAbbyDataResponse } from "@tryabby/core"; import { transformFlagValue } from "lib/flags"; import createCache from "server/common/memory-cache"; -import { z } from "zod"; import { afterDataRequestQueue } from "server/queue/queues"; +import { z } from "zod"; const configCache = createCache({ name: "legacyConfigCache", diff --git a/apps/web/src/api/routes/v1_config.test.ts b/apps/web/src/api/routes/v1_config.test.ts index d6ae3777..6395d08a 100644 --- a/apps/web/src/api/routes/v1_config.test.ts +++ b/apps/web/src/api/routes/v1_config.test.ts @@ -1,7 +1,7 @@ import { testClient } from "hono/testing"; -import { makeConfigRoute } from "./v1_config"; -import { handleGET, handlePUT } from "server/services/ConfigService"; import { prisma } from "server/db/client"; +import { type handleGET, handlePUT } from "server/services/ConfigService"; +import { makeConfigRoute } from "./v1_config"; vi.mock("../../env/server.mjs", () => ({ env: { diff --git a/apps/web/src/api/routes/v1_config.ts b/apps/web/src/api/routes/v1_config.ts index b8080da3..4840adab 100644 --- a/apps/web/src/api/routes/v1_config.ts +++ b/apps/web/src/api/routes/v1_config.ts @@ -1,10 +1,10 @@ -import { Hono, MiddlewareHandler } from "hono"; import { zValidator } from "@hono/zod-validator"; +import type { ApiKey } from "@prisma/client"; +import { abbyConfigSchema } from "@tryabby/core"; +import { Hono, type MiddlewareHandler } from "hono"; import { prisma } from "server/db/client"; -import { hashString } from "utils/apiKey"; import * as ConfigService from "server/services/ConfigService"; -import { ApiKey } from "@prisma/client"; -import { abbyConfigSchema } from "@tryabby/core"; +import { hashString } from "utils/apiKey"; const apiKeyMiddleware: MiddlewareHandler<{ Variables: { diff --git a/apps/web/src/api/routes/v1_event.test.ts b/apps/web/src/api/routes/v1_event.test.ts index 65b76318..8db1af53 100644 --- a/apps/web/src/api/routes/v1_event.test.ts +++ b/apps/web/src/api/routes/v1_event.test.ts @@ -1,8 +1,8 @@ -import { testClient } from "hono/testing"; -import { makeEventRoute } from "./v1_event"; import { AbbyEventType } from "@tryabby/core"; +import { testClient } from "hono/testing"; import { prisma } from "server/db/client"; import { redis } from "server/db/redis"; +import { makeEventRoute } from "./v1_event"; vi.mock("server/common/plans", () => ({ getLimitByPlan: vi.fn(() => {}), @@ -34,7 +34,7 @@ afterEach(() => { it("should work with correct PING events", async () => { const app = makeEventRoute(); - const res = await testClient(app).index.$post({ + const _res = await testClient(app).index.$post({ json: { projectId: "test", selectedVariant: "test", diff --git a/apps/web/src/api/routes/v1_event.ts b/apps/web/src/api/routes/v1_event.ts index ec41592f..07324a97 100644 --- a/apps/web/src/api/routes/v1_event.ts +++ b/apps/web/src/api/routes/v1_event.ts @@ -1,11 +1,8 @@ import { zValidator } from "@hono/zod-validator"; -import { abbyEventSchema, AbbyEventType } from "@tryabby/core"; +import { abbyEventSchema } from "@tryabby/core"; import { Hono } from "hono"; import isbot from "isbot"; -import { EventService } from "server/services/EventService"; -import { RequestCache } from "server/services/RequestCache"; -import { RequestService } from "server/services/RequestService"; import { checkRateLimit } from "server/common/ratelimit"; import { eventQueue } from "server/queue/queues"; diff --git a/apps/web/src/api/routes/v1_project_data.test.ts b/apps/web/src/api/routes/v1_project_data.test.ts index 158cbeb0..e9085fc4 100644 --- a/apps/web/src/api/routes/v1_project_data.test.ts +++ b/apps/web/src/api/routes/v1_project_data.test.ts @@ -1,8 +1,13 @@ +import type { + FeatureFlag, + FeatureFlagValue, + Option, + Test, +} from "@prisma/client"; +import type { Decimal } from "@prisma/client/runtime/library"; import { testClient } from "hono/testing"; -import { makeProjectDataRoute } from "./v1_project_data"; import { jobManager } from "server/queue/Manager"; -import { FeatureFlag, FeatureFlagValue, Option, Test } from "@prisma/client"; -import { Decimal } from "@prisma/client/runtime/library"; +import { makeProjectDataRoute } from "./v1_project_data"; vi.mock("../../env/server.mjs", () => ({ env: {}, @@ -38,7 +43,9 @@ vi.mock("server/db/client", () => ({ id: "", value: "2", }, - ] satisfies Array }>), + ] satisfies Array< + FeatureFlagValue & { flag: Pick } + >), }, test: { findMany: vi.fn().mockResolvedValue([ diff --git a/apps/web/src/api/routes/v1_project_data.ts b/apps/web/src/api/routes/v1_project_data.ts index 49d4c5f4..ac29565b 100644 --- a/apps/web/src/api/routes/v1_project_data.ts +++ b/apps/web/src/api/routes/v1_project_data.ts @@ -1,13 +1,13 @@ -import { Context, Hono } from "hono"; -import { timing, startTime, endTime } from "hono/timing"; -import { cors } from "hono/cors"; import { zValidator } from "@hono/zod-validator"; -import { prisma } from "server/db/client"; -import { ABBY_WINDOW_KEY, AbbyDataResponse } from "@tryabby/core"; -import { z } from "zod"; +import { ABBY_WINDOW_KEY, type AbbyDataResponse } from "@tryabby/core"; +import { type Context, Hono } from "hono"; +import { cors } from "hono/cors"; +import { endTime, startTime, timing } from "hono/timing"; import { transformFlagValue } from "lib/flags"; import { ConfigCache } from "server/common/config-cache"; +import { prisma } from "server/db/client"; import { afterDataRequestQueue } from "server/queue/queues"; +import { z } from "zod"; export const X_ABBY_CACHE_HEADER = "X-Abby-Cache"; diff --git a/apps/web/src/components/AddABTestModal.tsx b/apps/web/src/components/AddABTestModal.tsx index 488dcf04..454dc009 100644 --- a/apps/web/src/components/AddABTestModal.tsx +++ b/apps/web/src/components/AddABTestModal.tsx @@ -1,16 +1,15 @@ import { TRPCClientError } from "@trpc/client"; import { TRPC_ERROR_CODES_BY_KEY } from "@trpc/server/rpc"; +import { useTracking } from "lib/tracking"; import { useState } from "react"; import { toast } from "react-hot-toast"; -import { PlausibleEvents } from "types/plausible-events"; import { trpc } from "utils/trpc"; import { Modal } from "./Modal"; import { CreateTestSection, DEFAULT_NEW_VARIANT_PREFIX, } from "./Test/CreateTestSection"; -import { useTracking } from "lib/tracking"; type UIVariant = { name: string; weight: number }; @@ -42,6 +41,8 @@ export const AddABTestModal = ({ onClose, isOpen, projectId }: Props) => { const variantsWeightSum = variants .map(({ weight }) => weight) + // biome-ignore lint/suspicious/noAssignInExpressions: + // biome-ignore lint/style/noParameterAssign: .reduce((sum, weight) => (sum += weight), 0); const isConfirmButtonDisabled = diff --git a/apps/web/src/components/AddFeatureFlagModal.tsx b/apps/web/src/components/AddFeatureFlagModal.tsx index 7c1dd212..8187e97a 100644 --- a/apps/web/src/components/AddFeatureFlagModal.tsx +++ b/apps/web/src/components/AddFeatureFlagModal.tsx @@ -91,7 +91,7 @@ export function ChangeFlagForm({ .filter( ([, flagType]) => isRemoteConfig && flagType !== "BOOLEAN" ) - .map(([key, flagType]) => ({ + .map(([_key, flagType]) => ({ label: (
{ - const inputRef = useRef(null); + const _inputRef = useRef(null); const ctx = trpc.useContext(); const stateRef = useRef(); const trackEvent = useTracking(); @@ -235,7 +235,9 @@ export const AddFeatureFlagModal = ({ type: isRemoteConfig ? "STRING" : "BOOLEAN", value: isRemoteConfig ? "" : "false", }} - onChange={(newState) => (stateRef.current = newState)} + onChange={(newState) => { + stateRef.current = newState; + }} canChangeType isRemoteConfig={isRemoteConfig} /> diff --git a/apps/web/src/components/Avatar.tsx b/apps/web/src/components/Avatar.tsx index 2f5c6766..9197ad40 100644 --- a/apps/web/src/components/Avatar.tsx +++ b/apps/web/src/components/Avatar.tsx @@ -1,5 +1,5 @@ import * as RadixAvatar from "@radix-ui/react-avatar"; -import { ComponentProps } from "react"; +import type { ComponentProps } from "react"; import { twMerge } from "tailwind-merge"; function getNameFromEmail(email: string) { diff --git a/apps/web/src/components/BlogLayout.tsx b/apps/web/src/components/BlogLayout.tsx index bb161d21..499f0278 100644 --- a/apps/web/src/components/BlogLayout.tsx +++ b/apps/web/src/components/BlogLayout.tsx @@ -1,10 +1,10 @@ -import type { PostMeta } from "pages/tips-and-insights"; -import { MarketingLayout, MarketingLayoutProps } from "./MarketingLayout"; import dayjs from "dayjs"; +import { NextSeo } from "next-seo"; import Image from "next/image"; -import { SignupButton } from "./SignupButton"; +import type { PostMeta } from "pages/tips-and-insights"; import { Divider } from "./Divider"; -import { NextSeo } from "next-seo"; +import { MarketingLayout, type MarketingLayoutProps } from "./MarketingLayout"; +import { SignupButton } from "./SignupButton"; type Props = Pick & { meta: PostMeta; diff --git a/apps/web/src/components/Button.tsx b/apps/web/src/components/Button.tsx index f9ad580b..3659537d 100644 --- a/apps/web/src/components/Button.tsx +++ b/apps/web/src/components/Button.tsx @@ -1,7 +1,4 @@ -import React, { - type PropsWithChildren, - type ComponentPropsWithoutRef, -} from "react"; +import type React from "react"; import { twMerge } from "tailwind-merge"; interface ButtonProps { diff --git a/apps/web/src/components/CodeSnippet.tsx b/apps/web/src/components/CodeSnippet.tsx index 2a81b82c..d8399d88 100644 --- a/apps/web/src/components/CodeSnippet.tsx +++ b/apps/web/src/components/CodeSnippet.tsx @@ -1,13 +1,13 @@ import clsx from "clsx"; import { useState } from "react"; import toast from "react-hot-toast"; -import { FaAngular, FaCopy, FaReact } from "react-icons/fa"; +import { FaCopy, FaReact } from "react-icons/fa"; import { TbBrandAngular, TbBrandSvelte } from "react-icons/tb"; import { TbBrandNextjs } from "react-icons/tb"; +import { twMerge } from "tailwind-merge"; import type { CodeSnippetData, Integrations } from "utils/snippets"; import { trpc } from "utils/trpc"; import { LoadingSpinner } from "./LoadingSpinner"; -import { twMerge } from "tailwind-merge"; const INTEGRATIONS: Record< Integrations, @@ -62,6 +62,7 @@ export function BaseCodeSnippet(
{Object.entries(INTEGRATIONS).map(([key, { icon: Icon, name }]) => ( + // biome-ignore lint/a11y/useKeyWithClickEvents:>
- + Bold @@ -113,6 +135,7 @@ const MenuBar = ({ editor }: { editor: TipTapEditor | null }) => { - + Align Left @@ -162,6 +187,7 @@ const MenuBar = ({ editor }: { editor: TipTapEditor | null }) => {
- diff --git a/apps/web/src/components/FlagIcon.tsx b/apps/web/src/components/FlagIcon.tsx index bf7fea4c..1bf6bfc8 100644 --- a/apps/web/src/components/FlagIcon.tsx +++ b/apps/web/src/components/FlagIcon.tsx @@ -1,11 +1,5 @@ -import { FeatureFlagType } from "@prisma/client"; -import { - Baseline, - Hash, - LucideProps, - ToggleLeft, - CurlyBraces, -} from "lucide-react"; +import type { FeatureFlagType } from "@prisma/client"; +import { Baseline, CurlyBraces, Hash, ToggleLeft } from "lucide-react"; import { match } from "ts-pattern"; import { Tooltip, TooltipContent, TooltipTrigger } from "./Tooltip"; diff --git a/apps/web/src/components/FlagPage.tsx b/apps/web/src/components/FlagPage.tsx index b4d45c84..6e71a2a2 100644 --- a/apps/web/src/components/FlagPage.tsx +++ b/apps/web/src/components/FlagPage.tsx @@ -1,5 +1,5 @@ -import { FeatureFlagType } from "@prisma/client"; -import { InferQueryResult } from "@trpc/react-query/dist/utils/inferReactQueryProcedure"; +import type { FeatureFlagType } from "@prisma/client"; +import type { InferQueryResult } from "@trpc/react-query/dist/utils/inferReactQueryProcedure"; import { AddFeatureFlagModal } from "components/AddFeatureFlagModal"; import { CreateEnvironmentModal } from "components/CreateEnvironmentModal"; import { @@ -10,9 +10,9 @@ import { } from "components/DropdownMenu"; import { Editor } from "components/Editor"; import { FeatureFlag } from "components/FeatureFlag"; -import { Input } from "components/ui/input"; import { Modal } from "components/Modal"; import { Tooltip, TooltipContent, TooltipTrigger } from "components/Tooltip"; +import { Input } from "components/ui/input"; import { useProjectId } from "lib/hooks/useProjectId"; import { EditIcon, FileEditIcon, TrashIcon } from "lucide-react"; import { useState } from "react"; @@ -20,7 +20,7 @@ import { toast } from "react-hot-toast"; import { AiOutlinePlus } from "react-icons/ai"; import { BiInfoCircle } from "react-icons/bi"; import { BsThreeDotsVertical } from "react-icons/bs"; -import { appRouter } from "server/trpc/router/_app"; +import type { appRouter } from "server/trpc/router/_app"; import { trpc } from "utils/trpc"; import { Button } from "./ui/button"; @@ -242,7 +242,7 @@ export const FeatureFlagPageContent = ({ - @@ -256,6 +256,7 @@ export const FeatureFlagPageContent = ({

Description:

Integrations - React - Next.js - Svelte - Angular + React + Next.js + Svelte + Angular

Links

- Blog + Blog Documentation Github Discord diff --git a/apps/web/src/components/Integrations.tsx b/apps/web/src/components/Integrations.tsx index e65d678f..9d35bc00 100644 --- a/apps/web/src/components/Integrations.tsx +++ b/apps/web/src/components/Integrations.tsx @@ -100,8 +100,8 @@ export const Integrations = () => { (integration, index) => index === currentIntegrationIndex && ( {
{INTEGRATIONS.map((integration, index) => ( -
+
diff --git a/apps/web/src/components/Test/Serves.tsx b/apps/web/src/components/Test/Serves.tsx index 8934cf37..9deefd6f 100644 --- a/apps/web/src/components/Test/Serves.tsx +++ b/apps/web/src/components/Test/Serves.tsx @@ -1,13 +1,13 @@ -import { Event } from "@prisma/client"; +import type { Event } from "@prisma/client"; import { - Chart as ChartJS, BarElement, CategoryScale, + Chart as ChartJS, + type ChartOptions, Legend, LinearScale, Title, Tooltip, - ChartOptions, } from "chart.js"; import { useMemo } from "react"; import { Bar } from "react-chartjs-2"; @@ -40,7 +40,7 @@ export const OPTIONS: ChartOptions<"bar"> = { }, tooltip: { callbacks: { - label: function (context) { + label: (context) => { let label = context.dataset.label || ""; if (label) { @@ -88,7 +88,7 @@ const Serves = ({ { label: "Target", data: options.map( - (option) => parseFloat(option.chance.toString()) * 100 + (option) => Number.parseFloat(option.chance.toString()) * 100 ), backgroundColor: "#A9E4EF", }, diff --git a/apps/web/src/components/Test/Weights.tsx b/apps/web/src/components/Test/Weights.tsx index 15db5071..1cd822b1 100644 --- a/apps/web/src/components/Test/Weights.tsx +++ b/apps/web/src/components/Test/Weights.tsx @@ -1,7 +1,7 @@ import { Button } from "components/ui/button"; import { getUpdatedWeights } from "lib/helper"; import { useRouter } from "next/router"; -import { ChangeEvent, useState } from "react"; +import { type ChangeEvent, useState } from "react"; import { toast } from "react-hot-toast"; import type { ClientOption } from "server/trpc/router/project"; import { trpc } from "utils/trpc"; @@ -9,7 +9,6 @@ import { trpc } from "utils/trpc"; const Weight = ({ option, value, - index, onChange, }: { option: ClientOption; @@ -34,7 +33,7 @@ const Weight = ({ value={value} className="h-2 w-full cursor-pointer" onChange={onChange} - > + /> ); }; @@ -43,7 +42,7 @@ const Weights = ({ options }: { options: ClientOption[] }) => { const router = useRouter(); const trpcContext = trpc.useContext(); const [weights, setWeights] = useState( - options.map((option) => parseFloat(option.chance.toString()) * 100) + options.map((option) => Number.parseFloat(option.chance.toString()) * 100) ); const { mutateAsync } = trpc.tests.updateWeights.useMutation(); @@ -59,6 +58,8 @@ const Weights = ({ options }: { options: ClientOption[] }) => { }; const weightsSum = Math.round( + // biome-ignore lint/suspicious/noAssignInExpressions: + // biome-ignore lint/style/noParameterAssign: weights.reduce((sum, curr) => (sum += curr), 0) ); @@ -69,6 +70,7 @@ const Weights = ({ options }: { options: ClientOption[] }) => { await mutateAsync({ testId: options[0].testId, weights: weights.map((weight, index) => ({ + // biome-ignore lint/style/noNonNullAssertion: variantId: options[index]!.id, weight: weight / 100, })), @@ -92,7 +94,9 @@ const Weights = ({ options }: { options: ClientOption[] }) => { key={option.id} value={weights[index] || 0} index={index} - onChange={(e) => updateWeight(index, parseInt(e.target.value, 10))} + onChange={(e) => + updateWeight(index, Number.parseInt(e.target.value, 10)) + } option={option} /> ))} @@ -103,7 +107,7 @@ const Weights = ({ options }: { options: ClientOption[] }) => { {weightsSum}%

) : ( - + )} diff --git a/apps/web/src/components/analytics/EventGraph.tsx b/apps/web/src/components/analytics/EventGraph.tsx index d13c846d..8d722104 100644 --- a/apps/web/src/components/analytics/EventGraph.tsx +++ b/apps/web/src/components/analytics/EventGraph.tsx @@ -11,7 +11,7 @@ import { CardTitle, } from "components/ui/card"; import { - ChartConfig, + type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, @@ -40,16 +40,16 @@ export function EventGraph({ interval: string; }) { const chartConfig = React.useMemo(() => { - const variantsConfig = variants.reduce((acc, variant, index) => { - acc[variant] = { - label: variant, - color: `hsl(var(--chart-${index + 1}))`, - }; - return acc; - }, {} as Record) as Record< - string, - { label: string; color: string } - >; + const variantsConfig = variants.reduce( + (acc, variant, index) => { + acc[variant] = { + label: variant, + color: `hsl(var(--chart-${index + 1}))`, + }; + return acc; + }, + {} as Record + ) as Record; return { visitors: { @@ -76,6 +76,7 @@ export function EventGraph({ {variants.map((variant) => ( {variants.map((variant) => ( diff --git a/apps/web/src/components/app/UserNav.tsx b/apps/web/src/components/app/UserNav.tsx index fcd4437f..ffe3a6c5 100644 --- a/apps/web/src/components/app/UserNav.tsx +++ b/apps/web/src/components/app/UserNav.tsx @@ -1,5 +1,4 @@ -import { Avatar, AvatarFallback, AvatarImage } from "components/ui/avatar"; -import { Button } from "components/ui/button"; +import { DOCS_URL } from "@tryabby/core"; import { DropdownMenu, DropdownMenuContent, @@ -9,9 +8,10 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "components/DropdownMenu"; +import { Avatar, AvatarFallback, AvatarImage } from "components/ui/avatar"; +import { Button } from "components/ui/button"; import { signOut, useSession } from "next-auth/react"; import Link from "next/link"; -import { DOCS_URL } from "@tryabby/core"; export function UserNav() { const { data } = useSession(); diff --git a/apps/web/src/components/ui/avatar.tsx b/apps/web/src/components/ui/avatar.tsx index 4b2fcfbd..256a57e8 100644 --- a/apps/web/src/components/ui/avatar.tsx +++ b/apps/web/src/components/ui/avatar.tsx @@ -1,7 +1,7 @@ -import * as React from "react" -import * as AvatarPrimitive from "@radix-ui/react-avatar" +import * as AvatarPrimitive from "@radix-ui/react-avatar"; +import * as React from "react"; -import { cn } from "lib/utils" +import { cn } from "lib/utils"; const Avatar = React.forwardRef< React.ElementRef, @@ -15,8 +15,8 @@ const Avatar = React.forwardRef< )} {...props} /> -)) -Avatar.displayName = AvatarPrimitive.Root.displayName +)); +Avatar.displayName = AvatarPrimitive.Root.displayName; const AvatarImage = React.forwardRef< React.ElementRef, @@ -27,8 +27,8 @@ const AvatarImage = React.forwardRef< className={cn("aspect-square h-full w-full", className)} {...props} /> -)) -AvatarImage.displayName = AvatarPrimitive.Image.displayName +)); +AvatarImage.displayName = AvatarPrimitive.Image.displayName; const AvatarFallback = React.forwardRef< React.ElementRef, @@ -42,7 +42,7 @@ const AvatarFallback = React.forwardRef< )} {...props} /> -)) -AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName +)); +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; -export { Avatar, AvatarImage, AvatarFallback } +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/apps/web/src/components/ui/button.tsx b/apps/web/src/components/ui/button.tsx index 2961310c..eb81715f 100644 --- a/apps/web/src/components/ui/button.tsx +++ b/apps/web/src/components/ui/button.tsx @@ -1,6 +1,6 @@ -import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; +import { type VariantProps, cva } from "class-variance-authority"; +import * as React from "react"; import { cn } from "lib/utils"; diff --git a/apps/web/src/components/ui/card.tsx b/apps/web/src/components/ui/card.tsx index 28da0caa..7a8f74db 100644 --- a/apps/web/src/components/ui/card.tsx +++ b/apps/web/src/components/ui/card.tsx @@ -1,6 +1,6 @@ -import * as React from "react" +import * as React from "react"; -import { cn } from "lib/utils" +import { cn } from "lib/utils"; const Card = React.forwardRef< HTMLDivElement, @@ -14,8 +14,8 @@ const Card = React.forwardRef< )} {...props} /> -)) -Card.displayName = "Card" +)); +Card.displayName = "Card"; const CardHeader = React.forwardRef< HTMLDivElement, @@ -26,8 +26,8 @@ const CardHeader = React.forwardRef< className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} /> -)) -CardHeader.displayName = "CardHeader" +)); +CardHeader.displayName = "CardHeader"; const CardTitle = React.forwardRef< HTMLParagraphElement, @@ -41,8 +41,8 @@ const CardTitle = React.forwardRef< )} {...props} /> -)) -CardTitle.displayName = "CardTitle" +)); +CardTitle.displayName = "CardTitle"; const CardDescription = React.forwardRef< HTMLParagraphElement, @@ -53,16 +53,16 @@ const CardDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -CardDescription.displayName = "CardDescription" +)); +CardDescription.displayName = "CardDescription"; const CardContent = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ className, ...props }, ref) => (
-)) -CardContent.displayName = "CardContent" +)); +CardContent.displayName = "CardContent"; const CardFooter = React.forwardRef< HTMLDivElement, @@ -73,7 +73,14 @@ const CardFooter = React.forwardRef< className={cn("flex items-center p-6 pt-0", className)} {...props} /> -)) -CardFooter.displayName = "CardFooter" +)); +CardFooter.displayName = "CardFooter"; -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } +export { + Card, + CardHeader, + CardFooter, + CardTitle, + CardDescription, + CardContent, +}; diff --git a/apps/web/src/components/ui/chart.tsx b/apps/web/src/components/ui/chart.tsx index fdd2c68f..58448909 100644 --- a/apps/web/src/components/ui/chart.tsx +++ b/apps/web/src/components/ui/chart.tsx @@ -76,6 +76,7 @@ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { return (