Skip to content

Commit 88a2f6b

Browse files
committed
refactor(scripts): use @socketsecurity/lib/spawn for child processes
Update all scripts to use spawn from @socketsecurity/lib instead of node:child_process for consistent cross-platform behavior.
1 parent b21117e commit 88a2f6b

File tree

7 files changed

+81
-81
lines changed

7 files changed

+81
-81
lines changed

scripts/bump.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Includes interactive mode for reviewing and refining AI-generated changelogs.
55
*/
66

7-
import { spawn } from 'node:child_process'
7+
import { spawn } from '@socketsecurity/lib/spawn'
88
import { existsSync, promises as fs } from 'node:fs'
99
import path from 'node:path'
1010
import readline from 'node:readline'

scripts/claude.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Requires Claude Code (claude) CLI to be installed.
55
*/
66

7-
import { spawn } from 'node:child_process'
7+
import { spawn } from '@socketsecurity/lib/spawn'
88
import crypto from 'node:crypto'
99
import {
1010
existsSync,

scripts/fix.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @fileoverview Fix script that runs lint with auto-fix enabled.
33
*/
44

5-
import { spawn } from 'node:child_process'
5+
import { spawn } from '@socketsecurity/lib/spawn'
66
import path from 'node:path'
77
import { fileURLToPath } from 'node:url'
88

scripts/publish.mjs

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
* Supports both simple single-package and complex multi-package publishing.
44
*/
55

6-
import { spawn } from 'node:child_process'
76
import { existsSync, promises as fs } from 'node:fs'
87
import path from 'node:path'
98
import { fileURLToPath } from 'node:url'
109

1110
import { parseArgs } from '@socketsecurity/lib/argv/parse'
1211
import { getDefaultLogger } from '@socketsecurity/lib/logger'
12+
import { spawn } from '@socketsecurity/lib/spawn'
1313
import { printFooter, printHeader } from '@socketsecurity/lib/stdio/header'
1414

1515
const logger = getDefaultLogger()
@@ -22,55 +22,54 @@ const WIN32 = process.platform === 'win32'
2222
const CI = !!process.env.CI
2323

2424
async function runCommand(command, args = [], options = {}) {
25-
return new Promise((resolve, reject) => {
26-
const child = spawn(command, args, {
25+
try {
26+
const result = await spawn(command, args, {
2727
stdio: 'inherit',
2828
cwd: rootPath,
2929
...(WIN32 && { shell: true }),
3030
...options,
3131
})
32-
33-
child.on('exit', code => {
34-
resolve(code || 0)
35-
})
36-
37-
child.on('error', error => {
38-
reject(error)
39-
})
40-
})
32+
return result.code
33+
} catch (error) {
34+
// spawn() throws on non-zero exit
35+
if (error && typeof error === 'object' && 'code' in error) {
36+
return error.code
37+
}
38+
throw error
39+
}
4140
}
4241

4342
async function runCommandWithOutput(command, args = [], options = {}) {
44-
return new Promise((resolve, reject) => {
45-
let stdout = ''
46-
let stderr = ''
47-
48-
const child = spawn(command, args, {
43+
try {
44+
const result = await spawn(command, args, {
4945
cwd: rootPath,
46+
stdio: 'pipe',
47+
stdioString: true,
5048
...(WIN32 && { shell: true }),
5149
...options,
5250
})
53-
54-
if (child.stdout) {
55-
child.stdout.on('data', data => {
56-
stdout += data
57-
})
51+
return {
52+
exitCode: result.code,
53+
stderr: result.stderr,
54+
stdout: result.stdout,
5855
}
59-
60-
if (child.stderr) {
61-
child.stderr.on('data', data => {
62-
stderr += data
63-
})
56+
} catch (error) {
57+
// spawn() throws on non-zero exit
58+
if (
59+
error &&
60+
typeof error === 'object' &&
61+
'code' in error &&
62+
'stdout' in error &&
63+
'stderr' in error
64+
) {
65+
return {
66+
exitCode: error.code,
67+
stderr: error.stderr,
68+
stdout: error.stdout,
69+
}
6470
}
65-
66-
child.on('exit', code => {
67-
resolve({ exitCode: code || 0, stdout, stderr })
68-
})
69-
70-
child.on('error', error => {
71-
reject(error)
72-
})
73-
})
71+
throw error
72+
}
7473
}
7574

7675
/**

scripts/test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Combines check, build, and test steps with clean, consistent output.
44
*/
55

6-
import { spawn } from 'node:child_process'
6+
import { spawn } from '@socketsecurity/lib/spawn'
77
import { existsSync } from 'node:fs'
88
import path from 'node:path'
99
import { fileURLToPath } from 'node:url'

scripts/update.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Handles taze updates, Socket package updates, and project-specific tasks.
44
*/
55

6-
import { spawn } from 'node:child_process'
6+
import { spawn } from '@socketsecurity/lib/spawn'
77
import { existsSync } from 'node:fs'
88
import path from 'node:path'
99
import { fileURLToPath } from 'node:url'

scripts/utils/run-command.mjs

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/** @fileoverview Utility for running shell commands with proper error handling. */
22

3-
import { spawn, spawnSync } from 'node:child_process'
3+
import { spawn, spawnSync } from '@socketsecurity/lib/spawn'
44

55
import { getDefaultLogger } from '@socketsecurity/lib/logger'
66

@@ -13,22 +13,22 @@ const logger = getDefaultLogger()
1313
* @param {object} options - Spawn options
1414
* @returns {Promise<number>} Exit code
1515
*/
16-
export function runCommand(command, args = [], options = {}) {
17-
return new Promise((resolve, reject) => {
18-
const child = spawn(command, args, {
16+
export async function runCommand(command, args = [], options = {}) {
17+
try {
18+
const result = await spawn(command, args, {
1919
stdio: 'inherit',
2020
...(process.platform === 'win32' && { shell: true }),
2121
...options,
2222
})
23-
24-
child.on('exit', code => {
25-
resolve(code || 0)
26-
})
27-
28-
child.on('error', error => {
29-
reject(error)
30-
})
31-
})
23+
return result.code
24+
} catch (error) {
25+
// spawn() from @socketsecurity/lib throws on non-zero exit
26+
// Return the exit code from the error
27+
if (error && typeof error === 'object' && 'code' in error) {
28+
return error.code
29+
}
30+
throw error
31+
}
3232
}
3333

3434
/**
@@ -93,37 +93,38 @@ export async function runParallel(commands) {
9393
* @param {object} options - Spawn options
9494
* @returns {Promise<{exitCode: number, stdout: string, stderr: string}>}
9595
*/
96-
export function runCommandQuiet(command, args = [], options = {}) {
97-
return new Promise((resolve, reject) => {
98-
let stdout = ''
99-
let stderr = ''
100-
101-
const child = spawn(command, args, {
96+
export async function runCommandQuiet(command, args = [], options = {}) {
97+
try {
98+
const result = await spawn(command, args, {
10299
...options,
103100
...(process.platform === 'win32' && { shell: true }),
104-
stdio: ['inherit', 'pipe', 'pipe'],
105-
})
106-
107-
child.stdout?.on('data', data => {
108-
stdout += data.toString()
101+
stdio: 'pipe',
102+
stdioString: true,
109103
})
110104

111-
child.stderr?.on('data', data => {
112-
stderr += data.toString()
113-
})
114-
115-
child.on('exit', code => {
116-
resolve({
117-
exitCode: code || 0,
118-
stderr,
119-
stdout,
120-
})
121-
})
122-
123-
child.on('error', error => {
124-
reject(error)
125-
})
126-
})
105+
return {
106+
exitCode: result.code,
107+
stderr: result.stderr,
108+
stdout: result.stdout,
109+
}
110+
} catch (error) {
111+
// spawn() from @socketsecurity/lib throws on non-zero exit
112+
// Return the exit code and output from the error
113+
if (
114+
error &&
115+
typeof error === 'object' &&
116+
'code' in error &&
117+
'stdout' in error &&
118+
'stderr' in error
119+
) {
120+
return {
121+
exitCode: error.code,
122+
stderr: error.stderr,
123+
stdout: error.stdout,
124+
}
125+
}
126+
throw error
127+
}
127128
}
128129

129130
/**

0 commit comments

Comments
 (0)