Compare commits

...

11 Commits

909 changed files with 170055 additions and 46 deletions

View File

@@ -25,6 +25,12 @@ PROD_PLANT_TOKEN=test3
PROD_USER=alplaprod PROD_USER=alplaprod
PROD_PASSWORD=password PROD_PASSWORD=password
# Auth stuff
BETTER_AUTH_SECRET="3d2b7d64ac2f9ebd6854325a84390666f4bbd2c7c3f537bb60fca3740f081e1e"
# Your APP URL
BETTER_AUTH_URL="http://localhost:3000"
# Docker Related # Docker Related
PROD_IP=10.193.0.56 PROD_IP=10.193.0.56
LOGISTICS_NETWORK=10.193.14.0/24 LOGISTICS_NETWORK=10.193.14.0/24

2
.gitignore vendored
View File

@@ -11,7 +11,7 @@ testScripts
builds builds
controllerBuilds controllerBuilds
# ignoring the old app that will be built into this one to make deploying faster and more easy as we do the migration # ignoring the old app that will be built into this one to make deploying faster and more easy as we do the migration
lstV2 lstV2/frontend/.tanstack
# Logs # Logs
logs logs

View File

@@ -8,7 +8,13 @@ README.md
CHANGELOG.md CHANGELOG.md
package.json package.json
package-lock.json package-lock.json
lstV2 lstV2/dist
lstV2/database
lstV2/frontend/dist
lstV2/drizzle.config.ts
lstV2/package.json
lstV2/package-lock.json
lstV2/README.md
lang lang
scripts/services.ps1 scripts/services.ps1
drizzle.config.ts drizzle.config.ts

View File

@@ -0,0 +1,19 @@
meta {
name: Auth Me
type: http
seq: 1
}
get {
url: http://{{url}}/lst/api/me
body: none
auth: inherit
}
headers {
Cookie: {{session_cookie}}
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,24 @@
meta {
name: Register
type: http
seq: 2
}
post {
url: http://{{url}}/lst/api/register
body: json
auth: inherit
}
body:json {
{
"username":"matthes01",
"name":"blake",
"email":"blake.matthes@alpla.com",
"password":"nova0511"
}
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,35 @@
meta {
name: Sign-In - email
type: http
seq: 3
}
post {
url: http://{{url}}/lst/api/auth/sign-in/email
body: json
auth: inherit
}
body:json {
{
"email": "blake.matthes@alpla.com",
"password": "nova0511"
}
}
script:post-response {
// grab the raw Set-Cookie header
const cookies = res.headers["set-cookie"];
// cookies is usually an array, e.g. ["auth_session=abcd123; Path=/; HttpOnly; Secure; SameSite=Lax"]
// Extract just the value part ("auth_session=abcd123")
const sessionCookie = cookies[0].split(";")[0];
// Save it as an environment variable
bru.setEnvVar("session_cookie", sessionCookie);
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,35 @@
meta {
name: Sign-In - username
type: http
seq: 4
}
post {
url: http://{{url}}/lst/api/auth/sign-in/username
body: json
auth: inherit
}
body:json {
{
"username": "matthes01",
"password": "nova0511"
}
}
script:post-response {
// grab the raw Set-Cookie header
const cookies = res.headers["set-cookie"];
// cookies is usually an array, e.g. ["auth_session=abcd123; Path=/; HttpOnly; Secure; SameSite=Lax"]
// Extract just the value part ("auth_session=abcd123")
const sessionCookie = cookies[0].split(";")[0];
// Save it as an environment variable
bru.setEnvVar("session_cookie", sessionCookie);
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,8 @@
meta {
name: auth
seq: 1
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,8 @@
meta {
name: app
seq: 2
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,15 @@
meta {
name: Health
type: http
seq: 1
}
get {
url: http://{{url}}/lst/api/system/health
body: none
auth: inherit
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,8 @@
meta {
name: system
seq: 2
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,4 @@
vars {
url: localhost:4200
session_cookie:
}

View File

@@ -13,7 +13,10 @@ import { returnFunc } from "./src/pkg/utils/return.js";
import { initializeProdPool } from "./src/pkg/prodSql/prodSqlConnect.js"; import { initializeProdPool } from "./src/pkg/prodSql/prodSqlConnect.js";
import { tryCatch } from "./src/pkg/utils/tryCatch.js"; import { tryCatch } from "./src/pkg/utils/tryCatch.js";
import os from "os"; import os from "os";
import cors from "cors";
import { sendNotify } from "./src/pkg/utils/notify.js"; import { sendNotify } from "./src/pkg/utils/notify.js";
import { toNodeHandler } from "better-auth/node";
import { auth } from "./src/pkg/auth/auth.js";
const main = async () => { const main = async () => {
const env = validateEnv(process.env); const env = validateEnv(process.env);
@@ -59,9 +62,6 @@ const main = async () => {
// express app // express app
const app = express(); const app = express();
// global middleware
app.use(express.json());
// global env that run only in dev // global env that run only in dev
if (process.env.NODE_ENV?.trim() !== "production") { if (process.env.NODE_ENV?.trim() !== "production") {
app.use(morgan("tiny")); app.use(morgan("tiny"));
@@ -73,6 +73,33 @@ const main = async () => {
); );
} }
// global middleware
app.all(basePath + "/api/auth/*splat", toNodeHandler(auth)); // sign-in sign-out
app.use(express.json());
const allowedOrigins = [
"http://localhost:5173", // dev
"http://localhost:4200",
env.BETTER_AUTH_URL, // prod
];
app.use(
cors({
origin: (origin, callback) => {
// allow requests with no origin (like curl, service workers, PWAs)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
return callback(null, true);
} else {
return callback(new Error("Not allowed by CORS"));
}
},
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
credentials: true,
})
);
// docs and api stuff // docs and api stuff
app.use( app.use(
basePath + "/d", basePath + "/d",

View File

@@ -0,0 +1,15 @@
import { Router } from "express";
import { auth } from "../../../pkg/auth/auth.js";
import { fromNodeHeaders } from "better-auth/node";
const router = Router();
// GET /health
router.get("/", async (req, res) => {
const session = await auth.api.getSession({
headers: fromNodeHeaders(req.headers),
});
return res.json(session);
});
export default router;

View File

@@ -0,0 +1,44 @@
import { Router } from "express";
import type { Request, Response } from "express";
import z from "zod";
import { auth } from "../../../pkg/auth/auth.js";
const router = Router();
const registerSchema = z.object({
email: z.email(),
name: z.string().min(2).max(100),
password: z.string().min(8, "Password must be at least 8 characters"),
username: z
.string()
.min(3)
.max(32)
.regex(/^[a-zA-Z0-9_]+$/, "Only alphanumeric + underscores"),
displayUsername: z.string().min(2).max(100).optional(), // optional in your API, but supported
});
router.post("/", async (req: Request, res: Response) => {
try {
// Parse + validate incoming JSON against Zod schema
const validated = registerSchema.parse(req.body);
// Call Better Auth signUp
const user = await auth.api.signUpEmail({
body: validated,
});
return res.status(201).json(user);
} catch (err) {
if (err instanceof z.ZodError) {
const flattened = z.flattenError(err);
return res.status(400).json({
error: "Validation failed",
details: flattened,
});
}
console.error(err);
return res.status(500).json({ error: "Internal server error" });
}
});
export default router;

View File

@@ -0,0 +1,8 @@
import type { Express, Request, Response } from "express";
import me from "./me.js";
import register from "./register.js";
export const setupAuthRoutes = (app: Express, basePath: string) => {
app.use(basePath + "/api/me", me);
app.use(basePath + "/api/auth/register", register);
};

View File

@@ -1,10 +1,14 @@
import type { Express, Request, Response } from "express"; import type { Express, Request, Response } from "express";
import healthRoutes from "./routes/healthRoutes.js"; import healthRoutes from "./routes/healthRoutes.js";
import { setupAuthRoutes } from "../auth/routes/routes.js";
export const setupRoutes = (app: Express, basePath: string) => { export const setupRoutes = (app: Express, basePath: string) => {
// Root / health check // Root / health check
app.use(basePath + "/health", healthRoutes); app.use(basePath + "/api/system/health", healthRoutes);
// all routes
setupAuthRoutes(app, basePath);
// always try to go to the app weather we are in dev or in production. // always try to go to the app weather we are in dev or in production.
app.get(basePath + "/", (req: Request, res: Response) => { app.get(basePath + "/", (req: Request, res: Response) => {

View File

@@ -0,0 +1,19 @@
import { createAuthClient } from "better-auth/client";
import {
inferAdditionalFields,
usernameClient,
adminClient,
apiKeyClient,
} from "better-auth/client/plugins";
import type { auth } from "./auth.js";
export const authClient = createAuthClient({
baseURL: "http://localhost:3000",
plugins: [
inferAdditionalFields<typeof auth>(),
usernameClient(),
adminClient(),
apiKeyClient(),
],
});

52
app/src/pkg/auth/auth.ts Normal file
View File

@@ -0,0 +1,52 @@
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "../db/db.js";
import { username, admin, apiKey, jwt } from "better-auth/plugins";
import { betterAuth } from "better-auth";
import * as rawSchema from "../db/schema/auth-schema.js";
import type { User } from "better-auth/types";
import { eq } from "drizzle-orm";
export const schema = {
user: rawSchema.user,
session: rawSchema.session,
account: rawSchema.account,
verification: rawSchema.verification,
jwks: rawSchema.jwks,
apiKey: rawSchema.apikey, // 🔑 rename to apiKey
};
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
schema,
}),
appName: "lst",
emailAndPassword: {
enabled: true,
minPasswordLength: 8, // optional config
},
plugins: [
jwt({ jwt: { expirationTime: "1h" } }),
apiKey(),
admin(),
username(),
],
session: {
expiresIn: 60 * 60,
updateAge: 60 * 1,
cookieCache: {
enabled: true,
maxAge: 5 * 60, // Cache duration in seconds
},
},
events: {
async onSignInSuccess({ user }: { user: User }) {
await db
.update(schema.user)
.set({ lastLogin: new Date() })
.where(eq(schema.user.id, user.id));
},
},
});
export type Auth = typeof auth;

View File

@@ -0,0 +1,108 @@
import {
pgTable,
text,
timestamp,
boolean,
integer,
} from "drizzle-orm/pg-core";
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified").default(false).notNull(),
image: text("image"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
role: text("role"),
banned: boolean("banned").default(false),
banReason: text("ban_reason"),
banExpires: timestamp("ban_expires"),
username: text("username").unique(),
displayUsername: text("display_username"),
lastLogin: timestamp("last_login"),
});
export const session = pgTable("session", {
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
impersonatedBy: text("impersonated_by"),
});
export const account = pgTable("account", {
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
});
export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.defaultNow()
.$onUpdate(() => /* @__PURE__ */ new Date())
.notNull(),
});
export const jwks = pgTable("jwks", {
id: text("id").primaryKey(),
publicKey: text("public_key").notNull(),
privateKey: text("private_key").notNull(),
createdAt: timestamp("created_at").notNull(),
});
export const apikey = pgTable("apikey", {
id: text("id").primaryKey(),
name: text("name"),
start: text("start"),
prefix: text("prefix"),
key: text("key").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
refillInterval: integer("refill_interval"),
refillAmount: integer("refill_amount"),
lastRefillAt: timestamp("last_refill_at"),
enabled: boolean("enabled").default(true),
rateLimitEnabled: boolean("rate_limit_enabled").default(true),
rateLimitTimeWindow: integer("rate_limit_time_window").default(86400000),
rateLimitMax: integer("rate_limit_max").default(10),
requestCount: integer("request_count").default(0),
remaining: integer("remaining"),
lastRequest: timestamp("last_request"),
expiresAt: timestamp("expires_at"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
permissions: text("permissions"),
metadata: text("metadata"),
});

View File

@@ -0,0 +1,17 @@
import { pgTable, text, uuid, uniqueIndex } from "drizzle-orm/pg-core";
import { user } from "./auth-schema.js";
export const userRole = pgTable(
"user_role",
{
userRoleId: uuid("user_role_id").defaultRandom().primaryKey(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
module: text("module").notNull(), // e.g. "siloAdjustments"
role: text("role").notNull(), // e.g. "admin" | "manager" | "viewer"
},
(table) => [
uniqueIndex("unique_user_module").on(table.userId, table.module),
]
);

View File

@@ -18,6 +18,10 @@ const envSchema = z.object({
PROD_USER: z.string(), PROD_USER: z.string(),
PROD_PASSWORD: z.string(), PROD_PASSWORD: z.string(),
// auth stuff
BETTER_AUTH_URL: z.string(),
BETTER_AUTH_SECRET: z.string(),
// docker specifc // docker specifc
RUNNING_IN_DOCKER: z.string().default("false"), RUNNING_IN_DOCKER: z.string().default("false"),
}); });

View File

@@ -1,3 +1,3 @@
# What type of deploy ment do we have for the frontend # What type of deploy ment do we have for the frontend
NODE_ENV=dev APP_MODE=dev

View File

@@ -19,7 +19,7 @@ func runNpmV2Build(server *socketio.Server) error {
if err != nil { if err != nil {
return err return err
} }
dir := filepath.Join(cwd, "..", "..", "lstV2") dir := filepath.Join(cwd, "..", "lstV2")
cmd.Dir = dir cmd.Dir = dir
} }

View File

@@ -78,8 +78,10 @@
<button id="USMCD1VMS036">USMCD1VMS036</button> <button id="USMCD1VMS036">USMCD1VMS036</button>
<button id="USBET1VMS006">USBET1VMS006</button> <button id="USBET1VMS006">USBET1VMS006</button>
<button id="USBOW1VMS006">USBOW1VMS006</button> <button id="USBOW1VMS006">USBOW1VMS006</button>
<button id="USKSC1VMS006">USKSC1VMS006</button>
<button id="USSLC1VMS006">USSLC1VMS006</button> <button id="USSLC1VMS006">USSLC1VMS006</button>
<button id="USSTP1VMS006">USSTP1VMS006</button> <button id="USSTP1VMS006">USSTP1VMS006</button>
<button id="USDAY1VMS006">USDAY1VMS006</button>
</div> </div>
<script> <script>
@@ -168,23 +170,23 @@
const updateServerButton = const updateServerButton =
document.getElementById("updateServerButton"); document.getElementById("updateServerButton");
button.onclick = () => { // button.onclick = () => {
const fromMyInput = input.value; // const fromMyInput = input.value;
if (!fromMyInput) return; // if (!fromMyInput) return;
// Emit to backend (adjust event name as required) // // Emit to backend (adjust event name as required)
socket.emit("update", { // socket.emit("update", {
action: "copy", // action: "copy",
target: fromMyInput, // target: fromMyInput,
}); // });
// You can define your own logMessage function // // You can define your own logMessage function
logMessage("info", `Copying to ${fromMyInput}`); // logMessage("info", `Copying to ${fromMyInput}`);
input.value = ""; // input.value = "";
input.focus(); // input.focus();
}; // };
updateServerButton.onclick = () => { updateServerButton.onclick = () => {
const fromMyInput = updateServerInput.value; const fromMyInput = updateServerInput.value;
@@ -246,7 +248,23 @@
target: "USSTP1VMS006", target: "USSTP1VMS006",
drive: "d", drive: "d",
}); // "frontend" = payload target }); // "frontend" = payload target
logMessage("info", "Copying to USSLC1VMS006"); logMessage("info", "Copying to USSTP1VMS006");
};
document.getElementById("USKSC1VMS006").onclick = () => {
socket.emit("update", {
action: "copy",
target: "USksc1VMS006",
drive: "e",
}); // "frontend" = payload target
logMessage("info", "Copying to USKSC1VMS006");
};
document.getElementById("USDAY1VMS006").onclick = () => {
socket.emit("update", {
action: "copy",
target: "USDAY1VMS006",
drive: "e",
}); // "frontend" = payload target
logMessage("info", "Copying to USDAY1VMS006");
}; };
socket.on("logs", (msg) => logMessage("logs", msg)); socket.on("logs", (msg) => logMessage("logs", msg));

View File

@@ -28,7 +28,7 @@ func main() {
// gin stuff // gin stuff
basePath := "/api/controller" basePath := "/api/controller"
if os.Getenv("NODE_ENV") != "production" { if os.Getenv("APP_MODE") != "production" {
basePath = "/lst/api/controller" basePath = "/lst/api/controller"
} }
@@ -139,7 +139,16 @@ func main() {
} }
}() }()
go bot.TheBot() // only activate the bot if its on VMS036 or my dev server
host, err := os.Hostname()
if err != nil {
server.BroadcastToRoom("/", "update", "updateLogs", "Could not retrieve hostname")
return
}
if host == os.Getenv("PRIMARY_SERVER") {
go bot.TheBot()
}
go server.Serve() go server.Serve()
defer server.Close() defer server.Close()

View File

@@ -18,6 +18,8 @@ services:
- PROD_PLANT_TOKEN=${PROD_PLANT_TOKEN} - PROD_PLANT_TOKEN=${PROD_PLANT_TOKEN}
- PROD_USER=${PROD_USER} - PROD_USER=${PROD_USER}
- PROD_PASSWORD=${PROD_PASSWORD} - PROD_PASSWORD=${PROD_PASSWORD}
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
- BETTER_AUTH_URL=${BETTER_AUTH_URL}
restart: unless-stopped restart: unless-stopped
# for all host including prod servers, plc's, printers, or other de # for all host including prod servers, plc's, printers, or other de
extra_hosts: extra_hosts:

View File

@@ -4,7 +4,7 @@ const dbURL = `postgres://${process.env.DATABASE_USER}:${process.env.DATABASE_PA
export default defineConfig({ export default defineConfig({
dialect: "postgresql", dialect: "postgresql",
schema: "./app/src/pkg/db/schema", schema: "./dist/src/pkg/db/schema",
out: "./migrations", out: "./migrations",
dbCredentials: { url: dbURL }, dbCredentials: { url: dbURL },
// verbose: true, // optional, logs more details // verbose: true, // optional, logs more details

View File

@@ -10,8 +10,10 @@
"dependencies": { "dependencies": {
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/vite": "^4.1.13", "@tailwindcss/vite": "^4.1.13",
"@tanstack/react-query": "^5.89.0",
"@tanstack/react-router": "^1.131.36", "@tanstack/react-router": "^1.131.36",
"@tanstack/react-router-devtools": "^1.131.36", "@tanstack/react-router-devtools": "^1.131.36",
"better-auth": "^1.3.11",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"lucide-react": "^0.542.0", "lucide-react": "^0.542.0",
@@ -500,6 +502,17 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@better-auth/utils": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz",
"integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==",
"license": "MIT"
},
"node_modules/@better-fetch/fetch": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz",
"integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA=="
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.25.9", "version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
@@ -1070,6 +1083,12 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@hexagon/base64": {
"version": "1.1.28",
"resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz",
"integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==",
"license": "MIT"
},
"node_modules/@humanfs/core": { "node_modules/@humanfs/core": {
"version": "0.19.1", "version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1193,6 +1212,36 @@
"@jridgewell/sourcemap-codec": "^1.4.14" "@jridgewell/sourcemap-codec": "^1.4.14"
} }
}, },
"node_modules/@levischuck/tiny-cbor": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz",
"integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==",
"license": "MIT"
},
"node_modules/@noble/ciphers": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.0.0.tgz",
"integrity": "sha512-j/l6jpnpaIBM87cAYPJzi/6TgqmBv9spkqPyCXvRYsu5uxqh6tPJZDnD85yo8VWqzTuTQPgfv7NgT63u7kbwAQ==",
"license": "MIT",
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/hashes": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.0.tgz",
"integrity": "sha512-h8VUBlE8R42+XIDO229cgisD287im3kdY6nbNZJFjc6ZvKIXPYXe6Vc/t+kyjFdMFyt5JpapzTsEg8n63w5/lw==",
"license": "MIT",
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1231,6 +1280,162 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@peculiar/asn1-android": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.5.0.tgz",
"integrity": "sha512-t8A83hgghWQkcneRsgGs2ebAlRe54ns88p7ouv8PW2tzF1nAW4yHcL4uZKrFpIU+uszIRzTkcCuie37gpkId0A==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-cms": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.5.0.tgz",
"integrity": "sha512-p0SjJ3TuuleIvjPM4aYfvYw8Fk1Hn/zAVyPJZTtZ2eE9/MIer6/18ROxX6N/e6edVSfvuZBqhxAj3YgsmSjQ/A==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"@peculiar/asn1-x509-attr": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-csr": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.5.0.tgz",
"integrity": "sha512-ioigvA6WSYN9h/YssMmmoIwgl3RvZlAYx4A/9jD2qaqXZwGcNlAxaw54eSx2QG1Yu7YyBC5Rku3nNoHrQ16YsQ==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-ecc": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.5.0.tgz",
"integrity": "sha512-t4eYGNhXtLRxaP50h3sfO6aJebUCDGQACoeexcelL4roMFRRVgB20yBIu2LxsPh/tdW9I282gNgMOyg3ywg/mg==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-pfx": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.5.0.tgz",
"integrity": "sha512-Vj0d0wxJZA+Ztqfb7W+/iu8Uasw6hhKtCdLKXLG/P3kEPIQpqGI4P4YXlROfl7gOCqFIbgsj1HzFIFwQ5s20ug==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-cms": "^2.5.0",
"@peculiar/asn1-pkcs8": "^2.5.0",
"@peculiar/asn1-rsa": "^2.5.0",
"@peculiar/asn1-schema": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-pkcs8": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.5.0.tgz",
"integrity": "sha512-L7599HTI2SLlitlpEP8oAPaJgYssByI4eCwQq2C9eC90otFpm8MRn66PpbKviweAlhinWQ3ZjDD2KIVtx7PaVw==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-pkcs9": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.5.0.tgz",
"integrity": "sha512-UgqSMBLNLR5TzEZ5ZzxR45Nk6VJrammxd60WMSkofyNzd3DQLSNycGWSK5Xg3UTYbXcDFyG8pA/7/y/ztVCa6A==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-cms": "^2.5.0",
"@peculiar/asn1-pfx": "^2.5.0",
"@peculiar/asn1-pkcs8": "^2.5.0",
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"@peculiar/asn1-x509-attr": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-rsa": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.5.0.tgz",
"integrity": "sha512-qMZ/vweiTHy9syrkkqWFvbT3eLoedvamcUdnnvwyyUNv5FgFXA3KP8td+ATibnlZ0EANW5PYRm8E6MJzEB/72Q==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-schema": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.5.0.tgz",
"integrity": "sha512-YM/nFfskFJSlHqv59ed6dZlLZqtZQwjRVJ4bBAiWV08Oc+1rSd5lDZcBEx0lGDHfSoH3UziI2pXt2UM33KerPQ==",
"license": "MIT",
"dependencies": {
"asn1js": "^3.0.6",
"pvtsutils": "^1.3.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-x509": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.5.0.tgz",
"integrity": "sha512-CpwtMCTJvfvYTFMuiME5IH+8qmDe3yEWzKHe7OOADbGfq7ohxeLaXwQo0q4du3qs0AII3UbLCvb9NF/6q0oTKQ==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"asn1js": "^3.0.6",
"pvtsutils": "^1.3.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/asn1-x509-attr": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.5.0.tgz",
"integrity": "sha512-9f0hPOxiJDoG/bfNLAFven+Bd4gwz/VzrCIIWc1025LEI4BXO0U5fOCTNDPbbp2ll+UzqKsZ3g61mpBp74gk9A==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"asn1js": "^3.0.6",
"tslib": "^2.8.1"
}
},
"node_modules/@peculiar/x509": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.0.tgz",
"integrity": "sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg==",
"license": "MIT",
"dependencies": {
"@peculiar/asn1-cms": "^2.5.0",
"@peculiar/asn1-csr": "^2.5.0",
"@peculiar/asn1-ecc": "^2.5.0",
"@peculiar/asn1-pkcs9": "^2.5.0",
"@peculiar/asn1-rsa": "^2.5.0",
"@peculiar/asn1-schema": "^2.5.0",
"@peculiar/asn1-x509": "^2.5.0",
"pvtsutils": "^1.3.6",
"reflect-metadata": "^0.2.2",
"tslib": "^2.8.1",
"tsyringe": "^4.10.0"
}
},
"node_modules/@radix-ui/react-compose-refs": { "node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
@@ -1531,6 +1736,31 @@
"win32" "win32"
] ]
}, },
"node_modules/@simplewebauthn/browser": {
"version": "13.2.0",
"resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.2.0.tgz",
"integrity": "sha512-N3fuA1AAnTo5gCStYoIoiasPccC+xPLx2YU88Dv0GeAmPQTWHETlZQq5xZ0DgUq1H9loXMWQH5qqUjcI7BHJ1A==",
"license": "MIT"
},
"node_modules/@simplewebauthn/server": {
"version": "13.2.0",
"resolved": "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.2.0.tgz",
"integrity": "sha512-meBOTUhWZsQyrBcXDva82Tiyes5UlPQu+fKuMKQlhmAJwR/a+orU8xYfpTQviEaV7qEYD4aMj9He/eBj1KX9hA==",
"license": "MIT",
"dependencies": {
"@hexagon/base64": "^1.1.27",
"@levischuck/tiny-cbor": "^0.2.2",
"@peculiar/asn1-android": "^2.3.10",
"@peculiar/asn1-ecc": "^2.3.8",
"@peculiar/asn1-rsa": "^2.3.8",
"@peculiar/asn1-schema": "^2.3.8",
"@peculiar/asn1-x509": "^2.3.8",
"@peculiar/x509": "^1.13.0"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/@swc/core": { "node_modules/@swc/core": {
"version": "1.13.5", "version": "1.13.5",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz",
@@ -2032,6 +2262,32 @@
"url": "https://github.com/sponsors/tannerlinsley" "url": "https://github.com/sponsors/tannerlinsley"
} }
}, },
"node_modules/@tanstack/query-core": {
"version": "5.89.0",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.89.0.tgz",
"integrity": "sha512-joFV1MuPhSLsKfTzwjmPDrp8ENfZ9N23ymFu07nLfn3JCkSHy0CFgsyhHTJOmWaumC/WiNIKM0EJyduCF/Ih/Q==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "5.89.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.89.0.tgz",
"integrity": "sha512-SXbtWSTSRXyBOe80mszPxpEbaN4XPRUp/i0EfQK1uyj3KCk/c8FuPJNIRwzOVe/OU3rzxrYtiNabsAmk1l714A==",
"license": "MIT",
"dependencies": {
"@tanstack/query-core": "5.89.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^18 || ^19"
}
},
"node_modules/@tanstack/react-router": { "node_modules/@tanstack/react-router": {
"version": "1.131.36", "version": "1.131.36",
"resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.131.36.tgz", "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.131.36.tgz",
@@ -2676,6 +2932,20 @@
"dev": true, "dev": true,
"license": "Python-2.0" "license": "Python-2.0"
}, },
"node_modules/asn1js": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz",
"integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==",
"license": "BSD-3-Clause",
"dependencies": {
"pvtsutils": "^1.3.6",
"pvutils": "^1.1.3",
"tslib": "^2.8.1"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/ast-types": { "node_modules/ast-types": {
"version": "0.16.1", "version": "0.16.1",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
@@ -2709,6 +2979,83 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/better-auth": {
"version": "1.3.11",
"resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.3.11.tgz",
"integrity": "sha512-7l8bHX5rnON4vsVmWB7g2UucNpRlXnDUX/n65mHeR3Zn2/lcpQvfBvGbTaHYU8UGCQadtJ7DLHW/zA3ZR7IfdA==",
"license": "MIT",
"dependencies": {
"@better-auth/utils": "0.3.0",
"@better-fetch/fetch": "^1.1.18",
"@noble/ciphers": "^2.0.0",
"@noble/hashes": "^2.0.0",
"@simplewebauthn/browser": "^13.1.2",
"@simplewebauthn/server": "^13.1.2",
"better-call": "1.0.19",
"defu": "^6.1.4",
"jose": "^6.1.0",
"kysely": "^0.28.5",
"nanostores": "^1.0.1",
"zod": "^4.1.5"
},
"peerDependencies": {
"@lynx-js/react": "*",
"@sveltejs/kit": "^2.0.0",
"next": "^14.0.0 || ^15.0.0",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"solid-js": "^1.0.0",
"svelte": "^4.0.0 || ^5.0.0",
"vue": "^3.0.0"
},
"peerDependenciesMeta": {
"@lynx-js/react": {
"optional": true
},
"@sveltejs/kit": {
"optional": true
},
"next": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
},
"solid-js": {
"optional": true
},
"svelte": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/better-auth/node_modules/zod": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.9.tgz",
"integrity": "sha512-HI32jTq0AUAC125z30E8bQNz0RQ+9Uc+4J7V97gLYjZVKRjeydPgGt6dvQzFrav7MYOUGFqqOGiHpA/fdbd0cQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/better-call": {
"version": "1.0.19",
"resolved": "https://registry.npmjs.org/better-call/-/better-call-1.0.19.tgz",
"integrity": "sha512-sI3GcA1SCVa3H+CDHl8W8qzhlrckwXOTKhqq3OOPXjgn5aTOMIqGY34zLY/pHA6tRRMjTUC3lz5Mi7EbDA24Kw==",
"dependencies": {
"@better-auth/utils": "^0.3.0",
"@better-fetch/fetch": "^1.1.4",
"rou3": "^0.5.1",
"set-cookie-parser": "^2.7.1",
"uncrypto": "^0.1.3"
}
},
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -2981,6 +3328,12 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/defu": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
"license": "MIT"
},
"node_modules/detect-libc": { "node_modules/detect-libc": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
@@ -3604,6 +3957,15 @@
"jiti": "lib/jiti-cli.mjs" "jiti": "lib/jiti-cli.mjs"
} }
}, },
"node_modules/jose": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz",
"integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -3681,6 +4043,15 @@
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
} }
}, },
"node_modules/kysely": {
"version": "0.28.7",
"resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.7.tgz",
"integrity": "sha512-u/cAuTL4DRIiO2/g4vNGRgklEKNIj5Q3CG7RoUB5DV5SfEC2hMvPxKi0GWPmnzwL2ryIeud2VTcEEmqzTzEPNw==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/levn": { "node_modules/levn": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -4072,6 +4443,21 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
} }
}, },
"node_modules/nanostores": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.0.1.tgz",
"integrity": "sha512-kNZ9xnoJYKg/AfxjrVL4SS0fKX++4awQReGqWnwTRHxeHGZ1FJFVgTqr/eMrNQdp0Tz7M7tG/TDaX8QfHDwVCw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"engines": {
"node": "^20.0.0 || >=22.0.0"
}
},
"node_modules/natural-compare": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -4262,6 +4648,24 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/pvtsutils": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz",
"integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.8.1"
}
},
"node_modules/pvutils": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz",
"integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -4344,6 +4748,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/reflect-metadata": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
"license": "Apache-2.0"
},
"node_modules/resolve-from": { "node_modules/resolve-from": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -4414,6 +4824,12 @@
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
"node_modules/rou3": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/rou3/-/rou3-0.5.1.tgz",
"integrity": "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==",
"license": "MIT"
},
"node_modules/run-parallel": { "node_modules/run-parallel": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -4478,6 +4894,12 @@
"seroval": "^1.0" "seroval": "^1.0"
} }
}, },
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -4699,7 +5121,6 @@
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"devOptional": true,
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/tsx": { "node_modules/tsx": {
@@ -4722,6 +5143,24 @@
"fsevents": "~2.3.3" "fsevents": "~2.3.3"
} }
}, },
"node_modules/tsyringe": {
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz",
"integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==",
"license": "MIT",
"dependencies": {
"tslib": "^1.9.3"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/tsyringe/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"license": "0BSD"
},
"node_modules/tw-animate-css": { "node_modules/tw-animate-css": {
"version": "1.3.8", "version": "1.3.8",
"resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.8.tgz", "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.8.tgz",
@@ -4783,6 +5222,12 @@
"typescript": ">=4.8.4 <6.0.0" "typescript": ">=4.8.4 <6.0.0"
} }
}, },
"node_modules/uncrypto": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
"license": "MIT"
},
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "7.10.0", "version": "7.10.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",

View File

@@ -12,8 +12,10 @@
"dependencies": { "dependencies": {
"@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/vite": "^4.1.13", "@tailwindcss/vite": "^4.1.13",
"@tanstack/react-query": "^5.89.0",
"@tanstack/react-router": "^1.131.36", "@tanstack/react-router": "^1.131.36",
"@tanstack/react-router-devtools": "^1.131.36", "@tanstack/react-router-devtools": "^1.131.36",
"better-auth": "^1.3.11",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"lucide-react": "^0.542.0", "lucide-react": "^0.542.0",

View File

@@ -0,0 +1,11 @@
import { createAuthClient } from "better-auth/client";
import { usernameClient } from "better-auth/client/plugins";
export const authClient = createAuthClient({
baseURL: `${window.location.origin}/lst/api/auth`, // 👈 This is fine
callbacks: {
onUpdate: (session: any) => console.log("Session updated", session),
onSignIn: (session: any) => console.log("Signed in!", session),
onSignOut: () => console.log("Signed out!"),
},
plugins: [usernameClient()],
});

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

@@ -1,12 +1,15 @@
import { StrictMode } from "react"; import { StrictMode } from "react";
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client";
import "./index.css"; import "./index.css";
import { RouterProvider, createRouter } from "@tanstack/react-router"; import { RouterProvider, createRouter } from "@tanstack/react-router";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
// Import the generated route tree // Import the generated route tree
import { routeTree } from "./routeTree.gen"; import { routeTree } from "./routeTree.gen";
// Create a client
const queryClient = new QueryClient();
// Create a new router instance // Create a new router instance
const router = createRouter({ routeTree, basepath: "/lst/app" }); const router = createRouter({ routeTree, basepath: "/lst/app" });
@@ -19,6 +22,8 @@ declare module "@tanstack/react-router" {
ReactDOM.createRoot(document.getElementById("root")!).render( ReactDOM.createRoot(document.getElementById("root")!).render(
<StrictMode> <StrictMode>
<RouterProvider router={router} /> <QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</StrictMode> </StrictMode>
); );

View File

@@ -9,38 +9,160 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root' import { Route as rootRouteImport } from './routes/__root'
import { Route as _adminRouteImport } from './routes/__admin'
import { Route as AdminLayoutRouteRouteImport } from './routes/_adminLayout/route'
import { Route as IndexRouteImport } from './routes/index' import { Route as IndexRouteImport } from './routes/index'
import { Route as AdminSettingsRouteImport } from './routes/admin_/settings'
import { Route as AdminLayoutAdminIndexRouteImport } from './routes/_adminLayout/admin/index'
import { Route as AdminLayoutAdminUsersRouteImport } from './routes/_adminLayout/admin/users'
import { Route as AdminLayoutAdminServersRouteImport } from './routes/_adminLayout/admin/servers'
import { Route as AdminLayoutAdminUserUserIdRouteImport } from './routes/_adminLayout/admin/user/$userId'
import { Route as AdminLayoutAdminServersServerIdRouteImport } from './routes/_adminLayout/admin/servers/$serverId'
import { Route as AdminLayoutAdminServersServerIdEditRouteImport } from './routes/_adminLayout/admin/servers/$serverId_/edit'
const _adminRoute = _adminRouteImport.update({
id: '/__admin',
getParentRoute: () => rootRouteImport,
} as any)
const AdminLayoutRouteRoute = AdminLayoutRouteRouteImport.update({
id: '/_adminLayout',
getParentRoute: () => rootRouteImport,
} as any)
const IndexRoute = IndexRouteImport.update({ const IndexRoute = IndexRouteImport.update({
id: '/', id: '/',
path: '/', path: '/',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const AdminSettingsRoute = AdminSettingsRouteImport.update({
id: '/admin_/settings',
path: '/admin/settings',
getParentRoute: () => rootRouteImport,
} as any)
const AdminLayoutAdminIndexRoute = AdminLayoutAdminIndexRouteImport.update({
id: '/admin/',
path: '/admin/',
getParentRoute: () => AdminLayoutRouteRoute,
} as any)
const AdminLayoutAdminUsersRoute = AdminLayoutAdminUsersRouteImport.update({
id: '/admin/users',
path: '/admin/users',
getParentRoute: () => AdminLayoutRouteRoute,
} as any)
const AdminLayoutAdminServersRoute = AdminLayoutAdminServersRouteImport.update({
id: '/admin/servers',
path: '/admin/servers',
getParentRoute: () => AdminLayoutRouteRoute,
} as any)
const AdminLayoutAdminUserUserIdRoute =
AdminLayoutAdminUserUserIdRouteImport.update({
id: '/admin/user/$userId',
path: '/admin/user/$userId',
getParentRoute: () => AdminLayoutRouteRoute,
} as any)
const AdminLayoutAdminServersServerIdRoute =
AdminLayoutAdminServersServerIdRouteImport.update({
id: '/$serverId',
path: '/$serverId',
getParentRoute: () => AdminLayoutAdminServersRoute,
} as any)
const AdminLayoutAdminServersServerIdEditRoute =
AdminLayoutAdminServersServerIdEditRouteImport.update({
id: '/$serverId_/edit',
path: '/$serverId/edit',
getParentRoute: () => AdminLayoutAdminServersRoute,
} as any)
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute '/': typeof IndexRoute
'/admin/settings': typeof AdminSettingsRoute
'/admin/servers': typeof AdminLayoutAdminServersRouteWithChildren
'/admin/users': typeof AdminLayoutAdminUsersRoute
'/admin': typeof AdminLayoutAdminIndexRoute
'/admin/servers/$serverId': typeof AdminLayoutAdminServersServerIdRoute
'/admin/user/$userId': typeof AdminLayoutAdminUserUserIdRoute
'/admin/servers/$serverId/edit': typeof AdminLayoutAdminServersServerIdEditRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute '/': typeof IndexRoute
'/admin/settings': typeof AdminSettingsRoute
'/admin/servers': typeof AdminLayoutAdminServersRouteWithChildren
'/admin/users': typeof AdminLayoutAdminUsersRoute
'/admin': typeof AdminLayoutAdminIndexRoute
'/admin/servers/$serverId': typeof AdminLayoutAdminServersServerIdRoute
'/admin/user/$userId': typeof AdminLayoutAdminUserUserIdRoute
'/admin/servers/$serverId/edit': typeof AdminLayoutAdminServersServerIdEditRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
'/': typeof IndexRoute '/': typeof IndexRoute
'/_adminLayout': typeof AdminLayoutRouteRouteWithChildren
'/__admin': typeof _adminRoute
'/admin_/settings': typeof AdminSettingsRoute
'/_adminLayout/admin/servers': typeof AdminLayoutAdminServersRouteWithChildren
'/_adminLayout/admin/users': typeof AdminLayoutAdminUsersRoute
'/_adminLayout/admin/': typeof AdminLayoutAdminIndexRoute
'/_adminLayout/admin/servers/$serverId': typeof AdminLayoutAdminServersServerIdRoute
'/_adminLayout/admin/user/$userId': typeof AdminLayoutAdminUserUserIdRoute
'/_adminLayout/admin/servers/$serverId_/edit': typeof AdminLayoutAdminServersServerIdEditRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' fullPaths:
| '/'
| '/admin/settings'
| '/admin/servers'
| '/admin/users'
| '/admin'
| '/admin/servers/$serverId'
| '/admin/user/$userId'
| '/admin/servers/$serverId/edit'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: '/' to:
id: '__root__' | '/' | '/'
| '/admin/settings'
| '/admin/servers'
| '/admin/users'
| '/admin'
| '/admin/servers/$serverId'
| '/admin/user/$userId'
| '/admin/servers/$serverId/edit'
id:
| '__root__'
| '/'
| '/_adminLayout'
| '/__admin'
| '/admin_/settings'
| '/_adminLayout/admin/servers'
| '/_adminLayout/admin/users'
| '/_adminLayout/admin/'
| '/_adminLayout/admin/servers/$serverId'
| '/_adminLayout/admin/user/$userId'
| '/_adminLayout/admin/servers/$serverId_/edit'
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute IndexRoute: typeof IndexRoute
AdminLayoutRouteRoute: typeof AdminLayoutRouteRouteWithChildren
_adminRoute: typeof _adminRoute
AdminSettingsRoute: typeof AdminSettingsRoute
} }
declare module '@tanstack/react-router' { declare module '@tanstack/react-router' {
interface FileRoutesByPath { interface FileRoutesByPath {
'/__admin': {
id: '/__admin'
path: ''
fullPath: ''
preLoaderRoute: typeof _adminRouteImport
parentRoute: typeof rootRouteImport
}
'/_adminLayout': {
id: '/_adminLayout'
path: ''
fullPath: ''
preLoaderRoute: typeof AdminLayoutRouteRouteImport
parentRoute: typeof rootRouteImport
}
'/': { '/': {
id: '/' id: '/'
path: '/' path: '/'
@@ -48,11 +170,97 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport parentRoute: typeof rootRouteImport
} }
'/admin_/settings': {
id: '/admin_/settings'
path: '/admin/settings'
fullPath: '/admin/settings'
preLoaderRoute: typeof AdminSettingsRouteImport
parentRoute: typeof rootRouteImport
}
'/_adminLayout/admin/': {
id: '/_adminLayout/admin/'
path: '/admin'
fullPath: '/admin'
preLoaderRoute: typeof AdminLayoutAdminIndexRouteImport
parentRoute: typeof AdminLayoutRouteRoute
}
'/_adminLayout/admin/users': {
id: '/_adminLayout/admin/users'
path: '/admin/users'
fullPath: '/admin/users'
preLoaderRoute: typeof AdminLayoutAdminUsersRouteImport
parentRoute: typeof AdminLayoutRouteRoute
}
'/_adminLayout/admin/servers': {
id: '/_adminLayout/admin/servers'
path: '/admin/servers'
fullPath: '/admin/servers'
preLoaderRoute: typeof AdminLayoutAdminServersRouteImport
parentRoute: typeof AdminLayoutRouteRoute
}
'/_adminLayout/admin/user/$userId': {
id: '/_adminLayout/admin/user/$userId'
path: '/admin/user/$userId'
fullPath: '/admin/user/$userId'
preLoaderRoute: typeof AdminLayoutAdminUserUserIdRouteImport
parentRoute: typeof AdminLayoutRouteRoute
}
'/_adminLayout/admin/servers/$serverId': {
id: '/_adminLayout/admin/servers/$serverId'
path: '/$serverId'
fullPath: '/admin/servers/$serverId'
preLoaderRoute: typeof AdminLayoutAdminServersServerIdRouteImport
parentRoute: typeof AdminLayoutAdminServersRoute
}
'/_adminLayout/admin/servers/$serverId_/edit': {
id: '/_adminLayout/admin/servers/$serverId_/edit'
path: '/$serverId/edit'
fullPath: '/admin/servers/$serverId/edit'
preLoaderRoute: typeof AdminLayoutAdminServersServerIdEditRouteImport
parentRoute: typeof AdminLayoutAdminServersRoute
}
} }
} }
interface AdminLayoutAdminServersRouteChildren {
AdminLayoutAdminServersServerIdRoute: typeof AdminLayoutAdminServersServerIdRoute
AdminLayoutAdminServersServerIdEditRoute: typeof AdminLayoutAdminServersServerIdEditRoute
}
const AdminLayoutAdminServersRouteChildren: AdminLayoutAdminServersRouteChildren =
{
AdminLayoutAdminServersServerIdRoute: AdminLayoutAdminServersServerIdRoute,
AdminLayoutAdminServersServerIdEditRoute:
AdminLayoutAdminServersServerIdEditRoute,
}
const AdminLayoutAdminServersRouteWithChildren =
AdminLayoutAdminServersRoute._addFileChildren(
AdminLayoutAdminServersRouteChildren,
)
interface AdminLayoutRouteRouteChildren {
AdminLayoutAdminServersRoute: typeof AdminLayoutAdminServersRouteWithChildren
AdminLayoutAdminUsersRoute: typeof AdminLayoutAdminUsersRoute
AdminLayoutAdminIndexRoute: typeof AdminLayoutAdminIndexRoute
AdminLayoutAdminUserUserIdRoute: typeof AdminLayoutAdminUserUserIdRoute
}
const AdminLayoutRouteRouteChildren: AdminLayoutRouteRouteChildren = {
AdminLayoutAdminServersRoute: AdminLayoutAdminServersRouteWithChildren,
AdminLayoutAdminUsersRoute: AdminLayoutAdminUsersRoute,
AdminLayoutAdminIndexRoute: AdminLayoutAdminIndexRoute,
AdminLayoutAdminUserUserIdRoute: AdminLayoutAdminUserUserIdRoute,
}
const AdminLayoutRouteRouteWithChildren =
AdminLayoutRouteRoute._addFileChildren(AdminLayoutRouteRouteChildren)
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute, IndexRoute: IndexRoute,
AdminLayoutRouteRoute: AdminLayoutRouteRouteWithChildren,
_adminRoute: _adminRoute,
AdminSettingsRoute: AdminSettingsRoute,
} }
export const routeTree = rootRouteImport export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren) ._addFileChildren(rootRouteChildren)

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/__admin')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/(__admin)/__admin"!</div>
}

View File

@@ -1,8 +1,13 @@
import { createRootRoute, Outlet } from "@tanstack/react-router"; import { createRootRoute, Link, Outlet } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
const RootLayout = () => ( const RootLayout = () => (
<> <>
<nav className="flex gap-1">
<Link to="/">Home</Link>
{/* <Link to="/admin">Admin</Link> */}
</nav>
<hr></hr>
<Outlet /> <Outlet />
<TanStackRouterDevtools /> <TanStackRouterDevtools />
</> </>

View File

@@ -0,0 +1,23 @@
import { Link } from "@tanstack/react-router";
export default function Nav() {
return (
<div>
<nav className="flex gap-1">
<Link
to="/admin"
className="[&.active]:font-bold"
activeOptions={{ exact: true }}
>
Admin
</Link>
<Link to="/admin/servers" className="[&.active]:font-bold">
Servers
</Link>
<Link to="/admin/users" className="[&.active]:font-bold">
Users
</Link>
</nav>
</div>
);
}

View File

@@ -0,0 +1,8 @@
import { getRouteApi } from "@tanstack/react-router";
export default function Server() {
const { useParams } = getRouteApi("/_adminLayout/admin/servers/$serverId");
const { serverId } = useParams();
return <div>server id {serverId}!</div>;
}

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_adminLayout/admin/')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_adminLayout/admin/"!</div>
}

View File

@@ -0,0 +1,27 @@
import { createFileRoute, Link } from "@tanstack/react-router";
export const Route = createFileRoute("/_adminLayout/admin/servers")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
Hello "/admin/servers"! <br />
<Link
to="/admin/servers/$serverId"
params={{
serverId: "5",
}}
>
Server 5
</Link>
<Link
to="/admin/servers/$serverId"
params={(prev) => ({ ...prev, serverId: "10" })}
>
Server 5
</Link>
</div>
);
}

View File

@@ -0,0 +1,10 @@
import { createFileRoute } from "@tanstack/react-router";
import Server from "../../-components/Server";
export const Route = createFileRoute("/_adminLayout/admin/servers/$serverId")({
component: RouteComponent,
});
function RouteComponent() {
return <Server />;
}

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_adminLayout/admin/servers/$serverId_/edit')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_adminLayout/admin/_server/$edit"!</div>
}

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_adminLayout/admin/user/$userId')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_adminLayout/admin/$userId"!</div>
}

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_adminLayout/admin/users')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/admin/users"!</div>
}

View File

@@ -0,0 +1,16 @@
import { createFileRoute, Outlet } from "@tanstack/react-router";
import Nav from "./-components/Nav";
export const Route = createFileRoute("/_adminLayout")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<Nav />
<hr />
<Outlet />
</div>
);
}

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/admin_/settings')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/admin_/settings"!</div>
}

View File

@@ -7,12 +7,14 @@ export const Route = createFileRoute("/")({
function Index() { function Index() {
return ( return (
<div className="h-screen flex items-center justify-center"> <div>
<Button className="h-96 w-96"> <div className="h-screen flex items-center justify-center">
<a href="/lst/d" target="_blank" className="text-4xl"> <Button className="h-96 w-96">
LST-DOCS <a href="/lst/d" target="_blank" className="text-4xl">
</a> LST-DOCS
</Button> </a>
</Button>
</div>
</div> </div>
); );
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 56 KiB

160
lstV2/.gitignore vendored Normal file
View File

@@ -0,0 +1,160 @@
dist
frontend/dist
server/dist
dist
apiDocsLSTV2
testFiles
builds
nssm.exe
backend-0.1.2-217.zip
backend-0.1.2-218.zip
backend-0.1.2.zip
postgresql-17.2-3-windows-x64.exe
jsTesting
dotnetwrapper/bin
dotnetwrapper/obj
dotnetwrapper/wwwroot
prodBuild
# ---> Node
bun.lock
.nx
.nx/cache
.nx/worksapce-data
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
backend-0.1.3.zip
BulkForecastTemplate
BulkOrdersTemplate
check.json
server/services/ocp/controller/materials/materialcheck.bak

8
lstV2/.includes Normal file
View File

@@ -0,0 +1,8 @@
database
dist
frontend/dist
CHANGELOG.md
drizzle.config.ts
package.json
package-lock.json
README.md

17
lstV2/.versionrc.json Normal file
View File

@@ -0,0 +1,17 @@
{
"types": [
{ "type": "feat", "section": "🌟 Enhancements" },
{ "type": "fix", "section": "🐛 Bug fixes" },
{ "type": "chore", "hidden": false, "section": "📝 Chore" },
{ "type": "docs", "section": "📚 Documentation" },
{ "type": "style", "hidden": true },
{ "type": "refactor", "section": "🛠️ Code Refactor" },
{ "type": "perf", "hidden": false, "section": "🚀 Performance" },
{ "type": "test", "section": "📝 Testing Code" },
{ "type": "ci", "hidden": true, "section": "📈 Project changes" },
{ "type": "build", "hidden": true, "section": "📈 Project Builds" }
],
"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"
}

1305
lstV2/CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

173
lstV2/README.md Normal file
View File

@@ -0,0 +1,173 @@
# lstV2
Logistics Support Tool V2
A support tool to alpla prod please see below for install.
# Install
## Files needed to be downloaded before install.
### To run the server
- [PostgresSQL](https://www.postgresql.org/download/windows/) - current version using is 17
- [NodeJS](https://nodejs.org)
- [NSSM](https://nssm.cc/)
### To manage the server
- [VSCODE](https://code.visualstudio.com/)
- [Postman](https://www.postman.com/downloads/)
## Creating directories needed
- Create a new folder where we will host the server files.
- Copy the nssm.exe into this folder
- Copy the build files to the server (only needed for intial install).
- This will house all the compiles and minified files needed to start the server up, this includes the frontend.
- Save the nssm.exe into this folder as well, this will be used to control the service.
## Do the intial install
### DB instal setup
1. Install postgres
2. Open pgAdmin
3. create a new Database named lst_db
### Intial server setup
1. Open VSCode and navigate to the folder where you extracted the files.
2. Click trusted when it pops up.
3. Open a terminal window inside vscode.
4. Run the install script this will install all dependaceys needed as well as do all the database migrations
```bash
npm run prodinstall
```
Next we want to do an intial build for the db
```bash
npm run build
```
### Create the .env file
In the root of the folder create a new .env file
add in the below and change each setting area that says change me to something that suits your needs
```env
# PORTS
PROD_PORT=4000
# To keep it all simple we will pass VITE to the ports that are used on both sides.
VITE_SERVER_PORT=4000
# logLevel
LOG_LEVEL=info
# Auth stuff
SALTING=12
SECRET=CHANGEME
JWT_SECRET=CHANGEME
JWT_REFRESH_SECRET=CHANGEME
# Expire info plus refresh change as needed
JWT_EXPIRES=60
JWT_REFRESH_THRESHOLD=30
JWT_ACCESS_EXPIRATION="1h"
JWT_REFRESH_EXPIRATION="7d"
# this code will need to be used when a user needs to have access to everything.
SECRETOVERRIDECODE="supersecretKey"
# Database url - please change the password if this is all you changed
DATABASE_URL="postgresql://postgres:PASSWORD@localhost:5432/lst_db"
# This is for usday1 restrictions with the lgvs and customer constraints.
FIFO=100
MAXLOTS=3
```
### Run the start command to get all the basic settings and modules installed
1. Run the below
```bash
npm start
```
This command will start up the server and seed the database.
- Settings will be set here.
- All modules will be added.
2. Press CTRL + C to stop the server.
3. Reopen postgres and review the settings make the changes to match the server your going to be running in.
- Change the server
- change the dbServer
- change plantToken
- then the remaining settings confirm if you need on or want to leave as default.
### Creating first user.
1. Start the server back up.
```bash
npm start
```
2. Open http://[SERVER]:[PORT]/api/docs or postman and create a user.
- Please do not try to manually enter a new user this is due to how the password is hashed, as well as setting systemAdmin for the first user.
- Change the server and port to what you changed in the DB.
3. Stop the server again with CTRL + C.
### Running as a serivice.
You want to CD into the scripts folder.
```bash
cd .\dist\server\scripts\
```
Next use the example command below to get the service up and running.
- Options legend
- serviceName = not recommended to change to reduce issues with the update process
- option = use install for the install, but you can use this script later to stop, start, restart the service.
- appPath = where did you extract the server files
- description = no need to change this unless you want it to be something else
- command = do not change this unless you know what your doing and really need to change this.
```powershell
.\services.ps1 -serviceName "LSTV2" -option "install" -appPath "E:\LST\lstV2" -description "Logistics Support Tool V2" -command "run start"
```
### Adding servers to the mix to update on from the front end
you will need to add your servers into the serverData.json.
when the server starts up it will look at this file and make changes as needed.
below is an example of the server
```JSON
{
"sName": "Kansas City",
"serverDNS": "usksc1vms006",
"plantToken": "usksc1",
"idAddress": "10.42.9.26",
"greatPlainsPlantCode": "85",
"streetAddress": "1800 E 94th St Suite 300",
"cityState": "Kansas City, MO",
"zipcode": "64131",
"contactEmail": "example@example.com",
"contactPhone": "555-555-5555",
"customerTiAcc": "ALPL01KCINT",
"lstServerPort": "4000",
"active": false,
"serverLoc": "E:\\LST\\lstv2",
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{ "specialInstructions": "" }]
}
```

View File

@@ -0,0 +1,22 @@
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, {
max: 10,
idle_timeout: 60,
connect_timeout: 10,
max_lifetime: 1000 * 60 * 5,
onnotice: (notice) => {
console.log("PG NOTICE:", notice.message);
},
// debug: (...args) => {
// console.log("QUERY DEBUG:", ...args);
// },
});
export const db = drizzle({ client: queryClient });

View File

@@ -0,0 +1,55 @@
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,
"upd_date" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE "roles" (
"role_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" 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 "userRoles" (
"user_id" uuid NOT NULL,
"role_id" uuid NOT NULL,
"module_id" uuid 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,
"upd_date" timestamp DEFAULT now()
);
--> statement-breakpoint
ALTER TABLE "userRoles" ADD CONSTRAINT "userRoles_user_id_users_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "userRoles" ADD CONSTRAINT "userRoles_role_id_roles_role_id_fk" FOREIGN KEY ("role_id") REFERENCES "public"."roles"("role_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 "role_name" ON "roles" USING btree ("name");--> statement-breakpoint
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

@@ -0,0 +1,2 @@
ALTER TABLE "settings" RENAME COLUMN "role" TO "roles";--> statement-breakpoint
ALTER TABLE "modules" DROP COLUMN "roles";

View File

@@ -0,0 +1 @@
ALTER TABLE "modules" ADD COLUMN "roles" jsonb DEFAULT '["view","systemAdmin"]'::jsonb NOT NULL;

View File

@@ -0,0 +1,5 @@
CREATE TABLE "eom" (
"eomMonth" date NOT NULL,
"article" text NOT NULL,
"articleDescription" text NOT NULL
);

View File

@@ -0,0 +1,4 @@
ALTER TABLE "settings" RENAME COLUMN "module_id" TO "moduleName";--> statement-breakpoint
ALTER TABLE "settings" DROP CONSTRAINT "settings_module_id_modules_module_id_fk";
--> statement-breakpoint
ALTER TABLE "settings" ADD CONSTRAINT "settings_moduleName_modules_name_fk" FOREIGN KEY ("moduleName") REFERENCES "public"."modules"("name") ON DELETE no action ON UPDATE no action;

View File

@@ -0,0 +1,3 @@
ALTER TABLE "settings" DROP CONSTRAINT "settings_moduleName_modules_name_fk";
--> statement-breakpoint
ALTER TABLE "settings" DROP COLUMN "moduleName";

View File

@@ -0,0 +1,2 @@
ALTER TABLE "settings" ADD COLUMN "moduleName" uuid;--> statement-breakpoint
ALTER TABLE "settings" ADD CONSTRAINT "settings_moduleName_modules_name_fk" FOREIGN KEY ("moduleName") REFERENCES "public"."modules"("name") ON DELETE no action ON UPDATE no action;

View File

@@ -0,0 +1 @@
ALTER TABLE "settings" ALTER COLUMN "moduleName" SET DATA TYPE text;

View File

@@ -0,0 +1 @@
ALTER TABLE "settings" DROP CONSTRAINT "settings_moduleName_modules_name_fk";

View File

@@ -0,0 +1,13 @@
CREATE TABLE "ocmeData" (
"ocme_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"sscc" text,
"runningNr" numeric NOT NULL,
"completed" boolean DEFAULT false,
"lineNum" numeric NOT NULL,
"pickedUp" boolean DEFAULT false,
"areaFrom" 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()
);

View File

@@ -0,0 +1,8 @@
CREATE TABLE "logs" (
"log_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"level" text,
"username" text DEFAULT 'LST_Serivce',
"service" text DEFAULT 'system' NOT NULL,
"message" text NOT NULL,
"add_Date" timestamp DEFAULT now()
);

View File

@@ -0,0 +1,34 @@
CREATE TABLE "apiHits" (
"ip" text,
"endpoint" text,
"action" text,
"lastBody" text,
"stats" text,
"add_date" timestamp DEFAULT now(),
"upd_date" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE "serverData" (
"server_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"sName" text NOT NULL,
"serverDNS" text NOT NULL,
"plantToken" text NOT NULL,
"idAddress" text NOT NULL,
"greatPlainsPlantCode" numeric NOT NULL,
"streetAddress" text NOT NULL,
"cityState" text NOT NULL,
"zipcode" numeric,
"contactEmail" text,
"contactPhone" text,
"customerTiAcc" text,
"lstServerPort" numeric DEFAULT '4000',
"active" boolean DEFAULT true,
"serverLoc" text NOT NULL,
"oldVersion" text NOT NULL,
"lastUpdated" timestamp DEFAULT now(),
"shippingHours" text DEFAULT '[{"early": "06:30", "late": "23:00"}]',
"tiPostTime" text DEFAULT '[{"from": "24", "to": "24"}]',
"otherSettings" jsonb DEFAULT '[{"specialInstructions":"something for ti","active":false}]'::jsonb NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX "plantToken" ON "serverData" USING btree ("plantToken");

View File

@@ -0,0 +1,10 @@
ALTER TABLE "serverData" ALTER COLUMN "serverDNS" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "plantToken" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "idAddress" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "greatPlainsPlantCode" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "streetAddress" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "cityState" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "lstServerPort" DROP DEFAULT;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "serverLoc" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "oldVersion" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "serverData" ALTER COLUMN "otherSettings" DROP NOT NULL;

View File

@@ -0,0 +1,20 @@
CREATE TABLE "rfidReaders" (
"rfidReader_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"reader" text,
"readerIP" text,
"lastHeartBeat" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE "rfidTags" (
"rfidTag_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"tagHex" text,
"tag" text,
"timeStamp" timestamp DEFAULT now(),
"counts" jsonb NOT NULL,
"lastareaIn" text NOT NULL,
"runningNumber" numeric NOT NULL,
"created_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE UNIQUE INDEX "reader" ON "rfidReaders" USING btree ("reader");--> statement-breakpoint
CREATE UNIQUE INDEX "tagHex" ON "rfidTags" USING btree ("tagHex");

View File

@@ -0,0 +1 @@
ALTER TABLE "serverData" ADD COLUMN "isUpgrading" boolean DEFAULT false;

View File

@@ -0,0 +1 @@
ALTER TABLE "rfidReaders" ADD COLUMN "lastTrigger" timestamp DEFAULT now();

View File

@@ -0,0 +1 @@
ALTER TABLE "rfidReaders" ADD COLUMN "active" boolean DEFAULT true;

View File

@@ -0,0 +1,2 @@
ALTER TABLE "rfidTags" ADD COLUMN "antenna" numeric;--> statement-breakpoint
ALTER TABLE "rfidTags" ADD COLUMN "tagStrength" numeric;

View File

@@ -0,0 +1,2 @@
ALTER TABLE "rfidTags" ALTER COLUMN "counts" SET DEFAULT '[]'::jsonb;--> statement-breakpoint
ALTER TABLE "rfidTags" ALTER COLUMN "counts" DROP NOT NULL;

View File

@@ -0,0 +1,4 @@
ALTER TABLE "rfidTags" ALTER COLUMN "runningNumber" SET DATA TYPE integer;--> statement-breakpoint
ALTER TABLE "rfidTags" ALTER COLUMN "runningNumber" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "rfidTags" ALTER COLUMN "antenna" SET DATA TYPE integer;--> statement-breakpoint
ALTER TABLE "rfidTags" ALTER COLUMN "tagStrength" SET DATA TYPE integer;

View File

@@ -0,0 +1 @@
ALTER TABLE "rfidReaders" ADD COLUMN "lastTiggerGood" boolean DEFAULT true;

View File

@@ -0,0 +1,2 @@
ALTER TABLE "logs" ADD COLUMN "checked" boolean DEFAULT false;--> statement-breakpoint
ALTER TABLE "logs" ADD COLUMN "checkedAt" timestamp;

View File

@@ -0,0 +1,9 @@
CREATE TABLE "manualPrinting" (
"print_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"line" integer,
"printReason" text NOT NULL,
"initials" text NOT NULL,
"additionalComments" text NOT NULL,
"add_date" timestamp DEFAULT now(),
"add_user" text
);

View File

@@ -0,0 +1,2 @@
DROP TABLE "apiHits" CASCADE;--> statement-breakpoint
DROP TABLE "eom" CASCADE;

View File

@@ -0,0 +1,17 @@
CREATE TABLE "printers" (
"printer_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"humanReadableId" text,
"name" text NOT NULL,
"ipAddress" text,
"port" numeric NOT NULL,
"status" text,
"statusText" text NOT NULL,
"lastTimePrinted" text,
"assigned" boolean DEFAULT false NOT NULL,
"remark" text,
"monitorState" boolean DEFAULT false NOT NULL,
"add_Date" timestamp DEFAULT now(),
"upd_date" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE UNIQUE INDEX "humanReadableId" ON "printers" USING btree ("name");

View File

@@ -0,0 +1,3 @@
ALTER TABLE "printers" ALTER COLUMN "statusText" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "printers" ALTER COLUMN "assigned" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "printers" ALTER COLUMN "monitorState" DROP NOT NULL;

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" ALTER COLUMN "port" DROP NOT NULL;

View File

@@ -0,0 +1,2 @@
DROP INDEX "humanReadableId";--> statement-breakpoint
CREATE UNIQUE INDEX "humanReadableId" ON "printers" USING btree ("humanReadableId");

View File

@@ -0,0 +1,4 @@
CREATE TABLE "prodlabels" (
"label_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"runningNr" integer NOT NULL
);

View File

@@ -0,0 +1,7 @@
ALTER TABLE "prodlabels" ADD COLUMN "printerID" integer;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "printerName" text;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "line" integer;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "status" text;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "add_date" timestamp;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "upd_date" timestamp;--> statement-breakpoint
CREATE UNIQUE INDEX "runningNr" ON "prodlabels" USING btree ("runningNr");

View File

@@ -0,0 +1,4 @@
ALTER TABLE "prodlabels" ALTER COLUMN "add_date" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "prodlabels" ALTER COLUMN "upd_date" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "add_user" text DEFAULT 'lst';--> statement-breakpoint
CREATE UNIQUE INDEX "ocme_runningNr" ON "ocmeData" USING btree ("runningNr");

View File

@@ -0,0 +1,13 @@
CREATE TABLE "notifications" (
"notify_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" text NOT NULL,
"description" text NOT NULL,
"checkInterval" text DEFAULT '1',
"timeType" text DEFAULT 'hour',
"emails" text,
"active" boolean DEFAULT false,
"lastRan" timestamp DEFAULT now(),
"notifiySettings" jsonb DEFAULT '{}'::jsonb
);
--> statement-breakpoint
CREATE UNIQUE INDEX "notify_name" ON "notifications" USING btree ("name");

View File

@@ -0,0 +1,2 @@
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp;--> statement-breakpoint
ALTER TABLE "printers" ADD COLUMN "printDelay" numeric;

View File

@@ -0,0 +1,2 @@
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET NOT NULL;

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp with time zone;

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" DROP COLUMN "lastTimePrinted";

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" DROP COLUMN "printDelay";

View File

@@ -0,0 +1,19 @@
CREATE TABLE "printerData" (
"printer_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"humanReadableId" text,
"name" text NOT NULL,
"ipAddress" text,
"port" numeric,
"status" text,
"statusText" text,
"lastTimePrinted" timestamp DEFAULT now() NOT NULL,
"assigned" boolean DEFAULT false,
"remark" text,
"printDelay" numeric,
"monitorState" boolean DEFAULT false,
"add_Date" timestamp DEFAULT now(),
"upd_date" timestamp DEFAULT now()
);
--> statement-breakpoint
DROP TABLE "printers" CASCADE;--> statement-breakpoint
CREATE UNIQUE INDEX "humanReadableId" ON "printerData" USING btree ("humanReadableId");

View File

@@ -0,0 +1,17 @@
CREATE TABLE "subModules" (
"submodule_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"moduleName" text NOT NULL,
"name" text NOT NULL,
"description" text,
"link" text NOT NULL,
"active" boolean DEFAULT false,
"roles" jsonb DEFAULT '["systemAdmin"]'::jsonb NOT NULL,
"subSubModule" jsonb DEFAULT '[]'::jsonb,
"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
ALTER TABLE "subModules" ADD CONSTRAINT "subModules_moduleName_modules_name_fk" FOREIGN KEY ("moduleName") REFERENCES "public"."modules"("name") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "subModule_name" ON "subModules" USING btree ("name");

View File

@@ -0,0 +1 @@
DROP INDEX "subModule_name";

View File

@@ -0,0 +1,3 @@
ALTER TABLE "subModules" DROP CONSTRAINT "subModules_moduleName_modules_name_fk";
--> statement-breakpoint
ALTER TABLE "subModules" ALTER COLUMN "moduleName" DROP NOT NULL;

View File

@@ -0,0 +1,12 @@
CREATE TABLE "siloAdjustments" (
"lsiloAdjust_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"level" integer,
"locationID" integer,
"currentStockLevel" numeric,
"newLevel" numeric,
"comments" text DEFAULT '',
"dateAdjusted" timestamp DEFAULT now(),
"lastDateAdjusted" timestamp DEFAULT now(),
"statusMessage" text DEFAULT '',
"add_user" text DEFAULT 'LST_Serivce'
);

View File

@@ -0,0 +1,5 @@
ALTER TABLE "siloAdjustments" ADD COLUMN "comment" text DEFAULT '';--> statement-breakpoint
ALTER TABLE "siloAdjustments" ADD COLUMN "commentAddedBy" text;--> statement-breakpoint
ALTER TABLE "siloAdjustments" ADD COLUMN "commentDate" text;--> statement-breakpoint
ALTER TABLE "siloAdjustments" DROP COLUMN "comments";--> statement-breakpoint
ALTER TABLE "siloAdjustments" DROP COLUMN "statusMessage";

View File

@@ -0,0 +1 @@
ALTER TABLE "siloAdjustments" ADD COLUMN "commentKey" text;

View File

@@ -0,0 +1 @@
CREATE UNIQUE INDEX "subModule_name" ON "subModules" USING btree ("name");

View File

@@ -0,0 +1 @@
ALTER TABLE "subModules" ADD COLUMN "icon" text;

Some files were not shown because too many files have changed in this diff Show More