From af71c152c1e1244d13ef7117d7edf6191e47cb9f Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Tue, 5 Aug 2025 15:07:46 +0300 Subject: [PATCH 1/3] Use node: for Node.js builtin modules Use the the `node:` protocol when importing Node.js builtin modules and enable rule in eslint to enforce. The `node:` protocol for Node.js builtin modules has been available since Node.js v14. See: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/enforce-node-protocol-usage.md --- .eslintrc.json | 4 ++++ cypress/plugins/index.ts | 2 +- lint/generate-docs.ts | 4 ++-- lint/src/util/theme-support.ts | 5 +++-- src/app/core/services/server-xhr.service.ts | 9 +++++---- src/backend/api.ts | 2 +- src/config/config.server.ts | 13 +++++++------ .../translate-server.loader.ts | 3 ++- 8 files changed, 25 insertions(+), 17 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index af2342d822..179876e682 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -253,6 +253,10 @@ "forceSingleLine": true } ], + "import/enforce-node-protocol-usage": [ + "error", + "always" + ], "unused-imports/no-unused-imports": "error", "lodash/import-scope": [ diff --git a/cypress/plugins/index.ts b/cypress/plugins/index.ts index 091f11d0f7..16aab015d7 100644 --- a/cypress/plugins/index.ts +++ b/cypress/plugins/index.ts @@ -1,4 +1,4 @@ -const fs = require('fs'); +const fs = require('node:fs'); // These two global variables are used to store information about the REST API used // by these e2e tests. They are filled out prior to running any tests in the before() diff --git a/lint/generate-docs.ts b/lint/generate-docs.ts index fb2bf53fb5..d49e33a44b 100644 --- a/lint/generate-docs.ts +++ b/lint/generate-docs.ts @@ -12,8 +12,8 @@ import { readFileSync, rmSync, writeFileSync, -} from 'fs'; -import { join } from 'path'; +} from 'node:fs'; +import { join } from 'node:path'; import { default as htmlPlugin } from './src/rules/html'; import { default as tsPlugin } from './src/rules/ts'; diff --git a/lint/src/util/theme-support.ts b/lint/src/util/theme-support.ts index 7bc680b930..5be6554020 100644 --- a/lint/src/util/theme-support.ts +++ b/lint/src/util/theme-support.ts @@ -6,10 +6,11 @@ * http://www.dspace.org/license/ */ +import { readFileSync } from 'node:fs'; +import { basename } from 'node:path'; + import { TSESTree } from '@typescript-eslint/utils'; import { RuleContext } from '@typescript-eslint/utils/ts-eslint'; -import { readFileSync } from 'fs'; -import { basename } from 'path'; import ts, { Identifier } from 'typescript'; import { diff --git a/src/app/core/services/server-xhr.service.ts b/src/app/core/services/server-xhr.service.ts index 4b58c6b127..af59172c7e 100644 --- a/src/app/core/services/server-xhr.service.ts +++ b/src/app/core/services/server-xhr.service.ts @@ -6,13 +6,14 @@ * http://www.dspace.org/license/ */ -import { XhrFactory } from '@angular/common'; -import { Injectable } from '@angular/core'; import { Agent as HttpAgent, AgentOptions as HttpAgentOptions, -} from 'http'; -import { Agent as HttpsAgent } from 'https'; +} from 'node:http'; +import { Agent as HttpsAgent } from 'node:https'; + +import { XhrFactory } from '@angular/common'; +import { Injectable } from '@angular/core'; import { prototype, XMLHttpRequest, diff --git a/src/backend/api.ts b/src/backend/api.ts index b84f06a960..de5ca29e98 100644 --- a/src/backend/api.ts +++ b/src/backend/api.ts @@ -8,7 +8,7 @@ import ITEMS from './data/items.json'; import { fakeDataBase } from './db'; const { Router } = require('express'); -const util = require('util'); +const util = require('node:util'); // you would use cookies/token etc const USER_ID = 'f9d98cf1-1b96-464e-8755-bcc2a5c09077'; // hardcoded as an example diff --git a/src/config/config.server.ts b/src/config/config.server.ts index 3cbce3a42b..4f5a989253 100644 --- a/src/config/config.server.ts +++ b/src/config/config.server.ts @@ -1,16 +1,17 @@ +import { + existsSync, + readFileSync, + writeFileSync, +} from 'node:fs'; +import { join } from 'node:path'; + import { blue, bold, green, red, } from 'colors'; -import { - existsSync, - readFileSync, - writeFileSync, -} from 'fs'; import { load } from 'js-yaml'; -import { join } from 'path'; import { isNotEmpty } from '../app/shared/empty.util'; import { AppConfig } from './app-config.interface'; diff --git a/src/ngx-translate-loaders/translate-server.loader.ts b/src/ngx-translate-loaders/translate-server.loader.ts index e17784ecfb..06312b3a2b 100644 --- a/src/ngx-translate-loaders/translate-server.loader.ts +++ b/src/ngx-translate-loaders/translate-server.loader.ts @@ -1,6 +1,7 @@ +import { readFileSync } from 'node:fs'; + import { TransferState } from '@angular/core'; import { TranslateLoader } from '@ngx-translate/core'; -import { readFileSync } from 'fs'; import { Observable, of, From 2d31afb92f7981bd35e4a236609925c5f2de1a79 Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Tue, 5 Aug 2025 15:13:37 +0300 Subject: [PATCH 2/3] Remove axios dependency We can use the Node.js Fetch API directly instead of relying on an external dependency. --- package-lock.json | 25 +++++++------------------ package.json | 1 - server.ts | 5 ++--- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4284cc4158..29c2e59b04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,6 @@ "@terraformer/wkt": "^2.2.1", "altcha": "^0.9.0", "angulartics2": "^12.2.0", - "axios": "^1.11.0", "bootstrap": "^5.3", "cerialize": "0.1.18", "cli-progress": "^3.12.0", @@ -8472,7 +8471,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/at-least-node": { "version": "1.0.0", @@ -8559,17 +8559,6 @@ "node": ">=4" } }, - "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -9453,6 +9442,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -10712,6 +10702,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -11280,6 +11271,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -12727,6 +12719,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -13176,6 +13169,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -19230,11 +19224,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", diff --git a/package.json b/package.json index 5fc97ee515..d01fe966c2 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,6 @@ "@terraformer/wkt": "^2.2.1", "altcha": "^0.9.0", "angulartics2": "^12.2.0", - "axios": "^1.11.0", "bootstrap": "^5.3", "cerialize": "0.1.18", "cli-progress": "^3.12.0", diff --git a/server.ts b/server.ts index cf21eda6af..a72f1e43b6 100644 --- a/server.ts +++ b/server.ts @@ -25,7 +25,6 @@ import * as ejs from 'ejs'; import * as compression from 'compression'; import expressStaticGzip from 'express-static-gzip'; /* eslint-enable import/no-namespace */ -import axios from 'axios'; import LRU from 'lru-cache'; import { isbot } from 'isbot'; import { createCertificate } from 'pem'; @@ -648,9 +647,9 @@ function isExcludedFromSsr(path: string, excludePathPattern: SsrExcludePatterns[ */ function healthCheck(req, res) { const baseUrl = `${REST_BASE_URL}${environment.actuators.endpointPath}`; - axios.get(baseUrl) + fetch(baseUrl) .then((response) => { - res.status(response.status).send(response.data); + res.status(response.status).send(response); }) .catch((error) => { res.status(error.response.status).send({ From 4d7051007b19d265226d5c4a5bbbe383fe898f56 Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Tue, 5 Aug 2025 16:09:41 +0300 Subject: [PATCH 3/3] Use native Node.js watch instead of nodemon Modern Node.js can watch natively so we don't need nodemon anymore. --- package-lock.json | 116 ---------------------------------------------- package.json | 6 +-- 2 files changed, 2 insertions(+), 120 deletions(-) diff --git a/package-lock.json b/package-lock.json index 29c2e59b04..d64e37ea7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -143,7 +143,6 @@ "karma-mocha-reporter": "2.2.5", "ng-mocks": "^14.13.5", "ngx-mask": "14.2.4", - "nodemon": "^2.0.22", "postcss": "^8.5", "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3", @@ -13539,12 +13538,6 @@ "node": ">= 4" } }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, "node_modules/ignore-walk": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", @@ -17063,73 +17056,6 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, - "node_modules/nodemon": { - "version": "2.0.22", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", - "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "simple-update-notifier": "^1.0.7", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/nopt": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", @@ -19231,12 +19157,6 @@ "dev": true, "optional": true }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -20882,27 +20802,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/simple-update-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", - "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", - "dev": true, - "dependencies": { - "semver": "~7.0.0" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -21756,15 +21655,6 @@ "node": ">=0.6" } }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "dev": true, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, "node_modules/tough-cookie": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", @@ -22132,12 +22022,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", diff --git a/package.json b/package.json index d01fe966c2..2edf2830bb 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,9 @@ "version": "10.0.0-next", "scripts": { "ng": "ng", - "config:watch": "nodemon", "test:rest": "ts-node --project ./tsconfig.ts-node.json scripts/test-rest.ts", "start": "npm run start:prod", - "start:dev": "nodemon --exec \"cross-env NODE_ENV=development npm run serve\"", + "start:dev": "cross-env NODE_ENV=development npm run serve --watch", "start:prod": "npm run build:prod && cross-env NODE_ENV=production npm run serve:ssr", "start:mirador:prod": "npm run build:mirador && npm run start:prod", "preserve": "npm run base-href", @@ -19,7 +18,7 @@ "build:ssr": "ng build --configuration production && ng run dspace-angular:server:production", "build:lint": "rimraf 'lint/dist/**/*.js' 'lint/dist/**/*.js.map' && tsc -b lint/tsconfig.json", "test": "ng test --source-map=true --watch=false --configuration test", - "test:watch": "nodemon --exec \"ng test --source-map=true --watch=true --configuration test\"", + "test:watch": "ng test --source-map=true --watch=true --configuration test", "test:headless": "ng test --source-map=true --watch=false --configuration test --browsers=ChromeHeadless --code-coverage", "test:lint": "npm run build:lint && npm run test:lint:nobuild", "test:lint:nobuild": "jasmine --config=lint/jasmine.json", @@ -225,7 +224,6 @@ "karma-mocha-reporter": "2.2.5", "ng-mocks": "^14.13.5", "ngx-mask": "14.2.4", - "nodemon": "^2.0.22", "postcss": "^8.5", "postcss-import": "^14.0.0", "postcss-loader": "^4.0.3",