This commit is contained in:
Rizky 2023-10-14 14:59:32 +07:00
parent 073300d6d2
commit 02727d17fd
9 changed files with 177 additions and 1 deletions

View File

@ -0,0 +1,37 @@
import { apiContext } from "service-srv";
import { user } from "dbgen";
import { session } from "utils/session";
export const _ = {
url: "/_session",
async api() {
const { req, res } = apiContext(this);
const sdata = session.get<{
user: user & {
org: {
id: string;
name: string;
}[];
};
}>(req);
if (sdata) {
let setDefaultCookie = true;
const origin = req.headers.get("origin");
if (origin) {
const url = new URL(origin);
if (url.hostname === "localhost") {
setDefaultCookie = false;
res.setHeader("set-cookie", `${session.cookieKey}=${sdata.id};`);
}
}
if (setDefaultCookie) {
res.setHeader(
"set-cookie",
`${session.cookieKey}=${sdata.id}; SameSite=None; Secure; HttpOnly`
);
}
}
return sdata;
},
};

9
app/srv/api/session.ts Normal file
View File

@ -0,0 +1,9 @@
import { apiContext } from "service-srv";
export const _ = {
url: "/session)}",
async api() {
const { req, res } = apiContext(this);
return "This is session.ts";
}
}

13
app/srv/exports.d.ts vendored
View File

@ -1,4 +1,17 @@
declare module "api/session" {
export const _: {
url: string;
api(): Promise<string>;
};
}
declare module "exports" {
export const session: {
name: string;
url: string;
path: string;
args: any[];
handler: Promise<typeof import("api/session")>;
};
export const _web: {
name: string;
url: string;

View File

@ -1,3 +1,10 @@
export const session = {
name: "session",
url: "/session)}",
path: "app/srv/api/session.ts",
args: [],
handler: import("./api/session")
}
export const _web = {
name: "_web",
url: "/_web/:id/**",

View File

@ -13,6 +13,7 @@ import { prepareApiRoutes } from "./server/api-scan";
g.status = "init";
await createLogger();
g.datadir = g.mode === "dev" ? ".data" : "../data";
g.port = parseInt(process.env.PORT || "4550");
g.mode = process.argv.includes("dev") ? "dev" : "prod";
g.log.info(g.mode === "dev" ? "DEVELOPMENT" : "PRODUCTION");

View File

@ -1,4 +1,3 @@
import { g } from "../utils/global";
const parseQueryParams = (ctx: any) => {
const pageHref = ctx.req.url;

View File

@ -12,6 +12,7 @@ type SingleRoute = {
export const g = global as unknown as {
status: "init" | "ready";
datadir: string;
db: PrismaClient;
dburl: string;
mode: "dev" | "prod";

106
pkgs/core/utils/session.ts Normal file
View File

@ -0,0 +1,106 @@
import { createId } from "@paralleldrive/cuid2";
import { dirAsync } from "fs-jetpack";
import lmdb, { RootDatabase, open } from "lmdb";
import { dirname, join } from "path";
import { g } from "./global";
import { dir } from "./dir";
const cuid = createId;
type SessionEntry<T> = { id: string; expired: number; data: T };
export type SRVCache<T> = ReturnType<typeof createCache<T>>;
export const createCache = <T>() => ({
lmdb: null as unknown as RootDatabase<SessionEntry<T>>,
cookieKey: "",
async init(arg: { cookieKey: string; dbname?: string }) {
const dbpath = dir(join(g.datadir, (arg.dbname || "session") + ".lmdb"));
await dirAsync(dirname(dbpath));
self(this).lmdb = open({
path: dbpath,
compression: true,
});
self(this).cookieKey = arg.cookieKey;
},
async new(data: any, expired?: Date): Promise<SessionEntry<T>> {
const s = {
id: cuid(),
expired: expired ? expired.getTime() / 1000 : 0,
data,
};
await self(this).lmdb.put(s.id, s);
return s;
},
get<T>(req: string | Request): null | SessionEntry<T> {
let id = "";
if (typeof req === "string") {
id = req;
} else {
const cookie = req.headers.get("cookie");
if (cookie) {
id = parseCookies(cookie)[self(this).cookieKey];
}
}
if (!id) {
return null;
}
const s = self(this).lmdb.get(id) as unknown as SessionEntry<T>;
if (s) {
if (s.expired !== 0 && Date.now() / 1000 > s.expired) {
return null;
}
return s;
}
return null;
},
async set(id: string, data: any): Promise<SessionEntry<T>> {
await self(this).lmdb.put(id, data);
return data;
},
del(id: string) {
return self(this).lmdb.remove(id);
},
keys() {
return new Promise<lmdb.Key[]>((resolve) => {
const keys: lmdb.Key[] = [];
self(this)
.lmdb.getKeys()
.forEach((e) => {
keys.push(e);
});
resolve(keys);
});
},
clear() {
self(this).lmdb.clearSync();
},
count() {
return self(this).lmdb.getCount();
},
});
export const session = createCache();
const self = (me: Session) => me;
type Session = typeof session;
export function parseCookies(cookieHeader: string) {
const list: Record<string, string> = {};
if (!cookieHeader) return list;
cookieHeader.split(`;`).forEach(function (cookie) {
let [name, ...rest] = cookie.split(`=`);
name = name?.trim();
if (!name) return;
const value = rest.join(`=`).trim();
if (!value) return;
list[name] = decodeURIComponent(value);
});
return list;
}

View File

@ -23,6 +23,9 @@
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"paths": {
"dbgen": [
"./node_modules/.prisma/client/index.d.ts"
],
"service-srv": [
"./pkgs/core/server/api-ctx.ts"
],