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
bun.lock
.nx

View File

@@ -6,11 +6,11 @@
{"type": "docs", "section": "📚 Documentation"},
{"type": "style", "hidden": true},
{"type": "refactor", "section": "🛠️ Code Refactor"},
{"type": "perf", "hidden": false, "section": "🚀 Code Refactor"},
{"type": "perf", "hidden": false, "section": "🚀 Performance"},
{"type": "test", "section": "📝 Testing Code"},
{"type": "ci", "section": "📈 Project changes"}
],
"commitUrlFormat": "https://git.tuffraid.net/cowch/lstV2/commits{{hash}}",
"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 {
url: http://localhost:3000/api/auth/login
url: http://localhost:4000/api/auth/login
body: json
auth: none
}
body:json {
{
"username": "adm_matthes",
"password": "Nova0511!"
"username": "matthes01",
"password": "99Monsters200Scary!"
}
}

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ CREATE TABLE "modules" (
"module_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" text NOT NULL,
"active" boolean DEFAULT false,
"roles" text DEFAULT '["view", "systemAdmin"]' NOT NULL,
"add_User" text DEFAULT 'LST_System' NOT NULL,
"add_Date" timestamp DEFAULT now(),
"upd_User" text DEFAULT 'LST_System' NOT NULL,
@@ -21,7 +22,24 @@ CREATE TABLE "userRoles" (
"user_id" uuid NOT NULL,
"role_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_Date" timestamp DEFAULT now(),
"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
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 "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",
"prevId": "313590a8-2068-45b5-96fc-cfa5d2b32b56",
"id": "467c98f1-3785-42b5-80ed-528eac5fcbe4",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"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";
const database = process.env.DATABASE_URL || "";
import dotenv from "dotenv";
dotenv.config();
const database = process.env.DATABASE_URL! || "";
export default defineConfig({
dialect: "postgresql", // 'mysql' | 'sqlite' | 'turso'
schema: "./server/database/schema/",
out: "./server/database/migrations",
schema: "database/schema",
out: "database/migrations",
dbCredentials: {
url: database,
},

View File

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

View File

@@ -1,36 +1,51 @@
import * as React from "react";
import * as AvatarPrimitive from "@radix-ui/react-avatar";
import * as React from "react"
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>) {
return (
<AvatarPrimitive.Root
data-slot="avatar"
className={cn("relative flex size-8 shrink-0 overflow-hidden rounded-full", className)}
{...props}
/>
);
function Avatar({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
return (
<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>) {
return (
<AvatarPrimitive.Image
data-slot="avatar-image"
className={cn("aspect-square size-full", className)}
{...props}
/>
);
function AvatarImage({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
return (
<AvatarPrimitive.Image
data-slot="avatar-image"
className={cn("aspect-square size-full", className)}
{...props}
/>
)
}
function AvatarFallback({className, ...props}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
return (
<AvatarPrimitive.Fallback
data-slot="avatar-fallback"
className={cn("bg-muted flex size-full items-center justify-center rounded-full", className)}
{...props}
/>
);
function AvatarFallback({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
return (
<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 {Slot} from "@radix-ui/react-slot";
import {cva, type VariantProps} from "class-variance-authority";
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import {cn} from "../../lib/utils";
import { cn } from "@/lib/utils"
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",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90",
outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);
"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: {
variant: {
default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
outline:
"border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
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",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function Button({
className,
variant,
size,
asChild = false,
...props
className,
variant,
size,
asChild = false,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean;
}) {
const Comp = asChild ? Slot : "button";
VariantProps<typeof buttonVariants> & {
asChild?: boolean
}) {
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
data-slot="card"
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
)}
{...props}
@@ -19,7 +19,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
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}
/>
)
@@ -59,7 +59,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-footer"
className={cn("flex items-center px-6 pb-6", className)}
className={cn("flex items-center px-6", className)}
{...props}
/>
)

View File

@@ -12,14 +12,14 @@ function Checkbox({
<CheckboxPrimitive.Root
data-slot="checkbox"
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
)}
{...props}
>
<CheckboxPrimitive.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" />
</CheckboxPrimitive.Indicator>

View File

@@ -1,3 +1,5 @@
"use client"
import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
@@ -72,7 +74,7 @@ function DropdownMenuItem({
data-inset={inset}
data-variant={variant}
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
)}
{...props}
@@ -153,7 +155,7 @@ function DropdownMenuLabel({
data-slot="dropdown-menu-label"
data-inset={inset}
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
)}
{...props}

View File

@@ -11,7 +11,7 @@ function Label({
<LabelPrimitive.Root
data-slot="label"
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
)}
{...props}

View File

@@ -1,28 +1,28 @@
"use client";
"use client"
import * as React from "react";
import * as SeparatorPrimitive from "@radix-ui/react-separator";
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"
import {cn} from "../../lib/utils";
import { cn } from "@/lib/utils"
function Separator({
className,
orientation = "horizontal",
decorative = true,
...props
className,
orientation = "horizontal",
decorative = true,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
return (
<SeparatorPrimitive.Root
data-slot="separator-root"
decorative={decorative}
orientation={orientation}
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",
className
)}
{...props}
/>
);
return (
<SeparatorPrimitive.Root
data-slot="separator-root"
decorative={decorative}
orientation={orientation}
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",
className
)}
{...props}
/>
)
}
export {Separator};
export { Separator }

View File

@@ -1,101 +1,137 @@
import * as React from "react";
import * as SheetPrimitive from "@radix-ui/react-dialog";
import {XIcon} from "lucide-react";
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { XIcon } from "lucide-react"
import {cn} from "../../lib/utils";
import { cn } from "@/lib/utils"
function Sheet({...props}: React.ComponentProps<typeof SheetPrimitive.Root>) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />;
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />
}
function SheetTrigger({...props}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
function SheetTrigger({
...props
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
}
function SheetClose({...props}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
function SheetClose({
...props
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
}
function SheetPortal({...props}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;
function SheetPortal({
...props
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
}
function SheetOverlay({className, ...props}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
return (
<SheetPrimitive.Overlay
data-slot="sheet-overlay"
className={cn(
"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 SheetOverlay({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
return (
<SheetPrimitive.Overlay
data-slot="sheet-overlay"
className={cn(
"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({
className,
children,
side = "right",
...props
className,
children,
side = "right",
...props
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
side?: "top" | "right" | "bottom" | "left";
side?: "top" | "right" | "bottom" | "left"
}) {
return (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
data-slot="sheet-content"
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",
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",
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",
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",
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",
className
)}
{...props}
>
{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">
<XIcon className="size-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
);
return (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
data-slot="sheet-content"
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",
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",
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",
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",
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",
className
)}
{...props}
>
{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">
<XIcon className="size-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
)
}
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} />;
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}
/>
)
}
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} />;
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}
/>
)
}
function SheetTitle({className, ...props}: React.ComponentProps<typeof SheetPrimitive.Title>) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
className={cn("text-foreground font-semibold tracking-tight", className)}
{...props}
/>
);
function SheetTitle({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
className={cn("text-foreground font-semibold", className)}
{...props}
/>
)
}
function SheetDescription({className, ...props}: React.ComponentProps<typeof SheetPrimitive.Description>) {
return (
<SheetPrimitive.Description
data-slot="sheet-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
);
function SheetDescription({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
return (
<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">) {
return <div data-slot="skeleton" className={cn("bg-primary/10 animate-pulse rounded-md", className)} {...props} />;
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
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 * as TooltipPrimitive from "@radix-ui/react-tooltip";
import { cn } from "@/lib/utils"
import {cn} from "../../lib/utils";
function TooltipProvider({delayDuration = 0, ...props}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />;
function TooltipProvider({
delayDuration = 0,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
{...props}
/>
)
}
function Tooltip({...props}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return (
<TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
);
function Tooltip({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return (
<TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
)
}
function TooltipTrigger({...props}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
function TooltipTrigger({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}
function TooltipContent({
className,
sideOffset = 4,
children,
...props
className,
sideOffset = 0,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
sideOffset={sideOffset}
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",
className
)}
{...props}
>
{children}
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
);
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
sideOffset={sideOffset}
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 w-fit rounded-md px-3 py-1.5 text-xs text-balance",
className
)}
{...props}
>
{children}
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
</TooltipPrimitive.Content>
</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 { twMerge } from "tailwind-merge"
import {clsx, type ClassValue} from "clsx";
import {twMerge} from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
return twMerge(clsx(inputs));
}

View File

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

View File

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

View File

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

View File

@@ -7,10 +7,6 @@ import path from "path";
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss(), TanStackRouterVite({autoCodeSplitting: true})],
// build: {
// outDir: path.resolve(__dirname, "../../dist/frontend/dist"),
// emptyOutDir: true,
// },
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
@@ -18,7 +14,7 @@ export default defineConfig({
},
server: {
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",
"version": "1.2.0",
"description": "",
"main": "index.ts",
"name": "fullstack-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "concurrently -n 'server,frontend' -c '#007755,#2f6da3' 'bun --watch server/index.ts' 'cd frontend && bunx --bun vite'",
"dev:server": "bun --watch server/index.ts",
"dev:ocme": "bun --watch ocme/index.ts",
"dev:front": "cd frontend && bunx --bun vite",
"build:server": "cd apps/server && bun build index.js --outdir ../../dist/server",
"build:ocme": "rimraf dist/ocme && cd apps/ocme && bun build index.js --outdir ../../dist/ocme",
"build:front": "cd frontend && rimraf frontend/dist && bun run build",
"start": "bun --env-file .env server/index.js",
"commit": "cz",
"clean": "rimraf dist/server",
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
"dev:server": "dotenvx run -f .env -- tsx watch server/src/index.ts",
"dev:frontend": "cd frontend && npm run dev",
"build": "npm run build:server && npm run build:frontend",
"build:server": "cd server && npm run build",
"build:frontend": "cd frontend && npm run build",
"start": "npm run start:server",
"start:server": "cd server && npm start",
"db:generate": "npx drizzle-kit generate",
"db:migrate": "npx drizzle-kit push",
"deploy": "standard-version --conventional-commits",
"ui:add": "cd frontend && bun shadcn add ",
"db:dev": "bun drizzle-kit generate && bun drizzle-kit migrate"
"commit": "cz"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@dotenvx/dotenvx": "^1.35.0",
"@hono/zod-openapi": "^0.18.4",
"@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",
"@dotenvx/dotenvx": "^1.38.3",
"hono": "^4.7.2",
"drizzle-orm": "^0.39.3",
"drizzle-zod": "^0.7.0",
"hono": "^4.7.1",
"jsonwebtoken": "^9.0.2",
"pg": "^8.13.3",
"postgres": "^3.4.5",
"zod": "^3.24.2"
},
"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/js-cookie": "^3.0.6",
"@types/pg": "^8.11.11",
"concurrently": "^9.1.2",
"cz-conventional-changelog": "^3.3.0",
"drizzle-kit": "^0.30.4",
"rimraf": "^6.0.1",
"standard-version": "^9.5.0",
"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 {Context} from "hono";
// Define the request body schema
const requestSchema = z.object({
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 login from "./routes/login";
import register from "./routes/register";
import session from "./routes/session";
import login from "./routes/login.js";
import register from "./routes/register.js";
import session from "./routes/session.js";
const app = new OpenAPIHono();
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 {db} from "../../../../database/dbClient";
import {userRoles} from "../../../../database/schema/userRoles";
import {db} from "../../../../../database/dbclient.js";
import {userRoles} from "../../../../../database/schema/userRoles.js";
export const roleCheck = async (user_id: any) => {
// get the user roles by the user_id

View File

@@ -1,13 +1,14 @@
import {sign, verify} from "jsonwebtoken";
import {db} from "../../../../database/dbClient";
import {users} from "../../../../database/schema/users";
import {eq} from "drizzle-orm";
import {checkPassword} from "../utils/checkPassword";
import {roleCheck} from "./getUserAccess";
import jwt from "jsonwebtoken";
import {db} from "../../../../../database/dbclient.js";
import {users} from "../../../../../database/schema/users.js";
import {eq, sql} from "drizzle-orm";
import {checkPassword} from "../utils/checkPassword.js";
import {roleCheck} from "./getUserAccess.js";
/**
* Authenticate a user and return a JWT.
*/
const {sign, verify} = jwt;
export async function login(
username: string,
@@ -15,7 +16,7 @@ export async function login(
): Promise<{token: string; user: {user_id: string; username: string}}> {
const user = await db.select().from(users).where(eq(users.username, username));
console.log(user);
//console.log(user);
if (user.length === 0) {
throw new Error("Invalid or Missing user");
}
@@ -27,7 +28,7 @@ export async function login(
}
// 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;
// get the user roles
@@ -39,6 +40,15 @@ export async function login(
roles: roles || null,
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});
return {token, user: userData};

View File

@@ -11,7 +11,7 @@ export const authMiddleware: MiddlewareHandler = async (c, next) => {
const token = authHeader.split(" ")[1];
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;
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
let newToken = null;
if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD)) {
newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET, {expiresIn: process.env.EXPIRATION_TIME});
if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD!)) {
newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET!, {
expiresIn: parseInt(process.env.EXPIRATION_TIME!),
});
c.res.headers.set("Authorization", `Bearer ${newToken}`);
}

View File

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

View File

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

View File

@@ -47,7 +47,7 @@ app.get(
"undici",
],
spec: {
url: "/api",
url: "/api/ref",
},
baseServerURL: "https://scalar.com",
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 {modules} from "../../../../database/schema/modules";
import {db} from "../../../../database/dbClient";
import {modules} from "../../../../../database/schema/modules.js";
import {db} from "../../../../../database/dbclient.js";
import {eq} from "drizzle-orm";
// Define the request body schema
@@ -27,7 +27,7 @@ app.openapi(
tags: ["server"],
summary: "Returns all modules in the server",
method: "get",
path: "/server/modules",
path: "/",
responses: {
200: {
content: {
@@ -38,6 +38,7 @@ app.openapi(
},
}),
async (c) => {
//console.log("system modules");
let module: any = [];
try {
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"]
}