diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..bf619f2 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,19 @@ + +# Your PR Title + +## Problem + + +## Solution + + +## Reference + + +## Screenshots + + +## Checklist + +- [ ] Changes have been tested locally +- [ ] Changes have been self-reviewed diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 0000000..2f16260 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,21 @@ +name: Code quality + +on: + pull_request: + +jobs: + quality: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + persist-credentials: false + - name: Setup Biome + uses: biomejs/setup-biome@v2 + with: + version: latest + - name: Run Biome + run: biome ci . diff --git a/app/api/client.ts b/app/api/client.ts index 4f858d7..296fd04 100644 --- a/app/api/client.ts +++ b/app/api/client.ts @@ -1,4 +1,4 @@ -import { createClient } from '@supabase/supabase-js'; -import { databaseApiKey, databaseUrl } from '~/constants/db'; +import { createClient } from "@supabase/supabase-js"; +import { databaseApiKey, databaseUrl } from "~/constants/db"; export const client = createClient(databaseUrl, databaseApiKey); diff --git a/app/api/resources/methods.ts b/app/api/resources/methods.ts index 8400f66..088f7ed 100644 --- a/app/api/resources/methods.ts +++ b/app/api/resources/methods.ts @@ -1,10 +1,10 @@ +import { client } from "~/api/client"; +import type { ModelAPI } from "~/api/types"; import type { ResourceEntry, ResourceStatus, ResourceType, -} from '~/types/ResourceEntry'; -import type { ModelAPI } from '~/api/types'; -import { client } from '~/api/client'; +} from "~/types/ResourceEntry"; /** * Options for paginated fetching of resources @@ -20,7 +20,7 @@ export type ResourceEntryGetListParams = { status?: ResourceStatus; }; -const TABLE_NAME = 'resources'; +const TABLE_NAME = "resources"; const table = client.from(TABLE_NAME); export const ResourceEntryAPI: ModelAPI< @@ -30,20 +30,20 @@ export const ResourceEntryAPI: ModelAPI< getList: async (params) => { const { limit, offset, resourceType, status } = params; const isPaginating = - typeof limit === 'number' && typeof offset === 'number'; + typeof limit === "number" && typeof offset === "number"; - let query = table.select('*', { count: 'exact' }); + let query = table.select("*", { count: "exact" }); if (isPaginating) { query = query.range(offset, offset + limit - 1); } if (resourceType) { - query = query.eq('resource_type', resourceType); + query = query.eq("resource_type", resourceType); } if (status) { - query = query.eq('status', status); + query = query.eq("status", status); } const { data, error, count } = await query; @@ -64,8 +64,8 @@ export const ResourceEntryAPI: ModelAPI< }, getById: async (id) => { const { data, error } = await table - .select('*') - .eq('id', id) + .select("*") + .eq("id", id) .single(); if (error) { @@ -89,7 +89,7 @@ export const ResourceEntryAPI: ModelAPI< updateById: async (id, values) => { const { data, error } = await table .update(values) - .eq('id', id) + .eq("id", id) .single(); if (error) { @@ -99,7 +99,7 @@ export const ResourceEntryAPI: ModelAPI< return data; }, delete: async (id) => { - const { error } = await table.delete().eq('id', id); + const { error } = await table.delete().eq("id", id); if (error) { throw error; diff --git a/app/app.css b/app/app.css index 99345d8..75c6338 100644 --- a/app/app.css +++ b/app/app.css @@ -1,8 +1,9 @@ -@import "tailwindcss"; +@import 'tailwindcss'; @theme { - --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif, - "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-sans: + 'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } html, diff --git a/app/root.tsx b/app/root.tsx index 449dc14..9fc6636 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -5,21 +5,21 @@ import { Outlet, Scripts, ScrollRestoration, -} from 'react-router'; +} from "react-router"; -import type { Route } from './+types/root'; -import './app.css'; +import type { Route } from "./+types/root"; +import "./app.css"; export const links: Route.LinksFunction = () => [ - { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { rel: "preconnect", href: "https://fonts.googleapis.com" }, { - rel: 'preconnect', - href: 'https://fonts.gstatic.com', - crossOrigin: 'anonymous', + rel: "preconnect", + href: "https://fonts.gstatic.com", + crossOrigin: "anonymous", }, { - rel: 'stylesheet', - href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + rel: "stylesheet", + href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap", }, ]; @@ -46,15 +46,15 @@ export default function App() { } export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) { - let message = 'Oops!'; - let details = 'An unexpected error occurred.'; + let message = "Oops!"; + let details = "An unexpected error occurred."; let stack: string | undefined; if (isRouteErrorResponse(error)) { - message = error.status === 404 ? '404' : 'Error'; + message = error.status === 404 ? "404" : "Error"; details = error.status === 404 - ? 'The requested page could not be found.' + ? "The requested page could not be found." : error.statusText || details; } else if (import.meta.env.DEV && error && error instanceof Error) { details = error.message; diff --git a/app/routes.ts b/app/routes.ts index 205ff3c..38f1a4d 100644 --- a/app/routes.ts +++ b/app/routes.ts @@ -1,3 +1,3 @@ -import { type RouteConfig, index } from '@react-router/dev/routes'; +import { index, type RouteConfig } from "@react-router/dev/routes"; -export default [index('routes/home.tsx')] satisfies RouteConfig; +export default [index("routes/home.tsx")] satisfies RouteConfig; diff --git a/app/routes/home.tsx b/app/routes/home.tsx index 0fd5493..7a93ee0 100644 --- a/app/routes/home.tsx +++ b/app/routes/home.tsx @@ -1,12 +1,12 @@ -import type { Route } from './+types/home'; -import { useLoaderData } from 'react-router'; -import { Welcome } from '../welcome/welcome'; -import ResourcesAPI from '~/api/resources/methods'; +import { useLoaderData } from "react-router"; +import ResourcesAPI from "~/api/resources/methods"; +import { Welcome } from "../welcome/welcome"; +import type { Route } from "./+types/home"; -export function meta({}: Route.MetaArgs) { +export function meta(_metaArgs: Route.MetaArgs) { return [ - { title: 'New React Router App' }, - { name: 'description', content: 'Welcome to React Router!' }, + { title: "New React Router App" }, + { name: "description", content: "Welcome to React Router!" }, ]; } diff --git a/app/types/ResourceEntry.ts b/app/types/ResourceEntry.ts index 75a3f2c..d7dcc07 100644 --- a/app/types/ResourceEntry.ts +++ b/app/types/ResourceEntry.ts @@ -8,86 +8,86 @@ /** * Type of data source for a resource entry. */ -export type DataSourceType = 'MANUAL' | 'WEB_SCRAPE'; +export type DataSourceType = "MANUAL" | "WEB_SCRAPE"; /** * Type of resource available in the system. */ -export type ResourceType = 'WATER' | 'FOOD' | 'FORAGE' | 'BATHROOM'; +export type ResourceType = "WATER" | "FOOD" | "FORAGE" | "BATHROOM"; /** * Status of a resource. */ export type ResourceStatus = - | 'OPERATIONAL' - | 'TEMPORARILY_CLOSED' - | 'PERMANENTLY_CLOSED' - | 'HIDDEN'; + | "OPERATIONAL" + | "TEMPORARILY_CLOSED" + | "PERMANENTLY_CLOSED" + | "HIDDEN"; /** * Entry permission type for a resource. */ -export type EntryType = 'OPEN' | 'RESTRICTED' | 'UNSURE'; +export type EntryType = "OPEN" | "RESTRICTED" | "UNSURE"; /** * Type of water dispenser. */ export type DispenserType = - | 'DRINKING_FOUNTAIN' - | 'BOTTLE_FILLER' - | 'SINK' - | 'JUG' - | 'SODA_MACHINE' - | 'PITCHER' - | 'WATER_COOLER'; + | "DRINKING_FOUNTAIN" + | "BOTTLE_FILLER" + | "SINK" + | "JUG" + | "SODA_MACHINE" + | "PITCHER" + | "WATER_COOLER"; /** * Tags for water resources. */ export type WaterTag = - | 'WHEELCHAIR_ACCESSIBLE' - | 'FILTERED' - | 'BYOB' - | 'ID_REQUIRED'; + | "WHEELCHAIR_ACCESSIBLE" + | "FILTERED" + | "BYOB" + | "ID_REQUIRED"; /** * Type of food available. */ -export type FoodType = 'PERISHABLE' | 'NON_PERISHABLE' | 'PREPARED'; +export type FoodType = "PERISHABLE" | "NON_PERISHABLE" | "PREPARED"; /** * Distribution type for food resources. */ -export type DistributionType = 'EAT_ON_SITE' | 'DELIVERY' | 'PICKUP'; +export type DistributionType = "EAT_ON_SITE" | "DELIVERY" | "PICKUP"; /** * Organization type for food resources. */ export type OrganizationType = - | 'GOVERNMENT' - | 'BUSINESS' - | 'NON_PROFIT' - | 'UNSURE'; + | "GOVERNMENT" + | "BUSINESS" + | "NON_PROFIT" + | "UNSURE"; /** * Type of foraging resources. */ -export type ForageType = 'NUT' | 'FRUIT' | 'LEAVES' | 'BARK' | 'FLOWERS'; +export type ForageType = "NUT" | "FRUIT" | "LEAVES" | "BARK" | "FLOWERS"; /** * Tags for foraging resources. */ -export type ForageTag = 'MEDICINAL' | 'IN_SEASON' | 'COMMUNITY_GARDEN'; +export type ForageTag = "MEDICINAL" | "IN_SEASON" | "COMMUNITY_GARDEN"; /** * Tags for bathroom resources. */ export type BathroomTag = - | 'WHEELCHAIR_ACCESSIBLE' - | 'GENDER_NEUTRAL' - | 'CHANGING_TABLE' - | 'SINGLE_OCCUPANCY' - | 'FAMILY'; + | "WHEELCHAIR_ACCESSIBLE" + | "GENDER_NEUTRAL" + | "CHANGING_TABLE" + | "SINGLE_OCCUPANCY" + | "FAMILY"; /** * A data source defining where the resource data entry came from. @@ -243,7 +243,7 @@ export type ResourceEntry = { /** * Resource type constants for easy use */ -export const WATER_RESOURCE_TYPE = 'WATER'; -export const FOOD_RESOURCE_TYPE = 'FOOD'; -export const FORAGE_RESOURCE_TYPE = 'FORAGE'; -export const BATHROOM_RESOURCE_TYPE = 'BATHROOM'; +export const WATER_RESOURCE_TYPE = "WATER"; +export const FOOD_RESOURCE_TYPE = "FOOD"; +export const FORAGE_RESOURCE_TYPE = "FORAGE"; +export const BATHROOM_RESOURCE_TYPE = "BATHROOM"; diff --git a/app/welcome/welcome.tsx b/app/welcome/welcome.tsx index 48c7a25..0bc1400 100644 --- a/app/welcome/welcome.tsx +++ b/app/welcome/welcome.tsx @@ -1,5 +1,5 @@ -import logoDark from './logo-dark.svg'; -import logoLight from './logo-light.svg'; +import logoDark from "./logo-dark.svg"; +import logoLight from "./logo-light.svg"; export function Welcome() { return ( @@ -19,71 +19,7 @@ export function Welcome() { /> -
- -
); } - -const resources = [ - { - href: 'https://reactrouter.com/docs', - text: 'React Router Docs', - icon: ( - - - - ), - }, - { - href: 'https://rmx.as/discord', - text: 'Join Discord', - icon: ( - - - - ), - }, -]; diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..58f2367 --- /dev/null +++ b/biome.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.3.14/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "main" + }, + "files": { + "ignoreUnknown": false + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "bracketSpacing": true, + "bracketSameLine": false, + "expand": "auto", + "formatWithErrors": false, + "lineEnding": "lf", + "lineWidth": 80, + "indentWidth": 2, + "attributePosition": "auto" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "css": { + "assist": { + "enabled": true + }, + "linter": { + "enabled": true + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "quoteStyle": "single", + "lineWidth": 80 + }, + "parser": { + "tailwindDirectives": true + } + }, + "javascript": { + "formatter": { + "enabled": true, + "arrowParentheses": "always", + "jsxQuoteStyle": "double", + "trailingCommas": "all", + "quoteStyle": "double", + "quoteProperties": "asNeeded", + "semicolons": "always" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on", + "recommended": true + } + } + }, + "json": { + "formatter": { + "lineEnding": "lf" + } + } +} diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..2be238c --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,5 @@ +pre-push: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + run: npx @biomejs/biome check --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {push_files} diff --git a/package.json b/package.json index c465834..554bd00 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "", + "name": "phlask-admin-dashboard", "private": true, "type": "module", "scripts": { @@ -7,7 +7,9 @@ "dev": "react-router dev", "start": "react-router-serve ./build/server/index.js", "typecheck": "react-router typegen && tsc", - "format": "prettier --write app/**/*.{tsx,ts}" + "format": "biome format", + "lint": "biome lint", + "ci": "biome ci" }, "dependencies": { "@react-router/node": "^7.9.2", @@ -19,12 +21,13 @@ "react-router": "^7.9.2" }, "devDependencies": { + "@biomejs/biome": "2.3.14", "@react-router/dev": "^7.9.2", "@tailwindcss/vite": "^4.1.13", "@types/node": "^22", "@types/react": "^19.1.13", "@types/react-dom": "^19.1.9", - "prettier": "^3.8.1", + "lefthook": "^2.1.0", "tailwindcss": "^4.1.13", "typescript": "^5.9.2", "vite": "^7.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 90b2320..3ddf7e5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,6 +30,9 @@ importers: specifier: ^7.9.2 version: 7.9.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0) devDependencies: + '@biomejs/biome': + specifier: 2.3.14 + version: 2.3.14 '@react-router/dev': specifier: ^7.9.2 version: 7.9.5(@react-router/serve@7.9.5(react-router@7.9.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3))(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.2)(react-router@7.9.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3)(vite@7.2.2(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.2)) @@ -45,9 +48,9 @@ importers: '@types/react-dom': specifier: ^19.1.9 version: 19.2.2(@types/react@19.2.3) - prettier: - specifier: ^3.8.1 - version: 3.8.1 + lefthook: + specifier: ^2.1.0 + version: 2.1.0 tailwindcss: specifier: ^4.1.13 version: 4.1.17 @@ -192,6 +195,63 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} + '@biomejs/biome@2.3.14': + resolution: {integrity: sha512-QMT6QviX0WqXJCaiqVMiBUCr5WRQ1iFSjvOLoTk6auKukJMvnMzWucXpwZB0e8F00/1/BsS9DzcKgWH+CLqVuA==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@2.3.14': + resolution: {integrity: sha512-UJGPpvWJMkLxSRtpCAKfKh41Q4JJXisvxZL8ChN1eNW3m/WlPFJ6EFDCE7YfUb4XS8ZFi3C1dFpxUJ0Ety5n+A==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@2.3.14': + resolution: {integrity: sha512-PNkLNQG6RLo8lG7QoWe/hhnMxJIt1tEimoXpGQjwS/dkdNiKBLPv4RpeQl8o3s1OKI3ZOR5XPiYtmbGGHAOnLA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@2.3.14': + resolution: {integrity: sha512-LInRbXhYujtL3sH2TMCH/UBwJZsoGwfQjBrMfl84CD4hL/41C/EU5mldqf1yoFpsI0iPWuU83U+nB2TUUypWeg==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@biomejs/cli-linux-arm64@2.3.14': + resolution: {integrity: sha512-KT67FKfzIw6DNnUNdYlBg+eU24Go3n75GWK6NwU4+yJmDYFe9i/MjiI+U/iEzKvo0g7G7MZqoyrhIYuND2w8QQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@biomejs/cli-linux-x64-musl@2.3.14': + resolution: {integrity: sha512-KQU7EkbBBuHPW3/rAcoiVmhlPtDSGOGRPv9js7qJVpYTzjQmVR+C9Rfcz+ti8YCH+zT1J52tuBybtP4IodjxZQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@biomejs/cli-linux-x64@2.3.14': + resolution: {integrity: sha512-ZsZzQsl9U+wxFrGGS4f6UxREUlgHwmEfu1IrXlgNFrNnd5Th6lIJr8KmSzu/+meSa9f4rzFrbEW9LBBA6ScoMA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@biomejs/cli-win32-arm64@2.3.14': + resolution: {integrity: sha512-+IKYkj/pUBbnRf1G1+RlyA3LWiDgra1xpS7H2g4BuOzzRbRB+hmlw0yFsLprHhbbt7jUzbzAbAjK/Pn0FDnh1A==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@2.3.14': + resolution: {integrity: sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} @@ -473,56 +533,67 @@ packages: resolution: {integrity: sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.53.2': resolution: {integrity: sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.53.2': resolution: {integrity: sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.53.2': resolution: {integrity: sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.53.2': resolution: {integrity: sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-gnu@4.53.2': resolution: {integrity: sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.53.2': resolution: {integrity: sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.53.2': resolution: {integrity: sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.53.2': resolution: {integrity: sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.53.2': resolution: {integrity: sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.53.2': resolution: {integrity: sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openharmony-arm64@4.53.2': resolution: {integrity: sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==} @@ -611,24 +682,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.1.17': resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.1.17': resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.1.17': resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.1.17': resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==} @@ -1044,6 +1119,60 @@ packages: engines: {node: '>=6'} hasBin: true + lefthook-darwin-arm64@2.1.0: + resolution: {integrity: sha512-u2hjHLQXWSFfzO7ln2n/uEydSzfC9sc5cDC7tvKSuOdhvBwaJ0AQ7ZeuqqCQ4YfVIJfYOom1SVE9CBd10FVyig==} + cpu: [arm64] + os: [darwin] + + lefthook-darwin-x64@2.1.0: + resolution: {integrity: sha512-zz5rcyrtOZpxon7uE+c0KC/o2ypJeLZql5CL0Y9oaTuECbmhfokm8glsGnyWstW/++PuMpZYYr/qsCJA5elxkQ==} + cpu: [x64] + os: [darwin] + + lefthook-freebsd-arm64@2.1.0: + resolution: {integrity: sha512-+mXNCNuFHNGYLrDqYWDeHH7kWCLCJFPpspx5PAAm+PD37PRMZJrTqDbaNK9qCghC1tdmT4/Lvilf/ewXHPlaKw==} + cpu: [arm64] + os: [freebsd] + + lefthook-freebsd-x64@2.1.0: + resolution: {integrity: sha512-+AU2HD7szuDsUdHue/E3OnF84B2ae/h7CGKpuIUHJntgoJ4kxf89oDvq2/xl8kDCn9cT76UUjgeZUgFYLRj+6Q==} + cpu: [x64] + os: [freebsd] + + lefthook-linux-arm64@2.1.0: + resolution: {integrity: sha512-KM70eV1tsEib1/tk+3TFxIdH84EaYlIg5KTQWAg+LB1N23nTQ7lL4Dnh1je6f6KW4tf21nmoMUqsh0xvMkQk8Q==} + cpu: [arm64] + os: [linux] + + lefthook-linux-x64@2.1.0: + resolution: {integrity: sha512-6Bxmv+l7LiYq9W0IE6v2lmlRtBp6pisnlzhcouMGvH3rDwEGw11NAyRJZA3IPGEMAkIuhnlnVTUwAUzKomfJLg==} + cpu: [x64] + os: [linux] + + lefthook-openbsd-arm64@2.1.0: + resolution: {integrity: sha512-ppJNK0bBSPLC8gqksRw5zI/0uLeMA5cK+hmZ4ofcuGNmdrN1dfl2Tx84fdeef0NcQY0ii9Y3j3icIKngIoid/g==} + cpu: [arm64] + os: [openbsd] + + lefthook-openbsd-x64@2.1.0: + resolution: {integrity: sha512-8k9lQsMYqQGu4spaQ8RNSOJidxIcOyfaoF2FPZhthtBfRV3cgVFGrsQ0hbIi5pvQRGUlCqYuCN79qauXHmnL3Q==} + cpu: [x64] + os: [openbsd] + + lefthook-windows-arm64@2.1.0: + resolution: {integrity: sha512-0WN+grrxt9zP9NGRcztoPXcz25tteem91rfLWgQFab+50csJ47zldlsB7/eOS/eHG5mUg5g5NPR4XefnXtjOcQ==} + cpu: [arm64] + os: [win32] + + lefthook-windows-x64@2.1.0: + resolution: {integrity: sha512-XbO/5nAZQLpUn0tPpgCYfFBFJHnymSglQ73jD6wymNrR1j8I5EcXGlP6YcLhnZ83yzsdLC+gup+N6IqUeiyRdw==} + cpu: [x64] + os: [win32] + + lefthook@2.1.0: + resolution: {integrity: sha512-+vS+yywGQW6CN1J1hbGkez//6ixGHIQqfxDN/d3JDm531w9GfGt2lAWTDfZTw/CEl80XsN0raFcnEraR3ldw9g==} + hasBin: true + lightningcss-android-arm64@1.30.2: resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} engines: {node: '>= 12.0.0'} @@ -1079,24 +1208,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} @@ -1797,6 +1930,41 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@biomejs/biome@2.3.14': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 2.3.14 + '@biomejs/cli-darwin-x64': 2.3.14 + '@biomejs/cli-linux-arm64': 2.3.14 + '@biomejs/cli-linux-arm64-musl': 2.3.14 + '@biomejs/cli-linux-x64': 2.3.14 + '@biomejs/cli-linux-x64-musl': 2.3.14 + '@biomejs/cli-win32-arm64': 2.3.14 + '@biomejs/cli-win32-x64': 2.3.14 + + '@biomejs/cli-darwin-arm64@2.3.14': + optional: true + + '@biomejs/cli-darwin-x64@2.3.14': + optional: true + + '@biomejs/cli-linux-arm64-musl@2.3.14': + optional: true + + '@biomejs/cli-linux-arm64@2.3.14': + optional: true + + '@biomejs/cli-linux-x64-musl@2.3.14': + optional: true + + '@biomejs/cli-linux-x64@2.3.14': + optional: true + + '@biomejs/cli-win32-arm64@2.3.14': + optional: true + + '@biomejs/cli-win32-x64@2.3.14': + optional: true + '@esbuild/aix-ppc64@0.25.12': optional: true @@ -2587,6 +2755,49 @@ snapshots: json5@2.2.3: {} + lefthook-darwin-arm64@2.1.0: + optional: true + + lefthook-darwin-x64@2.1.0: + optional: true + + lefthook-freebsd-arm64@2.1.0: + optional: true + + lefthook-freebsd-x64@2.1.0: + optional: true + + lefthook-linux-arm64@2.1.0: + optional: true + + lefthook-linux-x64@2.1.0: + optional: true + + lefthook-openbsd-arm64@2.1.0: + optional: true + + lefthook-openbsd-x64@2.1.0: + optional: true + + lefthook-windows-arm64@2.1.0: + optional: true + + lefthook-windows-x64@2.1.0: + optional: true + + lefthook@2.1.0: + optionalDependencies: + lefthook-darwin-arm64: 2.1.0 + lefthook-darwin-x64: 2.1.0 + lefthook-freebsd-arm64: 2.1.0 + lefthook-freebsd-x64: 2.1.0 + lefthook-linux-arm64: 2.1.0 + lefthook-linux-x64: 2.1.0 + lefthook-openbsd-arm64: 2.1.0 + lefthook-openbsd-x64: 2.1.0 + lefthook-windows-arm64: 2.1.0 + lefthook-windows-x64: 2.1.0 + lightningcss-android-arm64@1.30.2: optional: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..39ad349 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +onlyBuiltDependencies: + - esbuild + - lefthook diff --git a/prettier.config.ts b/prettier.config.ts deleted file mode 100644 index 583bd5f..0000000 --- a/prettier.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default { - semi: true, - singleQuote: true, - trailingComma: "all", - arrowParens: "always", -}; diff --git a/tsconfig.json b/tsconfig.json index 763affb..cbe49c7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,26 @@ { - "include": [ - "**/*", - "**/.server/**/*", - "**/.client/**/*", - ".react-router/types/**/*" - ], - "compilerOptions": { - "lib": ["DOM", "DOM.Iterable", "ES2022"], - "types": ["node", "vite/client"], - "target": "ES2022", - "module": "ES2022", - "moduleResolution": "bundler", - "jsx": "react-jsx", - "rootDirs": [".", "./.react-router/types"], - "paths": { - "~/*": ["./app/*"] - }, - "esModuleInterop": true, - "verbatimModuleSyntax": true, - "noEmit": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true - } + "include": [ + "**/*", + "**/.server/**/*", + "**/.client/**/*", + ".react-router/types/**/*" + ], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "types": ["node", "vite/client"], + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "rootDirs": [".", "./.react-router/types"], + "paths": { + "~/*": ["./app/*"] + }, + "esModuleInterop": true, + "verbatimModuleSyntax": true, + "noEmit": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true + } } diff --git a/vite.config.ts b/vite.config.ts index 5c9b436..3f3f041 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,11 @@ -import { reactRouter } from '@react-router/dev/vite'; -import tailwindcss from '@tailwindcss/vite'; -import { defineConfig } from 'vite'; -import tsconfigPaths from 'vite-tsconfig-paths'; +import { reactRouter } from "@react-router/dev/vite"; +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig } from "vite"; +import tsconfigPaths from "vite-tsconfig-paths"; export default defineConfig({ - plugins: [tailwindcss(), reactRouter(), tsconfigPaths()], - server: { - port: 5174 - } + plugins: [tailwindcss(), reactRouter(), tsconfigPaths()], + server: { + port: 5174, + }, });