diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cea7e32..e353146 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,6 +2,8 @@ name: Bedrock Node.js CI on: [push] +permissions: {} + jobs: lint: runs-on: ubuntu-latest @@ -10,25 +12,28 @@ jobs: matrix: node-version: [24.x] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + with: + persist-credentials: false - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} - run: npm install - name: Run eslint run: npm run lint test-node: - needs: [lint] runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: - node-version: [22.x, 24.x] + node-version: [20.x, 22.x, 24.x] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + with: + persist-credentials: false - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} - run: | @@ -40,16 +45,17 @@ jobs: cd test npm test coverage: - needs: [test-node] runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: node-version: [24.x] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + with: + persist-credentials: false - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} - run: | @@ -61,9 +67,8 @@ jobs: cd test npm run coverage-ci - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: - file: ./test/coverage/lcov.info + files: ./test/coverage/lcov.info fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} - diff --git a/CHANGELOG.md b/CHANGELOG.md index 114c4b3..63c1ed9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # bedrock-express ChangeLog +## 8.6.0 - 2026-04-xx + +### Changed +- **BREAKING**: Update dependencies: + - `@fastify/express@4` + - `body-parser@2` + - `fastify@5` +- Update minor dependencies. +- Update peer minor dependencies: +- Update test dependencies. +- **NOTE**: Update supported platforms. + - Test on Node.js >=20. + - Update `engines.node` to `>=20`. + - Update README requirements section. + ## 8.5.2 - 2025-12-16 ### Fixed diff --git a/README.md b/README.md index d965a87..6b6d7cd 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,10 @@ server. ## Requirements -- node v18+ -- npm v9+ +This software requires and supports maintained recent versions of Node.js. +Updates may remove support for older unmaintained platform versions. Please use +dependency version lock files and testing to ensure compatibility with this +software. ## Quick Examples diff --git a/.eslintrc.cjs b/eslint.config.js similarity index 67% rename from .eslintrc.cjs rename to eslint.config.js index 42fd928..42b4cfe 100644 --- a/.eslintrc.cjs +++ b/eslint.config.js @@ -1,5 +1,5 @@ /*! - * Copyright 2022 - 2024 Digital Bazaar, Inc. + * Copyright 2022 - 2026 Digital Bazaar, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -module.exports = { - root: true, - parserOptions: { - // this is required for dynamic import() - ecmaVersion: 2020 - }, - env: { - node: true - }, - extends: ['digitalbazaar', 'digitalbazaar/jsdoc'], - ignorePatterns: ['node_modules/'] -}; +import config from '@digitalbazaar/eslint-config/node-recommended'; + +export default [ + ...config +]; diff --git a/package.json b/package.json index c633205..882d2bf 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,14 @@ "description": "Bedrock express module", "license": "Apache-2.0", "main": "./lib/index.js", + "files": [ + ".reuse/dep5", + "LICENSES/**/*.txt", + "lib/**/*.js" + ], "scripts": { - "test": "node test.js", - "lint": "eslint ." + "test": "cd test && npm run test", + "lint": "eslint" }, "repository": { "type": "git", @@ -27,32 +32,30 @@ }, "homepage": "https://github.com/digitalbazaar/bedrock-express", "dependencies": { - "@fastify/express": "^3.0.0", - "body-parser": "^1.20.3", + "@fastify/express": "^4.0.4", + "body-parser": "^2.2.2", "compression": "^1.8.1", "cookie-parser": "^1.4.7", - "cors": "^2.8.5", - "errorhandler": "^1.5.1", - "express": "^4.21.2", - "express-session": "^1.18.2", - "fastify": "^4.29.1", + "cors": "^2.8.6", + "errorhandler": "^1.5.2", + "express": "^4.22.1", + "express-session": "^1.19.0", + "fastify": "^5.8.4", "method-override": "^3.0.0", "morgan": "^1.10.1" }, "peerDependencies": { - "@bedrock/core": "^6.0.0", - "@bedrock/server": "^5.0.0" + "@bedrock/core": "^6.3.0", + "@bedrock/server": "^5.1.0" }, "directories": { "lib": "./lib" }, "devDependencies": { - "eslint": "^8.57.0", - "eslint-config-digitalbazaar": "^5.2.0", - "eslint-plugin-jsdoc": "^48.5.0", - "jsdoc-to-markdown": "^8.0.1" + "@digitalbazaar/eslint-config": "^8.0.1", + "eslint": "^9.39.4" }, "engines": { - "node": ">=18" + "node": ">=20" } } diff --git a/test/mocha/.eslintrc.cjs b/test/mocha/.eslintrc.cjs deleted file mode 100644 index d757148..0000000 --- a/test/mocha/.eslintrc.cjs +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - env: { - mocha: true - }, - globals: { - assertNoError: true, - should: true - } -}; diff --git a/test/mocha/01-api.js b/test/mocha/01-api.js index 94bd680..39e8c0f 100644 --- a/test/mocha/01-api.js +++ b/test/mocha/01-api.js @@ -17,13 +17,11 @@ */ import {agent} from '@bedrock/https-agent'; -import {fileURLToPath} from 'node:url'; import fs from 'node:fs'; import {httpClient} from '@digitalbazaar/http-client'; import path from 'node:path'; const {readFile} = fs.promises; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); describe('configured routes', () => { const BASE_URL = `https://localhost:18443`; @@ -106,7 +104,7 @@ describe('configured routes', () => { let err; try { res = await httpClient.get(`${BASE_URL}/static/foo`, { - agent, + agent }); } catch(e) { err = e; @@ -115,7 +113,7 @@ describe('configured routes', () => { should.not.exist(err); res.status.should.equal(200); const body = await res.text(); - const filepath = path.join(__dirname, '..', 'static', 'foo.html'); + const filepath = path.join(import.meta.dirname, '..', 'static', 'foo.html'); const content = await readFile(filepath, 'utf-8'); body.should.equal(content); }); @@ -126,7 +124,7 @@ describe('configured routes', () => { let err; try { res = await httpClient.get(`${BASE_URL}/static/bar.html`, { - agent, + agent }); } catch(e) { err = e; @@ -135,7 +133,8 @@ describe('configured routes', () => { should.not.exist(err); res.status.should.equal(200); const body = await res.text(); - const filepath = path.join(__dirname, '..', 'static', 'bar.html'); + const filepath = path.join( + import.meta.dirname, '..', 'static', 'bar.html'); const content = await readFile(filepath, 'utf-8'); body.should.equal(content); }); @@ -146,7 +145,7 @@ describe('configured routes', () => { let err; try { res = await httpClient.get(`${BASE_URL}/bar.html`, { - agent, + agent }); } catch(e) { err = e; @@ -155,7 +154,8 @@ describe('configured routes', () => { should.not.exist(err); res.status.should.equal(200); const body = await res.text(); - const filepath = path.join(__dirname, '..', 'static', 'bar.html'); + const filepath = path.join( + import.meta.dirname, '..', 'static', 'bar.html'); const content = await readFile(filepath, 'utf-8'); body.should.equal(content); }); @@ -165,7 +165,7 @@ describe('configured routes', () => { let err; try { res = await httpClient.get(`${BASE_URL}/baz.html`, { - agent, + agent }); } catch(e) { err = e; @@ -181,7 +181,7 @@ describe('configured routes', () => { let err; try { res = await httpClient.get(`${BASE_URL}/static/baz.html`, { - agent, + agent }); } catch(e) { err = e; diff --git a/test/package.json b/test/package.json index ec76060..df536b9 100644 --- a/test/package.json +++ b/test/package.json @@ -10,14 +10,14 @@ "coverage-report": "c8 report" }, "dependencies": { - "@digitalbazaar/http-client": "^3.0.0", - "@bedrock/core": "^6.0.0", + "@digitalbazaar/http-client": "^4.3.0", + "@bedrock/core": "^6.3.0", "@bedrock/express": "file:..", - "@bedrock/https-agent": "^4.0.0", - "@bedrock/server": "^5.0.0", - "@bedrock/test": "^8.0.0", - "c8": "^7.11.0", - "cross-env": "^7.0.3" + "@bedrock/https-agent": "^4.1.0", + "@bedrock/server": "^5.1.0", + "@bedrock/test": "^9.0.0", + "c8": "^11.0.0", + "cross-env": "^10.1.0" }, "c8": { "excludeNodeModules": false, diff --git a/test/test.config.js b/test/test.config.js index b38792f..9cccece 100644 --- a/test/test.config.js +++ b/test/test.config.js @@ -16,12 +16,9 @@ * SPDX-License-Identifier: Apache-2.0 */ import {config} from '@bedrock/core'; -import {fileURLToPath} from 'url'; -import path from 'path'; +import path from 'node:path'; import '@bedrock/https-agent'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - // set this to false to ignore SSL errors in development config['https-agent'].rejectUnauthorized = false; @@ -57,4 +54,4 @@ config.express.bodyParser.routes['/json-size-limit/any/101kb/*'] = { } }; -config.mocha.tests.push(path.join(__dirname, 'mocha')); +config.mocha.tests.push(path.join(import.meta.dirname, 'mocha')); diff --git a/test/test.js b/test/test.js index 65fe084..2600b56 100644 --- a/test/test.js +++ b/test/test.js @@ -17,37 +17,35 @@ */ import * as bedrock from '@bedrock/core'; import {asyncHandler, middleware} from '@bedrock/express'; -import {fileURLToPath} from 'url'; -import path from 'path'; +import path from 'node:path'; import '@bedrock/https-agent'; const {acceptableContent} = middleware; const {util: {BedrockError}} = bedrock; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); bedrock.events.on('bedrock-express.configure.static', () => { bedrock.config.express.static.push({ route: '/static/foo', - path: path.join(__dirname, 'static', 'foo.html'), + path: path.join(import.meta.dirname, 'static', 'foo.html'), file: true, - cors: true, + cors: true }); bedrock.config.express.static.push({ route: '/static', - path: path.join(__dirname, 'static'), + path: path.join(import.meta.dirname, 'static'), cors: { exposedHeaders: ['Date', 'Location', 'Content-Length'] - }, + } }); bedrock.config.express.static.push({ route: '/static', - path: path.join(__dirname, 'static', 'baz.html'), + path: path.join(import.meta.dirname, 'static', 'baz.html'), cors: { exposedHeaders: ['Date', 'Location', 'Content-Length'] - }, + } }); bedrock.config.express.static.push( - path.join(__dirname, 'static')); + path.join(import.meta.dirname, 'static')); }); bedrock.events.on('bedrock-express.configure.routes', app => { @@ -58,13 +56,13 @@ bedrock.events.on('bedrock-express.configure.routes', app => { app.get('/permission-denied-error', asyncHandler(async (req, res) => { throw new BedrockError('Permission denied.', 'PermissionDenied', { public: true, - httpStatusCode: 403, + httpStatusCode: 403 }); })); // eslint-disable-next-line no-unused-vars app.get('/not-found-error', asyncHandler(async (req, res) => { throw new BedrockError('Not Found.', 'NotFound', { - public: true, + public: true }); })); // eslint-disable-next-line no-unused-vars @@ -74,7 +72,7 @@ bedrock.events.on('bedrock-express.configure.routes', app => { // eslint-disable-next-line no-unused-vars app.get('/unhandled-error', asyncHandler(async (req, res) => { const err = new BedrockError('Not Found.', 'NotFound', { - public: true, + public: true }); err.status = 404; throw err;