UNPKG

koa-session

Version:

Koa cookie session middleware with external store support

291 lines 20.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SessionOptions = void 0; exports.createSession = createSession; const node_assert_1 = __importDefault(require("node:assert")); const node_util_1 = require("node:util"); const node_crypto_1 = require("node:crypto"); const is_type_of_1 = require("is-type-of"); const zod_1 = __importDefault(require("zod")); const context_js_1 = require("./context.js"); const util_js_1 = __importDefault(require("./util.js")); const debug = (0, node_util_1.debuglog)('koa-session'); const GET_CONTEXT_SESSION = Symbol('get contextSession'); const CONTEXT_SESSION_INSTANCE = Symbol('contextSession instance'); exports.SessionOptions = zod_1.default.object({ /** * cookie key * Default is `koa.sess` */ key: zod_1.default.string().default('koa.sess'), /** * maxAge in ms * Default is `86400000`, one day * If set to 'session' will result in a cookie that expires when session/browser is closed * * Warning: If a session cookie is stolen, this cookie will never expire */ maxAge: zod_1.default.union([zod_1.default.number(), zod_1.default.literal('session')]).optional(), /** * automatically commit headers * Default is `true` */ autoCommit: zod_1.default.boolean().default(true), /** * cookie value can overwrite or not * Default is `true` */ overwrite: zod_1.default.boolean().default(true), /** * httpOnly or not * Default is `true` */ httpOnly: zod_1.default.boolean().default(true), /** * signed or not * Default is `true` */ signed: zod_1.default.boolean().default(true), /** * Force a session identifier cookie to be set on every response. * The expiration is reset to the original `maxAge`, resetting the expiration countdown. * Default is `false` */ rolling: zod_1.default.boolean().default(false), /** * renew session when session is nearly expired, so we can always keep user logged in. * Default is `false` */ renew: zod_1.default.boolean().default(false), /** * secure cookie * Default is `undefined`, will be set to `true` if the connection is over HTTPS, otherwise `false`. */ secure: zod_1.default.boolean().optional(), /** * session cookie sameSite options * Default is `undefined`, meaning don't set it */ sameSite: zod_1.default.string().optional(), /** * External key is used the cookie by default, * but you can use `options.externalKey` to customize your own external key methods. */ externalKey: zod_1.default.object({ /** * get the external key * `(ctx) => string` */ get: zod_1.default.function() .args(zod_1.default.any()) .returns(zod_1.default.string()), /** * set the external key * `(ctx, key) => void` */ set: zod_1.default.function() .args(zod_1.default.any(), zod_1.default.string()) .returns(zod_1.default.void()), }).optional(), /** * session storage is dependent on your external store */ store: zod_1.default.object({ /** * get session data by key * `(key, maxAge, { rolling, ctx }) => sessionData | Promise<sessionData>` */ get: zod_1.default.function() .args(zod_1.default.string(), zod_1.default.number(), zod_1.default.object({ rolling: zod_1.default.boolean(), ctx: zod_1.default.any() })) .returns(zod_1.default.promise(zod_1.default.any())), /** * set session data for key, with a `maxAge` (in ms) * `(key, sess, maxAge, { rolling, changed, ctx }) => void | Promise<void>` */ set: zod_1.default.function() .args(zod_1.default.string(), zod_1.default.any(), zod_1.default.number(), zod_1.default.object({ rolling: zod_1.default.boolean(), changed: zod_1.default.boolean(), ctx: zod_1.default.any() })) .returns(zod_1.default.promise(zod_1.default.void())), /** * destroy session data for key * `(key, { ctx })=> void | Promise<void>` */ destroy: zod_1.default.function() .args(zod_1.default.string(), zod_1.default.object({ ctx: zod_1.default.any() })) .returns(zod_1.default.promise(zod_1.default.void())), }).optional(), /** * If your session store requires data or utilities from context, `opts.ContextStore` is also supported. * `ContextStore` must be a class which claims three instance methods demonstrated above. * `new ContextStore(ctx)` will be executed on every request. */ ContextStore: zod_1.default.any().optional(), encode: zod_1.default.function() .args(zod_1.default.any()) .returns(zod_1.default.string()) .optional() .default(() => util_js_1.default.encode), decode: zod_1.default.function() .args(zod_1.default.string()) .returns(zod_1.default.any()) .default(() => util_js_1.default.decode), /** * If you want to generate a new session id, you can use `genid` option to customize it. * Default is a function that uses `randomUUID()`. * `(ctx) => string` */ genid: zod_1.default.function() .args(zod_1.default.any()) .returns(zod_1.default.string()) .optional(), /** * If you want to prefix the session id, you can use `prefix` option to customize it. * It will not work if `options.genid(ctx)` present. */ prefix: zod_1.default.string().optional(), /** * valid session value before use it * `(ctx, sessionData) => boolean` */ valid: zod_1.default.function() .args(zod_1.default.any(), zod_1.default.any()) .returns(zod_1.default.any()) .optional(), /** * hook before save session * `(ctx, sessionModel) => void` */ beforeSave: zod_1.default.function() .args(zod_1.default.any(), zod_1.default.any()) .returns(zod_1.default.void()) .optional(), }); const DEFAULT_SESSION_OPTIONS = exports.SessionOptions.parse({}); function createSession(opts, app) { // session(app[, opts]) if (opts && 'use' in opts && typeof opts.use === 'function') { [app, opts] = [opts, app]; } // app required if (typeof app?.use !== 'function') { throw new TypeError('app instance required: `session(opts, app)`'); } const options = opts ?? {}; // back-compat maxage if (!('maxAge' in options) && 'maxage' in options) { Reflect.set(options, 'maxAge', Reflect.get(options, 'maxage')); if (process.env.NODE_ENV !== 'production') { console.warn('[koa-session] DeprecationWarning: `maxage` option has been renamed to `maxAge`'); } } // keep backwards compatibility: make sure options instance is not mutated Object.assign(options, { ...DEFAULT_SESSION_OPTIONS, ...options, }); exports.SessionOptions.parse(options); formatOptions(options); extendContext(app.context, options); return async function session(ctx, next) { const sess = ctx[GET_CONTEXT_SESSION]; if (sess.store) { await sess.initFromExternal(); } try { await next(); } catch (err) { throw err; } finally { if (options.autoCommit) { await sess.commit(); } } }; } // Usage: `import session from 'koa-session'` exports.default = createSession; /** * format and check session options */ function formatOptions(opts) { // defaults if (opts.overwrite == null) opts.overwrite = true; if (opts.httpOnly == null) opts.httpOnly = true; // delete null sameSite config if (opts.sameSite == null) delete opts.sameSite; if (opts.signed == null) opts.signed = true; if (opts.autoCommit == null) opts.autoCommit = true; debug('session options %j', opts); const store = opts.store; if (store) { (0, node_assert_1.default)(typeof store.get === 'function', 'store.get must be function'); (0, node_assert_1.default)(typeof store.set === 'function', 'store.set must be function'); (0, node_assert_1.default)(typeof store.destroy === 'function', 'store.destroy must be function'); } const externalKey = opts.externalKey; if (externalKey) { (0, node_assert_1.default)(typeof externalKey.get === 'function', 'externalKey.get must be function'); (0, node_assert_1.default)(typeof externalKey.set === 'function', 'externalKey.set must be function'); } const ContextStore = opts.ContextStore; if (ContextStore) { (0, node_assert_1.default)((0, is_type_of_1.isClass)(ContextStore), 'ContextStore must be a class'); (0, node_assert_1.default)(typeof ContextStore.prototype.get === 'function', 'ContextStore.prototype.get must be function'); (0, node_assert_1.default)(typeof ContextStore.prototype.set === 'function', 'ContextStore.prototype.set must be function'); (0, node_assert_1.default)(typeof ContextStore.prototype.destroy === 'function', 'ContextStore.prototype.destroy must be function'); } if (!opts.genid) { if (opts.prefix) { opts.genid = () => `${opts.prefix}${(0, node_crypto_1.randomUUID)()}`; } else { opts.genid = () => (0, node_crypto_1.randomUUID)(); } } } /** * extend context prototype, add session properties * * @param {Object} context koa's context prototype * @param {Object} opts session options */ function extendContext(context, opts) { if (context.hasOwnProperty(GET_CONTEXT_SESSION)) { return; } Object.defineProperties(context, { [GET_CONTEXT_SESSION]: { get() { if (this[CONTEXT_SESSION_INSTANCE]) { return this[CONTEXT_SESSION_INSTANCE]; } this[CONTEXT_SESSION_INSTANCE] = new context_js_1.ContextSession(this, opts); return this[CONTEXT_SESSION_INSTANCE]; }, }, session: { get() { return this[GET_CONTEXT_SESSION].get(); }, set(val) { this[GET_CONTEXT_SESSION].set(val); }, configurable: true, }, sessionOptions: { get() { return this[GET_CONTEXT_SESSION].opts; }, }, }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBb0xBLHNDQTRDQztBQWhPRCw4REFBaUM7QUFDakMseUNBQXFDO0FBQ3JDLDZDQUF5QztBQUN6QywyQ0FBcUM7QUFDckMsOENBQW9CO0FBQ3BCLDZDQUE4QztBQUM5Qyx3REFBNkI7QUFFN0IsTUFBTSxLQUFLLEdBQUcsSUFBQSxvQkFBUSxFQUFDLGFBQWEsQ0FBQyxDQUFDO0FBRXRDLE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUM7QUFDekQsTUFBTSx3QkFBd0IsR0FBRyxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQztBQUV0RCxRQUFBLGNBQWMsR0FBRyxhQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3JDOzs7T0FHRztJQUNILEdBQUcsRUFBRSxhQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUNuQzs7Ozs7O09BTUc7SUFDSCxNQUFNLEVBQUUsYUFBQyxDQUFDLEtBQUssQ0FBQyxDQUFFLGFBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxhQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUU7SUFDaEU7OztPQUdHO0lBQ0gsVUFBVSxFQUFFLGFBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0lBQ3JDOzs7T0FHRztJQUNILFNBQVMsRUFBRSxhQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztJQUNwQzs7O09BR0c7SUFDSCxRQUFRLEVBQUUsYUFBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7SUFDbkM7OztPQUdHO0lBQ0gsTUFBTSxFQUFFLGFBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFB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