Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

next-session

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

next-session - npm Package Compare versions

Comparing version 3.4.3 to 4.0.0

lib/compat.cjs

54

package.json
{
"type": "module",
"name": "next-session",
"version": "3.4.3",
"description": "Simple promise-based session middleware for Next.js",
"version": "4.0.0",
"description": "Simple promise-based session for Next.js",
"keywords": [
"javascript",
"nextjs",
"session",
"middleware",
"promise"
"promise",
"express-session"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"main": "./lib/session.cjs",
"exports": {
".": {
"import": "./lib/session.js",
"require": "./lib/session.cjs"
},
"./lib/compat": {
"import": "./lib/compat.js",
"require": "./lib/compat.cjs"
}
},
"types": "lib/session.d.ts",
"files": [
"dist/"
"lib/"
],
"sideEffects": false,
"scripts": {
"prepublish": "yarn build",
"build": "tsc --outDir dist",
"build:commonjs": "BUILD_MODULE=commonjs babel src -d lib --extensions .ts --out-file-extension .cjs",
"build:module": "babel src -d lib --extensions .ts",
"build:typescript": "tsc --outDir lib --emitDeclarationOnly",
"build": "rm -rf lib && yarn build:typescript && yarn build:commonjs && yarn build:module",
"lint": "eslint src --ext ts --ignore-path .gitignore",
"test": "yarn build && jest --coverageReporters=text-lcov > coverage.lcov"
"test:import": "cd test/import-test && rm -rf node_modules && yarn && node index.js && node index.cjs && cd ../../",
"test:unit": "jest --coverageReporters=text-lcov > coverage.lcov",
"test": "yarn test:unit && yarn test:import"
},

@@ -35,19 +49,15 @@ "repository": {

"devDependencies": {
"@babel/cli": "^7.15.7",
"@babel/core": "^7.15.5",
"@babel/plugin-transform-modules-commonjs": "^7.15.4",
"@babel/preset-typescript": "^7.15.0",
"@types/cookie": "^0.4.1",
"@types/cookie-signature": "^1.0.3",
"@types/express-session": "^1.17.4",
"@types/jest": "^27.0.1",
"@types/node": "^16.9.4",
"@types/react": "^17.0.22",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.1",
"cookie-signature": "^1.1.0",
"babel-plugin-add-import-extension": "^1.6.0",
"eslint": "^7.32.0",
"jest": "^27.2.0",
"next": "11.1.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"supertest": "^6.1.6",
"tree-kill": "^1.2.2",
"light-my-request": "^4.4.4",
"ts-jest": "^27.0.5",

@@ -61,4 +71,4 @@ "typescript": "^4.4.3"

"engines": {
"node": ">=10.0.0"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
}

@@ -9,6 +9,5 @@ # next-session

Simple _promise-based_ session middleware for [Next.js](https://github.com/zeit/next.js). Also works in [micro](https://github.com/zeit/micro) or [Node.js HTTP Server](https://nodejs.org/api/http.html), [Express](https://github.com/expressjs/express), and more.
Simple _promise-based_ session for [Next.js](https://github.com/zeit/next.js). Also works in [micro](https://github.com/zeit/micro) or [Node.js HTTP Server](https://nodejs.org/api/http.html), [Express](https://github.com/expressjs/express), and more.
> Also check out alternatives like [express-session](https://github.com/expressjs/session)+[next-connect](https://github.com/hoangvvo/next-connect) or [next-iron-session](https://github.com/vvo/next-iron-session) instead.
> Update: It is observed that express-session sometimes does not work properly with Next.js 11.x
> Check out alternatives like [next-iron-session](https://github.com/vvo/next-iron-session) instead. Also check out [nextjs-mongodb-app](https://github.com/hoangvvo/nextjs-mongodb-app) to see this module in use.

@@ -30,17 +29,39 @@ ## Installation

`next-session` has several named exports:
:point_right: **Upgrading from v3.x to v4.x?** Please read the release notes [here](https://github.com/hoangvvo/next-session/releases/tag/v4.0.0)!
- `session` to be used as a Connect/Express middleware. (Use [next-connect](https://github.com/hoangvvo/next-connect) if used in Next.js)
- `withSession` to be used as HOC in Page Components or API Routes wrapper (and several others).
- `applySession`, to manually initialize `next-session` by providing `req` and `res`.
**Warning** The default session store (if `options?.store` is `undefined`), `MemoryStore`, **DOES NOT** work in production or serverless environment. You must use a [Session Store](#session-store).
Use **one of them** to work with `next-session`. Can also be used in other frameworks in the same manner as long as they have `(req, res)` handler signature.
```js
// ./lib/get-session.js
import nextSession from "next-session";
export const getSession = nextSession(options);
```
**Warning** The default session store, `MemoryStore`, should not be used in production since it does not persist nor work in Serverless.
### API Routes
```js
import { getSession } from "./lib/get-session.js";
export default function handler(req, res) {
const session = await getSession(req, res);
session.views = session.views ? session.views + 1 : 1;
// Also available under req.session:
// req.session.views = req.session.views ? req.session.views + 1 : 1;
res.send(
`In this session, you have visited this website ${session.views} time(s).`
);
}
```
Usage in API Routes may result in `API resolved without sending a response`. This can be solved by either adding:
```js
import nextSession from "next-session";
const getSession = nextSession();
export default function handler(req, res) {
const session = await getSession(req, res);
/* ... */
}
export const config = {

@@ -53,45 +74,51 @@ api: {

...or setting `options.autoCommit` to `false` and do `await session.commit()` (See [this](https://github.com/hoangvvo/next-session#reqsessioncommit)).
...or setting `options.autoCommit` to `false` and do `await session.commit()`.
#### `{ session }`
```js
import nextSession from "next-session";
const getSession = nextSession({ autoCommit: false });
```javascript
import { session } from 'next-session';
import nextConnect from 'next-connect';
const mySession = session(options);
const handler = nextConnect()
.use(mySession)
.all(() => {
req.session.views = req.session.views ? req.session.views + 1 : 1;
res.send(
`In this session, you have visited this website ${req.session.views} time(s).`
);
});
export default handler;
export default function handler(req, res) {
const session = await getSession(req, res);
/* ... */
await session.commit();
}
```
#### `{ withSession }`
### getServerSideProps
```javascript
import { withSession } from 'next-session';
```js
import { getSession } from "./lib/get-session.js";
function handler(req, res) {
req.session.views = req.session.views ? req.session.views + 1 : 1;
res.send(
`In this session, you have visited this website ${req.session.views} time(s).`
export default function Page({ views }) {
return (
<div>In this session, you have visited this website {views} time(s).</div>
);
}
export default withSession(handler, options);
export async function getServerSideProps({ req, res }) {
const session = await getSession(req, res);
session.views = session.views ? session.views + 1 : 1;
// Also available under req.session:
// req.session.views = req.session.views ? req.session.views + 1 : 1;
return {
props: {
views: session.views,
},
};
}
```
#### `{ applySession }`
### Others
```javascript
import { applySession } from 'next-session';
[express](https://github.com/expressjs/express), [next-connect](https://github.com/hoangvvo/next-connect)
export default async function handler(req, res) {
await applySession(req, res, options);
```js
const express = require("express");
const app = express();
app.use(async (req, res, next) => {
await getSession(req, res); // session is set to req.session
next();
});
app.get("/", (req, res) => {
req.session.views = req.session.views ? req.session.views + 1 : 1;

@@ -101,59 +128,26 @@ res.send(

);
}
});
```
### Pages
[micro](https://github.com/vercel/micro), [Vercel Serverless Functions](https://vercel.com/docs/functions/introduction)
`next-session` does not work in [Custom App](https://nextjs.org/docs/advanced-features/custom-app) since it leads to deoptimization.
#### ~~`{ withSession }` ([`getInitialProps`](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps))~~
**This will be deprecated in the next major release!**
> `next@>9.3.0` recommends using `getServerSideProps` instead of `getInitialProps`.
> Also, it is not reliable since `req` or `req.session` is only available on [server only](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps#context-object)
```javascript
import { withSession } from 'next-session';
function Page({ views }) {
return (
<div>In this session, you have visited this website {views} time(s).</div>
```js
module.exports = (req, res) => {
const session = await getSession(req, res);
res.end(
`In this session, you have visited this website ${session.views} time(s).`
);
}
Page.getInitialProps = ({ req }) => {
let views;
if (typeof window === 'undefined') {
// req.session is only available on server-side.
req.session.views = req.session.views ? req.session.views + 1 : 1;
views = req.session.views;
}
// WARNING: On client-side routing, neither req nor req.session is available.
return { views };
};
export default withSession(Page, options);
```
#### `{ applySession }` ([`getServerSideProps`](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering))
[Node.js HTTP Server](https://nodejs.org/api/http.html)
```javascript
import { applySession } from 'next-session';
```js
const http = require("http");
export default function Page({ views }) {
return (
<div>In this session, you have visited this website {views} time(s).</div>
);
}
export async function getServerSideProps({ req, res }) {
await applySession(req, res, options);
req.session.views = req.session.views ? req.session.views + 1 : 1;
return {
props: {
views: req.session.views,
},
};
}
const server = http.createServer(async (req, res) => {
const session = await getSession(req, res);
res.end(`In this session, you have visited this website ${session.views} time(s).`;
});
server.listen(8080);
```

@@ -163,37 +157,19 @@

Regardless of the above approaches, to avoid bugs, you want to reuse the same `options` to in every route. For example:
```javascript
// Define the option only once
// foo/bar/session.js
export const options = { ...someOptions };
// Always import it at other places
// pages/index.js
import { options } from 'foo/bar/session';
/* ... */
export default withSession(Page, options);
// pages/api/index.js
import { options } from 'foo/bar/session';
/* ... */
await applySession(req, res, options);
```
`next-session` accepts the properties below.
| options | description | default |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------- |
| name | The name of the cookie to be read from the request and set to the response. | `sid` |
| store | The session store instance to be used. | `MemoryStore` |
| genid | The function that generates a string for a new session ID. | [`nanoid`](https://github.com/ai/nanoid) |
| encode | Transforms session ID before setting cookie. It takes the raw session ID and returns the decoded/decrypted session ID. | undefined |
| decode | Transforms session ID back while getting from cookie. It should return the encoded/encrypted session ID | undefined |
| touchAfter | Only touch after an amount of time **(in miliseconds)** since last access. 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` |
| cookie.secure | Specifies the boolean value for the **Secure** `Set-Cookie` attribute. | `false` |
| cookie.httpOnly | Specifies the boolean value for the **httpOnly** `Set-Cookie` attribute. | `true` |
| cookie.path | Specifies the value for the **Path** `Set-Cookie` attribute. | `/` |
| cookie.domain | Specifies the value for the **Domain** `Set-Cookie` attribute. | unset |
| cookie.sameSite | Specifies the value for the **SameSite** `Set-Cookie` attribute. | unset |
| cookie.maxAge | **(in seconds)** Specifies the value for the **Max-Age** `Set-Cookie` attribute. | unset (Browser session) |
| options | description | default |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| name | The name of the cookie to be read from the request and set to the response. | `sid` |
| store | The session store instance to be used. **Required** to work in production! | `MemoryStore` |
| genid | The function that generates a string for a new session ID. | [`nanoid`](https://github.com/ai/nanoid) |
| encode | Transforms session ID before setting cookie. It takes the raw session ID and returns the decoded/decrypted session ID. | undefined |
| decode | Transforms session ID back while getting from cookie. It should return the encoded/encrypted session ID | undefined |
| touchAfter | Only touch after an amount of time **(in seconds)** since last access. 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` |
| cookie.secure | Specifies the boolean value for the **Secure** `Set-Cookie` attribute. | `false` |
| cookie.httpOnly | Specifies the boolean value for the **httpOnly** `Set-Cookie` attribute. | `true` |
| cookie.path | Specifies the value for the **Path** `Set-Cookie` attribute. | `/` |
| cookie.domain | Specifies the value for the **Domain** `Set-Cookie` attribute. | unset |
| cookie.sameSite | Specifies the value for the **SameSite** `Set-Cookie` attribute. | unset |
| cookie.maxAge | **(in seconds)** Specifies the value for the **Max-Age** `Set-Cookie` attribute. | unset (Browser session) |

@@ -212,7 +188,7 @@ ### touchAfter

// `express-session` signing strategy
const signature = require('cookie-signature');
const secret = 'keyboard cat';
const signature = require("cookie-signature");
const secret = "keyboard cat";
session({
decode: (raw) => signature.unsign(raw.slice(2), secret),
encode: (sid) => (sid ? 's:' + signature.sign(sid, secret) : null),
encode: (sid) => (sid ? "s:" + signature.sign(sid, secret) : null),
});

@@ -223,3 +199,3 @@ ```

### req.session
### session object

@@ -230,16 +206,26 @@ This allows you to **set** or **get** a specific value that associates to the current session.

// Set a value
if (loggedIn) req.session.user = 'John Doe';
if (loggedIn) session.user = "John Doe";
// Get a value
const currentUser = req.session.user; // "John Doe"
const currentUser = session.user; // "John Doe"
```
### req.session.destroy()
### session.touch()
Manually extends the session expiry by maxAge. **Note:** You must still call session.commit() if `autoCommit = false`.
```js
session.touch();
```
If `touchAfter` is set with a non-negative value, this will be automatically called accordingly.
### session.destroy()
Destroy to current session and remove it from session store.
```javascript
if (loggedOut) await req.session.destroy();
if (loggedOut) await session.destroy();
```
### req.session.commit()
### session.commit()

@@ -251,15 +237,11 @@ Save the session and set neccessary headers. Return Promise. It must be called before _sending the headers (`res.writeHead`) or response (`res.send`, `res.end`, etc.)_.

```javascript
req.session.hello = 'world';
await req.session.commit();
session.hello = "world";
await session.commit();
// always calling res.end or res.writeHead after the above
```
### req.session.id
### session.id
The unique id that associates to the current session.
### req.session.isNew
Return _true_ if the session is new.
## Session Store

@@ -269,35 +251,50 @@

### Compatibility with Express/Connect stores
### Implementation
To use [Express/Connect stores](https://github.com/expressjs/session#compatible-session-stores), you may need to use `expressSession` from `next-session` if the store has the following pattern.
A compatible session store must include three functions: `set(sid, session)`, `get(sid)`, and `destroy(sid)`. The function `touch(sid, session)` is recommended. All functions must return **Promises**.
```javascript
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
Refer to [MemoryStore](https://github.com/hoangvvo/next-session/blob/master/src/memory-store.ts).
// Use `expressSession` as the replacement
_TypeScript:_ the `SessionStore` type can be used to aid implementation:
import { expressSession } from 'next-session';
const MongoStore = require('connect-mongo')(expressSession);
```ts
import type { SessionStore } from "next-session";
class CustomStore implements SessionStore {}
```
### Implementation
### Compatibility with Express/Connect stores
A compatible session store must include three functions: `set(sid, session)`, `get(sid)`, and `destroy(sid)`. The function `touch(sid, session)` is recommended. All functions can either return **Promises** or allowing **callback** in the last argument.
#### Promisify functions
To use [Express/Connect stores](https://github.com/expressjs/session#compatible-session-stores), you must promisify `get`, `set`, `destroy`, and (if exists) `touch` methods, possibly using [`util.promisify`](https://nodejs.org/dist/latest/docs/api/util.html#util_util_promisify_original).
We include the util [`promisifyStore`](./src/compat.ts#L29) in `next-session/lib/compat` to do just that:
```js
// Both of the below work!
import nextSession from "next-session";
import { promisifyStore } from "next-session/lib/compat";
import SomeConnectStore from "connect-xyz";
function get(sid) {
return promiseGetFn(sid);
}
const connectStore = new SomeConnectStore();
function get(sid, done) {
cbGetFn(sid, done);
}
const getSession = nextSession({
store: promisifyStore(connectStore),
});
```
Refer to [MemoryStore](https://github.com/hoangvvo/next-session/blob/master/src/store/memory.ts)
or the type of [SessionStore](https://github.com/hoangvvo/next-session/blob/master/src/types.ts#L23-L29).
You can use `expressSession` from `next-session/lib/compat` if the connect store has the following pattern.
```javascript
const session = require("express-session");
const RedisStore = require("connect-redis")(session);
// Use `expressSession` from `next-session/lib/compat` as the replacement
import { expressSession } from "next-session/lib/compat";
import RedisStoreFactory from "connect-redis";
const RedisStore = RedisStoreFactory(expressSession);
```
## Contributing

@@ -304,0 +301,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc