next-session
Advanced tools
Comparing version 3.3.2 to 3.4.0
# Changelog | ||
## 3.4.0 | ||
- Refactor, remove rolling option and fix unreliable tests (#283) | ||
- Avoid override set-cookie (#320) | ||
## 3.3.2 | ||
@@ -4,0 +9,0 @@ |
import { Store as ExpressStore } from 'express-session'; | ||
export declare function Store(): void; | ||
declare function CompatibleStore(): void; | ||
declare function expressSession(options?: any): any; | ||
declare namespace expressSession { | ||
var Store: typeof import("./compat").Store; | ||
var Store: typeof CompatibleStore; | ||
var MemoryStore: typeof CallbackMemoryStore; | ||
@@ -7,0 +7,0 @@ } |
@@ -6,18 +6,17 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.promisifyStore = exports.expressSession = exports.Store = void 0; | ||
exports.promisifyStore = exports.expressSession = void 0; | ||
const util_1 = require("util"); | ||
const events_1 = require("events"); | ||
const memory_1 = __importDefault(require("./store/memory")); | ||
function Store() { | ||
function CompatibleStore() { | ||
// @ts-ignore | ||
events_1.EventEmitter.call(this); | ||
} | ||
exports.Store = Store; | ||
util_1.inherits(Store, events_1.EventEmitter); | ||
util_1.inherits(CompatibleStore, events_1.EventEmitter); | ||
// no-op for compat | ||
function expressSession(options) { } | ||
exports.expressSession = expressSession; | ||
expressSession.Store = Store; | ||
expressSession.Store = CompatibleStore; | ||
function CallbackMemoryStore() { } | ||
util_1.inherits(CallbackMemoryStore, Store); | ||
util_1.inherits(CallbackMemoryStore, CompatibleStore); | ||
CallbackMemoryStore.prototype.get = util_1.callbackify(memory_1.default.prototype.get); | ||
@@ -29,5 +28,5 @@ CallbackMemoryStore.prototype.set = util_1.callbackify(memory_1.default.prototype.set); | ||
function promisifyStore(store) { | ||
console.warn('promisifyStore has been deprecated! You can simply remove it.'); | ||
console.warn('promisifyStore has been deprecated: express-session store still works without using this.'); | ||
return store; | ||
} | ||
exports.promisifyStore = promisifyStore; |
@@ -1,5 +0,3 @@ | ||
import { Options, SessionData } from './types'; | ||
import { Options } from './types'; | ||
import { IncomingMessage, ServerResponse } from 'http'; | ||
export default function session(opts?: Options): (req: IncomingMessage & { | ||
session: SessionData; | ||
}, res: ServerResponse, next: (err?: any) => void) => void; | ||
export default function session(opts?: Options): (req: IncomingMessage, res: ServerResponse, next: (err?: any) => void) => void; |
/// <reference types="node" /> | ||
import { IncomingMessage, ServerResponse } from 'http'; | ||
import { Options, SessionData } from './types'; | ||
import { Session, Options } from './types'; | ||
export declare function applySession<T = {}>(req: IncomingMessage & { | ||
session: SessionData; | ||
}, res: ServerResponse, opts?: Options): Promise<void>; | ||
session?: Session | null | undefined; | ||
}, res: ServerResponse, options?: Options): Promise<void>; |
192
dist/core.js
@@ -10,41 +10,34 @@ "use strict"; | ||
const memory_1 = __importDefault(require("./store/memory")); | ||
const shouldTouch = (cookie, touchAfter) => { | ||
if (touchAfter === -1 || !cookie.maxAge) | ||
return false; | ||
return (cookie.maxAge * 1000 - (cookie.expires.getTime() - Date.now()) >= | ||
touchAfter); | ||
}; | ||
const stringify = (sess) => JSON.stringify(sess, (key, val) => key === 'cookie' || key === 'isNew' || key === 'id' ? undefined : val); | ||
const SESS_PREV = Symbol('session#prev'); | ||
const SESS_TOUCHED = Symbol('session#touched'); | ||
const commitHead = (req, res, options) => { | ||
if (res.headersSent || !req.session) | ||
const stringify = (sess) => JSON.stringify(sess, (key, val) => (key === 'cookie' ? undefined : val)); | ||
const commitHead = (res, name, session, touched, encodeFn) => { | ||
if (res.headersSent || !session) | ||
return; | ||
if (req.session.isNew || (options.rolling && req[SESS_TOUCHED])) { | ||
res.setHeader('Set-Cookie', cookie_1.serialize(options.name, options.encode ? options.encode(req.session.id) : req.session.id, { | ||
path: req.session.cookie.path, | ||
httpOnly: req.session.cookie.httpOnly, | ||
expires: req.session.cookie.expires, | ||
domain: req.session.cookie.domain, | ||
sameSite: req.session.cookie.sameSite, | ||
secure: req.session.cookie.secure, | ||
})); | ||
if (session.isNew || touched) { | ||
const cookieArr = [ | ||
cookie_1.serialize(name, encodeFn ? encodeFn(session.id) : session.id, { | ||
path: session.cookie.path, | ||
httpOnly: session.cookie.httpOnly, | ||
expires: session.cookie.expires, | ||
domain: session.cookie.domain, | ||
sameSite: session.cookie.sameSite, | ||
secure: session.cookie.secure, | ||
}), | ||
]; | ||
const prevCookies = res.getHeader('set-cookie'); | ||
if (prevCookies) { | ||
if (Array.isArray(prevCookies)) | ||
cookieArr.push(...prevCookies); | ||
else | ||
cookieArr.push(prevCookies); | ||
} | ||
res.setHeader('set-cookie', cookieArr); | ||
} | ||
}; | ||
const save = async (req, options) => { | ||
var _a, _b; | ||
if (!req.session) | ||
return; | ||
const prepareSession = (session) => { | ||
const obj = {}; | ||
for (const key in req.session) { | ||
if (!(key === ('isNew' || key === 'id'))) | ||
obj[key] = req.session[key]; | ||
} | ||
if (stringify(req.session) !== req[SESS_PREV]) { | ||
await options.store.__set(req.session.id, obj); | ||
} | ||
else if (req[SESS_TOUCHED]) { | ||
await ((_b = (_a = options.store).__touch) === null || _b === void 0 ? void 0 : _b.call(_a, req.session.id, obj)); | ||
} | ||
for (const key in session) | ||
!(key === ('isNew' || key === 'id')) && (obj[key] = session[key]); | ||
return obj; | ||
}; | ||
const save = async (store, session) => session && store.__set(session.id, prepareSession(session)); | ||
function setupStore(store) { | ||
@@ -65,2 +58,3 @@ if ('__normalized' in store) | ||
const done = (err, val) => err ? reject(err) : resolve(val); | ||
// @ts-ignore: Certain differences between express-session type and ours | ||
const result = this.get(sid, done); | ||
@@ -74,2 +68,3 @@ if (result && typeof result.then === 'function') | ||
const done = (err) => (err ? reject(err) : resolve()); | ||
// @ts-ignore: Certain differences between express-session type and ours | ||
const result = this.set(sid, sess, done); | ||
@@ -84,2 +79,3 @@ if (result && typeof result.then === 'function') | ||
const done = (err) => (err ? reject(err) : resolve()); | ||
// @ts-ignore: Certain differences between express-session type and ours | ||
const result = this.touch(sid, sess, done); | ||
@@ -95,57 +91,48 @@ if (result && typeof result.then === 'function') | ||
let memoryStore; | ||
async function applySession(req, res, opts) { | ||
var _a, _b, _c, _d, _e, _f, _g; | ||
async function applySession(req, res, options = {}) { | ||
var _a, _b, _c, _d, _e, _f; | ||
if (req.session) | ||
return; | ||
const options = { | ||
name: (opts === null || opts === void 0 ? void 0 : opts.name) || 'sid', | ||
store: setupStore((opts === null || opts === void 0 ? void 0 : opts.store) || (memoryStore = memoryStore || new memory_1.default())), | ||
genid: (opts === null || opts === void 0 ? void 0 : opts.genid) || nanoid_1.nanoid, | ||
encode: opts === null || opts === void 0 ? void 0 : opts.encode, | ||
decode: opts === null || opts === void 0 ? void 0 : opts.decode, | ||
rolling: (opts === null || opts === void 0 ? void 0 : opts.rolling) || false, | ||
touchAfter: (opts === null || opts === void 0 ? void 0 : opts.touchAfter) ? opts.touchAfter : 0, | ||
autoCommit: typeof (opts === null || opts === void 0 ? void 0 : opts.autoCommit) !== 'undefined' ? opts.autoCommit : true, | ||
}; | ||
let sessId = req.headers && req.headers.cookie | ||
? cookie_1.parse(req.headers.cookie)[options.name] | ||
: null; | ||
if (sessId && options.decode) | ||
sessId = options.decode(sessId); | ||
const sess = sessId ? await options.store.__get(sessId) : null; | ||
// This allows both promised-based and callback-based store to work | ||
const store = setupStore(options.store || (memoryStore = memoryStore || new memory_1.default())); | ||
// compat: if rolling is `true`, user might have wanted to touch every time | ||
// thus defaulting options.touchAfter to 0 instead of -1 | ||
if (options.rolling && !('touchAfter' in options)) { | ||
console.warn('The use of options.rolling is deprecated. Setting this to `true` without options.touchAfter causes options.touchAfter to be defaulted to `0` (always)'); | ||
options.touchAfter = 0; | ||
} | ||
const name = options.name || 'sid'; | ||
const commit = async () => { | ||
commitHead(req, res, options); | ||
await save(req, options); | ||
commitHead(res, name, req.session, shouldTouch, options.encode); | ||
await save(store, req.session); | ||
}; | ||
const destroy = async () => { | ||
await options.store.__destroy(req.session.id); | ||
// This is a valid TS error, but considering its usage, it's fine. | ||
// @ts-ignore | ||
delete req.session; | ||
await store.__destroy(req.session.id); | ||
req.session = null; | ||
}; | ||
if (sess) { | ||
req[SESS_PREV] = stringify(sess); | ||
const { cookie, ...data } = sess; | ||
if (typeof cookie.expires === 'string') | ||
cookie.expires = new Date(cookie.expires); | ||
req.session = { | ||
cookie, | ||
commit, | ||
destroy, | ||
isNew: false, | ||
id: sessId, | ||
}; | ||
for (const key in data) | ||
req.session[key] = data[key]; | ||
let sessId = req.headers && req.headers.cookie ? cookie_1.parse(req.headers.cookie)[name] : null; | ||
if (sessId && options.decode) | ||
sessId = options.decode(sessId); | ||
// @ts-ignore: req.session as this point is not of type Session | ||
// but SessionData, but the missing keys will be added later | ||
req.session = sessId ? await store.__get(sessId) : null; | ||
if (req.session) { | ||
req.session.commit = commit; | ||
req.session.destroy = destroy; | ||
req.session.isNew = false; | ||
req.session.id = sessId; | ||
// Some store return cookie.expires as string, convert it to Date | ||
if (typeof req.session.cookie.expires === 'string') | ||
req.session.cookie.expires = new Date(req.session.cookie.expires); | ||
} | ||
else { | ||
req[SESS_PREV] = '{}'; | ||
req.session = { | ||
cookie: { | ||
path: ((_a = opts === null || opts === void 0 ? void 0 : opts.cookie) === null || _a === void 0 ? void 0 : _a.path) || '/', | ||
maxAge: ((_b = opts === null || opts === void 0 ? void 0 : opts.cookie) === null || _b === void 0 ? void 0 : _b.maxAge) || null, | ||
httpOnly: ((_c = opts === null || opts === void 0 ? void 0 : opts.cookie) === null || _c === void 0 ? void 0 : _c.httpOnly) || true, | ||
domain: ((_d = opts === null || opts === void 0 ? void 0 : opts.cookie) === null || _d === void 0 ? void 0 : _d.domain) || undefined, | ||
sameSite: (_e = opts === null || opts === void 0 ? void 0 : opts.cookie) === null || _e === void 0 ? void 0 : _e.sameSite, | ||
secure: ((_f = opts === null || opts === void 0 ? void 0 : opts.cookie) === null || _f === void 0 ? void 0 : _f.secure) || false, | ||
path: ((_a = options.cookie) === null || _a === void 0 ? void 0 : _a.path) || '/', | ||
httpOnly: ((_b = options.cookie) === null || _b === void 0 ? void 0 : _b.httpOnly) || true, | ||
domain: ((_c = options.cookie) === null || _c === void 0 ? void 0 : _c.domain) || undefined, | ||
sameSite: (_d = options.cookie) === null || _d === void 0 ? void 0 : _d.sameSite, | ||
secure: ((_e = options.cookie) === null || _e === void 0 ? void 0 : _e.secure) || false, | ||
...(((_f = options.cookie) === null || _f === void 0 ? void 0 : _f.maxAge) ? { maxAge: options.cookie.maxAge, expires: new Date() } | ||
: { maxAge: null }), | ||
}, | ||
@@ -155,16 +142,36 @@ commit, | ||
isNew: true, | ||
id: options.genid(), | ||
id: (options.genid || nanoid_1.nanoid)(), | ||
}; | ||
if ((_g = opts === null || opts === void 0 ? void 0 : opts.cookie) === null || _g === void 0 ? void 0 : _g.maxAge) | ||
req.session.cookie.expires = new Date(); | ||
} | ||
// Extend session expiry | ||
if ((req[SESS_TOUCHED] = shouldTouch(req.session.cookie, options.touchAfter))) { | ||
req.session.cookie.expires = new Date(Date.now() + req.session.cookie.maxAge * 1000); | ||
// prevSessStr is used to compare the session later | ||
// for touchability -- that is, we only touch the | ||
// session if it has changed. This check is used | ||
// in autoCommit mode only | ||
const prevSessStr = options.autoCommit !== false | ||
? req.session.isNew | ||
? '{}' | ||
: stringify(req.session) | ||
: undefined; | ||
let shouldTouch = false; | ||
if (req.session.cookie.maxAge) { | ||
if ( | ||
// Extend expires either if it is a new session | ||
req.session.isNew || | ||
// or if touchAfter condition is satsified | ||
(typeof options.touchAfter === 'number' && | ||
options.touchAfter !== -1 && | ||
(shouldTouch = | ||
req.session.cookie.maxAge * 1000 - | ||
(req.session.cookie.expires.getTime() - Date.now()) >= | ||
options.touchAfter))) { | ||
req.session.cookie.expires = new Date(Date.now() + req.session.cookie.maxAge * 1000); | ||
} | ||
} | ||
// autocommit | ||
if (options.autoCommit) { | ||
// autocommit: We commit the header and save the session automatically | ||
// by "proxying" res.writeHead and res.end methods. After committing, we | ||
// call the original res.writeHead and res.end. | ||
if (options.autoCommit !== false) { | ||
const oldWritehead = res.writeHead; | ||
res.writeHead = function resWriteHeadProxy(...args) { | ||
commitHead(req, res, options); | ||
commitHead(res, name, req.session, shouldTouch, options.encode); | ||
return oldWritehead.apply(this, args); | ||
@@ -174,3 +181,8 @@ }; | ||
res.end = async function resEndProxy(...args) { | ||
await save(req, options); | ||
if (stringify(req.session) !== prevSessStr) { | ||
await save(store, req.session); | ||
} | ||
else if (req.session && shouldTouch && store.__touch) { | ||
await store.__touch(req.session.id, prepareSession(req.session)); | ||
} | ||
oldEnd.apply(this, args); | ||
@@ -180,4 +192,4 @@ }; | ||
// Compat | ||
req.sessionStore = options.store; | ||
req.sessionStore = store; | ||
} | ||
exports.applySession = applySession; |
export { default as withSession } from './withSession'; | ||
export { default as session } from './connect'; | ||
export { applySession } from './core'; | ||
export { promisifyStore, expressSession, Store } from './compat'; | ||
export { promisifyStore, expressSession } from './compat'; | ||
export { default as MemoryStore } from './store/memory'; | ||
export { SessionData, SessionCookieData, SessionStore } from './types'; |
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SessionStore = exports.MemoryStore = exports.Store = exports.expressSession = exports.promisifyStore = exports.applySession = exports.session = exports.withSession = void 0; | ||
exports.SessionStore = exports.MemoryStore = exports.expressSession = exports.promisifyStore = exports.applySession = exports.session = exports.withSession = void 0; | ||
var withSession_1 = require("./withSession"); | ||
@@ -17,3 +17,2 @@ Object.defineProperty(exports, "withSession", { enumerable: true, get: function () { return __importDefault(withSession_1).default; } }); | ||
Object.defineProperty(exports, "expressSession", { enumerable: true, get: function () { return compat_1.expressSession; } }); | ||
Object.defineProperty(exports, "Store", { enumerable: true, get: function () { return compat_1.Store; } }); | ||
var memory_1 = require("./store/memory"); | ||
@@ -20,0 +19,0 @@ Object.defineProperty(exports, "MemoryStore", { enumerable: true, get: function () { return __importDefault(memory_1).default; } }); |
/// <reference types="node" /> | ||
import { EventEmitter } from "events"; | ||
import { SessionStore, SessionData } from "../types"; | ||
import { EventEmitter } from 'events'; | ||
import { SessionStore, SessionData } from '../types'; | ||
export default class MemoryStore extends EventEmitter implements SessionStore { | ||
@@ -9,5 +9,5 @@ sessions: Record<string, string>; | ||
set(sid: string, sess: SessionData): Promise<void>; | ||
touch(sid: string, session: SessionData): Promise<void | undefined>; | ||
touch(sid: string, session: SessionData): Promise<void>; | ||
all(): Promise<string[]>; | ||
destroy(sid: string): Promise<void>; | ||
} |
@@ -32,12 +32,3 @@ "use strict"; | ||
touch(sid, session) { | ||
return this.get(sid).then((sess) => { | ||
if (sess) { | ||
const newSess = { | ||
...sess, | ||
cookie: session.cookie, | ||
}; | ||
return this.set(sid, newSess); | ||
} | ||
return undefined; | ||
}); | ||
return this.set(sid, session); | ||
} | ||
@@ -44,0 +35,0 @@ all() { |
import { Store as ExpressStore } from 'express-session'; | ||
export declare type SessionData = { | ||
[key: string]: any; | ||
cookie: SessionCookieData; | ||
}; | ||
export interface Session extends SessionData { | ||
id: string; | ||
cookie: SessionCookieData; | ||
destroy: () => Promise<void>; | ||
commit(): Promise<void>; | ||
destroy(): Promise<void>; | ||
isNew: boolean; | ||
}; | ||
export interface SessionCookieData { | ||
} | ||
export declare type SessionCookieData = { | ||
path: string; | ||
maxAge: number | null; | ||
secure: boolean; | ||
httpOnly: boolean; | ||
domain?: string | undefined; | ||
expires?: Date; | ||
sameSite?: boolean | 'lax' | 'strict' | 'none'; | ||
} | ||
} & ({ | ||
maxAge: number; | ||
expires: Date; | ||
} | { | ||
maxAge: null; | ||
expires?: undefined; | ||
}); | ||
export declare abstract class SessionStore { | ||
abstract get: (sid: string) => Promise<SessionData | null>; | ||
abstract set: (sid: string, sess: SessionData) => Promise<void>; | ||
abstract destroy: (sid: string) => Promise<void>; | ||
abstract touch?: (sid: string, sess: SessionData) => Promise<void>; | ||
on?: (event: string | symbol, listener: (...args: any[]) => void) => this; | ||
abstract get(sid: string): Promise<SessionData | null | undefined>; | ||
abstract set(sid: string, sess: SessionData): Promise<void>; | ||
abstract destroy(sid: string): Promise<void>; | ||
abstract touch?(sid: string, sess: SessionData): Promise<void>; | ||
on?(event: string | symbol, listener: (...args: any[]) => void): this; | ||
} | ||
export interface NormalizedSessionStore { | ||
[key: string]: any; | ||
__get: (sid: string) => Promise<SessionData | null>; | ||
__set: (sid: string, sess: SessionData) => Promise<void>; | ||
__destroy: (sid: string) => Promise<void>; | ||
__touch?: (sid: string, sess: SessionData) => Promise<void>; | ||
export declare type NormalizedSessionStore = { | ||
__get(sid: string): Promise<SessionData | null | undefined>; | ||
__set(sid: string, sess: SessionData): Promise<void>; | ||
__destroy(sid: string): Promise<void>; | ||
__touch(sid: string, sess: SessionData): Promise<void>; | ||
__normalized: true; | ||
} | ||
export interface CookieOptions { | ||
secure?: boolean; | ||
httpOnly?: boolean; | ||
path?: string; | ||
domain?: string; | ||
sameSite?: boolean | 'lax' | 'strict' | 'none'; | ||
maxAge?: number | null; | ||
} | ||
} & (SessionStore | ExpressStore); | ||
export interface Options { | ||
@@ -46,7 +44,17 @@ name?: string; | ||
encode?: (rawSid: string) => string; | ||
decode?: (encryptedSid: string) => string; | ||
rolling?: boolean; | ||
decode?: (encryptedSid: string) => string | null; | ||
touchAfter?: number; | ||
cookie?: CookieOptions; | ||
cookie?: { | ||
secure?: boolean; | ||
httpOnly?: boolean; | ||
path?: string; | ||
domain?: string; | ||
sameSite?: boolean | 'lax' | 'strict' | 'none'; | ||
maxAge?: number | null; | ||
}; | ||
autoCommit?: boolean; | ||
/** | ||
* @deprecated | ||
*/ | ||
rolling?: boolean; | ||
} |
@@ -26,3 +26,2 @@ "use strict"; | ||
WithSession.getInitialProps = async (pageCtx) => { | ||
// @ts-ignore | ||
if (typeof window === 'undefined') { | ||
@@ -29,0 +28,0 @@ await core_1.applySession(pageCtx.req, pageCtx.res, options); |
{ | ||
"name": "next-session", | ||
"version": "3.3.2", | ||
"version": "3.4.0", | ||
"description": "Simple promise-based session middleware for Next.js", | ||
@@ -36,23 +36,23 @@ "keywords": [ | ||
"@types/cookie": "^0.4.0", | ||
"@types/express-session": "^1.17.0", | ||
"@types/jest": "^26.0.10", | ||
"@types/node": "^14.6.2", | ||
"@types/react": "^16.9.48", | ||
"@types/react-dom": "^16.9.8", | ||
"@types/express-session": "^1.17.3", | ||
"@types/jest": "^26.0.15", | ||
"@types/node": "^14.14.9", | ||
"@types/react": "^17.0.0", | ||
"@types/react-dom": "^17.0.0", | ||
"@types/supertest": "^2.0.10", | ||
"@typescript-eslint/eslint-plugin": "^3.10.1", | ||
"@typescript-eslint/parser": "^3.10.1", | ||
"@typescript-eslint/eslint-plugin": "^4.8.2", | ||
"@typescript-eslint/parser": "^4.8.2", | ||
"cookie-signature": "^1.1.0", | ||
"eslint": "^7.7.0", | ||
"jest": "^26.4.2", | ||
"next": "9.5.3", | ||
"react": "^16.13.0", | ||
"react-dom": "^16.13.0", | ||
"supertest": "^4.0.2", | ||
"ts-jest": "^26.3.0", | ||
"typescript": "^4.0.2" | ||
"eslint": "^7.14.0", | ||
"jest": "^26.6.3", | ||
"next": "10.0.3", | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"supertest": "^6.0.1", | ||
"ts-jest": "^26.4.4", | ||
"typescript": "^4.1.2" | ||
}, | ||
"dependencies": { | ||
"cookie": "^0.4.1", | ||
"nanoid": "^3.1.12" | ||
"nanoid": "^3.1.18" | ||
}, | ||
@@ -59,0 +59,0 @@ "engines": { |
@@ -11,2 +11,4 @@ # next-session | ||
> For a more battle-tested solution, you should use [express-session](https://github.com/expressjs/session) with [next-connect](https://github.com/hoangvvo/next-connect) instead. | ||
## Installation | ||
@@ -182,4 +184,3 @@ | ||
| decode | Transforms session ID back while getting from cookie. It should return the encoded/encrypted session ID | undefined | | ||
| touchAfter | Only touch (extend session lifetime despite no modification) after an amount of time to decrease database load. Setting the value to `-1` will disable `touch()`. | `0` (Touch every time) | | ||
| rolling | Extends the life time of the cookie in the browser if the session is touched. This respects touchAfter. | `false` | | ||
| touchAfter | Only touch after an amount of time. Disabled by default or if set to `-1`. See [touchAfter](#touchAfter). | `-1` (Disabled) | | ||
| autoCommit | Automatically commit session. Disable this if you want to manually `session.commit()` | `true` | | ||
@@ -193,2 +194,8 @@ | cookie.secure | Specifies the boolean value for the **Secure** `Set-Cookie` attribute. | `false` | | ||
### touchAfter | ||
Touching refers to the extension of session lifetime, both in browser (by modifying `Expires` attribute in [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) header) and session store (using its respective method). This prevents the session from being expired after a while. | ||
In `autoCommit` mode (which is enabled by default), for optimization, a session is only touched, not saved, if it is not modified. The value of `touchAfter` allows you to skip touching if the session is still recent, thus, decreasing database load. | ||
### encode/decode | ||
@@ -195,0 +202,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42898
643
294
Updatednanoid@^3.1.18