Skip to content

Commit

Permalink
feat!: bump engines to Node.js >=22.12.0 (#312)
Browse files Browse the repository at this point in the history
  • Loading branch information
erickzhao authored Feb 18, 2025
1 parent ee6c197 commit 8be1f8d
Show file tree
Hide file tree
Showing 28 changed files with 2,554 additions and 3,613 deletions.
17 changes: 17 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"prettier",
"prettier/@typescript-eslint"
],
"rules": {
"@typescript-eslint/prefer-ts-expect-error": 0,
"@typescript-eslint/ban-ts-comment": 0,
"import/no-unresolved": "off"
}
}
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # tag: v4.2.0
with:
node-version: lts/*
node-version: 22.12.x
- run: yarn --frozen-lockfile
- run: yarn build:docs
- name: Prepare docs
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 20.x
node-version: 22.12.x
cache: 'yarn'
- name: Install
run: yarn install --frozen-lockfile
Expand Down
17 changes: 3 additions & 14 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,24 @@ jobs:
strategy:
matrix:
node-version:
- '20.10'
- '18.18'
- '16.20'
- '14.16'
- 22.12.x
os:
- macos-latest
- ubuntu-latest
- windows-latest
runs-on: "${{ matrix.os }}"
steps:
- run: git config --global core.autocrlf input
- name: Install Rosetta
if: ${{ matrix.os == 'macos-latest' && matrix.node-version == '14.16' }}
run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: "${{ matrix.node-version }}"
cache: 'yarn'
architecture: ${{ matrix.os == 'macos-latest' && matrix.node-version == '14.16' && 'x64' || env.RUNNER_ARCH }}
- name: Install (Node.js v16+)
if : ${{ matrix.node-version != '14.16' }}
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Install (Node.js < v16)
if : ${{ matrix.node-version == '14.16' }}
run: yarn install --frozen-lockfile --ignore-engines
- name: Test
run: yarn test
run: yarn lint && yarn test
- name: Build docs
run: yarn build:docs
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.12
7 changes: 0 additions & 7 deletions jest.config.js

This file was deleted.

70 changes: 26 additions & 44 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,77 +1,63 @@
{
"name": "@electron/get",
"version": "0.0.0-development",
"type": "module",
"exports": "./dist/index.js",
"description": "Utility for downloading artifacts from different versions of Electron",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"repository": "https://github.com/electron/get",
"author": "Samuel Attard",
"license": "MIT",
"publishConfig": {
"provenance": true
},
"scripts": {
"build": "tsc && tsc -p tsconfig.esm.json",
"build": "tsc",
"build:docs": "npx typedoc",
"eslint": "eslint --ext .ts src test",
"jest": "jest --coverage",
"lint": "npm run prettier && npm run eslint",
"prepare": "husky",
"prettier": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
"prettier:write": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"prepublishOnly": "npm run build",
"test": "npm run lint && npm run jest",
"test:nonetwork": "npm run lint && npm run jest -- --testPathIgnorePatterns network.spec"
"test": "vitest run --coverage",
"test:nonetwork": "npm run lint && vitest run --coverage --testPathIgnorePatterns network.spec"
},
"files": [
"dist/",
"README.md"
],
"engines": {
"node": ">=14"
"node": ">=22.12.0"
},
"dependencies": {
"debug": "^4.1.1",
"env-paths": "^2.2.0",
"fs-extra": "^8.1.0",
"got": "^11.8.5",
"env-paths": "^3.0.0",
"got": "^14.4.5",
"graceful-fs": "^4.2.11",
"progress": "^2.0.3",
"semver": "^6.2.0",
"semver": "^7.6.3",
"sumchecker": "^3.0.1"
},
"devDependencies": {
"@tsconfig/node22": "^22.0.0",
"@types/debug": "^4.1.4",
"@types/fs-extra": "^8.0.0",
"@types/jest": "^29.0.0",
"@types/node": "^12.20.55",
"@types/graceful-fs": "^4.1.9",
"@types/node": "~22.10.5",
"@types/progress": "^2.0.3",
"@types/semver": "^6.2.0",
"@typescript-eslint/eslint-plugin": "^2.34.0",
"@typescript-eslint/parser": "^2.34.0",
"eslint": "^6.8.0",
"@types/semver": "^7.5.8",
"@typescript-eslint/eslint-plugin": "^8.19.1",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/coverage-v8": "3.0.5",
"esbuild-plugin-file-path-extensions": "^2.1.4",
"eslint": "^8.57.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "< 24.0.0",
"husky": "^2.3.0",
"jest": "^29.3.1",
"lint-staged": "^13.0.4",
"eslint-plugin-import": "^2.31.0",
"husky": "^9.1.7",
"lint-staged": "^15.4.1",
"prettier": "^3.4.2",
"ts-jest": "^29.0.0",
"typedoc": "~0.24.8",
"typescript": "^4.9.3"
},
"eslintConfig": {
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"prettier",
"prettier/@typescript-eslint"
]
"typedoc": "~0.25.13",
"typescript": "~5.4.5",
"vitest": "^3.0.5"
},
"husky": {
"hooks": {
Expand All @@ -94,9 +80,5 @@
],
"optionalDependencies": {
"global-agent": "^3.0.0"
},
"resolutions": {
"eslint/inquirer": "< 7.3.0",
"**/@typescript-eslint/typescript-estree/semver": "^6.3.0"
}
}
25 changes: 15 additions & 10 deletions src/Cache.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import debug from 'debug';
import envPaths from 'env-paths';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as url from 'url';
import * as crypto from 'crypto';
import fs from 'graceful-fs';

import crypto from 'node:crypto';
import path from 'node:path';
import url from 'node:url';

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

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

public async getPathForFileInCache(url: string, fileName: string): Promise<string | null> {
public getPathForFileInCache(url: string, fileName: string): string | null {
const cachePath = this.getCachePath(url, fileName);
if (await fs.pathExists(cachePath)) {
if (fs.existsSync(cachePath)) {
return cachePath;
}

Expand All @@ -39,12 +40,16 @@ export class Cache {
public async putFileInCache(url: string, currentPath: string, fileName: string): Promise<string> {
const cachePath = this.getCachePath(url, fileName);
d(`Moving ${currentPath} to ${cachePath}`);
if (await fs.pathExists(cachePath)) {
d('* Replacing existing file');
await fs.remove(cachePath);

if (!fs.existsSync(path.dirname(cachePath))) {
await fs.promises.mkdir(path.dirname(cachePath), { recursive: true });
}

await fs.move(currentPath, cachePath);
if (fs.existsSync(cachePath)) {
d('* Replacing existing file');
await fs.promises.rm(cachePath, { recursive: true, force: true });
}
await fs.promises.rename(currentPath, cachePath);

return cachePath;
}
Expand Down
23 changes: 12 additions & 11 deletions src/GotDownloader.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as fs from 'fs-extra';
import got, { HTTPError, Progress as GotProgress, Options as GotOptions } from 'got';
import * as path from 'path';
import * as ProgressBar from 'progress';
import got, { HTTPError, Progress as GotProgress, Options as GotOptions, Progress } from 'got';
import fs from 'graceful-fs';

import { Downloader } from './Downloader';
import path from 'node:path';
import ProgressBar from 'progress';

import { Downloader } from './Downloader.js';

const PROGRESS_BAR_DELAY_IN_SECONDS = 30;

Expand Down Expand Up @@ -34,7 +35,7 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
async download(
url: string,
targetFilePath: string,
options?: GotDownloaderOptions,
options?: Partial<GotDownloaderOptions>,
): Promise<void> {
if (!options) {
options = {};
Expand All @@ -44,7 +45,7 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
let bar: ProgressBar | undefined;
let progressPercent: number;
let timeout: NodeJS.Timeout | undefined = undefined;
await fs.mkdirp(path.dirname(targetFilePath));
await fs.promises.mkdir(path.dirname(targetFilePath), { recursive: true });
const writeStream = fs.createWriteStream(targetFilePath);

if (!quiet || !process.env.ELECTRON_GET_NO_PROGRESS) {
Expand All @@ -66,7 +67,7 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
}
await new Promise<void>((resolve, reject) => {
const downloadStream = got.stream(url, gotOptions);
downloadStream.on('downloadProgress', async (progress) => {
downloadStream.on('downloadProgress', async (progress: Progress) => {
progressPercent = progress.percent;
if (bar) {
bar.update(progress.percent);
Expand All @@ -75,9 +76,9 @@ export class GotDownloader implements Downloader<GotDownloaderOptions> {
await getProgressCallback(progress);
}
});
downloadStream.on('error', (error) => {
if (error instanceof HTTPError && error.response.statusCode === 404) {
error.message += ` for ${error.response.url}`;
downloadStream.on('error', (error: Error) => {
if (error instanceof HTTPError && (error as HTTPError).response.statusCode === 404) {
error.message += ` for ${(error as HTTPError).response.url}`;
}
if (writeStream.destroy) {
writeStream.destroy(error);
Expand Down
12 changes: 3 additions & 9 deletions src/artifact-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ElectronArtifactDetails, MirrorOptions } from './types';
import { ensureIsTruthyString, normalizeVersion } from './utils';
import { ElectronArtifactDetails, MirrorOptions } from './types.js';
import { ensureIsTruthyString, normalizeVersion } from './utils.js';

const BASE_URL = 'https://github.com/electron/electron/releases/download/';
const NIGHTLY_BASE_URL = 'https://github.com/electron/nightlies/releases/download/';
Expand Down Expand Up @@ -51,13 +51,7 @@ export async function getArtifactRemoteURL(details: ElectronArtifactDetails): Pr
const opts: MirrorOptions = details.mirrorOptions || {};
let base = mirrorVar('mirror', opts, BASE_URL);
if (details.version.includes('nightly')) {
const nightlyDeprecated = mirrorVar('nightly_mirror', opts, '');
if (nightlyDeprecated) {
base = nightlyDeprecated;
console.warn(`nightly_mirror is deprecated, please use nightlyMirror`);
} else {
base = mirrorVar('nightlyMirror', opts, NIGHTLY_BASE_URL);
}
base = mirrorVar('nightlyMirror', opts, NIGHTLY_BASE_URL);
}
const path = mirrorVar('customDir', opts, details.version).replace(
'{{ version }}',
Expand Down
15 changes: 8 additions & 7 deletions src/downloader-resolver.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { DownloadOptions } from './types';
import { Downloader } from './Downloader';
import { DownloadOptions } from './types.js';
import { Downloader } from './Downloader.js';

// TODO: Resolve the downloader or default to GotDownloader
// Current thoughts are a dot-file traversal for something like
// ".electron.downloader" which would be a text file with the name of the
// npm module to import() and use as the downloader
import { GotDownloader } from './GotDownloader.js';

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

0 comments on commit 8be1f8d

Please sign in to comment.