From 6e4ef80b0a8bdeff0f039936200d6972a2cff359 Mon Sep 17 00:00:00 2001 From: Tony133 Date: Thu, 13 Aug 2026 12:39:12 +0200 Subject: [PATCH 1/5] feat!: switch to ESM and native TypeScript type-stripping - rewrite src/index.ts to use `export default` / `import` instead of TS-specific `export =` / `import = require()` - update tsconfig.json for `module: nodenext`, `verbatimModuleSyntax`, `erasableSyntaxOnly`, `allowImportingTsExtensions`, `rewriteRelativeImportExtensions` - add explicit `.ts` extensions to relative imports - replace `__dirname` with `import.meta.dirname` in tests - set "type": "module" in package.json, add "exports" map - bump engines to require Node >=20.19.0 <21 || >=22.12.0 (needed for require(esm) interop with CJS consumers) BREAKING CHANGE: this package is now ESM-only. CJS consumers can still `require()` it thanks to Node's require(esm) support (stable since Node 20.19.0 / 22.12.0); older Node versions are no longer supported. --- eslint.config.js => eslint.config.cjs | 0 package.json | 14 ++++++++++++-- src/index.ts | 7 +++---- test/index.test.ts | 8 ++++---- tsconfig.json | 10 +++++++--- 5 files changed, 26 insertions(+), 13 deletions(-) rename eslint.config.js => eslint.config.cjs (100%) diff --git a/eslint.config.js b/eslint.config.cjs similarity index 100% rename from eslint.config.js rename to eslint.config.cjs diff --git a/package.json b/package.json index e5553c5..5856e66 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,15 @@ "name": "@fastify/flash", "version": "6.0.4", "description": "Flash message plugin for fastify.", - "main": "./lib", - "type": "commonjs", + "type": "module", + "main": "./lib/index.js", + "types": "./lib/index.d.ts", + "exports": { + ".": { + "types": "./lib/index.d.ts", + "default": "./lib/index.js" + } + }, "scripts": { "build": "npm run clean-build && npm run lint && tsc -p ./tsconfig.build.json", "clean-build": "rimraf ./lib && mkdir lib", @@ -72,5 +79,8 @@ ], "publishConfig": { "access": "public" + }, + "engines": { + "node": ">=20.19.0 <21 || >=22.12.0" } } diff --git a/src/index.ts b/src/index.ts index e7047c0..7d020f5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ -import fp = require('fastify-plugin') -import { flashFactory } from './flash' +import fp from 'fastify-plugin' +import { flashFactory } from './flash.ts' import '@fastify/secure-session' declare module 'fastify' { @@ -11,10 +11,9 @@ declare module 'fastify' { } } -export = fp<{ core?: string }>( +export default fp<{ core?: string }>( function (fastify, _opts, done) { const flash = flashFactory() - fastify.decorateRequest('flash', flash.request) fastify.decorateReply('flash', flash.reply) done() diff --git a/test/index.test.ts b/test/index.test.ts index d3c8766..20ea418 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,12 +1,12 @@ -import { test, TestContext } from 'node:test' +import { test, type TestContext } from 'node:test' import { join } from 'node:path' import { readFileSync } from 'node:fs' import Fastify from 'fastify' -import fastifySession, { Session, SessionData } from '@fastify/secure-session' +import fastifySession, { type Session, type SessionData } from '@fastify/secure-session' import querystring from 'node:querystring' -import fastifyFlash from '../src' +import fastifyFlash from '../src/index.ts' -const key = readFileSync(join(__dirname, '..', '..', 'secret-key')) +const key = readFileSync(join(import.meta.dirname, '..', '..', 'secret-key')) test('should set error message and and clear up after displaying.', async (t: TestContext) => { t.plan(5) diff --git a/tsconfig.json b/tsconfig.json index ed79f80..fde3b51 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,13 @@ { "compilerOptions": { - "moduleResolution": "node16", + "target": "esnext", + "module": "nodenext", + "moduleResolution": "nodenext", + "allowImportingTsExtensions": true, + "rewriteRelativeImportExtensions": true, + "verbatimModuleSyntax": true, + "erasableSyntaxOnly": true, "declaration": true, - "target": "es2022", - "module": "node16", "outDir": "lib", "pretty": true, "noEmitOnError": true, From af1000c51a3f1e45967ca8e649b2707436de7834 Mon Sep 17 00:00:00 2001 From: Tony133 Date: Thu, 13 Aug 2026 13:09:41 +0200 Subject: [PATCH 2/5] docs: update README.md --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.md b/README.md index 6e3f0a1..3310e48 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,50 @@ This plugin is inspired by [connect-flash](https://github.com/jaredhanson/connec npm i @fastify/flash ``` +> **Note:** this package is ESM-only starting from v7. It can still be `require()`'d from CommonJS thanks to Node's native `require(esm)` support (stable since Node 20.19.0/22.12.0). See [engines](package.json) for the minimum supported Node.js version. + ## 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). +### ESM + +```javascript +import { readFileSync } from 'node:fs' +import { join } from 'node:path' +import Fastify from 'fastify' +import fastifySession from '@fastify/secure-session' +import fastifyFlash from '@fastify/flash' + +const fastify = Fastify() + +fastify.register(fastifySession, { + // adapt this to point to the directory where secret-key is located + key: readFileSync(join(import.meta.dirname, 'secret-key')), + cookie: { + // options from setCookie, see https://github.com/fastify/fastify-cookie + path: "/" + } +}) +fastify.register(fastifyFlash, { + prefix: "/" +}) + +fastify.get('/test', (req, reply) => { + req.flash('warning', ['username required', 'password required']) + + const warning = reply.flash('warning') + reply.send({ warning }) // {"warning":["username required","password required"]} +}) +``` + +### CommonJS + +Even though this package ships as ESM, it can still be `require()`'d from a CommonJS project (see the [Install](#install) note above): + ```javascript +const fs = require('node:fs') +const path = require('node:path') const fastify = require('fastify')() const fastifySession = require('@fastify/secure-session') const fastifyFlash = require('@fastify/flash') From 6c2b2e3c967ec88cff4d91c997cd0d4b1b57dab5 Mon Sep 17 00:00:00 2001 From: Tony133 Date: Thu, 13 Aug 2026 18:13:41 +0200 Subject: [PATCH 3/5] chore: upgrade borp v1.x and update ci --- .github/workflows/ci.yml | 2 ++ package.json | 2 +- test/index.test.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31bfa26..ca83751 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,5 +29,7 @@ jobs: pull-requests: write uses: fastify/workflows/.github/workflows/plugins-ci.yml@ef591e2186785d5ab36b9fe6a79c7ce2f1d94e57 # v7.0.0 with: + node-versions: '["22","24", "26"]' license-check: true lint: true + diff --git a/package.json b/package.json index 5856e66..7b7a9fc 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@fastify/secure-session": "^8.0.0", "@types/node": "^26.0.0", - "borp": "^0.21.0", + "borp": "^1.0.0", "eslint": "^9.35.0", "fastify": "^5.0.0", "neostandard": "^0.13.0", diff --git a/test/index.test.ts b/test/index.test.ts index 20ea418..6994191 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -6,7 +6,7 @@ import fastifySession, { type Session, type SessionData } from '@fastify/secure- import querystring from 'node:querystring' import fastifyFlash from '../src/index.ts' -const key = readFileSync(join(import.meta.dirname, '..', '..', 'secret-key')) +const key = readFileSync(join(import.meta.dirname, '..', 'secret-key')) test('should set error message and and clear up after displaying.', async (t: TestContext) => { t.plan(5) From 7b9ea1647ea428b11443d35ab6dae448f677498a Mon Sep 17 00:00:00 2001 From: Tony133 Date: Sat, 15 Aug 2026 10:33:15 +0200 Subject: [PATCH 4/5] docs: update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 3310e48..1278556 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,6 @@ This plugin is inspired by [connect-flash](https://github.com/jaredhanson/connec npm i @fastify/flash ``` -> **Note:** this package is ESM-only starting from v7. It can still be `require()`'d from CommonJS thanks to Node's native `require(esm)` support (stable since Node 20.19.0/22.12.0). See [engines](package.json) for the minimum supported Node.js version. - ## 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). From e4fe4550f8b5d91c999a0fb2e6dd76cb17b62a0e Mon Sep 17 00:00:00 2001 From: Tony133 Date: Sat, 15 Aug 2026 10:34:42 +0200 Subject: [PATCH 5/5] ci: update indentation --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca83751..6454bd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: pull-requests: write uses: fastify/workflows/.github/workflows/plugins-ci.yml@ef591e2186785d5ab36b9fe6a79c7ce2f1d94e57 # v7.0.0 with: - node-versions: '["22","24", "26"]' + node-versions: '["22", "24", "26"]' license-check: true lint: true