@worker-tools/middleware
Version:
A suite of standalone HTTP server middlewares for Worker Runtimes.
86 lines • 3.83 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.storageSession = exports.cookieSession = void 0;
const web_uuid_1 = require("web-uuid");
const base64_encoding_1 = require("base64-encoding");
const immer_1 = require("immer");
const msgpackr_1 = require("msgpackr");
(0, immer_1.enableMapSet)();
const stringifySessionCookie = (value) => new base64_encoding_1.Base64Encoder({ url: true }).encode(new msgpackr_1.Encoder({ structuredClone: true }).encode(value));
const parseSessionCookie = (value) => new msgpackr_1.Decoder({ structuredClone: true }).decode(new base64_encoding_1.Base64Decoder().decode(value));
/**
* Cookie session middleware for worker runtimes.
*
* Requires a cookie store, preferably encrypted or signed.
*
* Important: This will serialize the entire session data and store it in a cookie. It is sent with every request!
* Only applicable for small session objects. Use `storageSession` for a traditional, KV store-backed session.
*/
function cookieSession(options = {}) {
return async (ax) => {
const ctx = await ax;
const { cookieStore, cookies } = ctx;
const { defaultSession, cookieName = 'obj', expirationTtl = 5 * 60 } = options;
const cookieVal = cookies[cookieName];
const original = cookieVal ? parseSessionCookie(cookieVal) : defaultSession !== null && defaultSession !== void 0 ? defaultSession : {};
const session = (0, immer_1.createDraft)(original);
const newContext = Object.assign(ctx, { session, cookieSession: session });
ctx.effects.push(() => {
const next = (0, immer_1.finishDraft)(session);
if (next !== original) {
cookieStore.set({
name: cookieName,
value: stringifySessionCookie(next),
expires: new Date(Date.now() + expirationTtl * 1000),
sameSite: 'lax',
httpOnly: true,
});
}
});
return newContext;
};
}
exports.cookieSession = cookieSession;
/**
* Session middleware for worker runtimes.
*
* Need to provide a `StorageArea` to persist the session between requests.
* See `@worker-tools/kv-storage`.
*
*/
// FIXME: Will "block" until session object is retrieved from KV => provide "unyielding" version that returns a promise?
function storageSession(options) {
return async (ax) => {
var _a, _b;
const ctx = await ax;
const { cookies, cookieStore } = ctx;
const { storage, defaultSession, cookieName = 'sid', expirationTtl = 5 * 60 } = options;
const cookieVal = cookies[cookieName];
const sid = cookieVal ? new web_uuid_1.WebUUID(cookieVal) : web_uuid_1.WebUUID.v4();
const original = (_b = (_a = (await storage.get(sid))) !== null && _a !== void 0 ? _a : defaultSession) !== null && _b !== void 0 ? _b : {};
const session = (0, immer_1.createDraft)(original);
const newContext = Object.assign(ctx, { session, storageSession: session });
ctx.waitUntil((async () => {
await ctx.handled;
await ctx.flushed;
const next = (0, immer_1.finishDraft)(session);
if (next !== original) {
await storage.set(sid, next, { expirationTtl });
}
})());
if (!cookieVal) {
ctx.effects.push(() => {
cookieStore.set({
name: cookieName,
value: sid.id,
expires: new Date(Date.now() + expirationTtl * 1000),
sameSite: 'lax',
httpOnly: true,
});
});
}
return newContext;
};
}
exports.storageSession = storageSession;
//# sourceMappingURL=session.js.map
;