-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0e6fe02
Showing
17 changed files
with
3,879 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: CI workflow | ||
on: [push, pull_request] | ||
jobs: | ||
test: | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
matrix: | ||
node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x] | ||
os: [ubuntu-latest, windows-latest] | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v1 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- name: Setup pnpm | ||
uses: pnpm/action-setup@v3 | ||
with: | ||
version: latest | ||
- name: Install Dependencies | ||
run: pnpm install --ignore-scripts | ||
- name: Test | ||
run: pnpm run test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"singleQuote": true, | ||
"trailingComma": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Add files here to ignore them from prettier formatting | ||
|
||
/dist | ||
/coverage | ||
pnpm-lock.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
ts: false | ||
jsx: false | ||
coverage: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
# fastify-better-flash | ||
|
||
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/) ![CI workflow](__MY_PLUGIN_URL__ | ||
/workflows/CI%20workflow/badge.svg) | ||
|
||
This plugin is inspired by the [@fastify/flash](https://github.com/fastify/fastify-flash/tree/master) plugin. The main difference is the way it access the messages, using a "dot syntax" and it has a better typescript support. See below for more details. | ||
|
||
Supports Fastify versions `4.x` | ||
|
||
## Install | ||
```sh | ||
npm i fastify-better-flash @fastify/secure-session | ||
``` | ||
```sh | ||
pnpm i fastify-better-flash @fastify/secure-session | ||
``` | ||
```sh | ||
yarn add fastify-better-flash @fastify/secure-session | ||
``` | ||
|
||
|
||
## Usage | ||
Flash messages are stored in the session. First, we need to register the session plugin: (@fastify/secure-session)[https://www.npmjs.com/package/@fastify/secure-session]. | ||
|
||
```js | ||
const fastify = require('fastify')() | ||
const fastifySession = require('@fastify/secure-session') | ||
|
||
fastify.register(fastifySession, { | ||
// adapt this to point to the directory where secret-key is located | ||
key: fs.readFileSync(path.join(__dirname, 'secret-key')), | ||
cookie: { | ||
// options from setCookie, see https://github.com/fastify/fastify-cookie | ||
} | ||
}) | ||
fastify.register(require('fastify-better-flash')) | ||
|
||
fastify.listen({ port: 3000 }) | ||
``` | ||
|
||
### Usage | ||
|
||
In your route handler you can use the `flash` method to set a flash message. | ||
Let's say that we want to have the following messages: | ||
|
||
``` | ||
success: boolean | ||
validations: { | ||
errors: Array<{ field: string, message: string }> | ||
} | ||
genericError: string | ||
``` | ||
|
||
we can set them in the route handler like this: | ||
|
||
```js | ||
|
||
fastify.get('/', async (request, reply) => { | ||
request.flash('success', true) | ||
request.flash('validations.errors', [{ field: 'email', message: 'Email is required' }]) | ||
request.flash('genericError', 'Something went wrong') | ||
}) | ||
|
||
``` | ||
|
||
Then we can consume them like this: | ||
|
||
```js | ||
|
||
fastify.get('/flash', async (request, reply) => { | ||
const success = reply.flash('success') | ||
// Note that we can access the nested object using the dot notation | ||
const validation = reply.flash('validations') | ||
const validationErrors = validation ? validation.errors : [] | ||
// it works with arrays too, this will return the first error field property | ||
const validationErrors = reply.flash('validations.errors.0.field') | ||
const genericError = reply.flash('genericError') | ||
return { success, validationErrors, genericError } | ||
}) | ||
|
||
``` | ||
|
||
### Typescript | ||
|
||
You can define the schema of your flash messages using typescript. | ||
By using the `fastify-better-flash` module you can customize the interface `FlashSessionType` that be extended to define the schema of your flash messages. | ||
|
||
```ts | ||
|
||
declare module 'fastify-better-flash' { | ||
export interface FlashSessionType { | ||
// Define your flash message schema here | ||
success: boolean | ||
validations: { | ||
errors: Array<{ field: string, message: string }> | ||
} | ||
} | ||
} | ||
|
||
``` | ||
|
||
And then in your route handler you can use the `flash` method to set a flash message. | ||
|
||
```ts | ||
|
||
fastify.get('/', async (request, reply) => { | ||
// Also the keys will be typed | ||
request.flash('success', 'This is a success message') // This will not compile | ||
|
||
const validationErrors = reply.flash('validations.errors') // This will have the correct types | ||
return reply.redirect('/flash') | ||
}) | ||
|
||
``` | ||
|
||
By design the getter method `flash` will alaways return the type that you have defined or `undefined`. This is meant to signal the developer that the presence of the object in the flash session storage is not guaranteed on every request. | ||
|
||
## Acknowledgements | ||
|
||
## License | ||
|
||
Licensed under [MIT](./LICENSE).<br/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const utils = require('./utils') | ||
|
||
module.exports = function () { | ||
return { | ||
/** | ||
* @name flash | ||
* @description Set a flash message | ||
* @param {string} scope | ||
* @param {any} value | ||
*/ | ||
setter (scope, value) { | ||
if (!this.session) { | ||
throw new Error('Session not found, make sure to register @fastify/secure-session') | ||
} | ||
|
||
if (typeof scope !== 'string') { | ||
throw new Error('Expected scope to be a string') | ||
} | ||
|
||
// in this way we are a drop in replacement for @fastify/flash | ||
let currentSession = this.session.get('flash') | ||
if (!currentSession) { | ||
currentSession = {} | ||
} | ||
|
||
utils.attachThingToObjectGivenPath(scope, currentSession, value) | ||
|
||
this.session.set('flash', currentSession) | ||
}, | ||
getter (scope) { | ||
if (!this.request.session) { | ||
throw new Error('Session not found, make sure to register @fastify/secure-session') | ||
} | ||
|
||
if (typeof scope !== 'string') { | ||
throw new Error('Expected scope to be a string') | ||
} | ||
|
||
const currentSession = this.request.session.get('flash') | ||
if (!currentSession) { | ||
return undefined | ||
} | ||
|
||
const output = utils.retriveThingFromObjectGivenPath(scope, currentSession) | ||
utils.deleteThingFromObjectGivenPath(scope, currentSession) | ||
|
||
this.request.session.set('flash', currentSession) | ||
return output | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import './module.d' | ||
import { FastifyPluginCallback } from 'fastify' | ||
import { FlashSessionType } from 'fastify-better-flash' | ||
|
||
declare module 'fastify' { | ||
export interface FastifyRequest { | ||
flash: <PathType extends Path<FlashSessionType>>(scope: PathType, message: PathToValue<FlashSessionType, PathType>) => void | ||
} | ||
export interface FastifyReply { | ||
flash: <PathType extends Path<FlashSessionType>>(scope: PathType) => PathToValue<FlashSessionType, PathType> | undefined | ||
} | ||
} | ||
|
||
export type Path<T = unknown> = T extends object | ||
? T extends Array<infer ItemType> | ||
? ItemType extends object ? `${number}` | `${number}.${Path<ItemType>}` : `${number}` | ||
: { [K in keyof T]: T[K] extends object ? `${K & string}` | `${K & string}.${Path<T[K]>}` : `${K & string}` }[keyof T] | ||
: string | ||
|
||
export type PathToValue<T = unknown, P extends Path<T> = Path<T>> = | ||
T extends object | ||
? P extends keyof T | ||
? T[P] | ||
: P extends `${infer Key}.${infer Rest}` | ||
? Key extends keyof T | ||
? Rest extends Path<T[Key]> | ||
? PathToValue<T[Key], Rest> | ||
: never | ||
: T extends Array<infer ItemType> | ||
? Rest extends Path<ItemType> | ||
? PathToValue<ItemType, Rest> | ||
: never | ||
: never | ||
: P extends `${number}` | ||
? T extends Array<infer ItemType> | ||
? ItemType | ||
: never | ||
: never | ||
: any | ||
|
||
declare const betterflash: FastifyPluginCallback<() => string> | ||
export default betterflash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
'use strict' | ||
|
||
const fp = require('fastify-plugin') | ||
|
||
module.exports = fp(function (fastify, opts, done) { | ||
const flash = require('./flash')() | ||
fastify.decorateRequest('flash', flash.setter) | ||
fastify.decorateReply('flash', flash.getter) | ||
done() | ||
}, { | ||
fastify: '^4.x', | ||
name: 'fastify-better-flash', | ||
decorators: { | ||
request: ['session'] | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
declare module 'fastify-better-flash' { | ||
// eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
export interface FlashSessionType {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"name": "fastify-better-flash", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"scripts": { | ||
"test": "npm run lint && npm run unit && npm run test:typescript", | ||
"lint": "standard && npm run lint:typescript", | ||
"lint:typescript": "ts-standard", | ||
"test:typescript": "tsd", | ||
"unit": "node --test" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "MIT", | ||
"types": "index.d.ts", | ||
"dependencies": { | ||
"fastify-plugin": "^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.4.4", | ||
"fastify": "^4.0.0-rc.2", | ||
"fastify-tsconfig": "^2.0.0", | ||
"prettier": "^3.2.5", | ||
"standard": "^17.0.0", | ||
"ts-standard": "^12.0.1", | ||
"tsd": "^0.30.4", | ||
"typescript": "^5.3.3", | ||
"@fastify/secure-session": "^7.0.0" | ||
}, | ||
"tsd": { | ||
"directory": "test" | ||
} | ||
} |
Oops, something went wrong.