diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index e5d84f2..0000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "tabWidth": 2, - "trailingComma": "es5" -} diff --git a/client/src/App.tsx b/client/src/App.tsx index 93e250b..c66f778 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,24 +1,24 @@ -import { createSignal } from 'solid-js' -import solidLogo from './assets/solid.svg' -import viteLogo from '/vite.svg' -import './App.css' +import { createSignal } from 'solid-js'; +import solidLogo from './assets/solid.svg'; +import viteLogo from '/vite.svg'; +import './App.css'; function App() { - const [count, setCount] = createSignal(0) + const [count, setCount] = createSignal(0); return ( <>
- + - +

Vite + Solid

-

@@ -29,7 +29,7 @@ function App() { Click on the Vite and Solid logos to learn more

- ) + ); } -export default App +export default App; diff --git a/client/src/index.tsx b/client/src/index.tsx index af7bf04..b626e2f 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -1,9 +1,9 @@ /* @refresh reload */ -import { render } from 'solid-js/web' +import { render } from 'solid-js/web'; -import './index.css' -import App from './App' +import './index.css'; +import App from './App'; -const root = document.getElementById('root') +const root = document.getElementById('root') as HTMLElement; -render(() => , root!) +render(() => , root); diff --git a/client/vite.config.ts b/client/vite.config.ts index 4095d9b..da40253 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -1,6 +1,6 @@ -import { defineConfig } from 'vite' -import solid from 'vite-plugin-solid' +import { defineConfig } from 'vite'; +import solid from 'vite-plugin-solid'; export default defineConfig({ plugins: [solid()], -}) +}); diff --git a/package.json b/package.json index 9306e31..f78c7a2 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "kzilla.xyz-server", "version": "3.0", "scripts": { + "start": "tsx src/index.ts", + "lint": "biome check .", + "lint:fix": "biome check . --write --unsafe", "dev": "tsx watch src/index.ts" }, "dependencies": { diff --git a/src/index.ts b/src/index.ts index 617b111..8165eeb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ -import { serve } from "@hono/node-server"; -import { Hono } from "hono"; -import CONFIG from "./utils/env"; -import { BootstrapServer } from "./utils/server"; +import { serve } from '@hono/node-server'; +import { Hono } from 'hono'; +import CONFIG from './utils/env'; +import { BootstrapServer } from './utils/server'; function main() { const app = new Hono(); diff --git a/src/routes/index.ts b/src/routes/index.ts index 7422d21..42b58f7 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,8 +1,8 @@ -import { Hono } from "hono"; -import linkRouter from "./links-router"; +import { Hono } from 'hono'; +import linkRouter from './links-router'; const appRouter = new Hono(); -appRouter.route("/links", linkRouter); +appRouter.route('/links', linkRouter); export default appRouter; diff --git a/src/routes/links-router.ts b/src/routes/links-router.ts index 872cd7a..3c6202e 100644 --- a/src/routes/links-router.ts +++ b/src/routes/links-router.ts @@ -1,7 +1,7 @@ -import { Hono } from "hono"; +import { Hono } from 'hono'; const linkRouter = new Hono(); -linkRouter.get("/:id", (c) => c.json(`test get ${c.req.param("id")}`)); +linkRouter.get('/:id', c => c.json(`test get ${c.req.param('id')}`)); export default linkRouter; diff --git a/src/utils/db.ts b/src/utils/db.ts index 023c81c..6febaf8 100644 --- a/src/utils/db.ts +++ b/src/utils/db.ts @@ -1,5 +1,5 @@ -import config from "./env"; -import { type Db, MongoClient } from "mongodb"; +import config from './env'; +import { type Db, MongoClient } from 'mongodb'; let db: Db; diff --git a/src/utils/env.ts b/src/utils/env.ts index 4761109..89bda25 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -1,15 +1,15 @@ -import { config } from "dotenv"; -import { z } from "zod"; -import { MONGODB_URI_REGEX_PATTERN } from "./contants"; +import { config } from 'dotenv'; +import { z } from 'zod'; +import { MONGODB_URI_REGEX_PATTERN } from './contants'; config(); const envSchema = z.object({ - NODE_ENV: z.enum(["development", "production"]).default("development"), - PORT: z.string().regex(/^\d+$/).optional().default("5050"), - MONGODB_URI: z.string().refine((value) => { + NODE_ENV: z.enum(['development', 'production']).default('development'), + PORT: z.string().regex(/^\d+$/).optional().default('5050'), + MONGODB_URI: z.string().refine(value => { return MONGODB_URI_REGEX_PATTERN.test(value); - }, "Invalid MongoDB URI"), + }, 'Invalid MongoDB URI'), }); const parsedSchema = envSchema.parse(process.env); diff --git a/src/utils/errors.ts b/src/utils/errors.ts index f5b00b1..78d8ff8 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,71 +1,71 @@ -import consola from "consola"; -import type { NextFunction, Request, Response } from "express"; -import postgres from "postgres"; -import { ZodError } from "zod"; +import consola from 'consola'; +import type { NextFunction, Request, Response } from 'express'; +import postgres from 'postgres'; +import { ZodError } from 'zod'; type HttpErrorCode = - | "BAD_REQUEST" - | "UNAUTHORIZED" - | "NOT_FOUND" - | "METHOD_NOT_ALLOWED" - | "NOT_ACCEPTABLE" - | "REQUEST_TIMEOUT" - | "CONFLICT" - | "GONE" - | "LENGTH_REQUIRED" - | "PRECONDITION_FAILED" - | "PAYLOAD_TOO_LARGE" - | "URI_TOO_LONG" - | "UNSUPPORTED_MEDIA_TYPE" - | "RANGE_NOT_SATISFIABLE" - | "EXPECTATION_FAILED" - | "TEAPOT"; + | 'BAD_REQUEST' + | 'UNAUTHORIZED' + | 'NOT_FOUND' + | 'METHOD_NOT_ALLOWED' + | 'NOT_ACCEPTABLE' + | 'REQUEST_TIMEOUT' + | 'CONFLICT' + | 'GONE' + | 'LENGTH_REQUIRED' + | 'PRECONDITION_FAILED' + | 'PAYLOAD_TOO_LARGE' + | 'URI_TOO_LONG' + | 'UNSUPPORTED_MEDIA_TYPE' + | 'RANGE_NOT_SATISFIABLE' + | 'EXPECTATION_FAILED' + | 'TEAPOT'; type BackendErrorCode = - | "VALIDATION_ERROR" - | "USER_NOT_FOUND" - | "INVALID_PASSWORD"; + | 'VALIDATION_ERROR' + | 'USER_NOT_FOUND' + | 'INVALID_PASSWORD'; -type ErrorCode = HttpErrorCode | BackendErrorCode | "INTERNAL_ERROR"; +type ErrorCode = HttpErrorCode | BackendErrorCode | 'INTERNAL_ERROR'; export function getStatusFromErrorCode(code: ErrorCode): number { switch (code) { - case "BAD_REQUEST": - case "VALIDATION_ERROR": + case 'BAD_REQUEST': + case 'VALIDATION_ERROR': return 400; - case "UNAUTHORIZED": - case "INVALID_PASSWORD": + case 'UNAUTHORIZED': + case 'INVALID_PASSWORD': return 401; - case "NOT_FOUND": - case "USER_NOT_FOUND": + case 'NOT_FOUND': + case 'USER_NOT_FOUND': return 404; - case "METHOD_NOT_ALLOWED": + case 'METHOD_NOT_ALLOWED': return 405; - case "NOT_ACCEPTABLE": + case 'NOT_ACCEPTABLE': return 406; - case "REQUEST_TIMEOUT": + case 'REQUEST_TIMEOUT': return 408; - case "CONFLICT": + case 'CONFLICT': return 409; - case "GONE": + case 'GONE': return 410; - case "LENGTH_REQUIRED": + case 'LENGTH_REQUIRED': return 411; - case "PRECONDITION_FAILED": + case 'PRECONDITION_FAILED': return 412; - case "PAYLOAD_TOO_LARGE": + case 'PAYLOAD_TOO_LARGE': return 413; - case "URI_TOO_LONG": + case 'URI_TOO_LONG': return 414; - case "UNSUPPORTED_MEDIA_TYPE": + case 'UNSUPPORTED_MEDIA_TYPE': return 415; - case "RANGE_NOT_SATISFIABLE": + case 'RANGE_NOT_SATISFIABLE': return 416; - case "EXPECTATION_FAILED": + case 'EXPECTATION_FAILED': return 417; - case "TEAPOT": + case 'TEAPOT': return 418; // I'm a teapot - case "INTERNAL_ERROR": + case 'INTERNAL_ERROR': return 500; default: return 500; @@ -74,24 +74,24 @@ export function getStatusFromErrorCode(code: ErrorCode): number { export function getMessageFromErrorCode(code: ErrorCode): string { switch (code) { - case "BAD_REQUEST": - return "The request is invalid."; - case "VALIDATION_ERROR": - return "The request contains invalid or missing fields."; - case "UNAUTHORIZED": - return "You are not authorized to access this resource."; - case "NOT_FOUND": - return "The requested resource was not found."; - case "USER_NOT_FOUND": - return "The user was not found."; - case "INTERNAL_ERROR": - return "An internal server error occurred."; - case "CONFLICT": - return "The request conflicts with the current state of the server."; - case "INVALID_PASSWORD": - return "The password is incorrect."; + case 'BAD_REQUEST': + return 'The request is invalid.'; + case 'VALIDATION_ERROR': + return 'The request contains invalid or missing fields.'; + case 'UNAUTHORIZED': + return 'You are not authorized to access this resource.'; + case 'NOT_FOUND': + return 'The requested resource was not found.'; + case 'USER_NOT_FOUND': + return 'The user was not found.'; + case 'INTERNAL_ERROR': + return 'An internal server error occurred.'; + case 'CONFLICT': + return 'The request conflicts with the current state of the server.'; + case 'INVALID_PASSWORD': + return 'The password is incorrect.'; default: - return "An internal server error occurred."; + return 'An internal server error occurred.'; } } @@ -103,9 +103,9 @@ export function handleValidationError(err: ZodError): { const requiredFields = []; for (const error of err.errors) { - if (error.code === "invalid_type") invalidFields.push(error.path.join(".")); - else if (error.message === "Required") - requiredFields.push(error.path.join(".")); + if (error.code === 'invalid_type') invalidFields.push(error.path.join('.')); + else if (error.message === 'Required') + requiredFields.push(error.path.join('.')); } return { @@ -125,7 +125,7 @@ export class BackendError extends Error { }: { message?: string; details?: unknown; - } = {} + } = {}, ) { super(message ?? getMessageFromErrorCode(code)); this.code = code; @@ -141,7 +141,7 @@ export function errorHandler( message: string; details?: unknown; }>, - _next: NextFunction + _next: NextFunction, ) { let statusCode = 500; let code: ErrorCode | undefined; @@ -160,26 +160,26 @@ export function errorHandler( } if (error instanceof postgres.PostgresError) { - code = "INTERNAL_ERROR"; - message = "The DB crashed maybe because they dont like you :p"; + code = 'INTERNAL_ERROR'; + message = 'The DB crashed maybe because they dont like you :p'; statusCode = getStatusFromErrorCode(code); details = error; } if (error instanceof ZodError) { - code = "VALIDATION_ERROR"; + code = 'VALIDATION_ERROR'; message = getMessageFromErrorCode(code); details = handleValidationError(error); statusCode = getStatusFromErrorCode(code); } - if ((error as { code: string }).code === "ECONNREFUSED") { - code = "INTERNAL_ERROR"; - message = "The DB crashed maybe because they dont like you :p"; + if ((error as { code: string }).code === 'ECONNREFUSED') { + code = 'INTERNAL_ERROR'; + message = 'The DB crashed maybe because they dont like you :p'; details = error; } - code = code ?? "INTERNAL_ERROR"; + code = code ?? 'INTERNAL_ERROR'; message = message ?? getMessageFromErrorCode(code); details = details ?? error; @@ -193,10 +193,10 @@ export function errorHandler( } export function handle404Error(_req: Request, res: Response) { - const code: ErrorCode = "NOT_FOUND"; + const code: ErrorCode = 'NOT_FOUND'; res.status(getStatusFromErrorCode(code)).json({ code, - message: "Route not found", - details: "The route you are trying to access does not exist", + message: 'Route not found', + details: 'The route you are trying to access does not exist', }); } diff --git a/src/utils/server.ts b/src/utils/server.ts index e29be2b..c7bdbd1 100644 --- a/src/utils/server.ts +++ b/src/utils/server.ts @@ -1,14 +1,14 @@ -import type { Hono } from "hono"; -import appRouter from "../routes"; -import InitDatabase from "./db"; +import type { Hono } from 'hono'; +import appRouter from '../routes'; +import InitDatabase from './db'; export async function BootstrapServer(app: Hono) { await InitDatabase(); - console.log("✅ Database Connected!"); + console.log('✅ Database Connected!'); - app.get("/", (c) => { - return c.text("Hello Hono!"); + app.get('/', c => { + return c.text('Hello Hono!'); }); - app.route("api", appRouter); + app.route('api', appRouter); } diff --git a/tsconfig.json b/tsconfig.json index 667b7e7..a6697d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,10 +5,8 @@ "moduleResolution": "Bundler", "strict": true, "skipLibCheck": true, - "types": [ - "node" - ], + "types": ["node"], "jsx": "react-jsx", - "jsxImportSource": "hono/jsx", + "jsxImportSource": "hono/jsx" } -} \ No newline at end of file +}