launch-unity 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/launch.d.ts +1 -30
- package/dist/launch.d.ts.map +1 -1
- package/dist/launch.js +15 -619
- package/dist/lib.d.ts +32 -0
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +63 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Exports core functions for programmatic usage.
|
|
4
4
|
* Uses lib.ts which has no CLI side effects.
|
|
5
5
|
*/
|
|
6
|
-
export { LaunchOptions, LaunchResolvedOptions, UnityProcessInfo, parseArgs, findUnityProjectBfs, getUnityVersion, launch, findRunningUnityProcess, focusUnityProcess, killRunningUnity, quitRunningUnity, handleStaleLockfile, ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs, } from './lib.js';
|
|
6
|
+
export { LaunchOptions, LaunchResolvedOptions, UnityProcessInfo, OrchestrateOptions, OrchestrateResult, parseArgs, findUnityProjectBfs, getUnityVersion, launch, orchestrateLaunch, findRunningUnityProcess, focusUnityProcess, killRunningUnity, quitRunningUnity, handleStaleLockfile, ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs, } from './lib.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,aAAa,EACb,qBAAqB,EACrB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EAEjB,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,MAAM,EACN,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,2BAA2B,EAC3B,0BAA0B,EAC1B,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACb,MAAM,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export {
|
|
7
7
|
// Functions
|
|
8
|
-
parseArgs, findUnityProjectBfs, getUnityVersion, launch, findRunningUnityProcess, focusUnityProcess, killRunningUnity, quitRunningUnity, handleStaleLockfile, ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs, } from './lib.js';
|
|
8
|
+
parseArgs, findUnityProjectBfs, getUnityVersion, launch, orchestrateLaunch, findRunningUnityProcess, focusUnityProcess, killRunningUnity, quitRunningUnity, handleStaleLockfile, ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs, } from './lib.js';
|
package/dist/launch.d.ts
CHANGED
|
@@ -1,32 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export
|
|
3
|
-
subcommand?: "update";
|
|
4
|
-
projectPath?: string;
|
|
5
|
-
platform?: string | undefined;
|
|
6
|
-
unityArgs: string[];
|
|
7
|
-
searchMaxDepth: number;
|
|
8
|
-
restart: boolean;
|
|
9
|
-
quit: boolean;
|
|
10
|
-
addUnityHub: boolean;
|
|
11
|
-
favoriteUnityHub: boolean;
|
|
12
|
-
};
|
|
13
|
-
export type LaunchResolvedOptions = {
|
|
14
|
-
projectPath: string;
|
|
15
|
-
platform?: string | undefined;
|
|
16
|
-
unityArgs: string[];
|
|
17
|
-
unityVersion: string;
|
|
18
|
-
};
|
|
19
|
-
export type UnityProcessInfo = {
|
|
20
|
-
pid: number;
|
|
21
|
-
projectPath: string;
|
|
22
|
-
};
|
|
23
|
-
export declare function parseArgs(argv: string[]): LaunchOptions;
|
|
24
|
-
export declare function getUnityVersion(projectPath: string): string;
|
|
25
|
-
export declare function findRunningUnityProcess(projectPath: string): Promise<UnityProcessInfo | undefined>;
|
|
26
|
-
export declare function focusUnityProcess(pid: number): Promise<void>;
|
|
27
|
-
export declare function handleStaleLockfile(projectPath: string): Promise<void>;
|
|
28
|
-
export declare function killRunningUnity(projectPath: string): Promise<void>;
|
|
29
|
-
export declare function quitRunningUnity(projectPath: string): Promise<void>;
|
|
30
|
-
export declare function findUnityProjectBfs(rootDir: string, maxDepth: number): string | undefined;
|
|
31
|
-
export declare function launch(opts: LaunchResolvedOptions): Promise<void>;
|
|
2
|
+
export {};
|
|
32
3
|
//# sourceMappingURL=launch.d.ts.map
|
package/dist/launch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":""}
|
package/dist/launch.js
CHANGED
|
@@ -3,22 +3,11 @@
|
|
|
3
3
|
launch-unity: Open a Unity project with the matching Editor version.
|
|
4
4
|
Platforms: macOS, Windows
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { rm } from "node:fs/promises";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
9
8
|
import { dirname, join, resolve } from "node:path";
|
|
10
9
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
|
-
import {
|
|
12
|
-
import { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, groupCliArgs } from "./unityHub.js";
|
|
13
|
-
const execFileAsync = promisify(execFile);
|
|
14
|
-
const UNITY_EXECUTABLE_PATTERN_MAC = /Unity\.app\/Contents\/MacOS\/Unity/i;
|
|
15
|
-
const UNITY_EXECUTABLE_PATTERN_WINDOWS = /Unity\.exe/i;
|
|
16
|
-
const PROJECT_PATH_PATTERN = /-(?:projectPath|projectpath)(?:=|\s+)("[^"]+"|'[^']+'|[^\s"']+)/i;
|
|
17
|
-
const PROCESS_LIST_COMMAND_MAC = "ps";
|
|
18
|
-
const PROCESS_LIST_ARGS_MAC = ["-axo", "pid=,command=", "-ww"];
|
|
19
|
-
const WINDOWS_POWERSHELL = "powershell";
|
|
20
|
-
const UNITY_LOCKFILE_NAME = "UnityLockfile";
|
|
21
|
-
const TEMP_DIRECTORY_NAME = "Temp";
|
|
10
|
+
import { orchestrateLaunch } from "./lib.js";
|
|
22
11
|
const npmExecutableName = () => {
|
|
23
12
|
return process.platform === "win32" ? "npm.cmd" : "npm";
|
|
24
13
|
};
|
|
@@ -130,7 +119,7 @@ const compareSemverTriplet = (left, right) => {
|
|
|
130
119
|
}
|
|
131
120
|
return 0;
|
|
132
121
|
};
|
|
133
|
-
|
|
122
|
+
function parseArgs(argv) {
|
|
134
123
|
const args = argv.slice(2);
|
|
135
124
|
const doubleDashIndex = args.indexOf("--");
|
|
136
125
|
let cliArgs = doubleDashIndex >= 0 ? args.slice(0, doubleDashIndex) : args;
|
|
@@ -284,618 +273,25 @@ Commands:
|
|
|
284
273
|
`;
|
|
285
274
|
process.stdout.write(help);
|
|
286
275
|
}
|
|
287
|
-
export function getUnityVersion(projectPath) {
|
|
288
|
-
const versionFile = join(projectPath, "ProjectSettings", "ProjectVersion.txt");
|
|
289
|
-
if (!existsSync(versionFile)) {
|
|
290
|
-
console.error(`Error: ProjectVersion.txt not found at ${versionFile}`);
|
|
291
|
-
console.error("This does not appear to be a Unity project.");
|
|
292
|
-
process.exit(1);
|
|
293
|
-
}
|
|
294
|
-
const content = readFileSync(versionFile, "utf8");
|
|
295
|
-
const version = content.match(/m_EditorVersion:\s*([^\s\n]+)/)?.[1];
|
|
296
|
-
if (!version) {
|
|
297
|
-
console.error(`Error: Could not extract Unity version from ${versionFile}`);
|
|
298
|
-
process.exit(1);
|
|
299
|
-
}
|
|
300
|
-
return version;
|
|
301
|
-
}
|
|
302
|
-
function getUnityPathWindows(version) {
|
|
303
|
-
const candidates = [];
|
|
304
|
-
const programFiles = process.env["PROGRAMFILES"];
|
|
305
|
-
const programFilesX86 = process.env["PROGRAMFILES(X86)"];
|
|
306
|
-
const localAppData = process.env["LOCALAPPDATA"];
|
|
307
|
-
const addCandidate = (base) => {
|
|
308
|
-
if (!base) {
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
candidates.push(join(base, "Unity", "Hub", "Editor", version, "Editor", "Unity.exe"));
|
|
312
|
-
};
|
|
313
|
-
addCandidate(programFiles);
|
|
314
|
-
addCandidate(programFilesX86);
|
|
315
|
-
addCandidate(localAppData);
|
|
316
|
-
candidates.push(join("C:\\", "Program Files", "Unity", "Hub", "Editor", version, "Editor", "Unity.exe"));
|
|
317
|
-
for (const candidate of candidates) {
|
|
318
|
-
if (existsSync(candidate)) {
|
|
319
|
-
return candidate;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
return candidates[0] ?? join("C:\\", "Program Files", "Unity", "Hub", "Editor", version, "Editor", "Unity.exe");
|
|
323
|
-
}
|
|
324
|
-
function getUnityPath(version) {
|
|
325
|
-
if (process.platform === "darwin") {
|
|
326
|
-
return `/Applications/Unity/Hub/Editor/${version}/Unity.app/Contents/MacOS/Unity`;
|
|
327
|
-
}
|
|
328
|
-
if (process.platform === "win32") {
|
|
329
|
-
return getUnityPathWindows(version);
|
|
330
|
-
}
|
|
331
|
-
return `/Applications/Unity/Hub/Editor/${version}/Unity.app/Contents/MacOS/Unity`;
|
|
332
|
-
}
|
|
333
|
-
function ensureProjectPath(projectPath) {
|
|
334
|
-
if (!existsSync(projectPath)) {
|
|
335
|
-
console.error(`Error: Project directory not found: ${projectPath}`);
|
|
336
|
-
process.exit(1);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
const removeTrailingSeparators = (target) => {
|
|
340
|
-
let trimmed = target;
|
|
341
|
-
while (trimmed.length > 1 && (trimmed.endsWith("/") || trimmed.endsWith("\\"))) {
|
|
342
|
-
trimmed = trimmed.slice(0, -1);
|
|
343
|
-
}
|
|
344
|
-
return trimmed;
|
|
345
|
-
};
|
|
346
|
-
const normalizePath = (target) => {
|
|
347
|
-
const resolvedPath = resolve(target);
|
|
348
|
-
const trimmed = removeTrailingSeparators(resolvedPath);
|
|
349
|
-
return trimmed;
|
|
350
|
-
};
|
|
351
|
-
const toComparablePath = (value) => {
|
|
352
|
-
return value.replace(/\\/g, "/").toLocaleLowerCase();
|
|
353
|
-
};
|
|
354
|
-
const pathsEqual = (left, right) => {
|
|
355
|
-
return toComparablePath(normalizePath(left)) === toComparablePath(normalizePath(right));
|
|
356
|
-
};
|
|
357
|
-
function extractProjectPath(command) {
|
|
358
|
-
const match = command.match(PROJECT_PATH_PATTERN);
|
|
359
|
-
if (!match) {
|
|
360
|
-
return undefined;
|
|
361
|
-
}
|
|
362
|
-
const raw = match[1];
|
|
363
|
-
if (!raw) {
|
|
364
|
-
return undefined;
|
|
365
|
-
}
|
|
366
|
-
const trimmed = raw.trim();
|
|
367
|
-
if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) {
|
|
368
|
-
return trimmed.slice(1, -1);
|
|
369
|
-
}
|
|
370
|
-
if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
371
|
-
return trimmed.slice(1, -1);
|
|
372
|
-
}
|
|
373
|
-
return trimmed;
|
|
374
|
-
}
|
|
375
|
-
const isUnityAuxiliaryProcess = (command) => {
|
|
376
|
-
const normalizedCommand = command.toLowerCase();
|
|
377
|
-
if (normalizedCommand.includes("-batchmode")) {
|
|
378
|
-
return true;
|
|
379
|
-
}
|
|
380
|
-
return normalizedCommand.includes("assetimportworker");
|
|
381
|
-
};
|
|
382
|
-
async function listUnityProcessesMac() {
|
|
383
|
-
let stdout = "";
|
|
384
|
-
try {
|
|
385
|
-
const result = await execFileAsync(PROCESS_LIST_COMMAND_MAC, PROCESS_LIST_ARGS_MAC);
|
|
386
|
-
stdout = result.stdout;
|
|
387
|
-
}
|
|
388
|
-
catch (error) {
|
|
389
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
390
|
-
console.error(`Failed to retrieve Unity process list: ${message}`);
|
|
391
|
-
return [];
|
|
392
|
-
}
|
|
393
|
-
const lines = stdout
|
|
394
|
-
.split("\n")
|
|
395
|
-
.map((line) => line.trim())
|
|
396
|
-
.filter((line) => line.length > 0);
|
|
397
|
-
const processes = [];
|
|
398
|
-
for (const line of lines) {
|
|
399
|
-
const match = line.match(/^(\d+)\s+(.*)$/);
|
|
400
|
-
if (!match) {
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
const pidValue = Number.parseInt(match[1] ?? "", 10);
|
|
404
|
-
if (!Number.isFinite(pidValue)) {
|
|
405
|
-
continue;
|
|
406
|
-
}
|
|
407
|
-
const command = match[2] ?? "";
|
|
408
|
-
if (!UNITY_EXECUTABLE_PATTERN_MAC.test(command)) {
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
if (isUnityAuxiliaryProcess(command)) {
|
|
412
|
-
continue;
|
|
413
|
-
}
|
|
414
|
-
const projectArgument = extractProjectPath(command);
|
|
415
|
-
if (!projectArgument) {
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
processes.push({
|
|
419
|
-
pid: pidValue,
|
|
420
|
-
projectPath: normalizePath(projectArgument),
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
return processes;
|
|
424
|
-
}
|
|
425
|
-
async function listUnityProcessesWindows() {
|
|
426
|
-
const scriptLines = [
|
|
427
|
-
"$ErrorActionPreference = 'Stop'",
|
|
428
|
-
"$processes = Get-CimInstance Win32_Process -Filter \"Name = 'Unity.exe'\" | Where-Object { $_.CommandLine }",
|
|
429
|
-
"foreach ($process in $processes) {",
|
|
430
|
-
" $commandLine = $process.CommandLine -replace \"`r\", ' ' -replace \"`n\", ' '",
|
|
431
|
-
" Write-Output (\"{0}|{1}\" -f $process.ProcessId, $commandLine)",
|
|
432
|
-
"}",
|
|
433
|
-
];
|
|
434
|
-
let stdout = "";
|
|
435
|
-
try {
|
|
436
|
-
const result = await execFileAsync(WINDOWS_POWERSHELL, ["-NoProfile", "-Command", scriptLines.join("\n")]);
|
|
437
|
-
stdout = result.stdout ?? "";
|
|
438
|
-
}
|
|
439
|
-
catch (error) {
|
|
440
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
441
|
-
console.error(`Failed to retrieve Unity process list on Windows: ${message}`);
|
|
442
|
-
return [];
|
|
443
|
-
}
|
|
444
|
-
const lines = stdout
|
|
445
|
-
.split("\n")
|
|
446
|
-
.map((line) => line.trim())
|
|
447
|
-
.filter((line) => line.length > 0);
|
|
448
|
-
const processes = [];
|
|
449
|
-
for (const line of lines) {
|
|
450
|
-
const delimiterIndex = line.indexOf("|");
|
|
451
|
-
if (delimiterIndex < 0) {
|
|
452
|
-
continue;
|
|
453
|
-
}
|
|
454
|
-
const pidText = line.slice(0, delimiterIndex).trim();
|
|
455
|
-
const command = line.slice(delimiterIndex + 1).trim();
|
|
456
|
-
const pidValue = Number.parseInt(pidText, 10);
|
|
457
|
-
if (!Number.isFinite(pidValue)) {
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
if (!UNITY_EXECUTABLE_PATTERN_WINDOWS.test(command)) {
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
if (isUnityAuxiliaryProcess(command)) {
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
const projectArgument = extractProjectPath(command);
|
|
467
|
-
if (!projectArgument) {
|
|
468
|
-
continue;
|
|
469
|
-
}
|
|
470
|
-
processes.push({
|
|
471
|
-
pid: pidValue,
|
|
472
|
-
projectPath: normalizePath(projectArgument),
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
return processes;
|
|
476
|
-
}
|
|
477
|
-
async function listUnityProcesses() {
|
|
478
|
-
if (process.platform === "darwin") {
|
|
479
|
-
return await listUnityProcessesMac();
|
|
480
|
-
}
|
|
481
|
-
if (process.platform === "win32") {
|
|
482
|
-
return await listUnityProcessesWindows();
|
|
483
|
-
}
|
|
484
|
-
return [];
|
|
485
|
-
}
|
|
486
|
-
export async function findRunningUnityProcess(projectPath) {
|
|
487
|
-
const normalizedTarget = normalizePath(projectPath);
|
|
488
|
-
const processes = await listUnityProcesses();
|
|
489
|
-
return processes.find((candidate) => pathsEqual(candidate.projectPath, normalizedTarget));
|
|
490
|
-
}
|
|
491
|
-
export async function focusUnityProcess(pid) {
|
|
492
|
-
if (process.platform === "darwin") {
|
|
493
|
-
await focusUnityProcessMac(pid);
|
|
494
|
-
return;
|
|
495
|
-
}
|
|
496
|
-
if (process.platform === "win32") {
|
|
497
|
-
await focusUnityProcessWindows(pid);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
async function focusUnityProcessMac(pid) {
|
|
501
|
-
const script = `tell application "System Events" to set frontmost of (first process whose unix id is ${pid}) to true`;
|
|
502
|
-
try {
|
|
503
|
-
await execFileAsync("osascript", ["-e", script]);
|
|
504
|
-
console.log("Brought existing Unity to the front.");
|
|
505
|
-
}
|
|
506
|
-
catch (error) {
|
|
507
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
508
|
-
console.warn(`Failed to bring Unity to front: ${message}`);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
async function focusUnityProcessWindows(pid) {
|
|
512
|
-
const addTypeLines = [
|
|
513
|
-
"Add-Type -TypeDefinition @\"",
|
|
514
|
-
"using System;",
|
|
515
|
-
"using System.Runtime.InteropServices;",
|
|
516
|
-
"public static class Win32Interop {",
|
|
517
|
-
" [DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hWnd);",
|
|
518
|
-
" [DllImport(\"user32.dll\")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);",
|
|
519
|
-
"}",
|
|
520
|
-
"\"@",
|
|
521
|
-
];
|
|
522
|
-
const scriptLines = [
|
|
523
|
-
"$ErrorActionPreference = 'Stop'",
|
|
524
|
-
...addTypeLines,
|
|
525
|
-
`try { $process = Get-Process -Id ${pid} -ErrorAction Stop } catch { return }`,
|
|
526
|
-
"$handle = $process.MainWindowHandle",
|
|
527
|
-
"if ($handle -eq 0) { return }",
|
|
528
|
-
"[Win32Interop]::ShowWindowAsync($handle, 9) | Out-Null",
|
|
529
|
-
"[Win32Interop]::SetForegroundWindow($handle) | Out-Null",
|
|
530
|
-
];
|
|
531
|
-
try {
|
|
532
|
-
await execFileAsync(WINDOWS_POWERSHELL, ["-NoProfile", "-Command", scriptLines.join("\n")]);
|
|
533
|
-
console.log("Brought existing Unity to the front.");
|
|
534
|
-
}
|
|
535
|
-
catch (error) {
|
|
536
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
537
|
-
console.warn(`Failed to bring Unity to front on Windows: ${message}`);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
export async function handleStaleLockfile(projectPath) {
|
|
541
|
-
const tempDirectoryPath = join(projectPath, TEMP_DIRECTORY_NAME);
|
|
542
|
-
const lockfilePath = join(tempDirectoryPath, UNITY_LOCKFILE_NAME);
|
|
543
|
-
if (!existsSync(lockfilePath)) {
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
console.log(`UnityLockfile found without active Unity process: ${lockfilePath}`);
|
|
547
|
-
console.log("Assuming previous crash. Cleaning Temp directory and continuing launch.");
|
|
548
|
-
try {
|
|
549
|
-
await rm(tempDirectoryPath, { recursive: true, force: true });
|
|
550
|
-
console.log("Deleted Temp directory.");
|
|
551
|
-
}
|
|
552
|
-
catch (error) {
|
|
553
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
554
|
-
console.warn(`Failed to delete Temp directory: ${message}`);
|
|
555
|
-
}
|
|
556
|
-
try {
|
|
557
|
-
await rm(lockfilePath, { force: true });
|
|
558
|
-
console.log("Deleted UnityLockfile.");
|
|
559
|
-
}
|
|
560
|
-
catch (error) {
|
|
561
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
562
|
-
console.warn(`Failed to delete UnityLockfile: ${message}`);
|
|
563
|
-
}
|
|
564
|
-
console.log();
|
|
565
|
-
}
|
|
566
|
-
const KILL_POLL_INTERVAL_MS = 100;
|
|
567
|
-
const KILL_TIMEOUT_MS = 10000;
|
|
568
|
-
const GRACEFUL_QUIT_TIMEOUT_MS = 10000;
|
|
569
|
-
function isProcessAlive(pid) {
|
|
570
|
-
try {
|
|
571
|
-
process.kill(pid, 0);
|
|
572
|
-
return true;
|
|
573
|
-
}
|
|
574
|
-
catch {
|
|
575
|
-
return false;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
function killProcess(pid) {
|
|
579
|
-
try {
|
|
580
|
-
process.kill(pid, "SIGKILL");
|
|
581
|
-
}
|
|
582
|
-
catch {
|
|
583
|
-
// Process already exited
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
async function waitForProcessExit(pid, timeoutMs) {
|
|
587
|
-
const start = Date.now();
|
|
588
|
-
while (Date.now() - start < timeoutMs) {
|
|
589
|
-
if (!isProcessAlive(pid)) {
|
|
590
|
-
return true;
|
|
591
|
-
}
|
|
592
|
-
await new Promise((resolve) => setTimeout(resolve, KILL_POLL_INTERVAL_MS));
|
|
593
|
-
}
|
|
594
|
-
return false;
|
|
595
|
-
}
|
|
596
|
-
export async function killRunningUnity(projectPath) {
|
|
597
|
-
const processInfo = await findRunningUnityProcess(projectPath);
|
|
598
|
-
if (!processInfo) {
|
|
599
|
-
console.log("No running Unity process found for this project.");
|
|
600
|
-
console.log();
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
const pid = processInfo.pid;
|
|
604
|
-
console.log(`Killing Unity (PID: ${pid})...`);
|
|
605
|
-
killProcess(pid);
|
|
606
|
-
const exited = await waitForProcessExit(pid, KILL_TIMEOUT_MS);
|
|
607
|
-
if (!exited) {
|
|
608
|
-
console.error(`Error: Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1000}s.`);
|
|
609
|
-
process.exit(1);
|
|
610
|
-
}
|
|
611
|
-
console.log("Unity killed.");
|
|
612
|
-
console.log();
|
|
613
|
-
}
|
|
614
|
-
async function sendGracefulQuitMac(pid) {
|
|
615
|
-
// System Events quit and "tell application to quit" leave UnityLockfile behind,
|
|
616
|
-
// so we send Cmd+Q keystroke to trigger Unity's normal user-initiated shutdown flow
|
|
617
|
-
const script = [
|
|
618
|
-
'tell application "System Events"',
|
|
619
|
-
` set frontmost of (first process whose unix id is ${pid}) to true`,
|
|
620
|
-
' keystroke "q" using {command down}',
|
|
621
|
-
"end tell",
|
|
622
|
-
].join("\n");
|
|
623
|
-
try {
|
|
624
|
-
await execFileAsync("osascript", ["-e", script]);
|
|
625
|
-
}
|
|
626
|
-
catch {
|
|
627
|
-
// Process may have already exited
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
async function sendGracefulQuitWindows(pid) {
|
|
631
|
-
// process.kill(pid, "SIGTERM") forcefully kills on Windows, so use CloseMainWindow() to send WM_CLOSE
|
|
632
|
-
const scriptLines = [
|
|
633
|
-
"$ErrorActionPreference = 'Stop'",
|
|
634
|
-
`try { $proc = Get-Process -Id ${pid} -ErrorAction Stop; $proc.CloseMainWindow() | Out-Null } catch { }`,
|
|
635
|
-
];
|
|
636
|
-
try {
|
|
637
|
-
await execFileAsync(WINDOWS_POWERSHELL, ["-NoProfile", "-Command", scriptLines.join("\n")]);
|
|
638
|
-
}
|
|
639
|
-
catch {
|
|
640
|
-
// Process may have already exited
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
async function sendGracefulQuit(pid) {
|
|
644
|
-
if (process.platform === "darwin") {
|
|
645
|
-
await sendGracefulQuitMac(pid);
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
|
-
if (process.platform === "win32") {
|
|
649
|
-
await sendGracefulQuitWindows(pid);
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
export async function quitRunningUnity(projectPath) {
|
|
654
|
-
const processInfo = await findRunningUnityProcess(projectPath);
|
|
655
|
-
if (!processInfo) {
|
|
656
|
-
console.log("No running Unity process found for this project.");
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
const pid = processInfo.pid;
|
|
660
|
-
console.log(`Quitting Unity (PID: ${pid})...`);
|
|
661
|
-
await sendGracefulQuit(pid);
|
|
662
|
-
console.log(`Sent graceful quit signal. Waiting up to ${GRACEFUL_QUIT_TIMEOUT_MS / 1000}s...`);
|
|
663
|
-
const exitedGracefully = await waitForProcessExit(pid, GRACEFUL_QUIT_TIMEOUT_MS);
|
|
664
|
-
if (exitedGracefully) {
|
|
665
|
-
console.log("Unity quit gracefully.");
|
|
666
|
-
return;
|
|
667
|
-
}
|
|
668
|
-
console.log("Unity did not respond to graceful quit. Force killing...");
|
|
669
|
-
killProcess(pid);
|
|
670
|
-
const exitedAfterKill = await waitForProcessExit(pid, KILL_TIMEOUT_MS);
|
|
671
|
-
if (!exitedAfterKill) {
|
|
672
|
-
console.error(`Error: Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1000}s.`);
|
|
673
|
-
process.exit(1);
|
|
674
|
-
}
|
|
675
|
-
console.log("Unity force killed.");
|
|
676
|
-
}
|
|
677
|
-
function hasBuildTargetArg(unityArgs) {
|
|
678
|
-
for (const arg of unityArgs) {
|
|
679
|
-
if (arg === "-buildTarget") {
|
|
680
|
-
return true;
|
|
681
|
-
}
|
|
682
|
-
if (arg.startsWith("-buildTarget=")) {
|
|
683
|
-
return true;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
return false;
|
|
687
|
-
}
|
|
688
|
-
const EXCLUDED_DIR_NAMES = new Set([
|
|
689
|
-
"library",
|
|
690
|
-
"temp",
|
|
691
|
-
"logs",
|
|
692
|
-
"obj",
|
|
693
|
-
".git",
|
|
694
|
-
"node_modules",
|
|
695
|
-
".idea",
|
|
696
|
-
".vscode",
|
|
697
|
-
".vs",
|
|
698
|
-
]);
|
|
699
|
-
function isUnityProjectRoot(candidateDir) {
|
|
700
|
-
const versionFile = join(candidateDir, "ProjectSettings", "ProjectVersion.txt");
|
|
701
|
-
return existsSync(versionFile);
|
|
702
|
-
}
|
|
703
|
-
function listSubdirectoriesSorted(dir) {
|
|
704
|
-
let entries = [];
|
|
705
|
-
try {
|
|
706
|
-
const dirents = readdirSync(dir, { withFileTypes: true });
|
|
707
|
-
const subdirs = dirents
|
|
708
|
-
.filter((d) => d.isDirectory())
|
|
709
|
-
.map((d) => d.name)
|
|
710
|
-
.filter((name) => !EXCLUDED_DIR_NAMES.has(name.toLocaleLowerCase()));
|
|
711
|
-
subdirs.sort((a, b) => a.localeCompare(b));
|
|
712
|
-
entries = subdirs.map((name) => join(dir, name));
|
|
713
|
-
}
|
|
714
|
-
catch {
|
|
715
|
-
// Ignore directories we cannot read
|
|
716
|
-
entries = [];
|
|
717
|
-
}
|
|
718
|
-
return entries;
|
|
719
|
-
}
|
|
720
|
-
export function findUnityProjectBfs(rootDir, maxDepth) {
|
|
721
|
-
const queue = [];
|
|
722
|
-
let rootCanonical;
|
|
723
|
-
try {
|
|
724
|
-
rootCanonical = realpathSync(rootDir);
|
|
725
|
-
}
|
|
726
|
-
catch {
|
|
727
|
-
rootCanonical = rootDir;
|
|
728
|
-
}
|
|
729
|
-
queue.push({ dir: rootCanonical, depth: 0 });
|
|
730
|
-
const visited = new Set([toComparablePath(normalizePath(rootCanonical))]);
|
|
731
|
-
while (queue.length > 0) {
|
|
732
|
-
const current = queue.shift();
|
|
733
|
-
if (!current) {
|
|
734
|
-
continue;
|
|
735
|
-
}
|
|
736
|
-
const { dir, depth } = current;
|
|
737
|
-
if (isUnityProjectRoot(dir)) {
|
|
738
|
-
return normalizePath(dir);
|
|
739
|
-
}
|
|
740
|
-
const canDescend = maxDepth === -1 || depth < maxDepth;
|
|
741
|
-
if (!canDescend) {
|
|
742
|
-
continue;
|
|
743
|
-
}
|
|
744
|
-
const children = listSubdirectoriesSorted(dir);
|
|
745
|
-
for (const child of children) {
|
|
746
|
-
let childCanonical = child;
|
|
747
|
-
try {
|
|
748
|
-
const stat = lstatSync(child);
|
|
749
|
-
if (stat.isSymbolicLink()) {
|
|
750
|
-
try {
|
|
751
|
-
childCanonical = realpathSync(child);
|
|
752
|
-
}
|
|
753
|
-
catch {
|
|
754
|
-
// Broken symlink: skip
|
|
755
|
-
continue;
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
catch {
|
|
760
|
-
continue;
|
|
761
|
-
}
|
|
762
|
-
const key = toComparablePath(normalizePath(childCanonical));
|
|
763
|
-
if (visited.has(key)) {
|
|
764
|
-
continue;
|
|
765
|
-
}
|
|
766
|
-
visited.add(key);
|
|
767
|
-
queue.push({ dir: childCanonical, depth: depth + 1 });
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
return undefined;
|
|
771
|
-
}
|
|
772
|
-
export async function launch(opts) {
|
|
773
|
-
const { projectPath, platform, unityArgs, unityVersion } = opts;
|
|
774
|
-
const unityPath = getUnityPath(unityVersion);
|
|
775
|
-
if (!existsSync(unityPath)) {
|
|
776
|
-
console.error(`Error: Unity ${unityVersion} not found at ${unityPath}`);
|
|
777
|
-
console.error("Please install Unity through Unity Hub.");
|
|
778
|
-
process.exit(1);
|
|
779
|
-
}
|
|
780
|
-
console.log("Opening Unity...");
|
|
781
|
-
console.log(`Project Path: ${projectPath}`);
|
|
782
|
-
console.log(`Detected Unity version: ${unityVersion}`);
|
|
783
|
-
const args = ["-projectPath", projectPath];
|
|
784
|
-
const unityArgsContainBuildTarget = hasBuildTargetArg(unityArgs);
|
|
785
|
-
if (platform && platform.length > 0 && !unityArgsContainBuildTarget) {
|
|
786
|
-
args.push("-buildTarget", platform);
|
|
787
|
-
}
|
|
788
|
-
const hubCliArgs = await getProjectCliArgs(projectPath);
|
|
789
|
-
if (hubCliArgs.length > 0) {
|
|
790
|
-
console.log("Unity Hub launch options:");
|
|
791
|
-
for (const line of groupCliArgs(hubCliArgs)) {
|
|
792
|
-
console.log(` ${line}`);
|
|
793
|
-
}
|
|
794
|
-
args.push(...hubCliArgs);
|
|
795
|
-
}
|
|
796
|
-
else {
|
|
797
|
-
console.log("Unity Hub launch options: none");
|
|
798
|
-
}
|
|
799
|
-
if (unityArgs.length > 0) {
|
|
800
|
-
args.push(...unityArgs);
|
|
801
|
-
}
|
|
802
|
-
return new Promise((resolve, reject) => {
|
|
803
|
-
const child = spawn(unityPath, args, {
|
|
804
|
-
stdio: "ignore",
|
|
805
|
-
detached: true,
|
|
806
|
-
// Git Bash (MSYS) がWindows パスをUnix 形式に自動変換するのを防ぐ
|
|
807
|
-
env: {
|
|
808
|
-
...process.env,
|
|
809
|
-
MSYS_NO_PATHCONV: "1",
|
|
810
|
-
},
|
|
811
|
-
});
|
|
812
|
-
const handleError = (error) => {
|
|
813
|
-
child.removeListener("spawn", handleSpawn);
|
|
814
|
-
reject(new Error(`Failed to launch Unity: ${error.message}`));
|
|
815
|
-
};
|
|
816
|
-
const handleSpawn = () => {
|
|
817
|
-
child.removeListener("error", handleError);
|
|
818
|
-
child.unref();
|
|
819
|
-
resolve();
|
|
820
|
-
};
|
|
821
|
-
child.once("error", handleError);
|
|
822
|
-
child.once("spawn", handleSpawn);
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
276
|
async function main() {
|
|
826
277
|
const options = parseArgs(process.argv);
|
|
827
278
|
if (options.subcommand === "update") {
|
|
828
279
|
await runSelfUpdate();
|
|
829
280
|
return;
|
|
830
281
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
console.log(`Searching for Unity project under ${searchRoot} (max-depth: ${depthInfo})...`);
|
|
836
|
-
const found = findUnityProjectBfs(searchRoot, options.searchMaxDepth);
|
|
837
|
-
if (!found) {
|
|
838
|
-
console.error(`Error: Unity project not found under ${searchRoot}.`);
|
|
839
|
-
process.exit(1);
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
console.log();
|
|
843
|
-
resolvedProjectPath = found;
|
|
844
|
-
}
|
|
845
|
-
ensureProjectPath(resolvedProjectPath);
|
|
846
|
-
const unityVersion = getUnityVersion(resolvedProjectPath);
|
|
847
|
-
// Unity Hub only mode: -a or -f flags skip launching Unity
|
|
848
|
-
const unityHubOnlyMode = options.addUnityHub || options.favoriteUnityHub;
|
|
849
|
-
if (unityHubOnlyMode) {
|
|
850
|
-
console.log(`Detected Unity version: ${unityVersion}`);
|
|
851
|
-
console.log(`Project Path: ${resolvedProjectPath}`);
|
|
852
|
-
const now = new Date();
|
|
853
|
-
try {
|
|
854
|
-
await ensureProjectEntryAndUpdate(resolvedProjectPath, unityVersion, now, options.favoriteUnityHub);
|
|
855
|
-
console.log("Unity Hub entry updated.");
|
|
856
|
-
}
|
|
857
|
-
catch (error) {
|
|
858
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
859
|
-
console.warn(`Failed to update Unity Hub: ${message}`);
|
|
860
|
-
}
|
|
861
|
-
return;
|
|
862
|
-
}
|
|
863
|
-
if (options.quit && options.restart) {
|
|
864
|
-
console.error("Error: --quit and --restart cannot be used together.");
|
|
865
|
-
process.exit(1);
|
|
866
|
-
}
|
|
867
|
-
if (options.quit) {
|
|
868
|
-
await quitRunningUnity(resolvedProjectPath);
|
|
869
|
-
return;
|
|
870
|
-
}
|
|
871
|
-
if (options.restart) {
|
|
872
|
-
await killRunningUnity(resolvedProjectPath);
|
|
873
|
-
}
|
|
874
|
-
else {
|
|
875
|
-
const runningProcess = await findRunningUnityProcess(resolvedProjectPath);
|
|
876
|
-
if (runningProcess) {
|
|
877
|
-
console.log(`Unity process already running for project: ${resolvedProjectPath} (PID: ${runningProcess.pid})`);
|
|
878
|
-
await focusUnityProcess(runningProcess.pid);
|
|
879
|
-
process.exit(0);
|
|
880
|
-
return;
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
await handleStaleLockfile(resolvedProjectPath);
|
|
884
|
-
const resolved = {
|
|
885
|
-
projectPath: resolvedProjectPath,
|
|
282
|
+
const result = await orchestrateLaunch({
|
|
283
|
+
projectPath: options.projectPath,
|
|
284
|
+
searchRoot: process.cwd(),
|
|
285
|
+
searchMaxDepth: options.searchMaxDepth,
|
|
886
286
|
platform: options.platform,
|
|
887
287
|
unityArgs: options.unityArgs,
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
}
|
|
896
|
-
catch (error) {
|
|
897
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
898
|
-
console.warn(`Failed to update Unity Hub lastModified: ${message}`);
|
|
288
|
+
restart: options.restart,
|
|
289
|
+
quit: options.quit,
|
|
290
|
+
addUnityHub: options.addUnityHub,
|
|
291
|
+
favoriteUnityHub: options.favoriteUnityHub,
|
|
292
|
+
});
|
|
293
|
+
if (result.action === "focused") {
|
|
294
|
+
process.exit(0);
|
|
899
295
|
}
|
|
900
296
|
}
|
|
901
297
|
async function runSelfUpdate() {
|
package/dist/lib.d.ts
CHANGED
|
@@ -33,5 +33,37 @@ export declare function killRunningUnity(projectPath: string): Promise<void>;
|
|
|
33
33
|
export declare function quitRunningUnity(projectPath: string): Promise<void>;
|
|
34
34
|
export declare function findUnityProjectBfs(rootDir: string, maxDepth: number): string | undefined;
|
|
35
35
|
export declare function launch(opts: LaunchResolvedOptions): Promise<void>;
|
|
36
|
+
export type OrchestrateOptions = {
|
|
37
|
+
projectPath?: string | undefined;
|
|
38
|
+
searchRoot: string;
|
|
39
|
+
searchMaxDepth: number;
|
|
40
|
+
platform?: string | undefined;
|
|
41
|
+
unityArgs: string[];
|
|
42
|
+
restart: boolean;
|
|
43
|
+
quit: boolean;
|
|
44
|
+
addUnityHub: boolean;
|
|
45
|
+
favoriteUnityHub: boolean;
|
|
46
|
+
};
|
|
47
|
+
export type OrchestrateResult = {
|
|
48
|
+
action: "launched";
|
|
49
|
+
projectPath: string;
|
|
50
|
+
unityVersion: string;
|
|
51
|
+
} | {
|
|
52
|
+
action: "focused";
|
|
53
|
+
projectPath: string;
|
|
54
|
+
pid: number;
|
|
55
|
+
} | {
|
|
56
|
+
action: "quit";
|
|
57
|
+
projectPath: string;
|
|
58
|
+
} | {
|
|
59
|
+
action: "killed-and-launched";
|
|
60
|
+
projectPath: string;
|
|
61
|
+
unityVersion: string;
|
|
62
|
+
} | {
|
|
63
|
+
action: "hub-updated";
|
|
64
|
+
projectPath: string;
|
|
65
|
+
unityVersion: string;
|
|
66
|
+
};
|
|
67
|
+
export declare function orchestrateLaunch(options: OrchestrateOptions): Promise<OrchestrateResult>;
|
|
36
68
|
export { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs };
|
|
37
69
|
//# sourceMappingURL=lib.d.ts.map
|
package/dist/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEvI,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,CAAC,EAAE,QAAQ,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAYF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAyHvD;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAc3D;AAoND,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAIxG;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlE;AA4CD,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B5E;AAkCD,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBzE;AA0CD,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BzE;AAgDD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAqDzF;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6DvE;AAGD,OAAO,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"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"}
|
package/dist/lib.js
CHANGED
|
@@ -656,5 +656,68 @@ export async function launch(opts) {
|
|
|
656
656
|
child.once("spawn", handleSpawn);
|
|
657
657
|
});
|
|
658
658
|
}
|
|
659
|
+
export async function orchestrateLaunch(options) {
|
|
660
|
+
if (options.quit && options.restart) {
|
|
661
|
+
throw new Error("--quit and --restart cannot be used together.");
|
|
662
|
+
}
|
|
663
|
+
let resolvedProjectPath = options.projectPath;
|
|
664
|
+
if (!resolvedProjectPath) {
|
|
665
|
+
const depthInfo = options.searchMaxDepth === -1 ? "unlimited" : String(options.searchMaxDepth);
|
|
666
|
+
console.log(`Searching for Unity project under ${options.searchRoot} (max-depth: ${depthInfo})...`);
|
|
667
|
+
const found = findUnityProjectBfs(options.searchRoot, options.searchMaxDepth);
|
|
668
|
+
if (!found) {
|
|
669
|
+
throw new Error(`Unity project not found under ${options.searchRoot}.`);
|
|
670
|
+
}
|
|
671
|
+
console.log();
|
|
672
|
+
resolvedProjectPath = found;
|
|
673
|
+
}
|
|
674
|
+
if (!existsSync(resolvedProjectPath)) {
|
|
675
|
+
throw new Error(`Project directory not found: ${resolvedProjectPath}`);
|
|
676
|
+
}
|
|
677
|
+
const unityVersion = getUnityVersion(resolvedProjectPath);
|
|
678
|
+
if (options.addUnityHub || options.favoriteUnityHub) {
|
|
679
|
+
console.log(`Detected Unity version: ${unityVersion}`);
|
|
680
|
+
console.log(`Project Path: ${resolvedProjectPath}`);
|
|
681
|
+
const now = new Date();
|
|
682
|
+
await ensureProjectEntryAndUpdate(resolvedProjectPath, unityVersion, now, options.favoriteUnityHub);
|
|
683
|
+
console.log("Unity Hub entry updated.");
|
|
684
|
+
return { action: "hub-updated", projectPath: resolvedProjectPath, unityVersion };
|
|
685
|
+
}
|
|
686
|
+
if (options.quit) {
|
|
687
|
+
await quitRunningUnity(resolvedProjectPath);
|
|
688
|
+
return { action: "quit", projectPath: resolvedProjectPath };
|
|
689
|
+
}
|
|
690
|
+
const isRestart = options.restart;
|
|
691
|
+
if (isRestart) {
|
|
692
|
+
await killRunningUnity(resolvedProjectPath);
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
const runningProcess = await findRunningUnityProcess(resolvedProjectPath);
|
|
696
|
+
if (runningProcess) {
|
|
697
|
+
console.log(`Unity process already running for project: ${resolvedProjectPath} (PID: ${runningProcess.pid})`);
|
|
698
|
+
await focusUnityProcess(runningProcess.pid);
|
|
699
|
+
return { action: "focused", projectPath: resolvedProjectPath, pid: runningProcess.pid };
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
await handleStaleLockfile(resolvedProjectPath);
|
|
703
|
+
const resolved = {
|
|
704
|
+
projectPath: resolvedProjectPath,
|
|
705
|
+
platform: options.platform,
|
|
706
|
+
unityArgs: options.unityArgs,
|
|
707
|
+
unityVersion,
|
|
708
|
+
};
|
|
709
|
+
await launch(resolved);
|
|
710
|
+
// Hub timestamp update is non-critical external I/O; failure should not block after successful launch
|
|
711
|
+
const now = new Date();
|
|
712
|
+
try {
|
|
713
|
+
await updateLastModifiedIfExists(resolvedProjectPath, now);
|
|
714
|
+
}
|
|
715
|
+
catch (error) {
|
|
716
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
717
|
+
console.warn(`Failed to update Unity Hub lastModified: ${message}`);
|
|
718
|
+
}
|
|
719
|
+
const action = isRestart ? "killed-and-launched" : "launched";
|
|
720
|
+
return { action, projectPath: resolvedProjectPath, unityVersion };
|
|
721
|
+
}
|
|
659
722
|
// Re-export Unity Hub functions
|
|
660
723
|
export { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs };
|