refactor(all): refactoring to remove monorepo taking to long to get it wokring as intended
This commit is contained in:
@@ -11,5 +11,5 @@ get {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auth:bearer {
|
auth:bearer {
|
||||||
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImlhdCI6MTczOTgyMTgyNiwiZXhwIjoxNzM5ODI1NDI2fQ.N5pn4PaPDhM_AXAOTGwd-_TOP9UOU1wK0vmICVE7vEc
|
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImlhdCI6MTczOTgyNjEwNiwiZXhwIjoxNzM5ODI2MTY2fQ.y8wm4PuduJdXp_fPnRohQ8VOlNRMeYszzcPdOLRwzic
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ meta {
|
|||||||
get {
|
get {
|
||||||
url: http://localhost:4000/api/auth/session
|
url: http://localhost:4000/api/auth/session
|
||||||
body: none
|
body: none
|
||||||
auth: bearer
|
auth: basic
|
||||||
}
|
}
|
||||||
|
|
||||||
headers {
|
headers {
|
||||||
:
|
:
|
||||||
}
|
}
|
||||||
|
|
||||||
auth:bearer {
|
auth:basic {
|
||||||
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsImlhdCI6MTczOTgyNzE1NiwiZXhwIjoxNzM5ODI3MjE2fQ.VE9URMrRI_5_wc8CEmj-VEVeP01LL412vKhNwWRRHRM
|
username: admin
|
||||||
|
password: pass123
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.7.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@scalar/hono-api-reference": "^0.5.174"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import {Hono} from "hono";
|
|
||||||
import {serveStatic} from "hono/bun";
|
import {serveStatic} from "hono/bun";
|
||||||
import {logger} from "hono/logger";
|
import {logger} from "hono/logger";
|
||||||
import {ocmeService} from "./services/ocmeServer";
|
|
||||||
import {authMiddleware} from "lst-auth";
|
import {authMiddleware} from "lst-auth";
|
||||||
import {cors} from "hono/cors";
|
import {cors} from "hono/cors";
|
||||||
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
|
||||||
//import { expensesRoute } from "./routes/expenses";
|
//routes
|
||||||
import login from "./route/auth/login";
|
import auth from "./services/auth/authService";
|
||||||
import session from "./route/auth/session";
|
import scalar from "./route/scalar";
|
||||||
|
// services
|
||||||
|
import {ocmeService} from "./services/ocme/ocmeServer";
|
||||||
|
|
||||||
const app = new Hono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
app.use("*", logger());
|
app.use("*", logger());
|
||||||
app.use(
|
app.use(
|
||||||
@@ -24,24 +25,32 @@ app.use(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
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
|
// as we dont want to change ocme again well use a proxy to this
|
||||||
app.all("/ocme/*", async (c) => {
|
app.all("/ocme/*", async (c) => {
|
||||||
return ocmeService(c);
|
return ocmeService(c);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.basePath("/api/auth").route("/login", login).route("/session", session);
|
const routes = [scalar, auth] as const;
|
||||||
|
|
||||||
|
routes.forEach((route) => {
|
||||||
|
app.route("/", route);
|
||||||
|
});
|
||||||
|
|
||||||
|
//app.basePath("/api/auth").route("/login", login).route("/session", session).route("/register", register);
|
||||||
|
|
||||||
//auth stuff
|
//auth stuff
|
||||||
app.get("/api/protected", authMiddleware, (c) => {
|
app.get("/api/protected", authMiddleware, (c) => {
|
||||||
return c.json({success: true, message: "is authenticated"});
|
return c.json({success: true, message: "is authenticated"});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/test", (c) => {
|
|
||||||
return c.json({success: true, message: "hello from bun"});
|
|
||||||
});
|
|
||||||
// const authRoute = app.basePath("/api/auth").route("*", )
|
|
||||||
|
|
||||||
//const apiRoute = app.basePath("/api").route("/expenses", expensesRoute);
|
|
||||||
|
|
||||||
app.get("*", serveStatic({root: "../frontend/dist"}));
|
app.get("*", serveStatic({root: "../frontend/dist"}));
|
||||||
app.get("*", serveStatic({path: "../frontend/dist/index.html"}));
|
app.get("*", serveStatic({path: "../frontend/dist/index.html"}));
|
||||||
|
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
import { Context } from "hono";
|
|
||||||
import { authHandler, initAuthConfig, verifyAuth } from "@hono/auth-js";
|
|
||||||
import Credentials from "@auth/core/providers/credentials";
|
|
||||||
import { AuthConfig } from "@auth/core/types";
|
|
||||||
|
|
||||||
export const authConfig: AuthConfig = {
|
|
||||||
secret: process.env.AUTH_SECRET,
|
|
||||||
providers: [
|
|
||||||
Credentials({
|
|
||||||
name: "Credentials",
|
|
||||||
credentials: {
|
|
||||||
username: { label: "Username", type: "text" },
|
|
||||||
password: { label: "Password", type: "password" },
|
|
||||||
},
|
|
||||||
async authorize(credentials) {
|
|
||||||
// Add your authentication logic here
|
|
||||||
const user = { id: "1", name: "John Doe", email: "john@example.com" };
|
|
||||||
if (
|
|
||||||
credentials?.username === "john" &&
|
|
||||||
credentials?.password === "password"
|
|
||||||
) {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
session: {
|
|
||||||
strategy: "jwt",
|
|
||||||
},
|
|
||||||
callbacks: {
|
|
||||||
// async session({ session, token }) {
|
|
||||||
// session.user.id = token.sub;
|
|
||||||
// return session;
|
|
||||||
// },
|
|
||||||
async jwt({ token, user }) {
|
|
||||||
if (user) {
|
|
||||||
token.sub = user.id;
|
|
||||||
}
|
|
||||||
return token;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// auth.use("/api/auth/*", authHandler());
|
|
||||||
|
|
||||||
// auth.use("/api/*", verifyAuth());
|
|
||||||
|
|
||||||
// auth.get("/api/protected", (c) => {
|
|
||||||
// const auth = c.get("authUser");
|
|
||||||
// return c.json(auth);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// export default auth;
|
|
||||||
13
apps/server/src/route/apiDoc.ts
Normal file
13
apps/server/src/route/apiDoc.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
// the doc endpoint
|
||||||
|
app.doc("/api", {
|
||||||
|
openapi: "3.0.0",
|
||||||
|
info: {
|
||||||
|
version: "1.0.0",
|
||||||
|
title: "LST API",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default app;
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import {Hono} from "hono";
|
|
||||||
import {login} from "lst-auth";
|
|
||||||
|
|
||||||
const router = new Hono().post("/", async (c) => {
|
|
||||||
let body = {username: "", password: "", error: ""};
|
|
||||||
try {
|
|
||||||
body = await c.req.json();
|
|
||||||
} catch (error) {
|
|
||||||
return c.json({success: false, message: "Username and password required"}, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!body?.username || !body?.password) {
|
|
||||||
return c.json({message: "Username and password required"}, 400);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const {token, user} = login(body?.username, body?.password);
|
|
||||||
|
|
||||||
// Set the JWT as an HTTP-only cookie
|
|
||||||
c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
|
|
||||||
|
|
||||||
return c.json({message: "Login successful", user});
|
|
||||||
} catch (err) {
|
|
||||||
// console.log(err);
|
|
||||||
return c.json({message: err}, 401);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
79
apps/server/src/route/scalar.ts
Normal file
79
apps/server/src/route/scalar.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
import {apiReference} from "@scalar/hono-api-reference";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
app.get(
|
||||||
|
"/api/docs",
|
||||||
|
apiReference({
|
||||||
|
theme: "kepler",
|
||||||
|
layout: "classic",
|
||||||
|
defaultHttpClient: {targetKey: "node", clientKey: "axios"},
|
||||||
|
pageTitle: "Lst API Reference",
|
||||||
|
hiddenClients: [
|
||||||
|
"libcurl",
|
||||||
|
"clj_http",
|
||||||
|
"httpclient",
|
||||||
|
"restsharp",
|
||||||
|
"native",
|
||||||
|
"http1.1",
|
||||||
|
"asynchttp",
|
||||||
|
"nethttp",
|
||||||
|
"okhttp",
|
||||||
|
"unirest",
|
||||||
|
"xhr",
|
||||||
|
"fetch",
|
||||||
|
"jquery",
|
||||||
|
"okhttp",
|
||||||
|
"native",
|
||||||
|
"request",
|
||||||
|
"unirest",
|
||||||
|
"nsurlsession",
|
||||||
|
"cohttp",
|
||||||
|
"curl",
|
||||||
|
"guzzle",
|
||||||
|
"http1",
|
||||||
|
"http2",
|
||||||
|
"webrequest",
|
||||||
|
"restmethod",
|
||||||
|
"python3",
|
||||||
|
"requests",
|
||||||
|
"httr",
|
||||||
|
"native",
|
||||||
|
"curl",
|
||||||
|
"httpie",
|
||||||
|
"wget",
|
||||||
|
"nsurlsession",
|
||||||
|
"undici",
|
||||||
|
],
|
||||||
|
spec: {
|
||||||
|
url: "/api",
|
||||||
|
},
|
||||||
|
baseServerURL: "https://scalar.com",
|
||||||
|
servers: [
|
||||||
|
{
|
||||||
|
url: "http://usday1vms006:3000",
|
||||||
|
description: "Production",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "http://localhost:4000",
|
||||||
|
description: "dev server",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// authentication: {
|
||||||
|
// preferredSecurityScheme: {'bearerAuth'},
|
||||||
|
// },
|
||||||
|
|
||||||
|
// metaData: {
|
||||||
|
// title: "Page title",
|
||||||
|
// description: "My page page",
|
||||||
|
// ogDescription: "Still about my my page",
|
||||||
|
// ogTitle: "Page title",
|
||||||
|
// ogImage: "https://example.com/image.png",
|
||||||
|
// twitterCard: "summary_large_image",
|
||||||
|
// // Add more...
|
||||||
|
// },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export default app;
|
||||||
12
apps/server/src/services/auth/authService.ts
Normal file
12
apps/server/src/services/auth/authService.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import {OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
|
||||||
|
import login from "./routes/login";
|
||||||
|
import register from "./routes/register";
|
||||||
|
import session from "./routes/session";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
app.route("api/auth/login", login);
|
||||||
|
app.route("api/auth//register", register);
|
||||||
|
app.route("api/auth/session", session);
|
||||||
|
|
||||||
|
export default app;
|
||||||
1
apps/server/src/services/auth/controllers/register.ts
Normal file
1
apps/server/src/services/auth/controllers/register.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const registerUser = async () => {};
|
||||||
17
apps/server/src/services/auth/lib/createPassword.ts
Normal file
17
apps/server/src/services/auth/lib/createPassword.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import bcrypt from "bcrypt";
|
||||||
|
|
||||||
|
export const passwordUpdate = (password: string) => {
|
||||||
|
// encypt password
|
||||||
|
let pass: string = process.env.SECRET;
|
||||||
|
let salt: string = process.env.SALTING;
|
||||||
|
|
||||||
|
if (!pass || !salt) {
|
||||||
|
pass = "error";
|
||||||
|
} else {
|
||||||
|
pass = bcrypt.hashSync(process.env.SECRET + password, parseInt(process.env.SALTING));
|
||||||
|
|
||||||
|
pass = btoa(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pass;
|
||||||
|
};
|
||||||
112
apps/server/src/services/auth/routes/login.ts
Normal file
112
apps/server/src/services/auth/routes/login.ts
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
import {login} from "lst-auth";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
const UserSchema = z
|
||||||
|
.object({
|
||||||
|
username: z.string().min(3).openapi({example: "smith002"}),
|
||||||
|
password: z.string().openapi({example: "password123"}),
|
||||||
|
})
|
||||||
|
.openapi("User");
|
||||||
|
|
||||||
|
// Define the response schema for the login endpoint
|
||||||
|
const LoginResponseSchema = z
|
||||||
|
.object({
|
||||||
|
message: z.string().openapi({example: "Login successful"}),
|
||||||
|
user: z.object({
|
||||||
|
username: z.string().openapi({example: "smith002"}),
|
||||||
|
// Add other user fields as needed
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.openapi("LoginResponse");
|
||||||
|
|
||||||
|
const route = createRoute({
|
||||||
|
tags: ["Auth"],
|
||||||
|
summary: "Login as user",
|
||||||
|
description: "Login as a user to get a JWT token",
|
||||||
|
method: "post",
|
||||||
|
path: "/",
|
||||||
|
request: {body: {content: {"application/json": {schema: UserSchema}}}},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: LoginResponseSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Login successful",
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: z.object({
|
||||||
|
success: z.boolean().openapi({example: false}),
|
||||||
|
message: z.string().openapi({example: "Username and password required"}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Bad request",
|
||||||
|
},
|
||||||
|
401: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: z.object({
|
||||||
|
message: z.string().openapi({example: "Invalid credentials"}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Unauthorized",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
app.openapi(route, async (c) => {
|
||||||
|
let body: {username: string; password: string};
|
||||||
|
try {
|
||||||
|
body = await c.req.json();
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({success: false, message: "Username and password required"}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!body?.username || !body?.password) {
|
||||||
|
return c.json({success: false, message: "Username and password required"}, 400);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const {token, user} = login(body.username, body.password);
|
||||||
|
|
||||||
|
// Set the JWT as an HTTP-only cookie
|
||||||
|
c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Path=/; SameSite=None; Max-Age=3600`);
|
||||||
|
|
||||||
|
return c.json({message: "Login successful", user});
|
||||||
|
} catch (err) {
|
||||||
|
return c.json({message: err instanceof Error ? err.message : "Invalid credentials"}, 401);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
let body = {username: "", password: "", error: ""};
|
||||||
|
try {
|
||||||
|
body = await c.req.json();
|
||||||
|
} catch (error) {
|
||||||
|
return c.json({success: false, message: "Username and password required"}, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!body?.username || !body?.password) {
|
||||||
|
return c.json({message: "Username and password required"}, 400);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const {token, user} = login(body?.username, body?.password);
|
||||||
|
|
||||||
|
// Set the JWT as an HTTP-only cookie
|
||||||
|
c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
|
||||||
|
|
||||||
|
return c.json({message: "Login successful", user});
|
||||||
|
} catch (err) {
|
||||||
|
// console.log(err);
|
||||||
|
return c.json({message: err}, 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
export default app;
|
||||||
33
apps/server/src/services/auth/routes/register.ts
Normal file
33
apps/server/src/services/auth/routes/register.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
const UserSchema = z
|
||||||
|
.object({
|
||||||
|
id: z.string().openapi({example: "123"}),
|
||||||
|
name: z.string().min(3).openapi({example: "John Doe"}),
|
||||||
|
age: z.number().openapi({example: 42}),
|
||||||
|
})
|
||||||
|
.openapi("User");
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["Auth"],
|
||||||
|
summary: "Register a new user",
|
||||||
|
method: "post",
|
||||||
|
path: "/",
|
||||||
|
request: {params: UserSchema},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {"application/json": {schema: UserSchema}},
|
||||||
|
description: "Retrieve the user",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(c) => {
|
||||||
|
const {id} = c.req.valid("param");
|
||||||
|
return c.json({id, age: 20, name: "Ultra-man"});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default app;
|
||||||
@@ -1,11 +1,29 @@
|
|||||||
import {Hono} from "hono";
|
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||||
import {verify} from "hono/jwt";
|
import {verify} from "hono/jwt";
|
||||||
|
|
||||||
const app = new Hono();
|
const session = new OpenAPIHono();
|
||||||
|
const tags = ["Auth"];
|
||||||
const JWT_SECRET = "your-secret-key";
|
const JWT_SECRET = "your-secret-key";
|
||||||
|
|
||||||
app.get("/", async (c) => {
|
const route = createRoute({
|
||||||
|
tags: ["Auth"],
|
||||||
|
summary: "Checks a user session based on there token",
|
||||||
|
description: "Can post there via Authentiaction header or cookies",
|
||||||
|
method: "get",
|
||||||
|
path: "/",
|
||||||
|
request: {body: {content: {"application/json": {schema: {username: "", password: ""}}}}},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {session: ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: "Login successful",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
session.openapi(route, async (c) => {
|
||||||
const authHeader = c.req.header("Authorization");
|
const authHeader = c.req.header("Authorization");
|
||||||
const cookies = c.req.header("cookie");
|
const cookies = c.req.header("cookie");
|
||||||
|
|
||||||
@@ -17,13 +35,6 @@ app.get("/", async (c) => {
|
|||||||
if (!authHeader && !cookies) {
|
if (!authHeader && !cookies) {
|
||||||
return c.json({error: "Unauthorized"}, 401);
|
return c.json({error: "Unauthorized"}, 401);
|
||||||
}
|
}
|
||||||
// if (!cookies || !cookies.startsWith("Bearer ")) {
|
|
||||||
// return c.json({error: "Unauthorized"}, 401);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
||||||
// return c.json({error: "Unauthorized"}, 401);
|
|
||||||
// }
|
|
||||||
|
|
||||||
const token = cookies?.split("auth_token=")[1].split(";")[0] || authHeader?.split("Bearer ")[1] || "";
|
const token = cookies?.split("auth_token=")[1].split(";")[0] || authHeader?.split("Bearer ")[1] || "";
|
||||||
|
|
||||||
@@ -35,4 +46,4 @@ app.get("/", async (c) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default session;
|
||||||
10
load-env.ts
Normal file
10
load-env.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
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);
|
||||||
@@ -29,9 +29,14 @@
|
|||||||
"@hono/zod-openapi": "^0.18.4",
|
"@hono/zod-openapi": "^0.18.4",
|
||||||
"@shared/lib": "*",
|
"@shared/lib": "*",
|
||||||
"@types/bun": "^1.2.2",
|
"@types/bun": "^1.2.2",
|
||||||
|
"axios": "^1.7.9",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"compression": "^1.8.0",
|
||||||
"concurrently": "^9.1.2",
|
"concurrently": "^9.1.2",
|
||||||
"cookie": "^1.0.2",
|
"cookie": "^1.0.2",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
|
"dotenv-expand": "^12.0.1",
|
||||||
"hono": "^4.7.1",
|
"hono": "^4.7.1",
|
||||||
"http-proxy-middleware": "^3.0.3",
|
"http-proxy-middleware": "^3.0.3",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
|||||||
175
packages/database/.gitignore
vendored
Normal file
175
packages/database/.gitignore
vendored
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
npm-debug.log_
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Caches
|
||||||
|
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# 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/)
|
||||||
|
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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.*
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
||||||
15
packages/database/README.md
Normal file
15
packages/database/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# database
|
||||||
|
|
||||||
|
To install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
To run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
This project was created using `bun init` in bun v1.2.2. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
||||||
8
packages/database/drizzle.config.ts
Normal file
8
packages/database/drizzle.config.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import {defineConfig} from "drizzle-kit";
|
||||||
|
export default defineConfig({
|
||||||
|
dialect: "postgresql", // 'mysql' | 'sqlite' | 'turso'
|
||||||
|
schema: "./schema",
|
||||||
|
dbCredentials: {
|
||||||
|
url: "postgresql://postgres:nova0511@localhost:5432/lst_db",
|
||||||
|
},
|
||||||
|
});
|
||||||
12
packages/database/drizzle/0000_stormy_thunderbolt.sql
Normal file
12
packages/database/drizzle/0000_stormy_thunderbolt.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE "users" (
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
"title" text NOT NULL,
|
||||||
|
"passwordToken" text NOT NULL,
|
||||||
|
"passwordTokenExpires" timestamp,
|
||||||
|
"active" boolean DEFAULT true NOT NULL,
|
||||||
|
"pingcode" numeric,
|
||||||
|
"add_Date" timestamp DEFAULT now(),
|
||||||
|
"add_User" text DEFAULT 'LST_System' NOT NULL,
|
||||||
|
"upd_date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
96
packages/database/drizzle/meta/0000_snapshot.json
Normal file
96
packages/database/drizzle/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"id": "d0e2effa-c6ac-4f81-b546-ef6b10037eca",
|
||||||
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "postgresql",
|
||||||
|
"tables": {
|
||||||
|
"public.users": {
|
||||||
|
"name": "users",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "serial",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"name": "title",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"passwordToken": {
|
||||||
|
"name": "passwordToken",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"add_Date": {
|
||||||
|
"name": "add_Date",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "now()"
|
||||||
|
},
|
||||||
|
"add_User": {
|
||||||
|
"name": "add_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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
packages/database/drizzle/meta/_journal.json
Normal file
13
packages/database/drizzle/meta/_journal.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "postgresql",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"idx": 0,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1739914245651,
|
||||||
|
"tag": "0000_stormy_thunderbolt",
|
||||||
|
"breakpoints": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
packages/database/index.ts
Normal file
7
packages/database/index.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import {drizzle} from "drizzle-orm/postgres-js";
|
||||||
|
import postgres from "postgres";
|
||||||
|
import "../../load-env";
|
||||||
|
|
||||||
|
const queryClient = postgres("postgresql://postgres:nova0511@localhost:5432/lst_db");
|
||||||
|
|
||||||
|
export const db = drizzle(queryClient);
|
||||||
20
packages/database/package.json
Normal file
20
packages/database/package.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "database",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest",
|
||||||
|
"@types/pg": "^8.11.11",
|
||||||
|
"drizzle-kit": "^0.30.4",
|
||||||
|
"tsx": "^4.19.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"drizzle-orm": "^0.39.3",
|
||||||
|
"drizzle-zod": "^0.7.0",
|
||||||
|
"pg": "^8.13.3",
|
||||||
|
"postgres": "^3.4.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
27
packages/database/schema/users.ts
Normal file
27
packages/database/schema/users.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import {text, pgTable, serial, numeric, index, timestamp, boolean} from "drizzle-orm/pg-core";
|
||||||
|
import {createInsertSchema, createSelectSchema} from "drizzle-zod";
|
||||||
|
import {z} from "zod";
|
||||||
|
|
||||||
|
export const users = pgTable("users", {
|
||||||
|
user_id: serial("id").primaryKey(),
|
||||||
|
username: text("user_id").notNull(),
|
||||||
|
email: text("title").notNull(),
|
||||||
|
passwordToken: text("passwordToken").notNull(),
|
||||||
|
passwordTokenExpires: timestamp("passwordTokenExpires"),
|
||||||
|
acitve: boolean("active").default(true).notNull(),
|
||||||
|
pinCode: numeric("pingcode"),
|
||||||
|
lastLogin: timestamp("add_Date").defaultNow(),
|
||||||
|
add_User: text("add_User").default("LST_System").notNull(),
|
||||||
|
add_Date: timestamp("add_Date").defaultNow(),
|
||||||
|
upd_user: text("add_User").default("LST_System").notNull(),
|
||||||
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
export const insertUsersSchema = createInsertSchema(users, {
|
||||||
|
username: z.string().min(3, {message: "Username must be at least 3 characters"}),
|
||||||
|
email: z.string().email({message: "Invalid email"}),
|
||||||
|
passwordToken: z.string().min(8, {message: "Password must be at least 8 characters"}),
|
||||||
|
});
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectExpensesSchema = createSelectSchema(users);
|
||||||
27
packages/database/tsconfig.json
Normal file
27
packages/database/tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Enable latest features
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
|
}
|
||||||
0
packages/shared/src/utils/createPassword.ts
Normal file
0
packages/shared/src/utils/createPassword.ts
Normal file
Reference in New Issue
Block a user