feat: centralize application framework primitives
This commit is contained in:
@@ -17,6 +17,16 @@ export interface CookieStore {
|
||||
set(name: string, value: string, options?: CookieOptions): void;
|
||||
delete(name: string, options?: CookieOptions): void;
|
||||
headers(): string[];
|
||||
transaction<T extends Record<string, unknown> = Record<string, unknown>>(
|
||||
name: string,
|
||||
options?: CookieOptions,
|
||||
): TransactionCookie<T>;
|
||||
}
|
||||
|
||||
export interface TransactionCookie<T extends Record<string, unknown>> {
|
||||
set(value: T): void;
|
||||
consume(): T | undefined;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
export interface SessionStore {
|
||||
@@ -259,7 +269,7 @@ export function createCookieStore(req: Request): CookieStore {
|
||||
const incoming = parseCookieHeader(req.headers.get("cookie") ?? "");
|
||||
const outgoing: string[] = [];
|
||||
|
||||
return {
|
||||
const store: CookieStore = {
|
||||
get(name) {
|
||||
return incoming[name];
|
||||
},
|
||||
@@ -287,7 +297,45 @@ export function createCookieStore(req: Request): CookieStore {
|
||||
headers() {
|
||||
return [...outgoing];
|
||||
},
|
||||
transaction<T extends Record<string, unknown>>(name: string, options: CookieOptions = {}) {
|
||||
const policy: CookieOptions = {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
sameSite: "Lax",
|
||||
maxAge: 600,
|
||||
secure: new URL(req.url).protocol === "https:",
|
||||
...options,
|
||||
};
|
||||
return {
|
||||
set(value: T) {
|
||||
const json = JSON.stringify(value);
|
||||
const encoded = btoa(unescape(encodeURIComponent(json)))
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "");
|
||||
store.set(name, encoded, policy);
|
||||
},
|
||||
consume(): T | undefined {
|
||||
const encoded = store.get(name);
|
||||
store.delete(name, policy);
|
||||
if (!encoded) return undefined;
|
||||
try {
|
||||
const padded = encoded
|
||||
.replace(/-/g, "+")
|
||||
.replace(/_/g, "/")
|
||||
.padEnd(Math.ceil(encoded.length / 4) * 4, "=");
|
||||
return JSON.parse(decodeURIComponent(escape(atob(padded)))) as T;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
store.delete(name, policy);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
return store;
|
||||
}
|
||||
|
||||
export function createSessionStore(
|
||||
|
||||
Reference in New Issue
Block a user