Skip to content

Commit cf9b3e8

Browse files
simoneprigavinaiken
andcommitted
feat!: rewrite as a pure ESM package (Node.js >= 18)
Modernizes the project for the first 1.0 release: - Pure ESM with default and named exports (import pidtree from 'pidtree') - Drops CommonJS and Node.js < 18 - Refreshed toolchain: ava 6, c8, xo 2, tsd; tests use dependency injection and a shared parser instead of mockery and stream mocks - Keeps the Windows wmic -> PowerShell fallback and zero runtime deps BREAKING CHANGE: pidtree is now ESM-only and requires Node.js >= 18. CommonJS consumers and older Node.js should stay on pidtree@0.6. Co-Authored-By: Gavin Aiken <gavin.aiken@netcuras.com>
1 parent 0d28415 commit cf9b3e8

30 files changed

Lines changed: 665 additions & 989 deletions

.github/workflows/lint.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,14 @@ on:
99
jobs:
1010
lint:
1111
runs-on: ubuntu-latest
12-
name: XO & Prettier
1312
steps:
1413
- name: Setup repo
15-
uses: actions/checkout@v2
14+
uses: actions/checkout@v4
1615
- name: Setup node
1716
uses: actions/setup-node@v4
1817
with:
19-
# Pinned: the legacy xo@0.20 toolchain crashes on modern Node
20-
# (util.isDate was removed). Revisit when the toolchain is updated.
21-
node-version: 14
22-
- name: Install dev dependencies
23-
run: |
24-
npm install --only=dev
25-
npm list --dev --depth=0
18+
node-version: 22
19+
- name: Install dependencies
20+
run: npm install
2621
- name: Run lint
2722
run: npm run lint

.github/workflows/test-macos.yml

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,20 @@ on:
99
jobs:
1010
test:
1111
runs-on: macos-latest
12-
name: AVA & TSD & Benchmark & Codecov
1312
strategy:
1413
fail-fast: false
14+
# Node 26+ is not yet supported by the coverage tool (c8); revisit
15+
# "current" once the toolchain catches up.
1516
matrix:
16-
node: [current, 22, 20, 18]
17+
node: [24, 22, 20, 18]
1718
steps:
1819
- name: Setup repo
19-
uses: actions/checkout@v3
20+
uses: actions/checkout@v4
2021
- name: Setup node ${{ matrix.node }}
21-
uses: actions/setup-node@v3
22+
uses: actions/setup-node@v4
2223
with:
2324
node-version: ${{ matrix.node }}
24-
- name: Install lib dependencies
25-
run: |
26-
npm install --only=prod
27-
npm list --prod --depth=0
28-
- name: Install dev dependencies
29-
run: |
30-
npm install --only=dev
31-
npm list --dev --depth=0
25+
- name: Install dependencies
26+
run: npm install
3227
- name: Run tests
33-
run: npm run test
34-
#- name: Run type checking
35-
# run: npm run types
36-
- name: Run benchmark
37-
run: |
38-
npm run bench
39-
- name: Upload coverage to Codecov
40-
uses: codecov/codecov-action@v2
28+
run: npm test

.github/workflows/test-ubuntu.yml

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,26 @@ on:
99
jobs:
1010
test:
1111
runs-on: ubuntu-latest
12-
name: AVA & TSD & Benchmark & Codecov
1312
strategy:
1413
fail-fast: false
14+
# Node 26+ is not yet supported by the coverage tool (c8); revisit
15+
# "current" once the toolchain catches up.
1516
matrix:
16-
node: [current, 22, 20, 18]
17+
node: [24, 22, 20, 18]
1718
steps:
1819
- name: Setup repo
19-
uses: actions/checkout@v3
20+
uses: actions/checkout@v4
2021
- name: Setup node ${{ matrix.node }}
21-
uses: actions/setup-node@v3
22+
uses: actions/setup-node@v4
2223
with:
2324
node-version: ${{ matrix.node }}
24-
- name: Install lib dependencies
25-
run: |
26-
npm install --only=prod
27-
npm list --prod --depth=0
28-
- name: Install dev dependencies
29-
run: |
30-
npm install --only=dev
31-
npm list --dev --depth=0
25+
- name: Install dependencies
26+
run: npm install
3227
- name: Run tests
33-
run: npm run test
34-
#- name: Run type checking
35-
# run: npm run types
28+
run: npm test
29+
- name: Run type checking
30+
run: npm run types
3631
- name: Run benchmark
37-
run: |
38-
npm run bench
32+
run: npm run bench
3933
- name: Upload coverage to Codecov
40-
uses: codecov/codecov-action@v2
34+
uses: codecov/codecov-action@v5

.github/workflows/test-windows.yml

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,20 @@ jobs:
1111
# windows-latest is Windows Server 2025, which ships without wmic, so the
1212
# integration tests here run against the PowerShell fallback in lib/get.js.
1313
runs-on: windows-latest
14-
name: AVA & TSD & Benchmark & Codecov
1514
strategy:
1615
fail-fast: false
16+
# Node 26+ is not yet supported by the coverage tool (c8); revisit
17+
# "current" once the toolchain catches up.
1718
matrix:
18-
node: [current, 22, 20, 18]
19+
node: [24, 22, 20, 18]
1920
steps:
2021
- name: Setup repo
21-
uses: actions/checkout@v3
22+
uses: actions/checkout@v4
2223
- name: Setup node ${{ matrix.node }}
23-
uses: actions/setup-node@v3
24+
uses: actions/setup-node@v4
2425
with:
2526
node-version: ${{ matrix.node }}
26-
- name: Install lib dependencies
27-
run: |
28-
npm install --only=prod
29-
npm list --prod --depth=0
30-
- name: Install dev dependencies
31-
run: |
32-
npm install --only=dev
33-
npm list --dev --depth=0
27+
- name: Install dependencies
28+
run: npm install
3429
- name: Run tests
35-
if: ${{ matrix.node <= 6 }}
36-
run: npm run test
37-
- name: Run tests
38-
if: ${{ !(matrix.node <= 6) }}
39-
run: npm run test:windows
40-
#- name: Run type checking
41-
# run: npm run types
42-
- name: Run benchmark
43-
run: |
44-
npm run bench
45-
- name: Upload coverage to Codecov
46-
if: ${{ matrix.node <= 6 }}
47-
uses: codecov/codecov-action@v2
30+
run: npm test

bin/pidtree.js

Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,28 @@
11
#!/usr/bin/env node
22

3-
'use strict';
4-
5-
var os = require('os');
6-
var pidtree = require('..');
7-
8-
// The method startsWith is not defined on string objects in node 0.10
9-
// eslint-disable-next-line no-extend-native
10-
String.prototype.startsWith = function(suffix) {
11-
return this.substring(0, suffix.length) === suffix;
12-
};
3+
import os from 'node:os';
4+
import pidtree from '../index.js';
135

146
function help() {
15-
var help =
7+
console.log(
168
' Usage\n' +
17-
' $ pidtree <ppid>\n' +
18-
'\n' +
19-
'Options\n' +
20-
' --list To print the pids as a list.\n' +
21-
'\n' +
22-
'Examples\n' +
23-
' $ pidtree\n' +
24-
' $ pidtree --list\n' +
25-
' $ pidtree 1\n' +
26-
' $ pidtree 1 --list\n';
27-
console.log(help);
9+
' $ pidtree <ppid>\n' +
10+
'\n' +
11+
'Options\n' +
12+
' --list To print the pids as a list.\n' +
13+
'\n' +
14+
'Examples\n' +
15+
' $ pidtree\n' +
16+
' $ pidtree --list\n' +
17+
' $ pidtree 1\n' +
18+
' $ pidtree 1 --list\n',
19+
);
2820
}
2921

3022
function list(ppid) {
31-
pidtree(ppid === undefined ? -1 : ppid, function(err, list) {
32-
if (err) {
33-
console.error(err.message);
23+
pidtree(ppid === undefined ? -1 : ppid, (error, list) => {
24+
if (error) {
25+
console.error(error.message);
3426
return;
3527
}
3628

@@ -39,16 +31,16 @@ function list(ppid) {
3931
}
4032

4133
function tree(ppid) {
42-
pidtree(ppid, {advanced: true}, function(err, list) {
43-
if (err) {
44-
console.error(err.message);
34+
pidtree(ppid, {advanced: true}, (error, list) => {
35+
if (error) {
36+
console.error(error.message);
4537
return;
4638
}
4739

48-
var parents = {}; // Hash Map of parents
49-
var tree = {}; // Adiacency Hash Map
40+
const parents = {}; // Hash Map of parents
41+
const tree = {}; // Adjacency Hash Map
5042
while (list.length > 0) {
51-
var element = list.pop();
43+
const element = list.pop();
5244
if (tree[element.ppid]) {
5345
tree[element.ppid].push(element.pid);
5446
} else {
@@ -60,55 +52,53 @@ function tree(ppid) {
6052
}
6153
}
6254

63-
var roots = [ppid];
55+
let roots = [ppid];
6456
if (ppid === -1) {
65-
// Get all the roots
66-
roots = Object.keys(tree).filter(function(node) {
67-
return parents[node] === undefined;
68-
});
57+
// Get all the roots.
58+
roots = Object.keys(tree).filter((node) => parents[node] === undefined);
6959
}
7060

71-
roots.forEach(function(root) {
61+
for (const root of roots) {
7262
print(tree, root);
73-
});
63+
}
7464
});
7565

7666
function print(tree, start) {
7767
function printBranch(node, branch) {
78-
var isGraphHead = branch.length === 0;
79-
var children = tree[node] || [];
68+
const isGraphHead = branch.length === 0;
69+
const children = tree[node] || [];
8070

81-
var branchHead = '';
71+
let branchHead = '';
8272
if (!isGraphHead) {
8373
branchHead = children.length > 0 ? '┬ ' : '─ ';
8474
}
8575

8676
console.log(branch + branchHead + node);
8777

88-
var baseBranch = branch;
78+
let baseBranch = branch;
8979
if (!isGraphHead) {
90-
var isChildOfLastBranch = branch.slice(-2) === '└─';
80+
const isChildOfLastBranch = branch.slice(-2) === '└─';
9181
baseBranch = branch.slice(0, -2) + (isChildOfLastBranch ? ' ' : '| ');
9282
}
9383

94-
var nextBranch = baseBranch + '├─';
95-
var lastBranch = baseBranch + '└─';
96-
children.forEach(function(child, index) {
84+
const nextBranch = baseBranch + '├─';
85+
const lastBranch = baseBranch + '└─';
86+
for (const [index, child] of children.entries()) {
9787
printBranch(
9888
child,
99-
children.length - 1 === index ? lastBranch : nextBranch
89+
children.length - 1 === index ? lastBranch : nextBranch,
10090
);
101-
});
91+
}
10292
}
10393

10494
printBranch(start, '');
10595
}
10696
}
10797

10898
function run() {
109-
var flag;
110-
var ppid;
111-
for (var i = 2; i < process.argv.length; i++) {
99+
let flag;
100+
let ppid;
101+
for (let i = 2; i < process.argv.length; i++) {
112102
if (process.argv[i].startsWith('--')) {
113103
flag = process.argv[i];
114104
} else {
@@ -120,9 +110,13 @@ function run() {
120110
ppid = -1;
121111
}
122112

123-
if (flag === '--list') list(ppid);
124-
else if (flag === undefined) tree(ppid);
125-
else help();
113+
if (flag === '--list') {
114+
list(ppid);
115+
} else if (flag === undefined) {
116+
tree(ppid);
117+
} else {
118+
help();
119+
}
126120
}
127121

128122
run();

0 commit comments

Comments
 (0)