Skip to content

Commit 0e2679d

Browse files
authored
feat!: bump engines to Node.js >=22.12.0 (#199)
BREAKING CHANGE: bumps minimum Node.js version to 22 * refactor: move private getNextTarget function to separate file * fix: ESM equivalent of __dirname * ci: use dynamic import
1 parent 85a689d commit 0e2679d

11 files changed

+203
-757
lines changed

.github/workflows/check-electron-abi.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ jobs:
3030
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
3131
with:
3232
script: |
33-
const nodeAbi = require('node-abi');
33+
const { getAbi } = await import('${{ github.workspace }}/node_modules/node-abi/index.js');
3434
35-
const abi = nodeAbi.getAbi('${{ github.event.inputs.electron-version }}', 'electron');
35+
const abi = getAbi('${{ github.event.inputs.electron-version }}', 'electron');
3636
3737
if (abi !== '${{ github.event.inputs.expected-abi }}') {
3838
core.error(`Got ABI ${abi}, expected ${{ github.event.inputs.expected-abi }}`);

.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-file: '.nvmrc'
2828
cache: 'yarn'
2929
- name: Install
3030
run: yarn install --frozen-lockfile

.github/workflows/test.yml

+1-7
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,11 @@ jobs:
1717
strategy:
1818
matrix:
1919
node-version:
20-
- '20.10'
21-
- '18.18'
22-
- '16.20'
23-
- '14.21'
20+
- 22.12.x
2421
os:
2522
- macos-latest
2623
- ubuntu-latest
2724
- windows-latest
28-
exclude:
29-
- os: macos-latest
30-
node-version: '14.21'
3125
runs-on: "${{ matrix.os }}"
3226
steps:
3327
- name: Checkout

.github/workflows/update-abi.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
token: ${{ steps.generate-token.outputs.token }}
2020
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
2121
with:
22-
node-version: '20.x'
22+
node-version-file: '.nvmrc'
2323
- name: Get npm cache directory
2424
id: npm-cache
2525
run: |

.nvmrc

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

getNextTarget.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import semver from 'semver';
2+
3+
export function getNextTarget (runtime, targets) {
4+
const latest = targets.filter((t) => { return t.runtime === runtime }).slice(-1)[0]
5+
const increment = runtime === 'electron' ? 'minor' : 'major'
6+
let next = semver.inc(latest.target, increment)
7+
// Electron releases appear in the registry in their beta form, sometimes there is
8+
// no active beta line. During this time we need to double bump
9+
if (runtime === 'electron' && semver.parse(latest.target).prerelease.length) {
10+
next = semver.inc(next, 'major')
11+
}
12+
return next
13+
}

index.js

+33-51
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
1-
var semver = require('semver')
2-
3-
function getNextTarget (runtime, targets) {
4-
if (targets == null) targets = allTargets
5-
var latest = targets.filter(function (t) { return t.runtime === runtime }).slice(-1)[0]
6-
var increment = runtime === 'electron' ? 'minor' : 'major'
7-
var next = semver.inc(latest.target, increment)
8-
// Electron releases appear in the registry in their beta form, sometimes there is
9-
// no active beta line. During this time we need to double bump
10-
if (runtime === 'electron' && semver.parse(latest.target).prerelease.length) {
11-
next = semver.inc(next, 'major')
12-
}
13-
return next
14-
}
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import { fileURLToPath } from 'node:url';
4+
5+
import semver from 'semver';
6+
7+
import { getNextTarget } from './getNextTarget.js';
158

16-
function getAbi (target, runtime) {
9+
export function getAbi (target, runtime) {
1710
if (target === String(Number(target))) return target
1811
if (target) target = target.replace(/^v/, '')
1912
if (!runtime) runtime = 'node'
@@ -23,37 +16,37 @@ function getAbi (target, runtime) {
2316
if (target === process.versions.node) return process.versions.modules
2417
}
2518

26-
var abi
27-
var lastTarget
19+
let abi
20+
let lastTarget
2821

29-
for (var i = 0; i < allTargets.length; i++) {
30-
var t = allTargets[i]
22+
for (let i = 0; i < allTargets.length; i++) {
23+
const t = allTargets[i]
3124
if (t.runtime !== runtime) continue
3225
if (semver.lte(t.target, target) && (!lastTarget || semver.gte(t.target, lastTarget))) {
3326
abi = t.abi
3427
lastTarget = t.target
3528
}
3629
}
3730

38-
if (abi && semver.lt(target, getNextTarget(runtime))) return abi
31+
if (abi && semver.lt(target, getNextTarget(runtime, allTargets))) return abi
3932
throw new Error('Could not detect abi for version ' + target + ' and runtime ' + runtime + '. Updating "node-abi" might help solve this issue if it is a new release of ' + runtime)
4033
}
4134

42-
function getTarget (abi, runtime) {
35+
export function getTarget (abi, runtime) {
4336
if (abi && abi !== String(Number(abi))) return abi
4437
if (!runtime) runtime = 'node'
4538

4639
if (runtime === 'node' && !abi) return process.versions.node
4740

48-
var match = allTargets
41+
const match = allTargets
4942
.filter(function (t) {
5043
return t.abi === abi && t.runtime === runtime
5144
})
5245
.map(function (t) {
5346
return t.target
5447
})
5548
if (match.length) {
56-
var betaSeparatorIndex = match[0].indexOf("-")
49+
const betaSeparatorIndex = match[0].indexOf("-")
5750
return betaSeparatorIndex > -1
5851
? match[0].substring(0, betaSeparatorIndex)
5952
: match[0]
@@ -63,31 +56,31 @@ function getTarget (abi, runtime) {
6356
}
6457

6558
function sortByTargetFn (a, b) {
66-
var abiComp = Number(a.abi) - Number(b.abi)
59+
const abiComp = Number(a.abi) - Number(b.abi)
6760
if (abiComp !== 0) return abiComp
6861
if (a.target < b.target) return -1
6962
if (a.target > b.target) return 1
7063
return 0
7164
}
7265

7366
function loadGeneratedTargets () {
74-
var registry = require('./abi_registry.json')
75-
var targets = {
67+
const registry = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'abi_registry.json'), 'utf8'))
68+
const targets = {
7669
supported: [],
7770
additional: [],
7871
future: []
7972
}
8073

8174
registry.forEach(function (item) {
82-
var target = {
75+
const target = {
8376
runtime: item.runtime,
8477
target: item.target,
8578
abi: item.abi
8679
}
8780
if (item.lts) {
88-
var startDate = new Date(Date.parse(item.lts[0]))
89-
var endDate = new Date(Date.parse(item.lts[1]))
90-
var currentDate = new Date()
81+
const startDate = new Date(Date.parse(item.lts[0]))
82+
const endDate = new Date(Date.parse(item.lts[1]))
83+
const currentDate = new Date()
9184
target.lts = startDate < currentDate && currentDate < endDate
9285
} else {
9386
target.lts = false
@@ -109,9 +102,9 @@ function loadGeneratedTargets () {
109102
return targets
110103
}
111104

112-
var generatedTargets = loadGeneratedTargets()
105+
const generatedTargets = loadGeneratedTargets()
113106

114-
var supportedTargets = [
107+
export const supportedTargets = [
115108
{runtime: 'node', target: '5.0.0', abi: '47', lts: false},
116109
{runtime: 'node', target: '6.0.0', abi: '48', lts: false},
117110
{runtime: 'node', target: '7.0.0', abi: '51', lts: false},
@@ -129,22 +122,20 @@ var supportedTargets = [
129122
{runtime: 'electron', target: '2.0.0', abi: '57', lts: false},
130123
{runtime: 'electron', target: '3.0.0', abi: '64', lts: false},
131124
{runtime: 'electron', target: '4.0.0', abi: '64', lts: false},
132-
{runtime: 'electron', target: '4.0.4', abi: '69', lts: false}
125+
{runtime: 'electron', target: '4.0.4', abi: '69', lts: false},
126+
...generatedTargets.supported
133127
]
134128

135-
supportedTargets.push.apply(supportedTargets, generatedTargets.supported)
136-
137-
var additionalTargets = [
129+
export const additionalTargets = [
138130
{runtime: 'node-webkit', target: '0.13.0', abi: '47', lts: false},
139131
{runtime: 'node-webkit', target: '0.15.0', abi: '48', lts: false},
140132
{runtime: 'node-webkit', target: '0.18.3', abi: '51', lts: false},
141133
{runtime: 'node-webkit', target: '0.23.0', abi: '57', lts: false},
142-
{runtime: 'node-webkit', target: '0.26.5', abi: '59', lts: false}
134+
{runtime: 'node-webkit', target: '0.26.5', abi: '59', lts: false},
135+
...generatedTargets.additional
143136
]
144137

145-
additionalTargets.push.apply(additionalTargets, generatedTargets.additional)
146-
147-
var deprecatedTargets = [
138+
export const deprecatedTargets = [
148139
{runtime: 'node', target: '0.2.0', abi: '1', lts: false},
149140
{runtime: 'node', target: '0.9.1', abi: '0x000A', lts: false},
150141
{runtime: 'node', target: '0.9.9', abi: '0x000B', lts: false},
@@ -162,18 +153,9 @@ var deprecatedTargets = [
162153
{runtime: 'electron', target: '0.33.0', abi: '46', lts: false}
163154
]
164155

165-
var futureTargets = generatedTargets.future
156+
export const futureTargets = generatedTargets.future
166157

167-
var allTargets = deprecatedTargets
158+
export const allTargets = deprecatedTargets
168159
.concat(supportedTargets)
169160
.concat(additionalTargets)
170161
.concat(futureTargets)
171-
172-
exports.getAbi = getAbi
173-
exports.getTarget = getTarget
174-
exports.deprecatedTargets = deprecatedTargets
175-
exports.supportedTargets = supportedTargets
176-
exports.additionalTargets = additionalTargets
177-
exports.futureTargets = futureTargets
178-
exports.allTargets = allTargets
179-
exports._getNextTarget = getNextTarget

package.json

+9-8
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
"name": "node-abi",
33
"version": "0.0.0-development",
44
"description": "Get the Node ABI for a given target and runtime, and vice versa.",
5-
"main": "index.js",
5+
"type": "module",
6+
"exports": "./index.js",
67
"scripts": {
7-
"test": "tape test/index.js",
8+
"test": "node --test test/index.js",
89
"update-abi-registry": "node --unhandled-rejections=strict scripts/update-abi-registry.js"
910
},
1011
"files": [
11-
"abi_registry.json"
12+
"abi_registry.json",
13+
"index.js",
14+
"getNextTarget.js"
1215
],
1316
"repository": {
1417
"type": "git",
@@ -27,14 +30,12 @@
2730
"url": "https://github.com/electron/node-abi/issues"
2831
},
2932
"homepage": "https://github.com/electron/node-abi#readme",
30-
"devDependencies": {
31-
"tape": "^5.3.1"
32-
},
33+
"devDependencies": {},
3334
"dependencies": {
34-
"semver": "^7.3.5"
35+
"semver": "^7.6.3"
3536
},
3637
"engines": {
37-
"node": ">=10"
38+
"node": ">=22.12.0"
3839
},
3940
"publishConfig": {
4041
"provenance": true

scripts/update-abi-registry.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
const { writeFile } = require('node:fs/promises')
2-
const path = require('node:path')
1+
import { writeFile } from 'node:fs/promises'
2+
import path from 'node:path'
3+
import { fileURLToPath } from 'node:url';
34

4-
const semver = require('semver')
5+
import semver from 'semver'
56

67
function sortByElectronVersionFn (a, b) {
78
const modulesComp = Number(a.modules) - Number(b.modules)
@@ -127,7 +128,7 @@ async function main () {
127128
...electronTargets,
128129
]
129130

130-
await writeFile(path.resolve(__dirname, '..', 'abi_registry.json'), JSON.stringify(supportedTargets, null, 2))
131+
await writeFile(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'abi_registry.json'), JSON.stringify(supportedTargets, null, 2))
131132
}
132133

133134
main()

0 commit comments

Comments
 (0)