From 557ffff075a29def2a0a6cbc20521706b703f2ee Mon Sep 17 00:00:00 2001 From: Cristian Cepeda <43882+pastuxso@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:06:58 -0500 Subject: [PATCH] Bump to Node v20.17.0 (#1696) * Bump to NodeJS v20.17.0 * Node modules cleanup * Code cleanup --- .github/workflows/test.yml | 3 ++ .nvmrc | 2 +- .tool-versions | 2 +- .vscode/launch.json | 6 +-- CONTRIBUTING.md | 20 ++++---- package-lock.json | 3 ++ package.json | 3 +- specifier-node.mjs | 78 ++++++++++++++++++++++++++++++++ specifier-register.mjs | 4 ++ tests/e2e/package-lock.json | 7 +-- tests/e2e/specifier-node.mjs | 1 + tests/e2e/specifier-register.mjs | 1 + tests/e2e/tsconfig.json | 6 ++- tsconfig.json | 11 +++-- 14 files changed, 125 insertions(+), 22 deletions(-) create mode 100644 specifier-node.mjs create mode 100644 specifier-register.mjs create mode 120000 tests/e2e/specifier-node.mjs create mode 120000 tests/e2e/specifier-register.mjs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bd2f4c376..008a46c12 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,6 +20,9 @@ jobs: DO_NOT_TRACK: 1 steps: - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20.17.0" - name: Install xvfb run: sudo apt-get update -y && sudo apt-get install xvfb - name: 👷 Install Dependencies diff --git a/.nvmrc b/.nvmrc index eb800ed45..016e34baf 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18.19.0 +v20.17.0 diff --git a/.tool-versions b/.tool-versions index 8f95919df..ffb152ed4 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -nodejs 18.20.2 +nodejs 20.17.0 diff --git a/.vscode/launch.json b/.vscode/launch.json index 37d174957..e6cc62288 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -64,7 +64,7 @@ "smartStep": true, "console": "integratedTerminal", "env": { - "NODE_OPTIONS": "--experimental-specifier-resolution=node" + "NODE_OPTIONS": "--import=./specifier-register.mjs" }, }, { @@ -86,8 +86,8 @@ "/**/*.js" ], "env": { - "NODE_OPTIONS": "--experimental-specifier-resolution=node" + "NODE_OPTIONS": "--import=./specifier-register.mjs" }, } ] -} \ No newline at end of file +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index edb5d5755..e04a983d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -144,14 +144,14 @@ To run the extension in a new Extension Development Host window of VS Code open To compile all extension files, run: ```sh {"id":"01HF7VQMH8ESX1EFV4PDNTDPTS","name":"build","promptEnv":"no"} -export NODE_OPTIONS="--experimental-specifier-resolution=node --max-old-space-size=8192" +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" npm run build ``` And then package the extension into a .vsix file: ```sh {"id":"01J04FQ8WSEVTDVS05VPZMKAYJ","name":"bundle","promptEnv":"no"} -export NODE_OPTIONS="--experimental-specifier-resolution=node --max-old-space-size=8192" +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" npm run bundle ``` @@ -160,19 +160,19 @@ npm run bundle The Runme project has several test stages that you can run individually or as a whole: ```sh {"id":"01HF7VQMH8ESX1EFV4PFZ87Q58","name":"test","promptEnv":"no"} -export NODE_OPTIONS="--experimental-specifier-resolution=node --max-old-space-size=8192" +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" npx runme run test:format test:lint test:unit test:e2e ``` -```sh {"id":"01J5VPD3TXY1EAZDCXNHN60S77","promptEnv":"no"} -export NODE_OPTIONS="--experimental-specifier-resolution=node --max-old-space-size=8192" +```sh {"id":"01J5VPD3TXY1EAZDCXNHN60S77"} +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" npx runme run test:format test:lint test:unit ``` When testing in CI environment, run: ```sh {"id":"01HF7VQMH8ESX1EFV4PGJBDGG0","name":"test:ci","promptEnv":"no"} -export NODE_OPTIONS="--experimental-specifier-resolution=node --max-old-space-size=8192" +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" npx runme run test:format test:lint test:unit test:e2e:ci ``` @@ -211,7 +211,7 @@ We use [Vitest](https://vitest.dev/) for running unit tests via: In case you experience a "Cannot find module '@buf/stateful'" error, it's probably caused because of a nvm cache issue, you can try clearing removing node_modules and reinstalling the dependencies. In case the issue persists, do a fresh clone of the repository. The issue is probably caused by nvm caching the wrong version of the package. ```sh {"id":"01HF7VQMH8ESX1EFV4PT2KN303","name":"test:unit","promptEnv":"no"} -export NODE_OPTIONS="--experimental-specifier-resolution=node --max-old-space-size=8192" +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" npx vitest -c ./vitest.conf.ts --run ``` @@ -226,6 +226,7 @@ open coverage/lcov-report/index.html We use WebdriverIO to run e2e tests on the VS Code extension: ```sh {"id":"01HF7VQMH8ESX1EFV4PX19FXW0","name":"test:e2e"} +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" npx wdio run ./tests/e2e/wdio.conf.ts ``` @@ -236,6 +237,7 @@ The process for testing in CI is a bit more complicated as we try to test closer Therefore to test in a closer production environment, run: ```sh {"id":"01HF7VQMH8ESX1EFV4PYWC0M3X","name":"test:e2e:ci"} +export NODE_OPTIONS="--import=./specifier-register.mjs --max-old-space-size=8192" # run reconcile command when previous commands pass or fail npx runme run test:e2e:ci:setup test:e2e:ci:run; npx runme run test:e2e:ci:reconcile ``` @@ -249,7 +251,7 @@ mv ./node_modules/ ./.node_modules mv ./package.json ./.package.json mv ./package-lock.json ./.package-lock.json # then install runme again -RUNME_DOWNLOAD_ON_INSTALL=1 npm i runme +RUNME_DOWNLOAD_ON_INSTALL=1 NODE_OPTIONS='' npm i runme || true # restore package.json to allow testing the extension mv ./.package.json ./package.json ``` @@ -260,7 +262,7 @@ Then we can run the e2e tests via: ```sh {"id":"01HF7VQMH8ESX1EFV4Q3XXMMX7","name":"test:e2e:ci:run"} cd ./tests/e2e/ -npm ci +NODE_OPTIONS='' npm ci npx wdio run ./wdio.conf.ts ``` diff --git a/package-lock.json b/package-lock.json index 141bd1b2f..d4cf813dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -106,6 +106,7 @@ "webpack-cli": "^5.1.4" }, "engines": { + "node": ">=20.17.0", "vscode": "^1.78.0" } }, @@ -15705,6 +15706,7 @@ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -21023,6 +21025,7 @@ "integrity": "sha512-T6Yow94Z3uSJAWcESv3Pa0SLSzctPm/5qgXIgBq6N43/zgLQbgXwv9A9evkgvhdh7xSwpFOAdyfWo+rsAWRp/A==", "dev": true, "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "@actions/exec": "^1.1.1", "get-port": "^7.0.0", diff --git a/package.json b/package.json index 2a2af161b..d4c517cc8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ }, "private": true, "engines": { - "vscode": "^1.78.0" + "vscode": "^1.78.0", + "node": ">=20.17.0" }, "galleryBanner": { "color": "#0D003D", diff --git a/specifier-node.mjs b/specifier-node.mjs new file mode 100644 index 000000000..ee5e844f1 --- /dev/null +++ b/specifier-node.mjs @@ -0,0 +1,78 @@ +import {dirname, isAbsolute, join, extname} from 'node:path' +import {cwd} from 'node:process' +import {readFile} from 'node:fs/promises' + + +let warn = (field, desc) => console.warn('⚠️ \x1b[33m%s\x1b[0m', + `Warning: The package.json field 'extensionless.${field}' must be ${desc}! Using the default value instead...`) + +let getPkgJson = async dirPath => { + do { + let path = join(dirPath, 'package.json') + + try { + return {body: JSON.parse(await readFile(path, 'utf8')), path} + } catch (e) { + if (!['ENOTDIR', 'ENOENT', 'EISDIR'].includes(e.code)) { + throw new Error('Cannot retrieve package.json', {cause: e}) + } + } + } while (dirPath !== (dirPath = dirname(dirPath))) +} + +export async function getConfig({argv1 = ''} = {}) { + let defaults = { + lookFor: ['js'] + }, dirPath = isAbsolute(argv1) ? argv1 : cwd(), { + lookFor + } = {...defaults, ...(await getPkgJson(dirPath))?.body.extensionless} + + Array.isArray(lookFor) && lookFor.length && lookFor.every(a => typeof a === 'string' && /^[a-z]\w*$/i.test(a)) || ( + lookFor = defaults.lookFor, warn('lookFor', 'an array of alphanumeric strings') + ) + + return {lookFor} +} + + +let initPromise +export function globalPreload({port}) { + port.onmessage = e => initPromise = initialize({argv1: e.data}) + + return 'port.postMessage(process.argv[1])' +} + +let indexFiles, candidates +export async function initialize(data) { + let {lookFor} = await getConfig(data) + + indexFiles = [lookFor.map(e => `index.${e}`), ['index.json']] + candidates = indexFiles.map(i => i.map(f => extname(f)).concat(i.map(f => `/${f}`))) +} + +let winAbsPath = /^[/\\]?[a-z]:[/\\]/i, relSpecs = ['.', '..'] +let specStarts = ['./', '../', '/', 'file://', 'https://', '.\\', '..\\', '\\'] +let knownExts = ['.js', '.cjs', '.mjs', '.json', '.node', '.wasm'], empty = [[], []] + +export async function resolve(specifier, context, nextResolve) { + let error, prefix = winAbsPath.test(specifier) ? 'file://' : '' + + if (!prefix && !relSpecs.includes(specifier) && !specStarts.some(s => specifier.startsWith(s))) { + try {return await nextResolve(specifier)} catch (e) {error = e} + } + + let {type} = context.importAttributes ?? context.importAssertions + let trySpec = error ? specifier : new URL(prefix + specifier, context.parentURL).href + let postfixes = (await initPromise, trySpec.endsWith('/') ? + indexFiles : knownExts.includes(extname(trySpec)) ? empty : candidates) + + for (let postfix of postfixes[+(type === 'json')]) { + try {return await nextResolve(trySpec + postfix)} catch {} + } + + if (error) { + throw error + } + + return await nextResolve(trySpec) +} diff --git a/specifier-register.mjs b/specifier-register.mjs new file mode 100644 index 000000000..3cc7f38ac --- /dev/null +++ b/specifier-register.mjs @@ -0,0 +1,4 @@ +import {register} from 'node:module' +import {argv} from 'node:process' + +register('./specifier-node.mjs', import.meta.url, {data: {argv1: argv[1]}}) diff --git a/tests/e2e/package-lock.json b/tests/e2e/package-lock.json index 418db8083..0baf0aa0f 100644 --- a/tests/e2e/package-lock.json +++ b/tests/e2e/package-lock.json @@ -4556,9 +4556,10 @@ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, "node_modules/import-meta-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", - "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" diff --git a/tests/e2e/specifier-node.mjs b/tests/e2e/specifier-node.mjs new file mode 120000 index 000000000..a52688149 --- /dev/null +++ b/tests/e2e/specifier-node.mjs @@ -0,0 +1 @@ +../../specifier-node.mjs \ No newline at end of file diff --git a/tests/e2e/specifier-register.mjs b/tests/e2e/specifier-register.mjs new file mode 120000 index 000000000..c59ffae6d --- /dev/null +++ b/tests/e2e/specifier-register.mjs @@ -0,0 +1 @@ +../../specifier-register.mjs \ No newline at end of file diff --git a/tests/e2e/tsconfig.json b/tests/e2e/tsconfig.json index a287168df..5ec090fd1 100644 --- a/tests/e2e/tsconfig.json +++ b/tests/e2e/tsconfig.json @@ -14,6 +14,10 @@ ], "target": "es2022" }, - "include": ["specs", "./wdio.conf.ts", "pageobjects"], + "include": [ + "specs", + "./wdio.conf.ts", + "pageobjects" + ], "exclude": [] } diff --git a/tsconfig.json b/tsconfig.json index efad52664..6b8d0f39b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,11 @@ "module": "commonjs", "outDir": "out", "rootDir": "src", - "target": "ES2021", - "lib": ["ES2021", "DOM"], + "target": "es2021", + "lib": [ + "es2021", + "DOM" + ], "moduleResolution": "node", "esModuleInterop": true, "experimentalDecorators": true, @@ -15,6 +18,8 @@ "vscode" ] }, - "include": ["src/"], + "include": [ + "src/" + ], "exclude": [] }