diff --git a/modules.json b/modules.json index 2e6f659..153d0b8 100755 --- a/modules.json +++ b/modules.json @@ -21,6 +21,7 @@ "@types/lodash.capitalize": "^4.2.9", "@types/lodash.get": "^4.4.9", "@types/react": "^18.2.65", + "drizzle-orm": "^0.33.0", "bun-types": "^1.1.24", "@types/react-dom": "^18.3.0", "rou3": "^0.5.1", diff --git a/server/server-route.ts b/server/server-route.ts index d1b521f..d097f31 100755 --- a/server/server-route.ts +++ b/server/server-route.ts @@ -1,7 +1,8 @@ import { _post } from "lib/utils/post"; import { addRoute, createRouter, findRoute } from "rou3"; +import { ServerSession, SessionData } from "./server-session"; -export type ServerArg = { +export type ServerContext = { req: Request; handle: (req: Request) => Promise; mode: "dev" | "prod"; @@ -11,6 +12,11 @@ export type ServerArg = { }; }; +export interface SessionContext> + extends ServerContext { + session: ServerSession; +} + type RouteFn = (...arg: any[]) => Promise; type SingleRoute = [string, () => Promise<{ default: RouteFn }>]; @@ -31,9 +37,7 @@ export const newServerRouter = < return arg; }; -export const createClientForServer = < - T extends ReturnType ->( +export const newClientRouter = >( router: T ) => { return new Proxy( @@ -72,7 +76,7 @@ export const useServerRouter = >( } return { - async handle(arg: ServerArg) { + async handle(arg: ServerContext | SessionContext) { const { url, req } = arg; const found = findRoute(rou, undefined, url.pathname); @@ -94,7 +98,7 @@ export const useServerRouter = >( if (typeof result === "object" && result instanceof Response) { return result; } - + return new Response(JSON.stringify(result)); } return await arg.handle(arg.req); diff --git a/server/server-session.ts b/server/server-session.ts index 0cda3d9..2ab91ce 100755 --- a/server/server-session.ts +++ b/server/server-session.ts @@ -1,43 +1,100 @@ /// -import { ServerArg, useServerRouter } from "./server-route"; +import { ServerContext, useServerRouter } from "./server-route"; -type ServerSession = { - handle: (arg: ServerArg) => Promise; +export type SessionData | undefined> = T & { + uid: string; + role: string; + sid: string; + expired_at?: number; + created_at: number; }; -export const sessionServer = (arg: { +export type SingleSession> = { + data: T; + track: (arg: { path: string }) => Promise; + destroy: () => Promise; +}; + +type FilterSessionArg = { + uid: string; + sid: string; + role: string; + created_at: { gt?: number; lt?: number }; + expired_at: { gt?: number; lt?: number }; +}; +export type ServerSession> = { + create: ( + data: Record & { + uid: string; + role: string; + expired_at?: number; + } + ) => Promise>; + findMany: (arg: Partial) => Promise[]>; + findFirst: ( + arg: Partial + ) => Promise>; + current?: SingleSession; +}; + +type SessionServerHandler = { + cleanup: () => Promise; + handle: (arg: ServerContext) => Promise; +}; + +export const createSessionServer = >(arg: { encrypt?: boolean; router?: ReturnType; - on: { - login: (arg: { - mode: "user-pass"; - username: string; - password: string; - }) => Promise; - }; -}): ServerSession => { +}): SessionServerHandler => { const internal = { has_router: false, router: null as null | ReturnType, }; + const server_session: Omit, "current"> = { + async create(data) { + const new_session: SingleSession = { + data: { ...data, created_at: Date.now() } as T, + async destroy() {}, + async track(arg) {}, + }; + return new_session; + }, + async findFirst(arg) { + return null; + }, + async findMany(arg) { + return []; + }, + }; + if (typeof arg.router === "object" && arg.router instanceof Promise) { internal.has_router = true; arg.router.then((e) => { internal.router = e; }); } - const s: ServerSession = { + + const server_handler: SessionServerHandler = { + async cleanup() {}, async handle(server_arg) { const { req, handle } = server_arg; - if (internal.has_router && internal.router) { - return await internal.router.handle(server_arg); - } + console.log("makaru", internal.has_router, internal.router); + return new Response("fas"); + // if (internal.has_router && internal.router) { + // return await internal.router.handle({ + // ...server_arg, + // session: { + // ...server_session, + // current: undefined, + // }, + // }); + // } - return handle(req); + // return handle(req); }, }; - return s; + return server_handler; }; diff --git a/server/session/schema.ts b/server/session/schema.ts new file mode 100755 index 0000000..74045f7 --- /dev/null +++ b/server/session/schema.ts @@ -0,0 +1,46 @@ +import { createId } from "@paralleldrive/cuid2"; +import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; + +export const session = sqliteTable( + "session", + { + session_id: text("session_id") + .notNull() + .primaryKey() + .$defaultFn(() => createId()), + created_at: integer("created_at", { mode: "timestamp_ms" }).default( + new Date() + ), + active: integer("active", { mode: "boolean" }), + data: text("data", { mode: "json" }), + expired_at: integer("expired_at", { mode: "timestamp_ms" }), + }, + (table) => { + return { + expired_at_idx: index("expired_at_idx").on(table.expired_at), + }; + } +); +export const track = sqliteTable( + "track", + { + track_id: text("track_id") + .notNull() + .primaryKey() + .$defaultFn(() => createId()), + created_at: integer("created_at", { mode: "timestamp_ms" }).default( + new Date() + ), + session_id: text("session_id"), + url: text("url").notNull(), + referer: text("referer"), + user_ip: text("user_ip"), + data: text("data", { mode: "json" }), + tstamp: integer("tstamp", { mode: "timestamp_ms" }).default(new Date()), + }, + (table) => { + return { + session_id: index("session_id").on(table.session_id), + }; + } +); diff --git a/utils/client-session.ts b/utils/client-session.ts index ec8e4b7..aff7da6 100755 --- a/utils/client-session.ts +++ b/utils/client-session.ts @@ -1,15 +1,15 @@ +import { SessionData } from "lib/server/server-session"; + const w = window as unknown as { _prasi_session: any; _prasi: { site_id: string }; }; -export type SessionData = Record & { role: string }; - type SessionResponse = | { active: false; reason: string } | { active: true; data: T; token: string }; -export const sessionClient = async (arg: { +export const sessionClient = async >(arg: { editorSampleData: T; auth: { mode: "user-pass"; @@ -70,7 +70,7 @@ export const sessionClient = async (arg: { return session; }; -export type Session = { +export type Session> = { active: boolean; id_site: string; login: (arg: { username: string; password: string }) => Promise;