koa-session
Version:
Koa cookie session middleware with external store support
291 lines • 20.5 kB
JavaScript
;
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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