uninstall fastify-session

master
Bhaskara Kishore 3 years ago
parent c945240adf
commit f4f6870831

18
node_modules/.package-lock.json generated vendored

@ -5304,24 +5304,6 @@
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.4.0.tgz", "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.4.0.tgz",
"integrity": "sha512-ovwFQG2qNy3jcCROiWpr94Hs0le+c7N/3t7m9aVwbFhkxcR/esp2xu25dP8e617HpQdmeDv+gFX4zagdUhDByw==" "integrity": "sha512-ovwFQG2qNy3jcCROiWpr94Hs0le+c7N/3t7m9aVwbFhkxcR/esp2xu25dP8e617HpQdmeDv+gFX4zagdUhDByw=="
}, },
"node_modules/fastify-session": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/fastify-session/-/fastify-session-5.2.1.tgz",
"integrity": "sha512-2ZOLPGPeeBE35HOgYD4/v9c304IGF2ExOh35tuKegrB3QSNB+kKeqqzUXrUJ2h0Vr5nTyvrimtPAPQZG963vOw==",
"dependencies": {
"cookie-signature": "^1.1.0",
"fastify-plugin": "^3.0.0",
"uid-safe": "^2.1.5"
},
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/fastify-session/node_modules/fastify-plugin": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz",
"integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA=="
},
"node_modules/fastify-static": { "node_modules/fastify-static": {
"version": "4.7.0", "version": "4.7.0",
"resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz", "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz",

@ -1,22 +0,0 @@
The MIT License
Copyright (c) 2017-2020 Denis Fäcke
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -1,122 +0,0 @@
# fastify-session
![Build Status](https://github.com/SerayaEryn/fastify-session/workflows/ci/badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/SerayaEryn/fastify-session/badge.svg?branch=master)](https://coveralls.io/github/SerayaEryn/fastify-session?branch=master)
[![NPM version](https://img.shields.io/npm/v/fastify-session.svg?style=flat)](https://www.npmjs.com/package/fastify-session)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
A session plugin for [fastify](http://fastify.io/).
Requires the [fastify-cookie](https://github.com/fastify/fastify-cookie) plugin.
## Install
```
npm install fastify-session
```
## Usage
```js
const fastify = require('fastify');
const fastifySession = require('fastify-session');
const fastifyCookie = require('fastify-cookie');
const app = fastify();
app.register(fastifyCookie);
app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'});
```
Store data in the session by adding it to the `session` decorator at the `request`:
```js
app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'});
app.addHook('preHandler', (request, reply, next) => {
request.session.user = {name: 'max'};
next();
})
```
**NOTE**: For all unencrypted (HTTP) connections, you need to set the `secure` cookie option to `false`. Look below for all cookie options and their details.
The `sessionStore` decorator of the `request` allows to get, save and delete sessions.
```js
app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'});
app.addHook('preHandler', (request, reply, next) => {
const session = request.session;
request.sessionStore.destroy(session.sessionId, next);
})
```
## Examples
* [Authentication](https://github.com/fastify/example/tree/master/fastify-session-authentication)
## API
### session(fastify, options, next)
The session plugin accepts the following options. It decorates the request with the `sessionStore` and a `session` object. The session data is stored server side using the configured session store.
#### options
##### secret (required)
The secret used to sign the cookie. Must be an array of strings, or a string with length 32 or greater.
If an array, the first secret is used to sign new cookies, and is the first one to be checked for incoming cookies.
Further secrets in the array are used to check incoming cookies, in the order specified.
Note that the array may be manipulated by the rest of the application during its life cycle. This can be done by storing the array in a separate variable that is later manipulated with mutating methods like unshift(), pop(), splice(), etc.
This can be used to rotate the signing secret at regular intervals. A secret should remain somewhere in the array as long as there are active sessions with cookies signed by it. Secrets management is left up to the rest of the application.
##### cookieName (optional)
The name of the session cookie. Defaults to `sessionId`.
##### cookie
The options object used to generate the `Set-Cookie` header of the session cookie. May have the following properties:
* `path` - The `Path` attribute. Defaults to `/` (the root path).
* `maxAge` - A `number` in milliseconds that specifies the `Expires` attribute by adding the specified milliseconds to the current date. If both `expires` and `maxAge` are set, then `expires` is used.
* `httpOnly` - The `boolean` value of the `HttpOnly` attribute. Defaults to true.
* `secure` - The `boolean` value of the `Secure` attribute. Set this option to false when communicating over an unencrypted (HTTP) connection. Value can be set to `auto`; in this case the `Secure` attribute will be set to false for HTTP request, in case of HTTPS it will be set to true. Defaults to true.
* `expires` - The expiration `date` used for the `Expires` attribute. If both `expires` and `maxAge` are set, then `expires` is used.
* `sameSite`- The `boolean` or `string` of the `SameSite` attribute. Using `Secure` mode with `auto` attribute will change the behaviour of the `SameSite` attribute in `http` mode. The `SameSite` attribute will automatically be set to `Lax` with a `http` request. See this [link](https://www.chromium.org/updates/same-site).
* `domain` - The `Domain` attribute.
##### store
A session store. Needs the following methods:
* set(sessionId, session, callback)
* get(sessionId, callback)
* destroy(sessionId, callback)
Compatible to stores from [express-session](https://github.com/expressjs/session).
Defaults to a simple in memory store.</br>
**Note**: The default store should not be used in a production environment because it will leak memory.
##### saveUninitialized (optional)
Save sessions to the store, even when they are new and not modified. Defaults to `true`.
Setting this to `false` can be useful to save storage space and to comply with the EU cookie law.
##### idGenerator (optional)
Function used to generate new session IDs. Defaults to [`uid(24)`](https://github.com/crypto-utils/uid-safe).
#### request.session
Allows to access or modify the session data.
#### request.destroySession(callback)
Allows to destroy the session in the store
#### Session#touch()
Updates the `expires` property of the session.
#### Session#regenerate()
Regenerates the session by generating a new `sessionId`.
### fastify.decryptSession(sessionId, request, next)
This plugin also decorates the fastify instance with `decryptSession` in case you want to decrypt the session manually.
```js
const { sessionId } = fastify.parseCookie(cookieHeader);
const request = {}
fastify.decryptSession(sessionId, request, () => {
// request.session should be available here
})
```
## License
[MIT](./LICENSE)

@ -1,46 +0,0 @@
'use strict'
module.exports = class Cookie {
constructor (cookieOpts) {
this.maxAge = cookieOpts.maxAge || null
this.path = cookieOpts.path || '/'
this.httpOnly = cookieOpts.httpOnly !== undefined ? cookieOpts.httpOnly : true
this.secure = cookieOpts.secure
this.expires = getExpires(cookieOpts)
this.sameSite = cookieOpts.sameSite || null
this.domain = cookieOpts.domain || null
}
options (secureConnection) {
let secure = this.secure
let sameSite = this.sameSite
if (secure === 'auto') {
if (secureConnection === true) {
secure = true
} else {
sameSite = 'Lax'
secure = false
}
} else {
secure = this.secure
}
return {
path: this.path,
httpOnly: this.httpOnly,
secure: secure,
expires: this.expires,
sameSite,
domain: this.domain
}
}
}
function getExpires (cookieOpts) {
let expires = null
if (cookieOpts.expires) {
expires = cookieOpts.expires
} else if (cookieOpts.maxAge) {
expires = new Date(Date.now() + cookieOpts.maxAge)
}
return expires
}

@ -1,208 +0,0 @@
'use strict'
const uid = require('uid-safe').sync
const fastifyPlugin = require('fastify-plugin')
const Store = require('./store')
const Session = require('./session')
const metadata = require('./metadata')
const cookieSignature = require('cookie-signature')
function session (fastify, options, next) {
const error = checkOptions(options)
if (error) {
return next(error)
}
options = ensureDefaults(options)
fastify.decorate('decryptSession', (sessionId, request, callback) => {
decryptSession(sessionId, options, request, callback)
})
fastify.decorateRequest('sessionStore', options.store)
fastify.decorateRequest('session', {})
fastify.decorateRequest('destroySession', destroySession)
fastify.addHook('preValidation', preValidation(options))
fastify.addHook('onSend', onSend(options))
next()
}
function decryptSession (sessionId, options, request, done) {
const cookieOpts = options.cookie
const idGenerator = options.idGenerator
const secrets = options.secret
const secretsLength = secrets.length
const secret = secrets[0]
let decryptedSessionId = false
for (let i = 0; i < secretsLength; ++i) {
decryptedSessionId = cookieSignature.unsign(sessionId, secrets[i])
if (decryptedSessionId !== false) {
break
}
}
if (decryptedSessionId === false) {
newSession(secret, request, cookieOpts, idGenerator, done)
} else {
options.store.get(decryptedSessionId, (err, session) => {
if (err) {
if (err.code === 'ENOENT') {
newSession(secret, request, cookieOpts, idGenerator, done)
} else {
done(err)
}
return
}
if (!session) {
newSession(secret, request, cookieOpts, idGenerator, done)
return
}
if (session && session.expires && session.expires <= Date.now()) {
options.store.destroy(sessionId, getDestroyCallback(secret, request, done, cookieOpts, idGenerator))
return
}
request.session = new Session(
idGenerator,
cookieOpts,
secret,
session
)
done()
})
}
}
function preValidation (options) {
const cookieOpts = options.cookie
const idGenerator = options.idGenerator
return function handleSession (request, reply, done) {
const url = request.raw.url
if (url.indexOf(cookieOpts.path || '/') !== 0) {
done()
return
}
const sessionId = request.cookies[options.cookieName]
const secret = options.secret[0]
if (!sessionId) {
newSession(secret, request, cookieOpts, idGenerator, done)
} else {
decryptSession(sessionId, options, request, done)
}
}
}
function onSend (options) {
return function saveSession (request, reply, payload, done) {
const session = request.session
if (!session || !session.sessionId || !shouldSaveSession(request, options.cookie, options.saveUninitialized)) {
done()
return
}
options.store.set(session.sessionId, session, (err) => {
if (err) {
done(err)
return
}
reply.setCookie(
options.cookieName,
session.encryptedSessionId,
session.cookie.options(isConnectionSecure(request))
)
done()
})
}
}
function getDestroyCallback (secret, request, done, cookieOpts, idGenerator) {
return function destroyCallback (err) {
if (err) {
done(err)
return
}
newSession(secret, request, cookieOpts, idGenerator, done)
}
}
function newSession (secret, request, cookieOpts, idGenerator, done) {
request.session = new Session(idGenerator, cookieOpts, secret)
done()
}
function destroySession (done) {
const request = this
request.sessionStore.destroy(request.session.sessionId, (err) => {
request.session = null
done(err)
})
}
function checkOptions (options) {
if (!options.secret) {
return new Error('the secret option is required!')
}
if (typeof options.secret === 'string' && options.secret.length < 32) {
return new Error('the secret must have length 32 or greater')
}
if (Array.isArray(options.secret) && options.secret.length === 0) {
return new Error('at least one secret is required')
}
}
function idGenerator () {
return uid(24)
}
function ensureDefaults (options) {
options.store = options.store || new Store()
options.idGenerator = options.idGenerator || idGenerator
options.cookieName = options.cookieName || 'sessionId'
options.cookie = options.cookie || {}
options.cookie.secure = option(options.cookie, 'secure', true)
options.saveUninitialized = option(options, 'saveUninitialized', true)
options.secret = Array.isArray(options.secret) ? options.secret : [options.secret]
return options
}
function getRequestProto (request) {
return request.headers['x-forwarded-proto'] || 'http'
}
function isConnectionSecure (request) {
if (isConnectionEncrypted(request)) {
return true
}
return getRequestProto(request) === 'https'
}
function isConnectionEncrypted (request) {
const socket = request.raw.socket
if (socket && socket.encrypted === true) {
return true
}
return false
}
function shouldSaveSession (request, cookieOpts, saveUninitialized) {
if (!saveUninitialized && !isSessionModified(request.session)) {
return false
}
if (cookieOpts.secure !== true || cookieOpts.secure === 'auto') {
return true
}
if (isConnectionEncrypted(request)) {
return true
}
const forwardedProto = getRequestProto(request)
return forwardedProto === 'https'
}
function isSessionModified (session) {
return (Object.keys(session).length !== 4)
}
function option (options, key, def) {
return options[key] === undefined ? def : options[key]
}
exports = module.exports = fastifyPlugin(session, metadata)
module.exports.Store = Store
module.exports.MemoryStore = Store

@ -1,9 +0,0 @@
'use strict'
module.exports = {
fastify: '>=2.0.0',
name: 'fastify-session',
dependencies: [
'fastify-cookie'
]
}

@ -1,49 +0,0 @@
'use strict'
const Cookie = require('./cookie')
const cookieSignature = require('cookie-signature')
const maxAge = Symbol('maxAge')
const secretKey = Symbol('secretKey')
const sign = Symbol('sign')
const addDataToSession = Symbol('addDataToSession')
const generateId = Symbol('generateId')
module.exports = class Session {
constructor (idGenerator, cookieOpts, secret, prevSession = {}) {
this[generateId] = idGenerator
this.expires = null
this.cookie = new Cookie(cookieOpts)
this[maxAge] = cookieOpts.maxAge
this[secretKey] = secret
this[addDataToSession](prevSession)
this.touch()
if (!this.sessionId) {
this.regenerate()
}
}
touch () {
if (this[maxAge]) {
this.expires = new Date(Date.now() + this[maxAge])
this.cookie.expires = this.expires
}
}
regenerate () {
this.sessionId = this[generateId]()
this.encryptedSessionId = this[sign]()
}
[addDataToSession] (prevSession) {
for (const key in prevSession) {
if (!['expires', 'cookie'].includes(key)) {
this[key] = prevSession[key]
}
}
}
[sign] () {
return cookieSignature.sign(this.sessionId, this[secretKey])
}
}

@ -1,28 +0,0 @@
'use strict'
const EventEmitter = require('events').EventEmitter
const util = require('util')
function Store (storeMap = new Map()) {
this.store = storeMap
EventEmitter.call(this)
}
util.inherits(Store, EventEmitter)
Store.prototype.set = function set (sessionId, session, callback) {
this.store.set(sessionId, session)
callback()
}
Store.prototype.get = function get (sessionId, callback) {
const session = this.store.get(sessionId)
callback(null, session)
}
Store.prototype.destroy = function destroy (sessionId, callback) {
this.store.delete(sessionId)
callback()
}
module.exports = Store

@ -1,16 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: '/'
ignore:
- dependency-name: "actions/*"
update-types:
["version-update:semver-minor", "version-update:semver-patch"]
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: npm
directory: '/'
schedule:
interval: daily
open-pull-requests-limit: 10

@ -1,21 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 15
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- "discussion"
- "feature request"
- "bug"
- "help wanted"
- "plugin suggestion"
- "good first issue"
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

@ -1,61 +0,0 @@
name: CI
'on':
push:
paths-ignore:
- docs/**
- '*.md'
pull_request:
paths-ignore:
- docs/**
- '*.md'
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version:
- 10
- 12
- 14
- 16
os:
- macos-latest
- ubuntu-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install Dependencies
run: |
npm install --ignore-scripts
- name: Run Tests
run: |
npm run test:ci
- name: Coveralls Parallel
uses: coverallsapp/github-action@1.1.3
with:
github-token: ${{ secrets.github_token }}
parallel: true
flag-name: run-${{ matrix.node-version }}-${{ matrix.os }}
coverage:
needs: test
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@1.1.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
automerge:
needs: test
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: write
steps:
- uses: fastify/github-action-merge-dependabot@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

@ -1,4 +0,0 @@
ts: false
jsx: false
flow: false
coverage: true

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017 Fastify
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -1,158 +0,0 @@
# fastify-plugin
![CI](https://github.com/fastify/fastify-plugin/workflows/CI/badge.svg?branch=master)
[![NPM version](https://img.shields.io/npm/v/fastify-plugin.svg?style=flat)](https://www.npmjs.com/package/fastify-plugin)
[![Known Vulnerabilities](https://snyk.io/test/github/fastify/fastify-plugin/badge.svg)](https://snyk.io/test/github/fastify/fastify-plugin)
[![Coverage Status](https://coveralls.io/repos/github/fastify/fastify-plugin/badge.svg?branch=master)](https://coveralls.io/github/fastify/fastify-plugin?branch=master)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
`fastify-plugin` is a plugin helper for [Fastify](https://github.com/fastify/fastify).
When you build plugins for Fastify and you want that them to be accessible in the same context where you require them, you have two ways:
1. Use the `skip-override` hidden property
2. Use this module
__Note: the v2.x & v3.x series of this module covers Fastify v3. For Fastify v2 support, refer to the v1.x series.__
## Usage
`fastify-plugin` can do three things for you:
- Add the `skip-override` hidden property
- Check the bare-minimum version of Fastify
- Pass some custom metadata of the plugin to Fastify
Example using a callback:
```js
const fp = require('fastify-plugin')
module.exports = fp(function (fastify, opts, next) {
// your plugin code
next()
})
```
Example using an [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function:
```js
const fp = require('fastify-plugin')
// A callback function param is not required for async functions
module.exports = fp(async function (fastify, opts) {
// Wait for an async function to fulfill promise before proceeding
await exampleAsyncFunction()
})
```
## Metadata
In addition, if you use this module when creating new plugins, you can declare the dependencies, the name, and the expected Fastify version that your plugin needs.
#### Fastify version
If you need to set a bare-minimum version of Fastify for your plugin, just add the [semver](https://semver.org/) range that you need:
```js
const fp = require('fastify-plugin')
module.exports = fp(function (fastify, opts, next) {
// your plugin code
next()
}, { fastify: '3.x' })
```
If you need to check the Fastify version only, you can pass just the version string.
You can check [here](https://github.com/npm/node-semver#ranges) how to define a `semver` range.
#### Name
Fastify uses this option to validate the dependency graph, allowing it to ensure that no name collisions occur and making it possible to perform [dependency checks](https://github.com/fastify/fastify-plugin#dependencies).
```js
const fp = require('fastify-plugin')
function plugin (fastify, opts, next) {
// your plugin code
next()
}
module.exports = fp(plugin, {
fastify: '3.x',
name: 'your-plugin-name'
})
```
#### Dependencies
You can also check if the `plugins` and `decorators` that your plugin intend to use are present in the dependency graph.
> *Note:* This is the point where registering `name` of the plugins become important, because you can reference `plugin` dependencies by their [name](https://github.com/fastify/fastify-plugin#name).
```js
const fp = require('fastify-plugin')
function plugin (fastify, opts, next) {
// your plugin code
next()
}
module.exports = fp(plugin, {
fastify: '3.x',
decorators: {
fastify: ['plugin1', 'plugin2'],
reply: ['compress']
},
dependencies: ['plugin1-name', 'plugin2-name']
})
```
#### Bundlers and Typescript
`fastify-plugin` adds a `.default` and `[name]` property to the passed in function.
The type definition would have to be updated to leverage this.
## Known Issue: TypeScript Contextual Inference
[Documentation Reference](https://www.typescriptlang.org/docs/handbook/functions.html#inferring-the-types)
It is common for developers to inline their plugin with fastify-plugin such as:
```js
fp((fastify, opts, next) => { next() })
fp(async (fastify, opts) => { return })
```
TypeScript can sometimes infer the types of the arguments for these functions. Plugins in fastify are recommended to be typed using either `FastifyPluginCallback` or `FastifyPluginAsync`. These two definitions only differ in two ways:
1. The third argument `next` (the callback part)
2. The return type `FastifyPluginCallback` or `FastifyPluginAsync`
At this time, TypeScript inference is not smart enough to differentiate by definition argument length alone.
Thus, if you are a TypeScript developer please use on the following patterns instead:
```ts
// Callback
// Assign type directly
const pluginCallback: FastifyPluginCallback = (fastify, options, next) => { }
fp(pluginCallback)
// or define your own function declaration that satisfies the existing definitions
const pluginCallbackWithTypes = (fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { }
fp(pluginCallbackWithTypes)
// or inline
fp((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })
// Async
// Assign type directly
const pluginAsync: FastifyPluginAsync = async (fastify, options) => { }
fp(pluginAsync)
// or define your own function declaration that satisfies the existing definitions
const pluginAsyncWithTypes = async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { }
fp(pluginAsyncWithTypes)
// or inline
fp(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { })
```
## Acknowledgements
This project is kindly sponsored by:
- [nearForm](https://nearform.com)
- [LetzDoIt](https://www.letzdoitapp.com/)
## License
Licensed under [MIT](./LICENSE).

@ -1,37 +0,0 @@
{
"name": "fastify-plugin",
"version": "3.0.1",
"description": "Plugin helper for Fastify",
"main": "plugin.js",
"types": "plugin.d.ts",
"scripts": {
"test": "standard && tap test/*.js test/esm/*.js --no-check-coverage && npm run typescript",
"test:ci": "standard && tap test/*.js test/esm/*.js --no-check-coverage --coverage-report=lcovonly && npm run typescript",
"typescript": "tsd"
},
"repository": {
"type": "git",
"url": "git+https://github.com/fastify/fastify-plugin.git"
},
"keywords": [
"plugin",
"helper",
"fastify"
],
"author": "Tomas Della Vedova - @delvedor (http://delved.org)",
"license": "MIT",
"bugs": {
"url": "https://github.com/fastify/fastify-plugin/issues"
},
"homepage": "https://github.com/fastify/fastify-plugin#readme",
"devDependencies": {
"@types/node": "^17.0.0",
"fastify": "^3.3.0",
"proxyquire": "^2.1.3",
"standard": "^16.0.3",
"tap": "^15.0.2",
"tsd": "^0.19.0",
"typescript": "^4.0.5"
},
"dependencies": {}
}

@ -1,36 +0,0 @@
/// <reference types="fastify" />
import {
FastifyPluginCallback,
FastifyPluginAsync,
} from 'fastify'
/**
* This function does three things for you:
* 1. Add the `skip-override` hidden property
* 2. Check bare-minimum version of Fastify
* 3. Pass some custom metadata of the plugin to Fastify
* @param fn Fastify plugin function
* @param options Optional plugin options
*/
export default function fp<Options>(fn: FastifyPluginAsync<Options>, options?: PluginMetadata): FastifyPluginAsync<Options>;
export default function fp<Options>(fn: FastifyPluginAsync<Options>, options?: string): FastifyPluginAsync<Options>;
export default function fp<Options>(fn: FastifyPluginCallback<Options>, options?: PluginMetadata): FastifyPluginCallback<Options>;
export default function fp<Options>(fn: FastifyPluginCallback<Options>, options?: string): FastifyPluginCallback<Options>;
export interface PluginMetadata {
/** Bare-minimum version of Fastify for your plugin, just add the semver range that you need. */
fastify?: string,
name?: string,
/** Decorator dependencies for this plugin */
decorators?: {
fastify?: (string | symbol)[],
reply?: (string | symbol)[],
request?: (string | symbol)[]
},
/** The plugin dependencies */
dependencies?: string[]
}
// Exporting PluginOptions for backward compatibility after renaming it to PluginMetadata
export interface PluginOptions extends PluginMetadata {}

@ -1,85 +0,0 @@
'use strict'
const extractPluginName = require('./stackParser')
let count = 0
function plugin (fn, options = {}) {
let autoName = false
if (typeof fn.default !== 'undefined') {
// Support for 'export default' behaviour in transpiled ECMAScript module
fn = fn.default
}
if (typeof fn !== 'function') {
throw new TypeError(
`fastify-plugin expects a function, instead got a '${typeof fn}'`
)
}
fn[Symbol.for('skip-override')] = true
const pluginName = (options && options.name) || checkName(fn)
if (typeof options === 'string') {
options = {
fastify: options
}
}
if (
typeof options !== 'object' ||
Array.isArray(options) ||
options === null
) {
throw new TypeError('The options object should be an object')
}
if (options.fastify !== undefined && typeof options.fastify !== 'string') {
throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`)
}
if (!options.name) {
autoName = true
options.name = pluginName + '-auto-' + count++
}
fn[Symbol.for('fastify.display-name')] = options.name
fn[Symbol.for('plugin-meta')] = options
// Faux modules support
if (!fn.default) {
fn.default = fn
}
// TypeScript support for named imports
// See https://github.com/fastify/fastify/issues/2404 for more details
// The type definitions would have to be update to match this.
const camelCase = toCamelCase(options.name)
if (!autoName && !fn[camelCase]) {
fn[camelCase] = fn
}
return fn
}
function checkName (fn) {
if (fn.name.length > 0) return fn.name
try {
throw new Error('anonymous function')
} catch (e) {
return extractPluginName(e.stack)
}
}
function toCamelCase (name) {
const newName = name.replace(/-(.)/g, function (match, g1) {
return g1.toUpperCase()
})
return newName
}
plugin.default = plugin
module.exports = plugin

@ -1,74 +0,0 @@
import fp from './plugin';
import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions } from 'fastify';
import { expectAssignable } from 'tsd'
interface Options {
foo: string
}
const testSymbol = Symbol('foobar')
// Callback
const pluginCallback: FastifyPluginCallback = (fastify, options, next) => { }
expectAssignable<FastifyPluginCallback>(fp(pluginCallback))
const pluginCallbackWithTypes = (fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { }
expectAssignable<FastifyPluginCallback>(fp(pluginCallbackWithTypes))
expectAssignable<FastifyPluginCallback>(fp((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { }))
expectAssignable<FastifyPluginCallback>(fp(pluginCallback, '' ))
expectAssignable<FastifyPluginCallback>(fp(pluginCallback, {
fastify: '',
name: '',
decorators: {
fastify: [ '', testSymbol ],
reply: [ '', testSymbol ],
request: [ '', testSymbol ]
},
dependencies: [ '' ]
}))
const pluginCallbackWithOptions: FastifyPluginCallback<Options> = (fastify, options, next) => {
expectAssignable<string>(options.foo)
}
expectAssignable<FastifyPluginCallback<Options>>(fp(pluginCallbackWithOptions))
// Async
const pluginAsync: FastifyPluginAsync = async (fastify, options) => { }
expectAssignable<FastifyPluginAsync>(fp(pluginAsync))
const pluginAsyncWithTypes = async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { }
expectAssignable<FastifyPluginAsync>(fp(pluginAsyncWithTypes))
expectAssignable<FastifyPluginAsync>(fp(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { }))
expectAssignable<FastifyPluginAsync>(fp(pluginAsync, '' ))
expectAssignable<FastifyPluginAsync>(fp(pluginAsync, {
fastify: '',
name: '',
decorators: {
fastify: [ '', testSymbol ],
reply: [ '', testSymbol ],
request: [ '', testSymbol ]
},
dependencies: [ '' ]
}))
const pluginAsyncWithOptions: FastifyPluginAsync<Options> = async (fastify, options) => {
expectAssignable<string>(options.foo)
}
expectAssignable<FastifyPluginAsync<Options>>(fp(pluginAsyncWithOptions))
// Fastify register
const server = fastify()
server.register(fp(pluginCallback))
server.register(fp(pluginCallbackWithTypes))
server.register(fp(pluginCallbackWithOptions))
server.register(fp(pluginAsync))
server.register(fp(pluginAsyncWithTypes))
server.register(fp(pluginAsyncWithOptions))

@ -1,11 +0,0 @@
'use strict'
const fpStackTracePattern = /at\s{1}(?:.*\.)?plugin\s{1}.*\n\s*(.*)/
const fileNamePattern = /(\w*(\.\w*)*)\..*/
module.exports = function extractPluginName (stack) {
const m = stack.match(fpStackTracePattern)
// get last section of path and match for filename
return m ? m[1].split(/[/\\]/).slice(-1)[0].match(fileNamePattern)[1] : 'anonymous'
}

@ -1,98 +0,0 @@
'use strict'
const { test } = require('tap')
const fp = require('../plugin')
test('webpack removes require.main.filename', (t) => {
const filename = require.main.filename
const info = console.info
t.teardown(() => {
require.main.filename = filename
console.info = info
})
require.main.filename = null
console.info = function (msg) {
t.fail('logged: ' + msg)
}
fp((fastify, opts, next) => {
next()
}, {
fastify: '^3.0.0'
})
t.end()
})
test('support faux modules', (t) => {
const plugin = fp((fastify, opts, next) => {
next()
})
t.equal(plugin.default, plugin)
t.end()
})
test('support faux modules does not override existing default field in babel module', (t) => {
const module = {
default: (fastify, opts, next) => next()
}
module.default.default = 'Existing default field'
const plugin = fp(module)
t.equal(plugin.default, 'Existing default field')
t.end()
})
test('support ts named imports', (t) => {
const plugin = fp((fastify, opts, next) => {
next()
}, {
name: 'hello'
})
t.equal(plugin.hello, plugin)
t.end()
})
test('from kebabo-case to camelCase', (t) => {
const plugin = fp((fastify, opts, next) => {
next()
}, {
name: 'hello-world'
})
t.equal(plugin.helloWorld, plugin)
t.end()
})
test('from kebab-case to camelCase multiple words', (t) => {
const plugin = fp((fastify, opts, next) => {
next()
}, {
name: 'hello-long-world'
})
t.equal(plugin.helloLongWorld, plugin)
t.end()
})
test('from kebab-case to camelCase multiple words does not override', (t) => {
const fn = (fastify, opts, next) => {
next()
}
const foobar = {}
fn.helloLongWorld = foobar
const plugin = fp(fn, {
name: 'hello-long-world'
})
t.equal(plugin.helloLongWorld, foobar)
t.end()
})

@ -1,73 +0,0 @@
'use strict'
const { test } = require('tap')
const fp = require('../plugin')
test('checkVersion having require.main.filename', (t) => {
const info = console.info
t.ok(require.main.filename)
t.teardown(() => {
console.info = info
})
console.info = function (msg) {
t.fail('logged: ' + msg)
}
fp((fastify, opts, next) => {
next()
}, {
fastify: '^3.0.0'
})
t.end()
})
test('checkVersion having no require.main.filename but process.argv[1]', (t) => {
const filename = require.main.filename
const info = console.info
t.teardown(() => {
require.main.filename = filename
console.info = info
})
require.main.filename = null
console.info = function (msg) {
t.fail('logged: ' + msg)
}
fp((fastify, opts, next) => {
next()
}, {
fastify: '^3.0.0'
})
t.end()
})
test('checkVersion having no require.main.filename and no process.argv[1]', (t) => {
const filename = require.main.filename
const argv = process.argv
const info = console.info
t.teardown(() => {
require.main.filename = filename
process.argv = argv
console.info = info
})
require.main.filename = null
process.argv[1] = null
console.info = function (msg) {
t.fail('logged: ' + msg)
}
fp((fastify, opts, next) => {
next()
}, {
fastify: '^3.0.0'
})
t.end()
})

@ -1,16 +0,0 @@
'use strict'
const t = require('tap')
const test = t.test
const fp = require('../plugin')
test('anonymous function should be named composite.test0', t => {
t.plan(2)
const fn = fp((fastify, opts, next) => {
next()
})
t.equal(fn[Symbol.for('plugin-meta')].name, 'composite.test-auto-0')
t.equal(fn[Symbol.for('fastify.display-name')], 'composite.test-auto-0')
})

@ -1,13 +0,0 @@
import t from 'tap'
import fp from '../../plugin.js'
t.test('esm base support', async t => {
fp((fastify, opts, next) => {
next()
}, {
fastify: '^3.0.0'
})
t.end()
})

@ -1,19 +0,0 @@
'use strict'
const t = require('tap')
const semver = require('semver')
if (semver.lt(process.versions.node, '13.3.0')) {
t.skip('Skip because Node version <= 13.3.0')
t.end()
} else {
// Node v8 throw a `SyntaxError: Unexpected token import`
// even if this branch is never touch in the code,
// by using `eval` we can avoid this issue.
// eslint-disable-next-line
new Function('module', 'return import(module)')('./esm.mjs').catch((err) => {
process.nextTick(() => {
throw err
})
})
}

@ -1,16 +0,0 @@
'use strict'
const t = require('tap')
const test = t.test
const fp = require('../plugin')
test('anonymous function should be named mu1tip1e.composite.test', t => {
t.plan(2)
const fn = fp((fastify, opts, next) => {
next()
})
t.equal(fn[Symbol.for('plugin-meta')].name, 'mu1tip1e.composite.test-auto-0')
t.equal(fn[Symbol.for('fastify.display-name')], 'mu1tip1e.composite.test-auto-0')
})

@ -1,48 +0,0 @@
'use strict'
const t = require('tap')
const extractPluginName = require('../stackParser')
const winStack = `Error: anonymous function
at checkName (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\index.js:43:11)
at plugin (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\index.js:24:20)
at Test.test (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\test\\hello.test.js:9:14)
at bound (domain.js:396:14)
at Test.runBound (domain.js:409:12)
at ret (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:278:21)
at Test.main (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:282:7)
at writeSubComment (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:371:13)
at TAP.writeSubComment (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:403:5)
at Test.runBeforeEach (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:370:14)
at loop (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\function-loop\\index.js:35:15)
at TAP.runBeforeEach (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:683:7)
at TAP.processSubtest (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:369:12)
at TAP.process (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:306:14)
at TAP.sub (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:185:10)
at TAP.test (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:209:17)`
const nixStack = `Error: anonymous function
at checkName (/home/leonardo/desktop/fastify-plugin/index.js:43:11)
at plugin (/home/leonardo/desktop/fastify-plugin/index.js:24:20)
at Test.test (/home/leonardo/desktop/fastify-plugin/test/this.is.a.test.js:9:14)
at bound (domain.js:396:14)
at Test.runBound (domain.js:409:12)
at ret (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:278:21)
at Test.main (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:282:7)
at writeSubComment (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:371:13)
at TAP.writeSubComment (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:403:5)
at Test.runBeforeEach (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:370:14)
at loop (/home/leonardo/desktop/fastify-plugin/node_modules/function-loop/index.js:35:15)
at TAP.runBeforeEach (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:683:7)
at TAP.processSubtest (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:369:12)
at TAP.process (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:306:14)
at TAP.sub (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:185:10)
at TAP.test (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:209:17)`
const anonymousStack = 'Unable to parse this'
t.plan(3)
t.equal(extractPluginName(winStack), 'hello.test')
t.equal(extractPluginName(nixStack), 'this.is.a.test')
t.equal(extractPluginName(anonymousStack), 'anonymous')

@ -1,239 +0,0 @@
'use strict'
const t = require('tap')
const proxyquire = require('proxyquire')
const test = t.test
const fp = require('../plugin')
const Fastify = require('fastify')
test('fastify-plugin is a function', t => {
t.plan(1)
t.type(fp, 'function')
})
test('should return the function with the skip-override Symbol', t => {
t.plan(1)
function plugin (fastify, opts, next) {
next()
}
fp(plugin)
t.ok(plugin[Symbol.for('skip-override')])
})
test('should support "default" function from babel module', t => {
t.plan(1)
const plugin = {
default: () => { }
}
try {
fp(plugin)
t.pass()
} catch (e) {
t.equal(e.message, 'fastify-plugin expects a function, instead got a \'object\'')
}
})
test('should throw if the plugin is not a function', t => {
t.plan(1)
try {
fp('plugin')
t.fail()
} catch (e) {
t.equal(e.message, 'fastify-plugin expects a function, instead got a \'string\'')
}
})
test('should check the fastify version', t => {
t.plan(1)
function plugin (fastify, opts, next) {
next()
}
try {
fp(plugin, { fastify: '>=0.10.0' })
t.pass()
} catch (e) {
t.fail()
}
})
test('should check the fastify version', t => {
t.plan(1)
function plugin (fastify, opts, next) {
next()
}
try {
fp(plugin, '>=0.10.0')
t.pass()
} catch (e) {
t.fail()
}
})
test('the options object should be an object', t => {
t.plan(2)
try {
fp(() => { }, null)
t.fail()
} catch (e) {
t.equal(e.message, 'The options object should be an object')
}
try {
fp(() => { }, [])
t.fail()
} catch (e) {
t.equal(e.message, 'The options object should be an object')
}
})
test('should throw if the version number is not a string', t => {
t.plan(1)
try {
fp(() => { }, { fastify: 12 })
t.fail()
} catch (e) {
t.equal(e.message, 'fastify-plugin expects a version string, instead got \'number\'')
}
})
test('Should accept an option object', t => {
t.plan(2)
const opts = { hello: 'world' }
function plugin (fastify, opts, next) {
next()
}
fp(plugin, opts)
t.ok(plugin[Symbol.for('skip-override')])
t.same(plugin[Symbol.for('plugin-meta')], opts)
})
test('Should accept an option object and checks the version', t => {
t.plan(2)
const opts = { hello: 'world', fastify: '>=0.10.0' }
function plugin (fastify, opts, next) {
next()
}
fp(plugin, opts)
t.ok(plugin[Symbol.for('skip-override')])
t.same(plugin[Symbol.for('plugin-meta')], opts)
})
test('should set anonymous function name to file it was called from with a counter', t => {
const fp = proxyquire('../plugin.js', { stubs: {} })
const fn = fp((fastify, opts, next) => {
next()
})
t.equal(fn[Symbol.for('plugin-meta')].name, 'test-auto-0')
t.equal(fn[Symbol.for('fastify.display-name')], 'test-auto-0')
const fn2 = fp((fastify, opts, next) => {
next()
})
t.equal(fn2[Symbol.for('plugin-meta')].name, 'test-auto-1')
t.equal(fn2[Symbol.for('fastify.display-name')], 'test-auto-1')
t.end()
})
test('should set display-name to meta name', t => {
t.plan(2)
const functionName = 'superDuperSpecialFunction'
const fn = fp((fastify, opts, next) => next(), {
name: functionName
})
t.equal(fn[Symbol.for('plugin-meta')].name, functionName)
t.equal(fn[Symbol.for('fastify.display-name')], functionName)
})
test('should preserve fastify version in meta', t => {
t.plan(1)
const opts = { hello: 'world', fastify: '>=0.10.0' }
const fn = fp((fastify, opts, next) => next(), opts)
t.equal(fn[Symbol.for('plugin-meta')].fastify, '>=0.10.0')
})
test('should check fastify dependency graph - plugin', t => {
t.plan(1)
const fastify = Fastify()
fastify.register(fp((fastify, opts, next) => next(), {
fastify: '3.x',
name: 'plugin1-name'
}))
fastify.register(fp((fastify, opts, next) => next(), {
fastify: '3.x',
name: 'test',
dependencies: ['plugin1-name', 'plugin2-name']
}))
fastify.ready(err => {
t.equal(err.message, "The dependency 'plugin2-name' of plugin 'test' is not registered")
})
})
test('should check fastify dependency graph - decorate', t => {
t.plan(1)
const fastify = Fastify()
fastify.decorate('plugin1', fp((fastify, opts, next) => next(), {
fastify: '3.x',
name: 'plugin1-name'
}))
fastify.register(fp((fastify, opts, next) => next(), {
fastify: '3.x',
name: 'test',
decorators: { fastify: ['plugin1', 'plugin2'] }
}))
fastify.ready(err => {
t.equal(err.message, "The decorator 'plugin2' required by 'test' is not present in Fastify")
})
})
test('should check fastify dependency graph - decorateReply', t => {
t.plan(1)
const fastify = Fastify()
fastify.decorateReply('plugin1', fp((fastify, opts, next) => next(), {
fastify: '3.x',
name: 'plugin1-name'
}))
fastify.register(fp((fastify, opts, next) => next(), {
fastify: '3.x',
name: 'test',
decorators: { reply: ['plugin1', 'plugin2'] }
}))
fastify.ready(err => {
t.equal(err.message, "The decorator 'plugin2' required by 'test' is not present in Reply")
})
})

@ -1,8 +0,0 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"noEmit": true,
"strict": true,
}
}

@ -1,47 +0,0 @@
{
"name": "fastify-session",
"version": "5.2.1",
"description": "a session plugin for fastify",
"main": "lib/fastifySession.js",
"scripts": {
"unit": "ava test/*.test.js",
"tsc-check": "tsc --project ./types/tsconfig.json --noEmit",
"test": "npm run lint && npm run unit && npm run tsc-check",
"lint": "standard lib/* test/*",
"coveralls": "nyc npm test",
"coverage": "nyc npm test && nyc report --reporter=html"
},
"keywords": [
"session",
"fastify"
],
"author": "Denis Fäcke",
"license": "MIT",
"dependencies": {
"cookie-signature": "^1.1.0",
"fastify-plugin": "^3.0.0",
"uid-safe": "^2.1.5"
},
"engines": {
"node": ">= 10.13.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/SerayaEryn/fastify-session.git"
},
"devDependencies": {
"@types/node": "^14.0.0",
"ava": "^3.6.0",
"fastify": "^3.0.0",
"fastify-cookie": "^4.1.0",
"got": "^11.6.0",
"nyc": "^15.0.0",
"standard": "^16.0.1",
"typescript": "^4.0.2"
},
"types": "types/types.d.ts",
"files": [
"lib",
"types/types.d.ts"
]
}

@ -1,89 +0,0 @@
/// <reference types="node" />
import { FastifyPlugin } from "fastify";
declare module "fastify" {
interface FastifyRequest {
/** Allows to access or modify the session data. */
session: Session;
/** A session store. */
sessionStore: FastifySessionPlugin.SessionStore;
/** Allows to destroy the session in the store. */
destroySession(callback: (err?: Error) => void): void;
}
interface Session extends Record<string, any> {
sessionId: string;
encryptedSessionId: string;
/** Updates the `expires` property of the session. */
touch(): void;
/** Regenerates the session by generating a new `sessionId`. */
regenerate(): void;
}
}
declare namespace FastifySessionPlugin {
interface SessionStore {
set(sessionId: string, session: any, callback: (err?: Error) => void): void;
get(
sessionId: string,
callback: (err?: Error, session?: any) => void
): void;
destroy(sessionId: string, callback: (err?: Error) => void): void;
}
interface Options {
/**
* The secret used to sign the cookie.
*
* Must be an array of strings, or a string with length 32 or greater. If an array, the first secret is used to
* sign new cookies, and is the first one to be checked for incoming cookies.
* Further secrets in the array are used to check incoming cookies, in the order specified.
*
* Note that the array may be manipulated by the rest of the application during its life cycle.
* This can be done by storing the array in a separate variable that is later manipulated with mutating methods
* like unshift(), pop(), splice(), etc.
* This can be used to rotate the signing secret at regular intervals.
* A secret should remain somewhere in the array as long as there are active sessions with cookies signed by it.
* Secrets management is left up to the rest of the application.
*/
secret: string | string[];
/** The name of the session cookie. Defaults to `sessionId`. */
cookieName?: string;
/** The options object used to generate the `Set-Cookie` header of the session cookie. */
cookie?: CookieOptions;
/**
* A session store.
* Compatible to stores from express-session.
* Defaults to a simple in memory store.
* Note: The default store should not be used in a production environment because it will leak memory.
*/
store?: FastifySessionPlugin.SessionStore;
/**
* Save sessions to the store, even when they are new and not modified.
* Defaults to true. Setting this to false can be useful to save storage space and to comply with the EU cookie law.
*/
saveUninitialized?: boolean;
}
interface CookieOptions {
/** The `Path` attribute. Defaults to `/` (the root path). */
path?: string;
/** A `number` in milliseconds that specifies the `Expires` attribute by adding the specified milliseconds to the current date. If both `expires` and `maxAge` are set, then `expires` is used. */
maxAge?: number;
/** The `boolean` value of the `HttpOnly` attribute. Defaults to true. */
httpOnly?: boolean;
/** The `boolean` value of the `Secure` attribute. Set this option to false when communicating over an unencrypted (HTTP) connection. Value can be set to `auto`; in this case the `Secure` attribute will be set to false for HTTP request, in case of HTTPS it will be set to true. Defaults to true. */
secure?: boolean | string;
/** The expiration `date` used for the `Expires` attribute. If both `expires` and `maxAge` are set, then `expires` is used. */
expires?: Date | number;
/** The `boolean` or `string` of the `SameSite` attribute. */
sameSite?: string | boolean;
/** The `Domain` attribute. */
domain?: string;
}
}
declare const FastifySessionPlugin: FastifyPlugin<FastifySessionPlugin.Options>;
export default FastifySessionPlugin;

36
package-lock.json generated

@ -32,7 +32,6 @@
"fastify-jwt": "^4.2.0", "fastify-jwt": "^4.2.0",
"fastify-multer": "^2.0.2", "fastify-multer": "^2.0.2",
"fastify-multipart": "^5.4.0", "fastify-multipart": "^5.4.0",
"fastify-session": "^5.2.1",
"fastify-static": "^4.7.0", "fastify-static": "^4.7.0",
"fastify-swagger": "^5.2.0", "fastify-swagger": "^5.2.0",
"form-data": "^2.3.3", "form-data": "^2.3.3",
@ -5353,24 +5352,6 @@
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.4.0.tgz", "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.4.0.tgz",
"integrity": "sha512-ovwFQG2qNy3jcCROiWpr94Hs0le+c7N/3t7m9aVwbFhkxcR/esp2xu25dP8e617HpQdmeDv+gFX4zagdUhDByw==" "integrity": "sha512-ovwFQG2qNy3jcCROiWpr94Hs0le+c7N/3t7m9aVwbFhkxcR/esp2xu25dP8e617HpQdmeDv+gFX4zagdUhDByw=="
}, },
"node_modules/fastify-session": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/fastify-session/-/fastify-session-5.2.1.tgz",
"integrity": "sha512-2ZOLPGPeeBE35HOgYD4/v9c304IGF2ExOh35tuKegrB3QSNB+kKeqqzUXrUJ2h0Vr5nTyvrimtPAPQZG963vOw==",
"dependencies": {
"cookie-signature": "^1.1.0",
"fastify-plugin": "^3.0.0",
"uid-safe": "^2.1.5"
},
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/fastify-session/node_modules/fastify-plugin": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz",
"integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA=="
},
"node_modules/fastify-static": { "node_modules/fastify-static": {
"version": "4.7.0", "version": "4.7.0",
"resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz", "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz",
@ -14239,23 +14220,6 @@
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.4.0.tgz", "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.4.0.tgz",
"integrity": "sha512-ovwFQG2qNy3jcCROiWpr94Hs0le+c7N/3t7m9aVwbFhkxcR/esp2xu25dP8e617HpQdmeDv+gFX4zagdUhDByw==" "integrity": "sha512-ovwFQG2qNy3jcCROiWpr94Hs0le+c7N/3t7m9aVwbFhkxcR/esp2xu25dP8e617HpQdmeDv+gFX4zagdUhDByw=="
}, },
"fastify-session": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/fastify-session/-/fastify-session-5.2.1.tgz",
"integrity": "sha512-2ZOLPGPeeBE35HOgYD4/v9c304IGF2ExOh35tuKegrB3QSNB+kKeqqzUXrUJ2h0Vr5nTyvrimtPAPQZG963vOw==",
"requires": {
"cookie-signature": "^1.1.0",
"fastify-plugin": "^3.0.0",
"uid-safe": "^2.1.5"
},
"dependencies": {
"fastify-plugin": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz",
"integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA=="
}
}
},
"fastify-static": { "fastify-static": {
"version": "4.7.0", "version": "4.7.0",
"resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz", "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz",

@ -33,7 +33,6 @@
"fastify-jwt": "^4.2.0", "fastify-jwt": "^4.2.0",
"fastify-multer": "^2.0.2", "fastify-multer": "^2.0.2",
"fastify-multipart": "^5.4.0", "fastify-multipart": "^5.4.0",
"fastify-session": "^5.2.1",
"fastify-static": "^4.7.0", "fastify-static": "^4.7.0",
"fastify-swagger": "^5.2.0", "fastify-swagger": "^5.2.0",
"form-data": "^2.3.3", "form-data": "^2.3.3",

Loading…
Cancel
Save