Skip to content

Commit 8be1f8d

Browse files
authored
feat!: bump engines to Node.js >=22.12.0 (#312)
1 parent ee6c197 commit 8be1f8d

28 files changed

+2554
-3613
lines changed

.eslintrc.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"parser": "@typescript-eslint/parser",
3+
"extends": [
4+
"eslint:recommended",
5+
"plugin:@typescript-eslint/recommended",
6+
"plugin:import/errors",
7+
"plugin:import/warnings",
8+
"plugin:import/typescript",
9+
"prettier",
10+
"prettier/@typescript-eslint"
11+
],
12+
"rules": {
13+
"@typescript-eslint/prefer-ts-expect-error": 0,
14+
"@typescript-eslint/ban-ts-comment": 0,
15+
"import/no-unresolved": "off"
16+
}
17+
}

.github/workflows/docs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
2626
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # tag: v4.2.0
2727
with:
28-
node-version: lts/*
28+
node-version: 22.12.x
2929
- run: yarn --frozen-lockfile
3030
- run: yarn build:docs
3131
- name: Prepare docs

.github/workflows/release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Setup Node.js
2525
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
2626
with:
27-
node-version: 20.x
27+
node-version: 22.12.x
2828
cache: 'yarn'
2929
- name: Install
3030
run: yarn install --frozen-lockfile

.github/workflows/test.yml

+3-14
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,24 @@ jobs:
1717
strategy:
1818
matrix:
1919
node-version:
20-
- '20.10'
21-
- '18.18'
22-
- '16.20'
23-
- '14.16'
20+
- 22.12.x
2421
os:
2522
- macos-latest
2623
- ubuntu-latest
2724
- windows-latest
2825
runs-on: "${{ matrix.os }}"
2926
steps:
3027
- run: git config --global core.autocrlf input
31-
- name: Install Rosetta
32-
if: ${{ matrix.os == 'macos-latest' && matrix.node-version == '14.16' }}
33-
run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license
3428
- name: Checkout
3529
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3630
- name: Setup Node.js
3731
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
3832
with:
3933
node-version: "${{ matrix.node-version }}"
4034
cache: 'yarn'
41-
architecture: ${{ matrix.os == 'macos-latest' && matrix.node-version == '14.16' && 'x64' || env.RUNNER_ARCH }}
42-
- name: Install (Node.js v16+)
43-
if : ${{ matrix.node-version != '14.16' }}
35+
- name: Install dependencies
4436
run: yarn install --frozen-lockfile
45-
- name: Install (Node.js < v16)
46-
if : ${{ matrix.node-version == '14.16' }}
47-
run: yarn install --frozen-lockfile --ignore-engines
4837
- name: Test
49-
run: yarn test
38+
run: yarn lint && yarn test
5039
- name: Build docs
5140
run: yarn build:docs

.husky/pre-commit

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npx lint-staged

.nvmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22.12

jest.config.js

-7
This file was deleted.

package.json

+26-44
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,63 @@
11
{
22
"name": "@electron/get",
33
"version": "0.0.0-development",
4+
"type": "module",
5+
"exports": "./dist/index.js",
46
"description": "Utility for downloading artifacts from different versions of Electron",
5-
"main": "dist/cjs/index.js",
6-
"module": "dist/esm/index.js",
77
"repository": "https://github.com/electron/get",
88
"author": "Samuel Attard",
99
"license": "MIT",
1010
"publishConfig": {
1111
"provenance": true
1212
},
1313
"scripts": {
14-
"build": "tsc && tsc -p tsconfig.esm.json",
14+
"build": "tsc",
1515
"build:docs": "npx typedoc",
1616
"eslint": "eslint --ext .ts src test",
17-
"jest": "jest --coverage",
1817
"lint": "npm run prettier && npm run eslint",
18+
"prepare": "husky",
1919
"prettier": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
2020
"prettier:write": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
2121
"prepublishOnly": "npm run build",
22-
"test": "npm run lint && npm run jest",
23-
"test:nonetwork": "npm run lint && npm run jest -- --testPathIgnorePatterns network.spec"
22+
"test": "vitest run --coverage",
23+
"test:nonetwork": "npm run lint && vitest run --coverage --testPathIgnorePatterns network.spec"
2424
},
2525
"files": [
2626
"dist/",
2727
"README.md"
2828
],
2929
"engines": {
30-
"node": ">=14"
30+
"node": ">=22.12.0"
3131
},
3232
"dependencies": {
3333
"debug": "^4.1.1",
34-
"env-paths": "^2.2.0",
35-
"fs-extra": "^8.1.0",
36-
"got": "^11.8.5",
34+
"env-paths": "^3.0.0",
35+
"got": "^14.4.5",
36+
"graceful-fs": "^4.2.11",
3737
"progress": "^2.0.3",
38-
"semver": "^6.2.0",
38+
"semver": "^7.6.3",
3939
"sumchecker": "^3.0.1"
4040
},
4141
"devDependencies": {
42+
"@tsconfig/node22": "^22.0.0",
4243
"@types/debug": "^4.1.4",
43-
"@types/fs-extra": "^8.0.0",
44-
"@types/jest": "^29.0.0",
45-
"@types/node": "^12.20.55",
44+
"@types/graceful-fs": "^4.1.9",
45+
"@types/node": "~22.10.5",
4646
"@types/progress": "^2.0.3",
47-
"@types/semver": "^6.2.0",
48-
"@typescript-eslint/eslint-plugin": "^2.34.0",
49-
"@typescript-eslint/parser": "^2.34.0",
50-
"eslint": "^6.8.0",
47+
"@types/semver": "^7.5.8",
48+
"@typescript-eslint/eslint-plugin": "^8.19.1",
49+
"@typescript-eslint/parser": "^8.0.0",
50+
"@vitest/coverage-v8": "3.0.5",
51+
"esbuild-plugin-file-path-extensions": "^2.1.4",
52+
"eslint": "^8.57.0",
5153
"eslint-config-prettier": "^6.15.0",
52-
"eslint-plugin-import": "^2.22.1",
53-
"eslint-plugin-jest": "< 24.0.0",
54-
"husky": "^2.3.0",
55-
"jest": "^29.3.1",
56-
"lint-staged": "^13.0.4",
54+
"eslint-plugin-import": "^2.31.0",
55+
"husky": "^9.1.7",
56+
"lint-staged": "^15.4.1",
5757
"prettier": "^3.4.2",
58-
"ts-jest": "^29.0.0",
59-
"typedoc": "~0.24.8",
60-
"typescript": "^4.9.3"
61-
},
62-
"eslintConfig": {
63-
"parser": "@typescript-eslint/parser",
64-
"extends": [
65-
"eslint:recommended",
66-
"plugin:@typescript-eslint/eslint-recommended",
67-
"plugin:@typescript-eslint/recommended",
68-
"plugin:jest/recommended",
69-
"plugin:import/errors",
70-
"plugin:import/warnings",
71-
"plugin:import/typescript",
72-
"prettier",
73-
"prettier/@typescript-eslint"
74-
]
58+
"typedoc": "~0.25.13",
59+
"typescript": "~5.4.5",
60+
"vitest": "^3.0.5"
7561
},
7662
"husky": {
7763
"hooks": {
@@ -94,9 +80,5 @@
9480
],
9581
"optionalDependencies": {
9682
"global-agent": "^3.0.0"
97-
},
98-
"resolutions": {
99-
"eslint/inquirer": "< 7.3.0",
100-
"**/@typescript-eslint/typescript-estree/semver": "^6.3.0"
10183
}
10284
}

src/Cache.ts

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import debug from 'debug';
22
import envPaths from 'env-paths';
3-
import * as fs from 'fs-extra';
4-
import * as path from 'path';
5-
import * as url from 'url';
6-
import * as crypto from 'crypto';
3+
import fs from 'graceful-fs';
4+
5+
import crypto from 'node:crypto';
6+
import path from 'node:path';
7+
import url from 'node:url';
78

89
const d = debug('@electron/get:cache');
910

@@ -27,9 +28,9 @@ export class Cache {
2728
return path.resolve(this.cacheRoot, Cache.getCacheDirectory(downloadUrl), fileName);
2829
}
2930

30-
public async getPathForFileInCache(url: string, fileName: string): Promise<string | null> {
31+
public getPathForFileInCache(url: string, fileName: string): string | null {
3132
const cachePath = this.getCachePath(url, fileName);
32-
if (await fs.pathExists(cachePath)) {
33+
if (fs.existsSync(cachePath)) {
3334
return cachePath;
3435
}
3536

@@ -39,12 +40,16 @@ export class Cache {
3940
public async putFileInCache(url: string, currentPath: string, fileName: string): Promise<string> {
4041
const cachePath = this.getCachePath(url, fileName);
4142
d(`Moving ${currentPath} to ${cachePath}`);
42-
if (await fs.pathExists(cachePath)) {
43-
d('* Replacing existing file');
44-
await fs.remove(cachePath);
43+
44+
if (!fs.existsSync(path.dirname(cachePath))) {
45+
await fs.promises.mkdir(path.dirname(cachePath), { recursive: true });
4546
}
4647

47-
await fs.move(currentPath, cachePath);
48+
if (fs.existsSync(cachePath)) {
49+
d('* Replacing existing file');
50+
await fs.promises.rm(cachePath, { recursive: true, force: true });
51+
}
52+
await fs.promises.rename(currentPath, cachePath);
4853

4954
return cachePath;
5055
}

src/GotDownloader.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import * as fs from 'fs-extra';
2-
import got, { HTTPError, Progress as GotProgress, Options as GotOptions } from 'got';
3-
import * as path from 'path';
4-
import * as ProgressBar from 'progress';
1+
import got, { HTTPError, Progress as GotProgress, Options as GotOptions, Progress } from 'got';
2+
import fs from 'graceful-fs';
53

6-
import { Downloader } from './Downloader';
4+
import path from 'node:path';
5+
import ProgressBar from 'progress';
6+
7+
import { Downloader } from './Downloader.js';
78

89
const PROGRESS_BAR_DELAY_IN_SECONDS = 30;
910

@@ -34,7 +35,7 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
3435
async download(
3536
url: string,
3637
targetFilePath: string,
37-
options?: GotDownloaderOptions,
38+
options?: Partial<GotDownloaderOptions>,
3839
): Promise<void> {
3940
if (!options) {
4041
options = {};
@@ -44,7 +45,7 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
4445
let bar: ProgressBar | undefined;
4546
let progressPercent: number;
4647
let timeout: NodeJS.Timeout | undefined = undefined;
47-
await fs.mkdirp(path.dirname(targetFilePath));
48+
await fs.promises.mkdir(path.dirname(targetFilePath), { recursive: true });
4849
const writeStream = fs.createWriteStream(targetFilePath);
4950

5051
if (!quiet || !process.env.ELECTRON_GET_NO_PROGRESS) {
@@ -66,7 +67,7 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
6667
}
6768
await new Promise<void>((resolve, reject) => {
6869
const downloadStream = got.stream(url, gotOptions);
69-
downloadStream.on('downloadProgress', async (progress) => {
70+
downloadStream.on('downloadProgress', async (progress: Progress) => {
7071
progressPercent = progress.percent;
7172
if (bar) {
7273
bar.update(progress.percent);
@@ -75,9 +76,9 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
7576
await getProgressCallback(progress);
7677
}
7778
});
78-
downloadStream.on('error', (error) => {
79-
if (error instanceof HTTPError && error.response.statusCode === 404) {
80-
error.message += ` for ${error.response.url}`;
79+
downloadStream.on('error', (error: Error) => {
80+
if (error instanceof HTTPError && (error as HTTPError).response.statusCode === 404) {
81+
error.message += ` for ${(error as HTTPError).response.url}`;
8182
}
8283
if (writeStream.destroy) {
8384
writeStream.destroy(error);

src/artifact-utils.ts

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ElectronArtifactDetails, MirrorOptions } from './types';
2-
import { ensureIsTruthyString, normalizeVersion } from './utils';
1+
import { ElectronArtifactDetails, MirrorOptions } from './types.js';
2+
import { ensureIsTruthyString, normalizeVersion } from './utils.js';
33

44
const BASE_URL = 'https://github.com/electron/electron/releases/download/';
55
const NIGHTLY_BASE_URL = 'https://github.com/electron/nightlies/releases/download/';
@@ -51,13 +51,7 @@ export async function getArtifactRemoteURL(details: ElectronArtifactDetails): Pr
5151
const opts: MirrorOptions = details.mirrorOptions || {};
5252
let base = mirrorVar('mirror', opts, BASE_URL);
5353
if (details.version.includes('nightly')) {
54-
const nightlyDeprecated = mirrorVar('nightly_mirror', opts, '');
55-
if (nightlyDeprecated) {
56-
base = nightlyDeprecated;
57-
console.warn(`nightly_mirror is deprecated, please use nightlyMirror`);
58-
} else {
59-
base = mirrorVar('nightlyMirror', opts, NIGHTLY_BASE_URL);
60-
}
54+
base = mirrorVar('nightlyMirror', opts, NIGHTLY_BASE_URL);
6155
}
6256
const path = mirrorVar('customDir', opts, details.version).replace(
6357
'{{ version }}',

src/downloader-resolver.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { DownloadOptions } from './types';
2-
import { Downloader } from './Downloader';
1+
import { DownloadOptions } from './types.js';
2+
import { Downloader } from './Downloader.js';
3+
4+
// TODO: Resolve the downloader or default to GotDownloader
5+
// Current thoughts are a dot-file traversal for something like
6+
// ".electron.downloader" which would be a text file with the name of the
7+
// npm module to import() and use as the downloader
8+
import { GotDownloader } from './GotDownloader.js';
39

410
export async function getDownloaderForSystem(): Promise<Downloader<DownloadOptions>> {
5-
// TODO: Resolve the downloader or default to GotDownloader
6-
// Current thoughts are a dot-file traversal for something like
7-
// ".electron.downloader" which would be a text file with the name of the
8-
// npm module to import() and use as the downloader
9-
const { GotDownloader } = await import('./GotDownloader');
1011
return new GotDownloader();
1112
}

0 commit comments

Comments
 (0)