|
5 | 5 |
|
6 | 6 | import * as fs from 'fs/promises'; |
7 | 7 | import * as path from 'path'; |
8 | | -import { execa, type ResultPromise } from 'execa'; |
| 8 | +import { spawn, type ChildProcess } from 'child_process'; |
| 9 | +import { execa } from 'execa'; |
9 | 10 | import { OutputHelper } from '@quenty/cli-output-helpers'; |
10 | 11 |
|
11 | 12 | // --------------------------------------------------------------------------- |
@@ -93,31 +94,31 @@ export function findPluginsFolder(): string { |
93 | 94 |
|
94 | 95 | export interface StudioProcess { |
95 | 96 | /** The underlying child process handle */ |
96 | | - process: ResultPromise; |
| 97 | + process: ChildProcess; |
97 | 98 | /** Kill the Studio process (idempotent, best-effort) */ |
98 | 99 | killAsync: () => Promise<void>; |
99 | 100 | } |
100 | 101 |
|
101 | 102 | /** |
102 | 103 | * Launch Roblox Studio with the given place file. |
| 104 | + * |
| 105 | + * Uses Node's built-in `spawn` with `detached: true` + `unref()` so that |
| 106 | + * Studio survives after the CLI process exits. execa's internal Job Object |
| 107 | + * on Windows kills children on parent exit, so we avoid it here. |
103 | 108 | */ |
104 | 109 | export async function launchStudioAsync( |
105 | 110 | placePath: string |
106 | 111 | ): Promise<StudioProcess> { |
107 | 112 | const studioExe = await findStudioPathAsync(); |
108 | 113 | OutputHelper.verbose(`[StudioBridge] ${studioExe} "${placePath}"`); |
109 | 114 |
|
110 | | - const proc = execa(studioExe, [placePath], { |
111 | | - // Don't tie Studio's lifetime to our process |
| 115 | + const proc = spawn(studioExe, placePath ? [placePath] : [], { |
112 | 116 | detached: true, |
113 | | - // Don't wait for stdio |
114 | 117 | stdio: 'ignore', |
115 | | - // Don't reject on non-zero exit |
116 | | - reject: false, |
117 | 118 | }); |
118 | 119 |
|
119 | | - // Allow our Node process to exit even if Studio is still running |
120 | | - proc.unref?.(); |
| 120 | + // Allow our Node process to exit without waiting for Studio |
| 121 | + proc.unref(); |
121 | 122 |
|
122 | 123 | let killed = false; |
123 | 124 | const killAsync = async () => { |
|
0 commit comments