diff --git a/.cta.json b/.cta.json index 7db6231..32aa3d2 100644 --- a/.cta.json +++ b/.cta.json @@ -24,4 +24,4 @@ "tanstack-query", "nitro" ] -} \ No newline at end of file +} diff --git a/.cursor/hooks.json b/.cursor/hooks.json new file mode 100644 index 0000000..0a92b6a --- /dev/null +++ b/.cursor/hooks.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "hooks": { + "afterFileEdit": [ + { + "command": "bun x ultracite fix" + } + ] + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d50c9ab..2487c00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,8 +5,14 @@ on: branches: ["main"] pull_request: +# Cancel previous runs if a new commit is pushed to the same PR +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: - test: + validate: + name: Validate & Test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -15,16 +21,21 @@ jobs: with: bun-version: "latest" - - name: Install + - name: Install dependencies run: bun install --frozen-lockfile - - name: Lint (Biome) + # 1. Linting (Ultracite) + # This runs "ultracite check", respecting your biome.jsonc ignores. + # It fails fast if there are style or logic errors. + - name: Lint (Ultracite) run: bun lint - - name: Typecheck - run: bun typecheck + # # 2. Type Checking + # # Essential because Ultracite (Biome) does not check Typescript types, only syntax. + # - name: Typecheck + # run: bun typecheck + # 3. Tests + # Only runs if the code is clean and type-safe. - name: Test - run: bun test - - + run: bun test \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..87e6bf0 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,70 @@ +#!/bin/sh +bun test + +# Exit on any error +set -e + +# Check if there are any staged files +if [ -z "$(git diff --cached --name-only)" ]; then + echo "No staged files to format" + exit 0 +fi + +# Store the hash of staged changes to detect modifications +STAGED_HASH=$(git diff --cached | sha256sum | cut -d' ' -f1) + +# Save list of staged files (handling all file states) +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR) +PARTIALLY_STAGED=$(git diff --name-only) + +# Stash unstaged changes to preserve working directory +# --keep-index keeps staged changes in working tree +git stash push --quiet --keep-index --message "pre-commit-stash" || true +STASHED=$? + +# Run formatter on the staged files +bun x ultracite fix +FORMAT_EXIT_CODE=$? + +# Restore working directory state +if [ $STASHED -eq 0 ]; then + # Re-stage the formatted files + if [ -n "$STAGED_FILES" ]; then + echo "$STAGED_FILES" | while IFS= read -r file; do + if [ -f "$file" ]; then + git add "$file" + fi + done + fi + + # Restore unstaged changes + git stash pop --quiet || true + + # Restore partial staging if files were partially staged + if [ -n "$PARTIALLY_STAGED" ]; then + for file in $PARTIALLY_STAGED; do + if [ -f "$file" ] && echo "$STAGED_FILES" | grep -q "^$file$"; then + # File was partially staged - need to unstage the unstaged parts + git restore --staged "$file" 2>/dev/null || true + git add -p "$file" < /dev/null 2>/dev/null || git add "$file" + fi + done + fi +else + # No stash was created, just re-add the formatted files + if [ -n "$STAGED_FILES" ]; then + echo "$STAGED_FILES" | while IFS= read -r file; do + if [ -f "$file" ]; then + git add "$file" + fi + done + fi +fi + +# Check if staged files actually changed +NEW_STAGED_HASH=$(git diff --cached | sha256sum | cut -d' ' -f1) +if [ "$STAGED_HASH" != "$NEW_STAGED_HASH" ]; then + echo "✨ Files formatted by Ultracite" +fi + +exit $FORMAT_EXIT_CODE diff --git a/.vscode/settings.json b/.vscode/settings.json index 00b5278..0a45b50 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,56 @@ }, "files.readonlyInclude": { "**/routeTree.gen.ts": true + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "typescript.tsdk": "node_modules/typescript/lib", + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "emmet.showExpandedAbbreviation": "never", + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[html]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[vue]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[svelte]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[css]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[yaml]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[graphql]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[markdown]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[mdx]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "editor.codeActionsOnSave": { + "source.fixAll.biome": "explicit", + "source.organizeImports.biome": "explicit" } } diff --git a/biome.jsonc b/biome.jsonc index e82bb91..3578306 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -1,16 +1,25 @@ { - "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", - "extends": ["ultracite/core", "ultracite/react"], - "linter": { - "rules": { - "style": { - "useConsistentTypeDefinitions": { - "options": { - "style": "type" - }, - "level": "error" - } - } - } - } + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "extends": ["ultracite/core", "ultracite/react", "ultracite/biome/core"], + "linter": { + "rules": { + "style": { + "useConsistentTypeDefinitions": { + "options": { + "style": "type" + }, + "level": "error" + } + } + } + }, + "files": { + "includes": [ + "src/**", + "!src/components/ui", + "!src/routes", + "!src/routeTree.gen.ts", + "!drizzle/*" + ] + } } diff --git a/bun.lock b/bun.lock index 82a7ce8..e2475ca 100644 --- a/bun.lock +++ b/bun.lock @@ -50,7 +50,7 @@ "zod": "^4.2.1", }, "devDependencies": { - "@biomejs/biome": "^2.3.10", + "@biomejs/biome": "2.3.10", "@tailwindcss/vite": "^4.1.18", "@tanstack/react-devtools": "^0.9.0", "@tanstack/react-query-devtools": "^5.91.2", @@ -67,8 +67,9 @@ "dotenv": "^17.2.3", "drizzle-kit": "^0.31.8", "happy-dom": "^20.0.11", + "husky": "^9.1.7", "typescript": "^5.9.3", - "ultracite": "^6.5.0", + "ultracite": "7.0.4", "vite": "^7.3.0", "vite-tsconfig-paths": "^6.0.3", "vitest": "^4.0.16", @@ -318,6 +319,22 @@ "@oxc-transform/binding-win32-x64-msvc": ["@oxc-transform/binding-win32-x64-msvc@0.96.0", "", { "os": "win32", "cpu": "x64" }, "sha512-0fI0P0W7bSO/GCP/N5dkmtB9vBqCA4ggo1WmXTnxNJVmFFOtcA1vYm1I9jl8fxo+sucW2WnlpnI4fjKdo3JKxA=="], + "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.36.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MJkj82GH+nhvWKJhSIM6KlZ8tyGKdogSQXtNdpIyP02r/tTayFJQaAEWayG2Jhsn93kske+nimg5MYFhwO/rlg=="], + + "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.36.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-VvEhfkqj/99dCTqOcfkyFXOSbx4lIy5u2m2GHbK4WCMDySokOcMTNRHGw8fH/WgQ5cDrDMSTYIGQTmnBGi9tiQ=="], + + "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.36.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-EMx92X5q+hHc3olTuj/kgkx9+yP0p/AVs4yvHbUfzZhBekXNpUWxWvg4hIKmQWn+Ee2j4o80/0ACGO0hDYJ9mg=="], + + "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.36.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-7YCxtrPIctVYLqWrWkk8pahdCxch6PtsaucfMLC7TOlDt4nODhnQd4yzEscKqJ8Gjrw1bF4g+Ngob1gB+Qr9Fw=="], + + "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.36.0", "", { "os": "linux", "cpu": "x64" }, "sha512-lnaJVlx5r3NWmoOMesfQXJSf78jHTn8Z+sdAf795Kgteo72+qGC1Uax2SToCJVN2J8PNG3oRV5bLriiCNR2i6Q=="], + + "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.36.0", "", { "os": "linux", "cpu": "x64" }, "sha512-AhuEU2Qdl66lSfTGu/Htirq8r/8q2YnZoG3yEXLMQWnPMn7efy8spD/N1NA7kH0Hll+cdfwgQkQqC2G4MS2lPQ=="], + + "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.36.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-GlWCBjUJY2QgvBFuNRkiRJu7K/djLmM0UQKfZV8IN+UXbP/JbjZHWKRdd4LXlQmzoz7M5Hd6p+ElCej8/90FCg=="], + + "@oxlint/win32-x64": ["@oxlint/win32-x64@1.36.0", "", { "os": "win32", "cpu": "x64" }, "sha512-J+Vc00Utcf8p77lZPruQgb0QnQXuKnFogN88kCnOqs2a83I+vTBB8ILr0+L9sTwVRvIDMSC0pLdeQH4svWGFZg=="], + "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], @@ -848,6 +865,8 @@ "htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], + "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], @@ -954,6 +973,8 @@ "oxc-transform": ["oxc-transform@0.96.0", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm64": "0.96.0", "@oxc-transform/binding-darwin-arm64": "0.96.0", "@oxc-transform/binding-darwin-x64": "0.96.0", "@oxc-transform/binding-freebsd-x64": "0.96.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.96.0", "@oxc-transform/binding-linux-arm64-gnu": "0.96.0", "@oxc-transform/binding-linux-arm64-musl": "0.96.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.96.0", "@oxc-transform/binding-linux-s390x-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-musl": "0.96.0", "@oxc-transform/binding-wasm32-wasi": "0.96.0", "@oxc-transform/binding-win32-arm64-msvc": "0.96.0", "@oxc-transform/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ=="], + "oxlint": ["oxlint@1.36.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.36.0", "@oxlint/darwin-x64": "1.36.0", "@oxlint/linux-arm64-gnu": "1.36.0", "@oxlint/linux-arm64-musl": "1.36.0", "@oxlint/linux-x64-gnu": "1.36.0", "@oxlint/linux-x64-musl": "1.36.0", "@oxlint/win32-arm64": "1.36.0", "@oxlint/win32-x64": "1.36.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.10.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxc_language_server": "bin/oxc_language_server", "oxlint": "bin/oxlint" } }, "sha512-IicUdXfXgI8OKrDPnoSjvBfeEF8PkKtm+CoLlg4LYe4ypc8U+T4r7730XYshdBGZdelg+JRw8GtCb2w/KaaZvw=="], + "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="], @@ -1132,7 +1153,7 @@ "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], - "ultracite": ["ultracite@6.5.0", "", { "dependencies": { "@clack/prompts": "^0.11.0", "@trpc/server": "^11.8.0", "deepmerge": "^4.3.1", "glob": "^13.0.0", "jsonc-parser": "^3.3.1", "nypm": "^0.6.2", "picocolors": "^1.1.1", "trpc-cli": "^0.12.1", "zod": "^4.1.13" }, "bin": { "ultracite": "dist/index.js" } }, "sha512-HrXvM0CX/S3t5HEoepWQ6kpMVD9mzNB5X0k/T7zvNObQ6X9+s1pAE4efDR3Nc4KwqDiemK/bwI7pgPApT7Fktw=="], + "ultracite": ["ultracite@7.0.4", "", { "dependencies": { "@clack/prompts": "^0.11.0", "@trpc/server": "^11.8.1", "deepmerge": "^4.3.1", "glob": "^13.0.0", "jsonc-parser": "^3.3.1", "nypm": "^0.6.2", "oxlint": "^1.36.0", "trpc-cli": "^0.12.1", "zod": "^4.3.2" }, "bin": { "ultracite": "dist/index.js" } }, "sha512-mjbFUhFdM/nBR+XR2WylUJCmXqrErDyrFxyIy1F0TQAPzZvigjMxnhbtZjKKxg0t3pj5wNr6JISUnFbSX1OeGw=="], "undici": ["undici@7.16.0", "", {}, "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g=="], @@ -1268,6 +1289,8 @@ "tsx/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], + "ultracite/zod": ["zod@4.3.4", "", {}, "sha512-Zw/uYiiyF6pUT1qmKbZziChgNPRu+ZRneAsMUDU6IwmXdWt5JwcUfy2bvLOCUtz5UniaN/Zx5aFttZYbYc7O/A=="], + "usesend-js/@react-email/render": ["@react-email/render@1.4.0", "", { "dependencies": { "html-to-text": "^9.0.5", "prettier": "^3.5.3", "react-promise-suspense": "^0.3.4" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ZtJ3noggIvW1ZAryoui95KJENKdCzLmN5F7hyZY1F/17B1vwzuxHB7YkuCg0QqHjDivc5axqYEYdIOw4JIQdUw=="], "vite/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], diff --git a/components.json b/components.json index 6998bdf..58bb3a2 100644 --- a/components.json +++ b/components.json @@ -18,4 +18,4 @@ "hooks": "@/hooks" }, "iconLibrary": "lucide" -} \ No newline at end of file +} diff --git a/package.json b/package.json index 3b99f63..28bdfe6 100644 --- a/package.json +++ b/package.json @@ -11,14 +11,16 @@ "start": "bun run .output/server/index.mjs", "test": "bun --bun vitest run", "typecheck": "bunx tsc -p tsconfig.json --noEmit", - "lint": "bunx biome check .", + "lint": "bunx ultracite check", + "lint:fix": "bunx ultracite fix", "db:generate": "bun --bun drizzle-kit generate", "db:migrate": "bun --bun drizzle-kit migrate", "db:push": "bun --bun drizzle-kit push", "db:pull": "bun --bun drizzle-kit pull", "db:studio": "bun --bun drizzle-kit studio", "better-auth:generate": "bunx --bun @better-auth/cli generate --config src/features/auth/auth.ts --output src/db/schema/auth.ts", - "better-auth:secret": "bunx --bun @better-auth/cli secret" + "better-auth:secret": "bunx --bun @better-auth/cli secret", + "prepare": "husky" }, "dependencies": { "@fontsource-variable/geist": "^5.2.8", @@ -66,7 +68,7 @@ "zod": "^4.2.1" }, "devDependencies": { - "@biomejs/biome": "^2.3.10", + "@biomejs/biome": "2.3.10", "@tailwindcss/vite": "^4.1.18", "@tanstack/react-devtools": "^0.9.0", "@tanstack/react-query-devtools": "^5.91.2", @@ -83,8 +85,9 @@ "dotenv": "^17.2.3", "drizzle-kit": "^0.31.8", "happy-dom": "^20.0.11", + "husky": "^9.1.7", "typescript": "^5.9.3", - "ultracite": "^6.5.0", + "ultracite": "7.0.4", "vite": "^7.3.0", "vite-tsconfig-paths": "^6.0.3", "vitest": "^4.0.16" diff --git a/src/components/default-not-found.tsx b/src/components/default-not-found.tsx index d24efd2..5c127bb 100644 --- a/src/components/default-not-found.tsx +++ b/src/components/default-not-found.tsx @@ -7,11 +7,16 @@ type DefaultNotFoundProps = { routeId: string; }; -export const DefaultNotFound: NotFoundRouteComponent = ({ isNotFound, routeId }: DefaultNotFoundProps) => ( +export const DefaultNotFound: NotFoundRouteComponent = ({ + isNotFound, + routeId, +}: DefaultNotFoundProps) => (
- {isNotFound ? "404" : routeId} + + {isNotFound ? "404" : routeId} +

Page not found

diff --git a/src/components/emails/verify-email.tsx b/src/components/emails/verify-email.tsx index 61aa4cd..2315c01 100644 --- a/src/components/emails/verify-email.tsx +++ b/src/components/emails/verify-email.tsx @@ -79,11 +79,14 @@ export default function VerifyEmail({ name, verifyUrl }: VerifyEmailProps) { {SITE_URL} - + Unsubscribe {" "} | - + Privacy Policy diff --git a/src/components/logo.tsx b/src/components/logo.tsx index 6247ef1..a0376af 100644 --- a/src/components/logo.tsx +++ b/src/components/logo.tsx @@ -9,4 +9,4 @@ export function Logo() { tano-stack
); -} \ No newline at end of file +} diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx index 296d5fe..e96e3bd 100644 --- a/src/components/theme-provider.tsx +++ b/src/components/theme-provider.tsx @@ -1,6 +1,6 @@ -import { ThemeProvider as NextThemesProvider } from "next-themes" -import type { ThemeProviderProps } from "next-themes" +import type { ThemeProviderProps } from "next-themes"; +import { ThemeProvider as NextThemesProvider } from "next-themes"; export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return {children} + return {children}; } diff --git a/src/db/schema/auth.ts b/src/db/schema/auth.ts index c8e0a99..264997f 100644 --- a/src/db/schema/auth.ts +++ b/src/db/schema/auth.ts @@ -1,12 +1,12 @@ import { relations } from "drizzle-orm"; import { - pgTable, - text, bigint, - timestamp, boolean, - integer, index, + integer, + pgTable, + text, + timestamp, } from "drizzle-orm/pg-core"; export const user = pgTable("user", { @@ -42,7 +42,7 @@ export const session = pgTable( .references(() => user.id, { onDelete: "cascade" }), impersonatedBy: text("impersonated_by"), }, - (table) => [index("session_userId_idx").on(table.userId)], + (table) => [index("session_userId_idx").on(table.userId)] ); export const account = pgTable( @@ -66,7 +66,7 @@ export const account = pgTable( .$onUpdate(() => new Date()) .notNull(), }, - (table) => [index("account_userId_idx").on(table.userId)], + (table) => [index("account_userId_idx").on(table.userId)] ); export const verification = pgTable( @@ -81,7 +81,7 @@ export const verification = pgTable( .$onUpdate(() => new Date()) .notNull(), }, - (table) => [index("verification_identifier_idx").on(table.identifier)], + (table) => [index("verification_identifier_idx").on(table.identifier)] ); export const rateLimit = pgTable("rate_limit", { diff --git a/src/hooks/use-mobile.ts b/src/hooks/use-mobile.ts index 2b0fe1d..08ea59e 100644 --- a/src/hooks/use-mobile.ts +++ b/src/hooks/use-mobile.ts @@ -1,19 +1,21 @@ -import * as React from "react" +import React from "react"; -const MOBILE_BREAKPOINT = 768 +const MOBILE_BREAKPOINT = 768; export function useIsMobile() { - const [isMobile, setIsMobile] = React.useState(undefined) + const [isMobile, setIsMobile] = React.useState( + undefined + ); React.useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); const onChange = () => { - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - } - mql.addEventListener("change", onChange) - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) - return () => mql.removeEventListener("change", onChange) - }, []) + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); + }; + mql.addEventListener("change", onChange); + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); + return () => mql.removeEventListener("change", onChange); + }, []); - return !!isMobile + return !!isMobile; } diff --git a/src/integrations/tanstack-query/devtools.tsx b/src/integrations/tanstack-query/devtools.tsx index 94c68c9..7c85d88 100644 --- a/src/integrations/tanstack-query/devtools.tsx +++ b/src/integrations/tanstack-query/devtools.tsx @@ -1,6 +1,6 @@ -import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools' +import { ReactQueryDevtoolsPanel } from "@tanstack/react-query-devtools"; export default { - name: 'Tanstack Query', + name: "Tanstack Query", render: , -} +}; diff --git a/src/lib/server/jobs/example.ts b/src/lib/server/jobs/example.ts index 1772c04..845390d 100644 --- a/src/lib/server/jobs/example.ts +++ b/src/lib/server/jobs/example.ts @@ -22,7 +22,7 @@ export async function registerExampleJobs(boss: PgBoss) { const { name } = job.data; await new Promise((resolve) => setTimeout(resolve, 1000)); - + return { message: `Example job completed for ${name}` }; }); } diff --git a/src/lib/server/middleware.ts b/src/lib/server/middleware.ts index 3353c2b..4663699 100644 --- a/src/lib/server/middleware.ts +++ b/src/lib/server/middleware.ts @@ -32,4 +32,4 @@ export function requireRoleMiddleware(role: string) { return next({ context }); }); -} \ No newline at end of file +} diff --git a/src/lib/server/queue.ts b/src/lib/server/queue.ts index 4d5e025..a7785ed 100644 --- a/src/lib/server/queue.ts +++ b/src/lib/server/queue.ts @@ -29,4 +29,4 @@ export async function initQueue() { } return boss; -} \ No newline at end of file +} diff --git a/src/styles.css b/src/styles.css index 525b59c..d92b568 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,7 +1,7 @@ -@import 'tailwindcss'; -@import 'tw-animate-css'; -@import '@fontsource-variable/geist'; -@import '@fontsource-variable/geist-mono'; +@import "tailwindcss"; +@import "tw-animate-css"; +@import "@fontsource-variable/geist"; +@import "@fontsource-variable/geist-mono"; @custom-variant dark (&:is(.dark *)); @@ -128,11 +128,18 @@ @apply m-0 bg-background font-sans text-foreground antialiased; } - h1, h2, h3, h4, h5, h6 { + h1, + h2, + h3, + h4, + h5, + h6 { @apply font-sans tracking-tight; } - code, pre, kbd { + code, + pre, + kbd { @apply font-mono; } } diff --git a/tests/setup.ts b/tests/setup.ts index 9a41425..f149f27 100644 --- a/tests/setup.ts +++ b/tests/setup.ts @@ -1 +1 @@ -import "@testing-library/jest-dom/vitest"; \ No newline at end of file +import "@testing-library/jest-dom/vitest"; diff --git a/tsconfig.json b/tsconfig.json index 31cbc0e..477479f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,7 +22,7 @@ "noUncheckedSideEffectImports": true, "baseUrl": ".", "paths": { - "@/*": ["./src/*"], + "@/*": ["./src/*"] } } } diff --git a/vite.config.ts b/vite.config.ts index 31b9f49..0bd1d25 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -13,7 +13,7 @@ const config = defineConfig({ }), tanstackStart(), nitro({ - preset: "bun" + preset: "bun", }), tailwindcss(), viteReact({ diff --git a/vitest.config.ts b/vitest.config.ts index f7ac0bd..4059025 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,5 +1,5 @@ -import { defineConfig } from "vitest/config"; import tsconfigPaths from "vite-tsconfig-paths"; +import { defineConfig } from "vitest/config"; export default defineConfig({ plugins: [tsconfigPaths()], @@ -9,5 +9,3 @@ export default defineConfig({ globals: true, }, }); - -