refactor(lst): refactored to be back to npm from bun

This commit is contained in:
2025-02-27 08:36:05 -06:00
parent 4c73fb0317
commit 379f7b836d
75 changed files with 15693 additions and 2705 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,6 @@
dist
frontend/dist
server/dist
# ---> Node # ---> Node
bun.lock bun.lock
.nx .nx

View File

@@ -6,11 +6,11 @@
{"type": "docs", "section": "📚 Documentation"}, {"type": "docs", "section": "📚 Documentation"},
{"type": "style", "hidden": true}, {"type": "style", "hidden": true},
{"type": "refactor", "section": "🛠️ Code Refactor"}, {"type": "refactor", "section": "🛠️ Code Refactor"},
{"type": "perf", "hidden": false, "section": "🚀 Code Refactor"}, {"type": "perf", "hidden": false, "section": "🚀 Performance"},
{"type": "test", "section": "📝 Testing Code"}, {"type": "test", "section": "📝 Testing Code"},
{"type": "ci", "section": "📈 Project changes"} {"type": "ci", "section": "📈 Project changes"}
], ],
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits{{hash}}", "commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits{{hash}}",
"compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}", "compareUrlFormat": "https://git.tuffraid.net/cowch/lstV2/compare/{{previousTag}}...{{currentTag}}",
"header": "# All CHanges to LST can be found below.\n`" "header": "# All CHanges to LST can be found below.\n"
} }

View File

@@ -5,14 +5,14 @@ meta {
} }
post { post {
url: http://localhost:3000/api/auth/login url: http://localhost:4000/api/auth/login
body: json body: json
auth: none auth: none
} }
body:json { body:json {
{ {
"username": "adm_matthes", "username": "matthes01",
"password": "Nova0511!" "password": "99Monsters200Scary!"
} }
} }

View File

@@ -5,8 +5,8 @@ meta {
} }
get { get {
url: http://localhost:3000/api/server/modules url: http://localhost:4000/api/server/modules
body: json body: none
auth: none auth: none
} }

View File

@@ -1,5 +1,9 @@
import {drizzle} from "drizzle-orm/postgres-js"; import {drizzle} from "drizzle-orm/postgres-js";
import postgres from "postgres"; import postgres from "postgres";
import dotenv from "dotenv";
dotenv.config();
const database = process.env.DATABASE_URL || ""; const database = process.env.DATABASE_URL || "";
const queryClient = postgres(database); const queryClient = postgres(database);

View File

@@ -2,6 +2,7 @@ CREATE TABLE "modules" (
"module_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "module_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" text NOT NULL, "name" text NOT NULL,
"active" boolean DEFAULT false, "active" boolean DEFAULT false,
"roles" text DEFAULT '["view", "systemAdmin"]' NOT NULL,
"add_User" text DEFAULT 'LST_System' NOT NULL, "add_User" text DEFAULT 'LST_System' NOT NULL,
"add_Date" timestamp DEFAULT now(), "add_Date" timestamp DEFAULT now(),
"upd_User" text DEFAULT 'LST_System' NOT NULL, "upd_User" text DEFAULT 'LST_System' NOT NULL,
@@ -21,7 +22,24 @@ CREATE TABLE "userRoles" (
"user_id" uuid NOT NULL, "user_id" uuid NOT NULL,
"role_id" uuid NOT NULL, "role_id" uuid NOT NULL,
"module_id" uuid NOT NULL, "module_id" uuid NOT NULL,
"roles" text NOT NULL, "role" text NOT NULL,
"add_User" text DEFAULT 'LST_System' NOT NULL,
"add_Date" timestamp DEFAULT now(),
"upd_User" text DEFAULT 'LST_System' NOT NULL,
"upd_date" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE "users" (
"user_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"username" text NOT NULL,
"email" text NOT NULL,
"password" text NOT NULL,
"passwordToken" text,
"passwordTokenExpires" timestamp,
"active" boolean DEFAULT true NOT NULL,
"pingcode" numeric,
"role" text DEFAULT 'user' NOT NULL,
"lastLogin" timestamp DEFAULT now(),
"add_User" text DEFAULT 'LST_System' NOT NULL, "add_User" text DEFAULT 'LST_System' NOT NULL,
"add_Date" timestamp DEFAULT now(), "add_Date" timestamp DEFAULT now(),
"upd_User" text DEFAULT 'LST_System' NOT NULL, "upd_User" text DEFAULT 'LST_System' NOT NULL,
@@ -33,4 +51,5 @@ ALTER TABLE "userRoles" ADD CONSTRAINT "userRoles_role_id_roles_role_id_fk" FORE
ALTER TABLE "userRoles" ADD CONSTRAINT "userRoles_module_id_modules_module_id_fk" FOREIGN KEY ("module_id") REFERENCES "public"."modules"("module_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint ALTER TABLE "userRoles" ADD CONSTRAINT "userRoles_module_id_modules_module_id_fk" FOREIGN KEY ("module_id") REFERENCES "public"."modules"("module_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "module_name" ON "modules" USING btree ("name");--> statement-breakpoint CREATE UNIQUE INDEX "module_name" ON "modules" USING btree ("name");--> statement-breakpoint
CREATE UNIQUE INDEX "role_name" ON "roles" USING btree ("name");--> statement-breakpoint CREATE UNIQUE INDEX "role_name" ON "roles" USING btree ("name");--> statement-breakpoint
CREATE UNIQUE INDEX "user_module_unique" ON "userRoles" USING btree ("user_id","module_id"); CREATE UNIQUE INDEX "user_module_unique" ON "userRoles" USING btree ("user_id","module_id");--> statement-breakpoint
CREATE UNIQUE INDEX "username" ON "users" USING btree ("username");

View File

@@ -1,6 +1,6 @@
{ {
"id": "eb681265-0d44-4a8a-acaf-840acc169228", "id": "467c98f1-3785-42b5-80ed-528eac5fcbe4",
"prevId": "313590a8-2068-45b5-96fc-cfa5d2b32b56", "prevId": "00000000-0000-0000-0000-000000000000",
"version": "7", "version": "7",
"dialect": "postgresql", "dialect": "postgresql",
"tables": { "tables": {

View File

@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1740534974452,
"tag": "0000_nebulous_bulldozer",
"breakpoints": true
}
]
}

View File

@@ -1,9 +1,13 @@
import {defineConfig} from "drizzle-kit"; import {defineConfig} from "drizzle-kit";
const database = process.env.DATABASE_URL || ""; import dotenv from "dotenv";
dotenv.config();
const database = process.env.DATABASE_URL! || "";
export default defineConfig({ export default defineConfig({
dialect: "postgresql", // 'mysql' | 'sqlite' | 'turso' dialect: "postgresql", // 'mysql' | 'sqlite' | 'turso'
schema: "./server/database/schema/", schema: "database/schema",
out: "./server/database/migrations", out: "database/migrations",
dbCredentials: { dbCredentials: {
url: database, url: database,
}, },

View File

@@ -5,7 +5,7 @@
"tsx": true, "tsx": true,
"tailwind": { "tailwind": {
"config": "", "config": "",
"css": "src/styles.css", "css": "src/style.css",
"baseColor": "neutral", "baseColor": "neutral",
"cssVariables": true, "cssVariables": true,
"prefix": "" "prefix": ""

5597
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,17 @@
{ {
"name": "frontend", "name": "vitefix",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "bun --bun vite", "dev": "vite",
"build": "vite build", "build": "tsc -b && vite build",
"lint": "eslint .", "lint": "eslint .",
"preview": "vite preview" "preview": "vite preview",
"shad": "npx shadcn@canary add "
}, },
"dependencies": { "dependencies": {
"@antfu/ni": "^23.3.1", "@hookform/resolvers": "^4.1.2",
"@hookform/resolvers": "^4.1.0",
"@radix-ui/react-avatar": "^1.1.3", "@radix-ui/react-avatar": "^1.1.3",
"@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-collapsible": "^1.1.3", "@radix-ui/react-collapsible": "^1.1.3",
@@ -21,42 +21,38 @@
"@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.8", "@radix-ui/react-tooltip": "^1.1.8",
"@tailwindcss/vite": "^4.0.6", "@tailwindcss/vite": "^4.0.9",
"@tanstack/react-query": "^5.66.5", "@tanstack/react-query": "^5.66.9",
"@tanstack/react-router": "^1.106.0", "@tanstack/react-router": "^1.111.11",
"@tanstack/zod-form-adapter": "^0.42.1",
"@types/react-grid-layout": "^1.3.5",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"lucide-react": "^0.475.0", "lucide-react": "^0.476.0",
"next-themes": "^0.4.4", "next-themes": "^0.4.4",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-grid-layout": "^1.5.0", "react-grid-layout": "^1.5.0",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"shadcn": "^2.4.0-canary.6",
"sonner": "^2.0.1", "sonner": "^2.0.1",
"tailwind-merge": "^3.0.1", "tailwind-merge": "^3.0.2",
"tailwindcss": "^4.0.6", "tailwindcss": "^4.0.9",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"zod": "^3.24.2", "zod": "^3.24.2",
"zustand": "^5.0.3" "zustand": "^5.0.3"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.19.0", "@eslint/js": "^9.21.0",
"@tanstack/router-devtools": "^1.106.0", "@tanstack/router-devtools": "^1.106.0",
"@tanstack/router-plugin": "^1.106.0", "@tanstack/router-plugin": "^1.106.0",
"@types/node": "^22.13.4", "@types/react": "^19.0.10",
"@types/react": "^19.0.8", "@types/react-dom": "^19.0.4",
"@types/react-dom": "^19.0.3", "@vitejs/plugin-react-swc": "^3.8.0",
"@vitejs/plugin-react-swc": "^3.5.0", "eslint": "^9.21.0",
"eslint": "^9.19.0",
"eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.18", "eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.14.0", "globals": "^15.15.0",
"typescript": "~5.7.2", "typescript": "~5.7.2",
"typescript-eslint": "^8.22.0", "typescript-eslint": "^8.24.1",
"vite": "^6.1.0" "vite": "^6.2.0"
} }
} }

View File

@@ -1,36 +1,51 @@
import * as React from "react"; import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar"; import * as AvatarPrimitive from "@radix-ui/react-avatar"
import {cn} from "../../lib/utils"; import { cn } from "@/lib/utils"
function Avatar({className, ...props}: React.ComponentProps<typeof AvatarPrimitive.Root>) { function Avatar({
return ( className,
<AvatarPrimitive.Root ...props
data-slot="avatar" }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
className={cn("relative flex size-8 shrink-0 overflow-hidden rounded-full", className)} return (
{...props} <AvatarPrimitive.Root
/> data-slot="avatar"
); className={cn(
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
className
)}
{...props}
/>
)
} }
function AvatarImage({className, ...props}: React.ComponentProps<typeof AvatarPrimitive.Image>) { function AvatarImage({
return ( className,
<AvatarPrimitive.Image ...props
data-slot="avatar-image" }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
className={cn("aspect-square size-full", className)} return (
{...props} <AvatarPrimitive.Image
/> data-slot="avatar-image"
); className={cn("aspect-square size-full", className)}
{...props}
/>
)
} }
function AvatarFallback({className, ...props}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) { function AvatarFallback({
return ( className,
<AvatarPrimitive.Fallback ...props
data-slot="avatar-fallback" }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
className={cn("bg-muted flex size-full items-center justify-center rounded-full", className)} return (
{...props} <AvatarPrimitive.Fallback
/> data-slot="avatar-fallback"
); className={cn(
"bg-muted flex size-full items-center justify-center rounded-full",
className
)}
{...props}
/>
)
} }
export {Avatar, AvatarImage, AvatarFallback}; export { Avatar, AvatarImage, AvatarFallback }

View File

@@ -1,48 +1,58 @@
import * as React from "react"; import * as React from "react"
import {Slot} from "@radix-ui/react-slot"; import { Slot } from "@radix-ui/react-slot"
import {cva, type VariantProps} from "class-variance-authority"; import { cva, type VariantProps } from "class-variance-authority"
import {cn} from "../../lib/utils"; import { cn } from "@/lib/utils"
const buttonVariants = cva( const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 focus-visible:ring-4 focus-visible:outline-1 aria-invalid:focus-visible:ring-0", "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{ {
variants: { variants: {
variant: { variant: {
default: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90", default:
destructive: "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90", "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground", destructive:
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
ghost: "hover:bg-accent hover:text-accent-foreground", outline:
link: "text-primary underline-offset-4 hover:underline", "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
}, secondary:
size: { "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
default: "h-9 px-4 py-2 has-[>svg]:px-3", ghost: "hover:bg-accent hover:text-accent-foreground",
sm: "h-8 rounded-md px-3 has-[>svg]:px-2.5", link: "text-primary underline-offset-4 hover:underline",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4", },
icon: "size-9", size: {
}, default: "h-9 px-4 py-2 has-[>svg]:px-3",
}, sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
defaultVariants: { lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
variant: "default", icon: "size-9",
size: "default", },
}, },
} defaultVariants: {
); variant: "default",
size: "default",
},
}
)
function Button({ function Button({
className, className,
variant, variant,
size, size,
asChild = false, asChild = false,
...props ...props
}: React.ComponentProps<"button"> & }: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & { VariantProps<typeof buttonVariants> & {
asChild?: boolean; asChild?: boolean
}) { }) {
const Comp = asChild ? Slot : "button"; const Comp = asChild ? Slot : "button"
return <Comp data-slot="button" className={cn(buttonVariants({variant, size, className}))} {...props} />; return (
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
} }
export {Button, buttonVariants}; export { Button, buttonVariants }

View File

@@ -7,7 +7,7 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
<div <div
data-slot="card" data-slot="card"
className={cn( className={cn(
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border shadow-sm", "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
className className
)} )}
{...props} {...props}
@@ -19,7 +19,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
return ( return (
<div <div
data-slot="card-header" data-slot="card-header"
className={cn("flex flex-col gap-1.5 px-6 pt-6", className)} className={cn("flex flex-col gap-1.5 px-6", className)}
{...props} {...props}
/> />
) )
@@ -59,7 +59,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return ( return (
<div <div
data-slot="card-footer" data-slot="card-footer"
className={cn("flex items-center px-6 pb-6", className)} className={cn("flex items-center px-6", className)}
{...props} {...props}
/> />
) )

View File

@@ -12,14 +12,14 @@ function Checkbox({
<CheckboxPrimitive.Root <CheckboxPrimitive.Root
data-slot="checkbox" data-slot="checkbox"
className={cn( className={cn(
"peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", "peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
className className
)} )}
{...props} {...props}
> >
<CheckboxPrimitive.Indicator <CheckboxPrimitive.Indicator
data-slot="checkbox-indicator" data-slot="checkbox-indicator"
className="flex items-center justify-center text-current" className="flex items-center justify-center text-current transition-none"
> >
<CheckIcon className="size-3.5" /> <CheckIcon className="size-3.5" />
</CheckboxPrimitive.Indicator> </CheckboxPrimitive.Indicator>

View File

@@ -1,3 +1,5 @@
"use client"
import * as React from "react" import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
@@ -72,7 +74,7 @@ function DropdownMenuItem({
data-inset={inset} data-inset={inset}
data-variant={variant} data-variant={variant}
className={cn( className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/40 data-[variant=destructive]:focus:text-destructive-foreground data-[variant=destructive]:*:[svg]:!text-destructive-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className className
)} )}
{...props} {...props}
@@ -153,7 +155,7 @@ function DropdownMenuLabel({
data-slot="dropdown-menu-label" data-slot="dropdown-menu-label"
data-inset={inset} data-inset={inset}
className={cn( className={cn(
"px-2 py-1.5 text-sm font-semibold data-[inset]:pl-8", "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
className className
)} )}
{...props} {...props}

View File

@@ -11,7 +11,7 @@ function Label({
<LabelPrimitive.Root <LabelPrimitive.Root
data-slot="label" data-slot="label"
className={cn( className={cn(
"text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
className className
)} )}
{...props} {...props}

View File

@@ -1,28 +1,28 @@
"use client"; "use client"
import * as React from "react"; import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"; import * as SeparatorPrimitive from "@radix-ui/react-separator"
import {cn} from "../../lib/utils"; import { cn } from "@/lib/utils"
function Separator({ function Separator({
className, className,
orientation = "horizontal", orientation = "horizontal",
decorative = true, decorative = true,
...props ...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) { }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
return ( return (
<SeparatorPrimitive.Root <SeparatorPrimitive.Root
data-slot="separator-root" data-slot="separator-root"
decorative={decorative} decorative={decorative}
orientation={orientation} orientation={orientation}
className={cn( className={cn(
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
className className
)} )}
{...props} {...props}
/> />
); )
} }
export {Separator}; export { Separator }

View File

@@ -1,101 +1,137 @@
import * as React from "react"; import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"; import * as SheetPrimitive from "@radix-ui/react-dialog"
import {XIcon} from "lucide-react"; import { XIcon } from "lucide-react"
import {cn} from "../../lib/utils"; import { cn } from "@/lib/utils"
function Sheet({...props}: React.ComponentProps<typeof SheetPrimitive.Root>) { function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />; return <SheetPrimitive.Root data-slot="sheet" {...props} />
} }
function SheetTrigger({...props}: React.ComponentProps<typeof SheetPrimitive.Trigger>) { function SheetTrigger({
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />; ...props
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
} }
function SheetClose({...props}: React.ComponentProps<typeof SheetPrimitive.Close>) { function SheetClose({
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />; ...props
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
} }
function SheetPortal({...props}: React.ComponentProps<typeof SheetPrimitive.Portal>) { function SheetPortal({
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />; ...props
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
} }
function SheetOverlay({className, ...props}: React.ComponentProps<typeof SheetPrimitive.Overlay>) { function SheetOverlay({
return ( className,
<SheetPrimitive.Overlay ...props
data-slot="sheet-overlay" }: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
className={cn( return (
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80", <SheetPrimitive.Overlay
className data-slot="sheet-overlay"
)} className={cn(
{...props} "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
/> className
); )}
{...props}
/>
)
} }
function SheetContent({ function SheetContent({
className, className,
children, children,
side = "right", side = "right",
...props ...props
}: React.ComponentProps<typeof SheetPrimitive.Content> & { }: React.ComponentProps<typeof SheetPrimitive.Content> & {
side?: "top" | "right" | "bottom" | "left"; side?: "top" | "right" | "bottom" | "left"
}) { }) {
return ( return (
<SheetPortal> <SheetPortal>
<SheetOverlay /> <SheetOverlay />
<SheetPrimitive.Content <SheetPrimitive.Content
data-slot="sheet-content" data-slot="sheet-content"
className={cn( className={cn(
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500", "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
side === "right" && side === "right" &&
"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm", "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
side === "left" && side === "left" &&
"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm", "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
side === "top" && side === "top" &&
"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b", "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
side === "bottom" && side === "bottom" &&
"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t", "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
className className
)} )}
{...props} {...props}
> >
{children} {children}
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none"> <SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<XIcon className="size-4" /> <XIcon className="size-4" />
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</SheetPrimitive.Close> </SheetPrimitive.Close>
</SheetPrimitive.Content> </SheetPrimitive.Content>
</SheetPortal> </SheetPortal>
); )
} }
function SheetHeader({className, ...props}: React.ComponentProps<"div">) { function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
return <div data-slot="sheet-header" className={cn("flex flex-col gap-1.5 p-4", className)} {...props} />; return (
<div
data-slot="sheet-header"
className={cn("flex flex-col gap-1.5 p-4", className)}
{...props}
/>
)
} }
function SheetFooter({className, ...props}: React.ComponentProps<"div">) { function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
return <div data-slot="sheet-footer" className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} />; return (
<div
data-slot="sheet-footer"
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
{...props}
/>
)
} }
function SheetTitle({className, ...props}: React.ComponentProps<typeof SheetPrimitive.Title>) { function SheetTitle({
return ( className,
<SheetPrimitive.Title ...props
data-slot="sheet-title" }: React.ComponentProps<typeof SheetPrimitive.Title>) {
className={cn("text-foreground font-semibold tracking-tight", className)} return (
{...props} <SheetPrimitive.Title
/> data-slot="sheet-title"
); className={cn("text-foreground font-semibold", className)}
{...props}
/>
)
} }
function SheetDescription({className, ...props}: React.ComponentProps<typeof SheetPrimitive.Description>) { function SheetDescription({
return ( className,
<SheetPrimitive.Description ...props
data-slot="sheet-description" }: React.ComponentProps<typeof SheetPrimitive.Description>) {
className={cn("text-muted-foreground text-sm", className)} return (
{...props} <SheetPrimitive.Description
/> data-slot="sheet-description"
); className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
} }
export {Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription}; export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,13 @@
import {cn} from "../../lib/utils"; import { cn } from "@/lib/utils"
function Skeleton({className, ...props}: React.ComponentProps<"div">) { function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
return <div data-slot="skeleton" className={cn("bg-primary/10 animate-pulse rounded-md", className)} {...props} />; return (
<div
data-slot="skeleton"
className={cn("bg-primary/10 animate-pulse rounded-md", className)}
{...props}
/>
)
} }
export {Skeleton}; export { Skeleton }

View File

@@ -1,48 +1,59 @@
"use client"; import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
import * as React from "react"; import { cn } from "@/lib/utils"
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import {cn} from "../../lib/utils"; function TooltipProvider({
delayDuration = 0,
function TooltipProvider({delayDuration = 0, ...props}: React.ComponentProps<typeof TooltipPrimitive.Provider>) { ...props
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />; }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
{...props}
/>
)
} }
function Tooltip({...props}: React.ComponentProps<typeof TooltipPrimitive.Root>) { function Tooltip({
return ( ...props
<TooltipProvider> }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
<TooltipPrimitive.Root data-slot="tooltip" {...props} /> return (
</TooltipProvider> <TooltipProvider>
); <TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
)
} }
function TooltipTrigger({...props}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) { function TooltipTrigger({
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />; ...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
} }
function TooltipContent({ function TooltipContent({
className, className,
sideOffset = 4, sideOffset = 0,
children, children,
...props ...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) { }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
return ( return (
<TooltipPrimitive.Portal> <TooltipPrimitive.Portal>
<TooltipPrimitive.Content <TooltipPrimitive.Content
data-slot="tooltip-content" data-slot="tooltip-content"
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-w-sm rounded-md px-3 py-1.5 text-xs", "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit rounded-md px-3 py-1.5 text-xs text-balance",
className className
)} )}
{...props} {...props}
> >
{children} {children}
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" /> <TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
</TooltipPrimitive.Content> </TooltipPrimitive.Content>
</TooltipPrimitive.Portal> </TooltipPrimitive.Portal>
); )
} }
export {Tooltip, TooltipTrigger, TooltipContent, TooltipProvider}; export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }

View File

@@ -1,6 +1,6 @@
import { clsx, type ClassValue } from "clsx" import {clsx, type ClassValue} from "clsx";
import { twMerge } from "tailwind-merge" import {twMerge} from "tailwind-merge";
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)) return twMerge(clsx(inputs));
} }

View File

@@ -5,74 +5,74 @@
@custom-variant dark (&:is(.dark *)); @custom-variant dark (&:is(.dark *));
:root { :root {
--background: hsl(0 0% 100%); --background: oklch(1 0 0);
--foreground: hsl(0 0% 3.9%); --foreground: oklch(0.145 0 0);
--card: hsl(0 0% 100%); --card: oklch(1 0 0);
--card-foreground: hsl(0 0% 3.9%); --card-foreground: oklch(0.145 0 0);
--popover: hsl(0 0% 100%); --popover: oklch(1 0 0);
--popover-foreground: hsl(0 0% 3.9%); --popover-foreground: oklch(0.145 0 0);
--primary: hsl(0 0% 9%); --primary: oklch(0.205 0 0);
--primary-foreground: hsl(0 0% 98%); --primary-foreground: oklch(0.985 0 0);
--secondary: hsl(0 0% 96.1%); --secondary: oklch(0.97 0 0);
--secondary-foreground: hsl(0 0% 9%); --secondary-foreground: oklch(0.205 0 0);
--muted: hsl(0 0% 96.1%); --muted: oklch(0.97 0 0);
--muted-foreground: hsl(0 0% 45.1%); --muted-foreground: oklch(0.556 0 0);
--accent: hsl(0 0% 96.1%); --accent: oklch(0.97 0 0);
--accent-foreground: hsl(0 0% 9%); --accent-foreground: oklch(0.205 0 0);
--destructive: hsl(0 84.2% 60.2%); --destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: hsl(0 0% 98%); --destructive-foreground: oklch(0.577 0.245 27.325);
--border: hsl(0 0% 89.8%); --border: oklch(0.922 0 0);
--input: hsl(0 0% 89.8%); --input: oklch(0.922 0 0);
--ring: hsl(0 0% 3.9%); --ring: oklch(0.87 0 0);
--chart-1: hsl(12 76% 61%); --chart-1: oklch(0.646 0.222 41.116);
--chart-2: hsl(173 58% 39%); --chart-2: oklch(0.6 0.118 184.704);
--chart-3: hsl(197 37% 24%); --chart-3: oklch(0.398 0.07 227.392);
--chart-4: hsl(43 74% 66%); --chart-4: oklch(0.828 0.189 84.429);
--chart-5: hsl(27 87% 67%); --chart-5: oklch(0.769 0.188 70.08);
--radius: 0.6rem; --radius: 0.625rem;
--sidebar: hsl(0 0% 98%); --sidebar: oklch(0.985 0 0);
--sidebar-foreground: hsl(240 5.3% 26.1%); --sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: hsl(240 5.9% 10%); --sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: hsl(0 0% 98%); --sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: hsl(240 4.8% 95.9%); --sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: hsl(240 5.9% 10%); --sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: hsl(220 13% 91%); --sidebar-border: oklch(0.922 0 0);
--sidebar-ring: hsl(217.2 91.2% 59.8%); --sidebar-ring: oklch(0.87 0 0);
} }
.dark { .dark {
--background: hsl(0 0% 3.9%); --background: oklch(0.145 0 0);
--foreground: hsl(0 0% 98%); --foreground: oklch(0.985 0 0);
--card: hsl(0 0% 3.9%); --card: oklch(0.145 0 0);
--card-foreground: hsl(0 0% 98%); --card-foreground: oklch(0.985 0 0);
--popover: hsl(0 0% 3.9%); --popover: oklch(0.145 0 0);
--popover-foreground: hsl(0 0% 98%); --popover-foreground: oklch(0.985 0 0);
--primary: hsl(0 0% 98%); --primary: oklch(0.985 0 0);
--primary-foreground: hsl(0 0% 9%); --primary-foreground: oklch(0.205 0 0);
--secondary: hsl(0 0% 14.9%); --secondary: oklch(0.269 0 0);
--secondary-foreground: hsl(0 0% 98%); --secondary-foreground: oklch(0.985 0 0);
--muted: hsl(0 0% 14.9%); --muted: oklch(0.269 0 0);
--muted-foreground: hsl(0 0% 63.9%); --muted-foreground: oklch(0.708 0 0);
--accent: hsl(0 0% 14.9%); --accent: oklch(0.269 0 0);
--accent-foreground: hsl(0 0% 98%); --accent-foreground: oklch(0.985 0 0);
--destructive: hsl(0 62.8% 30.6%); --destructive: oklch(0.396 0.141 25.723);
--destructive-foreground: hsl(0 0% 98%); --destructive-foreground: oklch(0.637 0.237 25.331);
--border: hsl(0 0% 14.9%); --border: oklch(0.269 0 0);
--input: hsl(0 0% 14.9%); --input: oklch(0.269 0 0);
--ring: hsl(0 0% 83.1%); --ring: oklch(0.439 0 0);
--chart-1: hsl(220 70% 50%); --chart-1: oklch(0.488 0.243 264.376);
--chart-2: hsl(160 60% 45%); --chart-2: oklch(0.696 0.17 162.48);
--chart-3: hsl(30 80% 55%); --chart-3: oklch(0.769 0.188 70.08);
--chart-4: hsl(280 65% 60%); --chart-4: oklch(0.627 0.265 303.9);
--chart-5: hsl(340 75% 55%); --chart-5: oklch(0.645 0.246 16.439);
--sidebar: hsl(240 5.9% 10%); --sidebar: oklch(0.205 0 0);
--sidebar-foreground: hsl(240 4.8% 95.9%); --sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: hsl(224.3 76.3% 48%); --sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: hsl(0 0% 100%); --sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: hsl(240 3.7% 15.9%); --sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: hsl(240 4.8% 95.9%); --sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: hsl(240 3.7% 15.9%); --sidebar-border: oklch(0.269 0 0);
--sidebar-ring: hsl(217.2 91.2% 59.8%); --sidebar-ring: oklch(0.439 0 0);
} }
@theme inline { @theme inline {
@@ -104,14 +104,14 @@
--radius-md: calc(var(--radius) - 2px); --radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius); --radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px); --radius-xl: calc(var(--radius) + 4px);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar); --color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
} }
@layer base { @layer base {

View File

@@ -1,26 +1,30 @@
{ {
"compilerOptions": { "compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020", "target": "ES2020",
"useDefineForClassFields": true, "useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"], "lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext", "module": "ESNext",
"skipLibCheck": true, "skipLibCheck": true,
/* Bundler mode */ /* Bundler mode */
"moduleResolution": "bundler", "moduleResolution": "bundler",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"isolatedModules": true, "isolatedModules": true,
"moduleDetection": "force", "moduleDetection": "force",
"noEmit": true, "noEmit": true,
"jsx": "react-jsx", "jsx": "react-jsx",
/* Linting */ /* Linting */
"strict": true, "strict": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true "noUncheckedSideEffectImports": true,
}, "baseUrl": ".",
"include": ["src"] "paths": {
"@/*": ["./src/*"]
}
},
"include": ["src"]
} }

View File

@@ -2,7 +2,7 @@
"files": [], "files": [],
"references": [{"path": "./tsconfig.app.json"}, {"path": "./tsconfig.node.json"}], "references": [{"path": "./tsconfig.app.json"}, {"path": "./tsconfig.node.json"}],
"compilerOptions": { "compilerOptions": {
// "baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} }

View File

@@ -7,10 +7,6 @@ import path from "path";
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react(), tailwindcss(), TanStackRouterVite({autoCodeSplitting: true})], plugins: [react(), tailwindcss(), TanStackRouterVite({autoCodeSplitting: true})],
// build: {
// outDir: path.resolve(__dirname, "../../dist/frontend/dist"),
// emptyOutDir: true,
// },
resolve: { resolve: {
alias: { alias: {
"@": path.resolve(__dirname, "./src"), "@": path.resolve(__dirname, "./src"),
@@ -18,7 +14,7 @@ export default defineConfig({
}, },
server: { server: {
proxy: { proxy: {
"/api": {target: `http://localhost:4000`, changeOrigin: true}, "/api": {target: `http://localhost:4400`, changeOrigin: true},
}, },
}, },
}); });

10
globals.d.ts vendored
View File

@@ -1,10 +0,0 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
JWT_SECRET: string;
JWT_EXPIRES: string;
}
}
}
export {};

View File

@@ -1,10 +0,0 @@
const path = require("path");
const dotenv = require("dotenv");
const dotenvExpand = require("dotenv-expand");
// Load the root .env file
const envPath = path.resolve(__dirname, ".env");
const envConfig = dotenv.config({path: envPath});
// Expand variables (e.g., `${VAR}`) in the .env file
dotenvExpand.expand(envConfig);

6574
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +1,40 @@
{ {
"name": "lstv2", "name": "fullstack-app",
"version": "1.2.0", "version": "1.0.0",
"description": "", "type": "module",
"main": "index.ts",
"scripts": { "scripts": {
"dev": "concurrently -n 'server,frontend' -c '#007755,#2f6da3' 'bun --watch server/index.ts' 'cd frontend && bunx --bun vite'", "dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
"dev:server": "bun --watch server/index.ts", "dev:server": "dotenvx run -f .env -- tsx watch server/src/index.ts",
"dev:ocme": "bun --watch ocme/index.ts", "dev:frontend": "cd frontend && npm run dev",
"dev:front": "cd frontend && bunx --bun vite", "build": "npm run build:server && npm run build:frontend",
"build:server": "cd apps/server && bun build index.js --outdir ../../dist/server", "build:server": "cd server && npm run build",
"build:ocme": "rimraf dist/ocme && cd apps/ocme && bun build index.js --outdir ../../dist/ocme", "build:frontend": "cd frontend && npm run build",
"build:front": "cd frontend && rimraf frontend/dist && bun run build", "start": "npm run start:server",
"start": "bun --env-file .env server/index.js", "start:server": "cd server && npm start",
"commit": "cz", "db:generate": "npx drizzle-kit generate",
"clean": "rimraf dist/server", "db:migrate": "npx drizzle-kit push",
"deploy": "standard-version --conventional-commits", "deploy": "standard-version --conventional-commits",
"ui:add": "cd frontend && bun shadcn add ", "commit": "cz"
"db:dev": "bun drizzle-kit generate && bun drizzle-kit migrate"
}, },
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": { "dependencies": {
"@dotenvx/dotenvx": "^1.35.0", "@dotenvx/dotenvx": "^1.38.3",
"@hono/zod-openapi": "^0.18.4", "hono": "^4.7.2",
"@scalar/hono-api-reference": "^0.5.175",
"@types/bun": "^1.2.2",
"@types/jsonwebtoken": "^9.0.8",
"axios": "^1.7.9",
"bcrypt": "^5.1.1",
"compression": "^1.8.0",
"cookie": "^1.0.2",
"date-fns": "^4.1.0",
"drizzle-orm": "^0.39.3", "drizzle-orm": "^0.39.3",
"drizzle-zod": "^0.7.0", "drizzle-zod": "^0.7.0",
"hono": "^4.7.1",
"jsonwebtoken": "^9.0.2",
"pg": "^8.13.3", "pg": "^8.13.3",
"postgres": "^3.4.5", "postgres": "^3.4.5",
"zod": "^3.24.2" "zod": "^3.24.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.13.5",
"concurrently": "^8.2.0",
"dotenv": "^16.3.1",
"drizzle-kit": "^0.30.4",
"tsx": "^4.7.1",
"@types/bcrypt": "^5.0.2", "@types/bcrypt": "^5.0.2",
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"@types/pg": "^8.11.11", "@types/pg": "^8.11.11",
"concurrently": "^9.1.2",
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",
"drizzle-kit": "^0.30.4",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"standard-version": "^9.5.0", "standard-version": "^9.5.0",
"typescript": "~5.7.3" "typescript": "~5.7.3"

28
server/.gitignore vendored Normal file
View File

@@ -0,0 +1,28 @@
# dev
.yarn/
!.yarn/releases
.vscode/*
!.vscode/launch.json
!.vscode/*.code-snippets
.idea/workspace.xml
.idea/usage.statistics.xml
.idea/shelf
# deps
node_modules/
# env
.env
.env.production
# logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# misc
.DS_Store

8
server/README.md Normal file
View File

@@ -0,0 +1,8 @@
```
npm install
npm run dev
```
```
open http://localhost:3000
```

View File

@@ -1,15 +0,0 @@
CREATE TABLE "users" (
"user_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"username" text NOT NULL,
"email" text NOT NULL,
"password" text NOT NULL,
"passwordToken" text,
"passwordTokenExpires" timestamp,
"active" boolean DEFAULT true NOT NULL,
"pingcode" numeric,
"lastLogin" timestamp DEFAULT now(),
"add_User" text DEFAULT 'LST_System' NOT NULL,
"add_Date" timestamp DEFAULT now(),
"upd_User" text DEFAULT 'LST_System' NOT NULL,
"upd_date" timestamp DEFAULT now()
);

View File

@@ -1 +0,0 @@
CREATE UNIQUE INDEX "username" ON "users" USING btree ("username");

View File

@@ -1,2 +0,0 @@
ALTER TABLE "userRoles" RENAME COLUMN "roles" TO "role";--> statement-breakpoint
ALTER TABLE "modules" ADD COLUMN "roles" text NOT NULL;

View File

@@ -1 +0,0 @@
ALTER TABLE "modules" ALTER COLUMN "roles" SET DEFAULT '["view", "systemAdmin"]';

View File

@@ -1 +0,0 @@
ALTER TABLE "users" ADD COLUMN "role" text DEFAULT 'user' NOT NULL;

View File

@@ -1,117 +0,0 @@
{
"id": "d1b4a8a6-caa3-4c45-a3a1-cdfc99ca7bea",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.users": {
"name": "users",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true
},
"passwordToken": {
"name": "passwordToken",
"type": "text",
"primaryKey": false,
"notNull": false
},
"passwordTokenExpires": {
"name": "passwordTokenExpires",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"pingcode": {
"name": "pingcode",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"lastLogin": {
"name": "lastLogin",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,133 +0,0 @@
{
"id": "d6c99236-0eea-49f1-817b-13139c0f42f5",
"prevId": "d1b4a8a6-caa3-4c45-a3a1-cdfc99ca7bea",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.users": {
"name": "users",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true
},
"passwordToken": {
"name": "passwordToken",
"type": "text",
"primaryKey": false,
"notNull": false
},
"passwordTokenExpires": {
"name": "passwordTokenExpires",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"pingcode": {
"name": "pingcode",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"lastLogin": {
"name": "lastLogin",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"username": {
"name": "username",
"columns": [
{
"expression": "username",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,407 +0,0 @@
{
"id": "9a2ddf11-fd30-4dd9-bf2d-259fe7aed201",
"prevId": "d6c99236-0eea-49f1-817b-13139c0f42f5",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.modules": {
"name": "modules",
"schema": "",
"columns": {
"module_id": {
"name": "module_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"module_name": {
"name": "module_name",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.roles": {
"name": "roles",
"schema": "",
"columns": {
"role_id": {
"name": "role_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"role_name": {
"name": "role_name",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.userRoles": {
"name": "userRoles",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"role_id": {
"name": "role_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"module_id": {
"name": "module_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"roles": {
"name": "roles",
"type": "text",
"primaryKey": false,
"notNull": true
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"user_module_unique": {
"name": "user_module_unique",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "module_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"userRoles_user_id_users_user_id_fk": {
"name": "userRoles_user_id_users_user_id_fk",
"tableFrom": "userRoles",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"user_id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userRoles_role_id_roles_role_id_fk": {
"name": "userRoles_role_id_roles_role_id_fk",
"tableFrom": "userRoles",
"tableTo": "roles",
"columnsFrom": [
"role_id"
],
"columnsTo": [
"role_id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userRoles_module_id_modules_module_id_fk": {
"name": "userRoles_module_id_modules_module_id_fk",
"tableFrom": "userRoles",
"tableTo": "modules",
"columnsFrom": [
"module_id"
],
"columnsTo": [
"module_id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true
},
"passwordToken": {
"name": "passwordToken",
"type": "text",
"primaryKey": false,
"notNull": false
},
"passwordTokenExpires": {
"name": "passwordTokenExpires",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"pingcode": {
"name": "pingcode",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"lastLogin": {
"name": "lastLogin",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"username": {
"name": "username",
"columns": [
{
"expression": "username",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,413 +0,0 @@
{
"id": "ad424668-721e-414f-ad0b-a8e7301e50c6",
"prevId": "9a2ddf11-fd30-4dd9-bf2d-259fe7aed201",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.modules": {
"name": "modules",
"schema": "",
"columns": {
"module_id": {
"name": "module_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"roles": {
"name": "roles",
"type": "text",
"primaryKey": false,
"notNull": true
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"module_name": {
"name": "module_name",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.roles": {
"name": "roles",
"schema": "",
"columns": {
"role_id": {
"name": "role_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"role_name": {
"name": "role_name",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.userRoles": {
"name": "userRoles",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"role_id": {
"name": "role_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"module_id": {
"name": "module_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"user_module_unique": {
"name": "user_module_unique",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "module_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"userRoles_user_id_users_user_id_fk": {
"name": "userRoles_user_id_users_user_id_fk",
"tableFrom": "userRoles",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"user_id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userRoles_role_id_roles_role_id_fk": {
"name": "userRoles_role_id_roles_role_id_fk",
"tableFrom": "userRoles",
"tableTo": "roles",
"columnsFrom": [
"role_id"
],
"columnsTo": [
"role_id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userRoles_module_id_modules_module_id_fk": {
"name": "userRoles_module_id_modules_module_id_fk",
"tableFrom": "userRoles",
"tableTo": "modules",
"columnsFrom": [
"module_id"
],
"columnsTo": [
"module_id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true
},
"passwordToken": {
"name": "passwordToken",
"type": "text",
"primaryKey": false,
"notNull": false
},
"passwordTokenExpires": {
"name": "passwordTokenExpires",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"pingcode": {
"name": "pingcode",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"lastLogin": {
"name": "lastLogin",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"username": {
"name": "username",
"columns": [
{
"expression": "username",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,414 +0,0 @@
{
"id": "313590a8-2068-45b5-96fc-cfa5d2b32b56",
"prevId": "ad424668-721e-414f-ad0b-a8e7301e50c6",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.modules": {
"name": "modules",
"schema": "",
"columns": {
"module_id": {
"name": "module_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"roles": {
"name": "roles",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'[\"view\", \"systemAdmin\"]'"
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"module_name": {
"name": "module_name",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.roles": {
"name": "roles",
"schema": "",
"columns": {
"role_id": {
"name": "role_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"role_name": {
"name": "role_name",
"columns": [
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.userRoles": {
"name": "userRoles",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"role_id": {
"name": "role_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"module_id": {
"name": "module_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"user_module_unique": {
"name": "user_module_unique",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "module_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"userRoles_user_id_users_user_id_fk": {
"name": "userRoles_user_id_users_user_id_fk",
"tableFrom": "userRoles",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"user_id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userRoles_role_id_roles_role_id_fk": {
"name": "userRoles_role_id_roles_role_id_fk",
"tableFrom": "userRoles",
"tableTo": "roles",
"columnsFrom": [
"role_id"
],
"columnsTo": [
"role_id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"userRoles_module_id_modules_module_id_fk": {
"name": "userRoles_module_id_modules_module_id_fk",
"tableFrom": "userRoles",
"tableTo": "modules",
"columnsFrom": [
"module_id"
],
"columnsTo": [
"module_id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true
},
"passwordToken": {
"name": "passwordToken",
"type": "text",
"primaryKey": false,
"notNull": false
},
"passwordTokenExpires": {
"name": "passwordTokenExpires",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"active": {
"name": "active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"pingcode": {
"name": "pingcode",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"lastLogin": {
"name": "lastLogin",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"add_User": {
"name": "add_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"add_Date": {
"name": "add_Date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"upd_User": {
"name": "upd_User",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'LST_System'"
},
"upd_date": {
"name": "upd_date",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {
"username": {
"name": "username",
"columns": [
{
"expression": "username",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,48 +0,0 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1740160921910,
"tag": "0000_typical_frightful_four",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1740161259149,
"tag": "0001_sharp_pet_avengers",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1740361491818,
"tag": "0002_bitter_oracle",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1740362541964,
"tag": "0003_luxuriant_namorita",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1740364483791,
"tag": "0004_quick_mandrill",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1740445275919,
"tag": "0005_tough_emma_frost",
"breakpoints": true
}
]
}

10
server/drizzle.config.js Normal file
View File

@@ -0,0 +1,10 @@
import { defineConfig } from "drizzle-kit";
const database = process.env.DATABASE_URL || "";
export default defineConfig({
dialect: "postgresql",
schema: "database/schema",
out: "database/migrations",
dbCredentials: {
url: database,
},
});

View File

@@ -1,14 +0,0 @@
import app from "./src/app";
const port = process.env.SERVER_PORT || 4000;
Bun.serve({
port,
fetch: app.fetch,
hostname: "0.0.0.0",
});
// await Bun.build({
// entrypoints: ["./index.js"],
// outdir: "../../dist/server",
// });
console.log(`server is running on port ${port}`);

2123
server/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

31
server/package.json Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "server",
"type": "module",
"scripts": {
"dev": "dotenvx run -f ../.env -- tsx watch src/index.ts",
"build": "rimraf dist && tsc --build",
"start": "dotenvx run node dist/server/src/index.js"
},
"dependencies": {
"@hono/node-server": "^1.13.8",
"@dotenvx/dotenvx": "^1.35.0",
"@hono/zod-openapi": "^0.18.4",
"@scalar/hono-api-reference": "^0.5.175",
"@types/jsonwebtoken": "^9.0.8",
"axios": "^1.7.9",
"bcrypt": "^5.1.1",
"compression": "^1.8.0",
"cookie": "^1.0.2",
"date-fns": "^4.1.0",
"dotenv": "^16.4.7",
"drizzle-orm": "^0.39.3",
"drizzle-zod": "^0.7.0",
"jsonwebtoken": "^9.0.2",
"pg": "^8.13.3",
"postgres": "^3.4.5",
"zod": "^3.24.2"
},
"devDependencies": {
"typescript": "~5.7.3"
}
}

View File

@@ -1,62 +0,0 @@
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
import {serveStatic} from "hono/bun";
import {logger} from "hono/logger";
import {cors} from "hono/cors";
import {OpenAPIHono} from "@hono/zod-openapi";
//routes
import auth from "./services/auth/authService";
import scalar from "./services/general/route/scalar";
import apiHits from "./services/general/route/apitHits";
import system from "./services/system/systemServer";
const app = new OpenAPIHono();
app.use("*", logger());
const allowedOrigins = ["http://localhost:3000", "http://localhost:4000", "http://localhost:5173"];
app.use(
"*",
cors({
origin: allowedOrigins,
allowHeaders: ["X-Custom-Header", "Upgrade-Insecure-Requests"],
allowMethods: ["POST", "GET", "OPTIONS"],
exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
maxAge: 600,
credentials: true,
})
);
app.doc("/api", {
openapi: "3.0.0",
info: {
version: "1.0.0",
title: "LST API",
},
});
// as we dont want to change ocme again well use a proxy to this
// app.all("/ocme/*", async (c) => {
// return ocmeService(c);
// });
const routes = [scalar, auth, apiHits, system] as const;
routes.forEach((route) => {
app.route("/api/", route);
});
//app.basePath("/api/auth").route("/login", login).route("/session", session).route("/register", register);
//auth stuff
// app.get("/api/protected", authMiddleware, (c) => {
// return c.json({success: true, message: "is authenticated"});
// });
app.get("*", serveStatic({root: "./frontend/dist"}));
app.get("*", serveStatic({path: "./frontend/dist/index.html"}));
export default app;
//export type ApiRoute = typeof apiRoute;

26
server/src/globalUtils/apiHits.d.ts vendored Normal file
View File

@@ -0,0 +1,26 @@
import type { Context } from "hono";
import { z } from "zod";
declare const requestSchema: z.ZodObject<{
ip: z.ZodOptional<z.ZodString>;
endpoint: z.ZodString;
action: z.ZodOptional<z.ZodString>;
stats: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
ip?: string;
endpoint?: string;
action?: string;
stats?: string;
}, {
ip?: string;
endpoint?: string;
action?: string;
stats?: string;
}>;
type ApiHitData = z.infer<typeof requestSchema>;
export declare const apiHit: (c: Context, data: unknown) => Promise<{
success: boolean;
data?: ApiHitData;
errors?: any[];
}>;
export {};
//# sourceMappingURL=apiHits.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"apiHits.d.ts","sourceRoot":"","sources":["apiHits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAClC,OAAO,EAAC,CAAC,EAAW,MAAM,KAAK,CAAC;AAGhC,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;EAKjB,CAAC;AAEH,KAAK,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD,eAAO,MAAM,MAAM,MACZ,OAAO,QACJ,OAAO,KACd,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAA;CAAC,CAuB/D,CAAC"}

View File

@@ -0,0 +1,20 @@
import { z, ZodError } from "zod";
const requestSchema = z.object({
ip: z.string().optional(),
endpoint: z.string(),
action: z.string().optional(),
stats: z.string().optional(),
});
export const apiHit = async (c, data) => {
try {
const forwarded = c.req.header("host");
const validatedData = requestSchema.parse(data);
return { success: true, data: validatedData };
}
catch (error) {
if (error instanceof ZodError) {
return { success: false, errors: error.errors };
}
return { success: false, errors: [{ message: "An unknown error occurred" }] };
}
};

View File

@@ -1,5 +1,6 @@
import type {Context} from "hono";
import {z, ZodError} from "zod"; import {z, ZodError} from "zod";
import {Context} from "hono";
// Define the request body schema // Define the request body schema
const requestSchema = z.object({ const requestSchema = z.object({
ip: z.string().optional(), ip: z.string().optional(),

71
server/src/index.ts Normal file
View File

@@ -0,0 +1,71 @@
import {serve} from "@hono/node-server";
import {OpenAPIHono} from "@hono/zod-openapi";
import {serveStatic} from "@hono/node-server/serve-static";
import {logger} from "hono/logger";
import {cors} from "hono/cors";
import {db} from "../../database/dbclient.js";
import {modules} from "../../database/schema/modules.js";
// custom routes
import scalar from "./services/general/route/scalar.js";
import system from "./services/server/systemServer.js";
import auth from "./services/auth/authService.js";
const allowedOrigins = ["http://localhost:3000", "http://localhost:4000", "http://localhost:5173"];
const app = new OpenAPIHono();
// middle ware
app.use("*", logger());
app.use(
"*",
cors({
origin: allowedOrigins,
allowHeaders: ["X-Custom-Header", "Upgrade-Insecure-Requests"],
allowMethods: ["POST", "GET", "OPTIONS"],
exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
maxAge: 600,
credentials: true,
})
);
app.doc("/api/ref", {
openapi: "3.0.0",
info: {
version: "1.0.0",
title: "LST API",
},
});
const routes = [
scalar,
auth,
// apiHits,
system,
] as const;
routes.forEach((route) => {
app.route("/api/", route);
});
// the catch all api route
app.all("/api/*", (c) => c.json({error: "API route not found"}, 404));
app.all("/ocme/*", async (c) => {
//return ocmeService(c);
c.json({error: "Ocme route not found"}, 404);
});
// front end static files
app.get("*", serveStatic({root: "../frontend/dist"}));
app.get("*", serveStatic({path: "../frontend/dist/index.html"}));
serve(
{
fetch: app.fetch,
port: Number(process.env.SERVER_PORT),
},
(info) => {
console.log(`Server is running on http://localhost:${info.port}`);
}
);

View File

@@ -1,8 +1,8 @@
import {OpenAPIHono} from "@hono/zod-openapi"; import {OpenAPIHono} from "@hono/zod-openapi";
import login from "./routes/login"; import login from "./routes/login.js";
import register from "./routes/register"; import register from "./routes/register.js";
import session from "./routes/session"; import session from "./routes/session.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
app.route("auth/login", login); app.route("auth/login", login);

View File

@@ -4,8 +4,8 @@ in the login route we attach it to user under roles.
*/ */
import {eq} from "drizzle-orm"; import {eq} from "drizzle-orm";
import {db} from "../../../../database/dbClient"; import {db} from "../../../../../database/dbclient.js";
import {userRoles} from "../../../../database/schema/userRoles"; import {userRoles} from "../../../../../database/schema/userRoles.js";
export const roleCheck = async (user_id: any) => { export const roleCheck = async (user_id: any) => {
// get the user roles by the user_id // get the user roles by the user_id

View File

@@ -1,13 +1,14 @@
import {sign, verify} from "jsonwebtoken"; import jwt from "jsonwebtoken";
import {db} from "../../../../database/dbClient"; import {db} from "../../../../../database/dbclient.js";
import {users} from "../../../../database/schema/users"; import {users} from "../../../../../database/schema/users.js";
import {eq} from "drizzle-orm"; import {eq, sql} from "drizzle-orm";
import {checkPassword} from "../utils/checkPassword"; import {checkPassword} from "../utils/checkPassword.js";
import {roleCheck} from "./getUserAccess"; import {roleCheck} from "./getUserAccess.js";
/** /**
* Authenticate a user and return a JWT. * Authenticate a user and return a JWT.
*/ */
const {sign, verify} = jwt;
export async function login( export async function login(
username: string, username: string,
@@ -15,7 +16,7 @@ export async function login(
): Promise<{token: string; user: {user_id: string; username: string}}> { ): Promise<{token: string; user: {user_id: string; username: string}}> {
const user = await db.select().from(users).where(eq(users.username, username)); const user = await db.select().from(users).where(eq(users.username, username));
console.log(user); //console.log(user);
if (user.length === 0) { if (user.length === 0) {
throw new Error("Invalid or Missing user"); throw new Error("Invalid or Missing user");
} }
@@ -27,7 +28,7 @@ export async function login(
} }
// Create a JWT // Create a JWT
const secret: string = process.env.JWT_SECRET! || "bnghsjhsd"; const secret: string = process.env.JWT_SECRET!;
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60; const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
// get the user roles // get the user roles
@@ -39,6 +40,15 @@ export async function login(
roles: roles || null, roles: roles || null,
role: user[0].role || null, // this should be removed onces full migration to v2 is completed role: user[0].role || null, // this should be removed onces full migration to v2 is completed
}; };
// update the user last login
// try {
// db.update(users)
// .set({lastLogin: sql`NOW()`})
// .where(eq(users.user_id, user[0].user_id));
// } catch (e) {
// console.log(e);
// }
const token = sign({user: userData}, secret, {expiresIn: expiresIn * 60}); const token = sign({user: userData}, secret, {expiresIn: expiresIn * 60});
return {token, user: userData}; return {token, user: userData};

View File

@@ -11,7 +11,7 @@ export const authMiddleware: MiddlewareHandler = async (c, next) => {
const token = authHeader.split(" ")[1]; const token = authHeader.split(" ")[1];
try { try {
const decoded = verify(token, process.env.JWT_SECRET, {ignoreExpiration: false}) as { const decoded = verify(token, process.env.JWT_SECRET!, {ignoreExpiration: false}) as {
userId: number; userId: number;
exp: number; exp: number;
}; };
@@ -22,8 +22,10 @@ export const authMiddleware: MiddlewareHandler = async (c, next) => {
// If the token has less than REFRESH_THRESHOLD seconds left, refresh it // If the token has less than REFRESH_THRESHOLD seconds left, refresh it
let newToken = null; let newToken = null;
if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD)) { if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD!)) {
newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET, {expiresIn: process.env.EXPIRATION_TIME}); newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET!, {
expiresIn: parseInt(process.env.EXPIRATION_TIME!),
});
c.res.headers.set("Authorization", `Bearer ${newToken}`); c.res.headers.set("Authorization", `Bearer ${newToken}`);
} }

View File

@@ -1,5 +1,5 @@
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
import {login} from "../controllers/login"; import {login} from "../controllers/login.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();

View File

@@ -1,8 +1,8 @@
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
import {db} from "../../../../database/dbClient"; import {db} from "../../../../../database/dbclient.js";
import {users} from "../../../../database/schema/users"; import {users} from "../../../../../database/schema/users.js";
import {apiHit} from "../../../globalUtils/apitHits"; import {apiHit} from "../../../globalUtils/apiHits.js";
import {createPassword} from "../utils/createPassword"; import {createPassword} from "../utils/createPassword.js";
import {eq} from "drizzle-orm"; import {eq} from "drizzle-orm";
const app = new OpenAPIHono(); const app = new OpenAPIHono();

View File

@@ -1,13 +0,0 @@
import {OpenAPIHono} from "@hono/zod-openapi";
const app = new OpenAPIHono();
// the doc endpoint
app.doc("/", {
openapi: "3.0.0",
info: {
version: "1.0.0",
title: "LST API",
},
});
export default app;

View File

@@ -1,5 +1,4 @@
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
import {apiHit} from "../../../globalUtils/apitHits";
const app = new OpenAPIHono(); const app = new OpenAPIHono();

View File

@@ -47,7 +47,7 @@ app.get(
"undici", "undici",
], ],
spec: { spec: {
url: "/api", url: "/api/ref",
}, },
baseServerURL: "https://scalar.com", baseServerURL: "https://scalar.com",
servers: [ servers: [

View File

@@ -1,23 +0,0 @@
import { Context } from "hono";
export const ocmeService = async (c: Context) => {
const url = new URL(c.req.url);
const ocmeUrl = `http://localhost:${
process.env.OCME_PORT
}${url.pathname.replace("/ocme", "")}`;
console.log(ocmeUrl);
const ocmeResponse = await fetch(ocmeUrl, {
method: c.req.method,
headers: c.req.raw.headers,
body:
c.req.method !== "GET" && c.req.method !== "HEAD"
? await c.req.text()
: undefined,
});
return new Response(ocmeResponse.body, {
status: ocmeResponse.status,
headers: ocmeResponse.headers,
});
};

View File

@@ -0,0 +1,19 @@
import type {Context} from "hono";
export const ocmeService = async (c: Context) => {
const url = new URL(c.req.url);
const ocmeUrl = `http://localhost:${process.env.OCME_PORT}${url.pathname.replace("/ocme", "")}`;
console.log(ocmeUrl);
const ocmeResponse = await fetch(ocmeUrl, {
method: c.req.method,
headers: c.req.raw.headers,
body: c.req.method !== "GET" && c.req.method !== "HEAD" ? await c.req.text() : undefined,
});
return new Response(ocmeResponse.body, {
status: ocmeResponse.status,
headers: ocmeResponse.headers,
});
};

View File

@@ -1,6 +1,6 @@
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
import {modules} from "../../../../database/schema/modules"; import {modules} from "../../../../../database/schema/modules.js";
import {db} from "../../../../database/dbClient"; import {db} from "../../../../../database/dbclient.js";
import {eq} from "drizzle-orm"; import {eq} from "drizzle-orm";
// Define the request body schema // Define the request body schema
@@ -27,7 +27,7 @@ app.openapi(
tags: ["server"], tags: ["server"],
summary: "Returns all modules in the server", summary: "Returns all modules in the server",
method: "get", method: "get",
path: "/server/modules", path: "/",
responses: { responses: {
200: { 200: {
content: { content: {
@@ -38,6 +38,7 @@ app.openapi(
}, },
}), }),
async (c) => { async (c) => {
//console.log("system modules");
let module: any = []; let module: any = [];
try { try {
module = await db.select().from(modules).where(eq(modules.active, true)); module = await db.select().from(modules).where(eq(modules.active, true));

View File

@@ -0,0 +1,7 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import modules from "./route/modules.js";
const app = new OpenAPIHono().route("server/modules", modules);
export default app;

View File

@@ -1,7 +0,0 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import modules from "./route/modules";
const app = new OpenAPIHono().route("system/module", modules);
export default app;

16
server/tsconfig.json Normal file
View File

@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "nodenext",
"strict": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"types": ["node"],
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
"outDir": "./dist",
"removeComments": true
},
"exclude": ["node_modules"]
}

View File

@@ -1,25 +0,0 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"module": "esnext",
"target": "esnext",
"moduleResolution": "bundler",
"moduleDetection": "force",
"allowImportingTsExtensions": true,
"noEmit": true,
"composite": true,
"strict": true,
"downlevelIteration": true,
"skipLibCheck": true,
"jsx": "react-jsx",
"removeComments": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"types": [
"bun-types" // add Bun global
],
"outDir": "dist"
},
"include": ["./server/src", "./server/index.ts", "./server/database"]
}