Skip to content

Commit 69ad79a

Browse files
committed
refactor: replace cross-spawn with execa in scripts and package files;
1 parent 338ac31 commit 69ad79a

File tree

5 files changed

+57
-108
lines changed

5 files changed

+57
-108
lines changed

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@
108108
"@qwik.dev/router": "workspace:*",
109109
"@types/brotli": "1.3.4",
110110
"@types/bun": "1.2.21",
111-
"@types/cross-spawn": "6.0.6",
112111
"@types/express": "5.0.3",
113112
"@types/node": "24.3.0",
114113
"@types/path-browserify": "1.0.3",
@@ -122,7 +121,6 @@
122121
"all-contributors-cli": "6.26.1",
123122
"brotli": "1.3.3",
124123
"create-qwik": "workspace:*",
125-
"cross-spawn": "7.0.6",
126124
"csstype": "3.1.3",
127125
"dotenv": "16.5.0",
128126
"esbuild": "0.25.10",

packages/qwik/src/cli/utils/utils.ts

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,36 @@
11
import { blue, gray, green, magenta, red, reset, white } from 'kleur/colors';
22
import { log, outro } from '@clack/prompts';
3-
4-
import type { ChildProcess } from 'node:child_process';
53
import type { IntegrationPackageJson } from '../types';
64
import detectPackageManager from 'which-pm-runs';
75
import fs from 'node:fs';
86
import { join } from 'node:path';
9-
import spawn from 'cross-spawn';
10-
7+
import { execa } from 'execa';
118
export function runCommand(cmd: string, args: string[], cwd: string) {
12-
let child: ChildProcess;
13-
14-
const install = new Promise<boolean>((resolve) => {
15-
try {
16-
child = spawn(cmd, args, {
17-
cwd,
18-
stdio: 'ignore',
19-
});
20-
21-
child.on('error', (e) => {
22-
if (e) {
23-
if (e.message) {
24-
log.error(red(String(e.message)) + `\n\n`);
25-
} else {
26-
log.error(red(String(e)) + `\n\n`);
27-
}
28-
}
29-
resolve(false);
30-
});
9+
const child = execa(cmd, args, {
10+
cwd,
11+
stdio: 'ignore',
12+
});
3113

32-
child.on('close', (code) => {
33-
if (code === 0) {
34-
resolve(true);
14+
const install: Promise<boolean> = child
15+
.then(() => {
16+
return true;
17+
})
18+
.catch((e) => {
19+
if (e) {
20+
if (e.message) {
21+
log.error(red(String(e.message)) + `\n\n`);
3522
} else {
36-
resolve(false);
23+
log.error(red(String(e)) + `\n\n`);
3724
}
38-
});
39-
} catch (e) {
40-
resolve(false);
41-
}
42-
});
25+
}
26+
return false;
27+
});
4328

4429
const abort = async () => {
45-
if (child) {
46-
child.kill('SIGINT');
47-
}
30+
child.kill('SIGINT');
4831
};
4932

33+
// 5. Return the object synchronously
5034
return { abort, install };
5135
}
5236

scripts/binding-platform.ts

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,36 @@
1-
import spawn from 'cross-spawn';
1+
import { execa } from 'execa';
22
import { copyFile, writeFile } from 'fs/promises';
33
import { existsSync } from 'node:fs';
44
import { join } from 'node:path';
55
import { ensureDir, type BuildConfig } from './util';
66

77
export async function buildPlatformBinding(config: BuildConfig) {
8-
await new Promise((resolve, reject) => {
9-
try {
10-
ensureDir(config.distQwikPkgDir);
11-
ensureDir(config.distBindingsDir);
12-
13-
const cmd = `napi`;
14-
const args = [
15-
`build`,
16-
`--cargo-name`,
17-
'qwik_napi',
18-
`--platform`,
19-
`--config=packages/qwik/src/napi/napi.config.json`,
20-
config.distBindingsDir,
21-
];
22-
23-
if (config.platformTarget) {
24-
args.push(`--target`, config.platformTarget);
25-
}
26-
if (!config.dev) {
27-
args.push(`--release`);
28-
args.push(`--strip`);
29-
}
8+
ensureDir(config.distQwikPkgDir);
9+
ensureDir(config.distBindingsDir);
3010

31-
const napiCwd = join(config.rootDir);
11+
const cmd = `napi`;
12+
const args = [
13+
`build`,
14+
`--cargo-name`,
15+
'qwik_napi',
16+
`--platform`,
17+
`--config=packages/qwik/src/napi/napi.config.json`,
18+
config.distBindingsDir,
19+
];
20+
21+
if (config.platformTarget) {
22+
args.push(`--target`, config.platformTarget);
23+
}
24+
if (!config.dev) {
25+
args.push(`--release`);
26+
args.push(`--strip`);
27+
}
3228

33-
const child = spawn(cmd, args, { stdio: 'inherit', cwd: napiCwd });
34-
child.on('error', reject);
29+
const napiCwd = join(config.rootDir);
3530

36-
child.on('close', (code) => {
37-
if (code === 0) {
38-
resolve(child.stdout);
39-
} else {
40-
reject(`napi exited with code ${code}`);
41-
}
42-
});
43-
} catch (e) {
44-
reject(e);
45-
}
31+
await execa(cmd, args, {
32+
stdio: 'inherit',
33+
cwd: napiCwd,
4634
});
4735

4836
console.log('🐯 native binding');
@@ -99,21 +87,7 @@ export async function copyPlatformBindingWasm(config: BuildConfig) {
9987
// now unpack the package using tar, into the cache directory
10088
const unpackedPath = join(cacheDir, `${realPackageName}-unpacked`);
10189
ensureDir(unpackedPath);
102-
await new Promise((resolve, reject) => {
103-
const child = spawn('tar', ['-xvf', cachedPath, '-C', unpackedPath]);
104-
child.on('error', (e) => {
105-
console.error(e);
106-
reject(e);
107-
});
108-
child.on('close', (code) => {
109-
if (code === 0) {
110-
resolve(child.stdout);
111-
} else {
112-
console.error(child.stdout);
113-
reject(`tar exited with code ${code}`);
114-
}
115-
});
116-
});
90+
await execa('tar', ['-xvf', cachedPath, '-C', unpackedPath]);
11791

11892
// now we need to find the bindings in the package
11993
cacheVersionDir = join(unpackedPath, 'package', 'bindings');

scripts/binding-wasm.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type BuildConfig, copyFile, emptyDir, ensureDir } from './util';
2-
import spawn from 'cross-spawn';
2+
import { execa } from 'execa';
33
import { join } from 'node:path';
44
import { rollup } from 'rollup';
55

@@ -18,25 +18,18 @@ export async function buildWasmBinding(config: BuildConfig) {
1818
args.push(`--release`);
1919
}
2020

21-
await new Promise((resolve, reject) => {
22-
const child = spawn(cmd, args, {
23-
stdio: 'inherit',
24-
shell: true,
25-
env: {
26-
...process.env,
27-
...env,
28-
},
29-
});
30-
child.on('error', reject);
31-
32-
child.on('close', (code) => {
33-
if (code === 0) {
34-
resolve(child.stdout);
35-
} else {
36-
reject(`wasm-pack exited with code ${code}`);
37-
}
38-
});
21+
// 2. Replace the entire Promise wrapper with one line
22+
// execa handles errors and non-zero exit codes automatically.
23+
await execa(cmd, args, {
24+
stdio: 'inherit', // 'inherit' is still used to show build output
25+
shell: true,
26+
env: {
27+
...process.env,
28+
...env,
29+
},
3930
});
31+
32+
// 3. The return statement is unchanged
4033
return join(tmpBuildDir, 'qwik_wasm.js');
4134
}
4235

scripts/submodule-cli.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function submoduleCli(config: BuildConfig) {
3535
},
3636
},
3737
],
38-
external: ['prettier', 'typescript', 'ts-morph', 'semver', 'ignore'],
38+
external: ['prettier', 'typescript', 'ts-morph', 'semver', 'ignore', 'execa'],
3939
define: {
4040
'globalThis.CODE_MOD': 'true',
4141
'globalThis.QWIK_VERSION': JSON.stringify(config.distVersion),

0 commit comments

Comments
 (0)