launch-unity 0.12.0 → 0.14.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 +3 -1
- package/dist/launch.d.ts.map +1 -1
- package/dist/launch.js +124 -11
- package/dist/lib.d.ts +5 -3
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +112 -9
- package/dist/unityHub.d.ts +3 -0
- package/dist/unityHub.d.ts.map +1 -1
- package/dist/unityHub.js +118 -0
- package/package.json +5 -5
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, handleStaleLockfile, ensureProjectEntryAndUpdate, updateLastModifiedIfExists, } from './lib.js';
|
|
6
|
+
export { LaunchOptions, LaunchResolvedOptions, UnityProcessInfo, parseArgs, findUnityProjectBfs, getUnityVersion, launch, 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,EAEhB,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,MAAM,EACN,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,2BAA2B,EAC3B,0BAA0B,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAEhB,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,MAAM,EACN,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, handleStaleLockfile, ensureProjectEntryAndUpdate, updateLastModifiedIfExists, } from './lib.js';
|
|
8
|
+
parseArgs, findUnityProjectBfs, getUnityVersion, launch, findRunningUnityProcess, focusUnityProcess, killRunningUnity, quitRunningUnity, handleStaleLockfile, ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs, } from './lib.js';
|
package/dist/launch.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type LaunchOptions = {
|
|
|
6
6
|
unityArgs: string[];
|
|
7
7
|
searchMaxDepth: number;
|
|
8
8
|
restart: boolean;
|
|
9
|
+
quit: boolean;
|
|
9
10
|
addUnityHub: boolean;
|
|
10
11
|
favoriteUnityHub: boolean;
|
|
11
12
|
};
|
|
@@ -25,6 +26,7 @@ export declare function findRunningUnityProcess(projectPath: string): Promise<Un
|
|
|
25
26
|
export declare function focusUnityProcess(pid: number): Promise<void>;
|
|
26
27
|
export declare function handleStaleLockfile(projectPath: string): Promise<void>;
|
|
27
28
|
export declare function killRunningUnity(projectPath: string): Promise<void>;
|
|
29
|
+
export declare function quitRunningUnity(projectPath: string): Promise<void>;
|
|
28
30
|
export declare function findUnityProjectBfs(rootDir: string, maxDepth: number): string | undefined;
|
|
29
|
-
export declare function launch(opts: LaunchResolvedOptions): void
|
|
31
|
+
export declare function launch(opts: LaunchResolvedOptions): Promise<void>;
|
|
30
32
|
//# 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":";AAeA,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,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;AAyJF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":";AAeA,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;AAyJF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CA2HvD;AA0CD,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAe3D;AA2ND,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,CAoBzE;AA0CD,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BzE;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"}
|
package/dist/launch.js
CHANGED
|
@@ -9,7 +9,7 @@ import { rm } from "node:fs/promises";
|
|
|
9
9
|
import { dirname, join, resolve } from "node:path";
|
|
10
10
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
11
|
import { promisify } from "node:util";
|
|
12
|
-
import { ensureProjectEntryAndUpdate, updateLastModifiedIfExists } from "./unityHub.js";
|
|
12
|
+
import { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, groupCliArgs } from "./unityHub.js";
|
|
13
13
|
const execFileAsync = promisify(execFile);
|
|
14
14
|
const UNITY_EXECUTABLE_PATTERN_MAC = /Unity\.app\/Contents\/MacOS\/Unity/i;
|
|
15
15
|
const UNITY_EXECUTABLE_PATTERN_WINDOWS = /Unity\.exe/i;
|
|
@@ -144,6 +144,7 @@ export function parseArgs(argv) {
|
|
|
144
144
|
const positionals = [];
|
|
145
145
|
let maxDepth = 3; // default 3; -1 means unlimited
|
|
146
146
|
let restart = false;
|
|
147
|
+
let quit = false;
|
|
147
148
|
let addUnityHub = false;
|
|
148
149
|
let favoriteUnityHub = false;
|
|
149
150
|
let platform;
|
|
@@ -161,6 +162,10 @@ export function parseArgs(argv) {
|
|
|
161
162
|
restart = true;
|
|
162
163
|
continue;
|
|
163
164
|
}
|
|
165
|
+
if (arg === "-q" || arg === "--quit") {
|
|
166
|
+
quit = true;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
164
169
|
if (arg === "-u" ||
|
|
165
170
|
arg === "-a" ||
|
|
166
171
|
arg === "--unity-hub-entry" ||
|
|
@@ -226,6 +231,7 @@ export function parseArgs(argv) {
|
|
|
226
231
|
unityArgs,
|
|
227
232
|
searchMaxDepth: maxDepth,
|
|
228
233
|
restart,
|
|
234
|
+
quit,
|
|
229
235
|
addUnityHub,
|
|
230
236
|
favoriteUnityHub,
|
|
231
237
|
};
|
|
@@ -266,6 +272,7 @@ Options:
|
|
|
266
272
|
-h, --help Show this help message
|
|
267
273
|
-v, --version Show version number
|
|
268
274
|
-r, --restart Kill running Unity and restart
|
|
275
|
+
-q, --quit Quit running Unity gracefully (force-kill on timeout)
|
|
269
276
|
-p, --platform <P> Passed to Unity as -buildTarget (e.g., StandaloneOSX, Android, iOS)
|
|
270
277
|
--max-depth <N> Search depth when PROJECT_PATH is omitted (default 3, -1 unlimited)
|
|
271
278
|
-u, -a, --unity-hub-entry, --add-unity-hub
|
|
@@ -554,9 +561,11 @@ export async function handleStaleLockfile(projectPath) {
|
|
|
554
561
|
const message = error instanceof Error ? error.message : String(error);
|
|
555
562
|
console.warn(`Failed to delete UnityLockfile: ${message}`);
|
|
556
563
|
}
|
|
564
|
+
console.log();
|
|
557
565
|
}
|
|
558
566
|
const KILL_POLL_INTERVAL_MS = 100;
|
|
559
567
|
const KILL_TIMEOUT_MS = 10000;
|
|
568
|
+
const GRACEFUL_QUIT_TIMEOUT_MS = 10000;
|
|
560
569
|
function isProcessAlive(pid) {
|
|
561
570
|
try {
|
|
562
571
|
process.kill(pid, 0);
|
|
@@ -574,9 +583,9 @@ function killProcess(pid) {
|
|
|
574
583
|
// Process already exited
|
|
575
584
|
}
|
|
576
585
|
}
|
|
577
|
-
async function waitForProcessExit(pid) {
|
|
586
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
578
587
|
const start = Date.now();
|
|
579
|
-
while (Date.now() - start <
|
|
588
|
+
while (Date.now() - start < timeoutMs) {
|
|
580
589
|
if (!isProcessAlive(pid)) {
|
|
581
590
|
return true;
|
|
582
591
|
}
|
|
@@ -588,17 +597,82 @@ export async function killRunningUnity(projectPath) {
|
|
|
588
597
|
const processInfo = await findRunningUnityProcess(projectPath);
|
|
589
598
|
if (!processInfo) {
|
|
590
599
|
console.log("No running Unity process found for this project.");
|
|
600
|
+
console.log();
|
|
591
601
|
return;
|
|
592
602
|
}
|
|
593
603
|
const pid = processInfo.pid;
|
|
594
604
|
console.log(`Killing Unity (PID: ${pid})...`);
|
|
595
605
|
killProcess(pid);
|
|
596
|
-
const exited = await waitForProcessExit(pid);
|
|
606
|
+
const exited = await waitForProcessExit(pid, KILL_TIMEOUT_MS);
|
|
597
607
|
if (!exited) {
|
|
598
608
|
console.error(`Error: Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1000}s.`);
|
|
599
609
|
process.exit(1);
|
|
600
610
|
}
|
|
601
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.");
|
|
602
676
|
}
|
|
603
677
|
function hasBuildTargetArg(unityArgs) {
|
|
604
678
|
for (const arg of unityArgs) {
|
|
@@ -695,10 +769,9 @@ export function findUnityProjectBfs(rootDir, maxDepth) {
|
|
|
695
769
|
}
|
|
696
770
|
return undefined;
|
|
697
771
|
}
|
|
698
|
-
export function launch(opts) {
|
|
772
|
+
export async function launch(opts) {
|
|
699
773
|
const { projectPath, platform, unityArgs, unityVersion } = opts;
|
|
700
774
|
const unityPath = getUnityPath(unityVersion);
|
|
701
|
-
console.log(`Detected Unity version: ${unityVersion}`);
|
|
702
775
|
if (!existsSync(unityPath)) {
|
|
703
776
|
console.error(`Error: Unity ${unityVersion} not found at ${unityPath}`);
|
|
704
777
|
console.error("Please install Unity through Unity Hub.");
|
|
@@ -706,16 +779,48 @@ export function launch(opts) {
|
|
|
706
779
|
}
|
|
707
780
|
console.log("Opening Unity...");
|
|
708
781
|
console.log(`Project Path: ${projectPath}`);
|
|
782
|
+
console.log(`Detected Unity version: ${unityVersion}`);
|
|
709
783
|
const args = ["-projectPath", projectPath];
|
|
710
784
|
const unityArgsContainBuildTarget = hasBuildTargetArg(unityArgs);
|
|
711
785
|
if (platform && platform.length > 0 && !unityArgsContainBuildTarget) {
|
|
712
786
|
args.push("-buildTarget", platform);
|
|
713
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
|
+
}
|
|
714
799
|
if (unityArgs.length > 0) {
|
|
715
800
|
args.push(...unityArgs);
|
|
716
801
|
}
|
|
717
|
-
|
|
718
|
-
|
|
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
|
+
});
|
|
719
824
|
}
|
|
720
825
|
async function main() {
|
|
721
826
|
const options = parseArgs(process.argv);
|
|
@@ -727,14 +832,14 @@ async function main() {
|
|
|
727
832
|
if (!resolvedProjectPath) {
|
|
728
833
|
const searchRoot = process.cwd();
|
|
729
834
|
const depthInfo = options.searchMaxDepth === -1 ? "unlimited" : String(options.searchMaxDepth);
|
|
730
|
-
console.log(`
|
|
835
|
+
console.log(`Searching for Unity project under ${searchRoot} (max-depth: ${depthInfo})...`);
|
|
731
836
|
const found = findUnityProjectBfs(searchRoot, options.searchMaxDepth);
|
|
732
837
|
if (!found) {
|
|
733
838
|
console.error(`Error: Unity project not found under ${searchRoot}.`);
|
|
734
839
|
process.exit(1);
|
|
735
840
|
return;
|
|
736
841
|
}
|
|
737
|
-
console.log(
|
|
842
|
+
console.log();
|
|
738
843
|
resolvedProjectPath = found;
|
|
739
844
|
}
|
|
740
845
|
ensureProjectPath(resolvedProjectPath);
|
|
@@ -755,6 +860,14 @@ async function main() {
|
|
|
755
860
|
}
|
|
756
861
|
return;
|
|
757
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
|
+
}
|
|
758
871
|
if (options.restart) {
|
|
759
872
|
await killRunningUnity(resolvedProjectPath);
|
|
760
873
|
}
|
|
@@ -774,7 +887,7 @@ async function main() {
|
|
|
774
887
|
unityArgs: options.unityArgs,
|
|
775
888
|
unityVersion,
|
|
776
889
|
};
|
|
777
|
-
launch(resolved);
|
|
890
|
+
await launch(resolved);
|
|
778
891
|
// Best-effort update of Unity Hub's lastModified timestamp.
|
|
779
892
|
const now = new Date();
|
|
780
893
|
try {
|
package/dist/lib.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* launch-unity core library functions.
|
|
3
3
|
* Pure library code without CLI entry point or side effects.
|
|
4
4
|
*/
|
|
5
|
-
import { ensureProjectEntryAndUpdate, updateLastModifiedIfExists } from "./unityHub.js";
|
|
5
|
+
import { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs } from "./unityHub.js";
|
|
6
6
|
export type LaunchOptions = {
|
|
7
7
|
subcommand?: "update";
|
|
8
8
|
projectPath?: string;
|
|
@@ -10,6 +10,7 @@ export type LaunchOptions = {
|
|
|
10
10
|
unityArgs: string[];
|
|
11
11
|
searchMaxDepth: number;
|
|
12
12
|
restart: boolean;
|
|
13
|
+
quit: boolean;
|
|
13
14
|
addUnityHub: boolean;
|
|
14
15
|
favoriteUnityHub: boolean;
|
|
15
16
|
};
|
|
@@ -29,7 +30,8 @@ export declare function findRunningUnityProcess(projectPath: string): Promise<Un
|
|
|
29
30
|
export declare function focusUnityProcess(pid: number): Promise<void>;
|
|
30
31
|
export declare function handleStaleLockfile(projectPath: string): Promise<void>;
|
|
31
32
|
export declare function killRunningUnity(projectPath: string): Promise<void>;
|
|
33
|
+
export declare function quitRunningUnity(projectPath: string): Promise<void>;
|
|
32
34
|
export declare function findUnityProjectBfs(rootDir: string, maxDepth: number): string | undefined;
|
|
33
|
-
export declare function launch(opts: LaunchResolvedOptions): void
|
|
34
|
-
export { ensureProjectEntryAndUpdate, updateLastModifiedIfExists };
|
|
35
|
+
export declare function launch(opts: LaunchResolvedOptions): Promise<void>;
|
|
36
|
+
export { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs };
|
|
35
37
|
//# 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,MAAM,eAAe,CAAC;
|
|
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"}
|
package/dist/lib.js
CHANGED
|
@@ -7,7 +7,7 @@ import { existsSync, readFileSync, readdirSync, lstatSync, realpathSync } from "
|
|
|
7
7
|
import { rm } from "node:fs/promises";
|
|
8
8
|
import { join, resolve } from "node:path";
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
|
-
import { ensureProjectEntryAndUpdate, updateLastModifiedIfExists } from "./unityHub.js";
|
|
10
|
+
import { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs } from "./unityHub.js";
|
|
11
11
|
const execFileAsync = promisify(execFile);
|
|
12
12
|
const UNITY_EXECUTABLE_PATTERN_MAC = /Unity\.app\/Contents\/MacOS\/Unity/i;
|
|
13
13
|
const UNITY_EXECUTABLE_PATTERN_WINDOWS = /Unity\.exe/i;
|
|
@@ -31,6 +31,7 @@ export function parseArgs(argv) {
|
|
|
31
31
|
const positionals = [];
|
|
32
32
|
let maxDepth = 3; // default 3; -1 means unlimited
|
|
33
33
|
let restart = false;
|
|
34
|
+
let quit = false;
|
|
34
35
|
let addUnityHub = false;
|
|
35
36
|
let favoriteUnityHub = false;
|
|
36
37
|
let platform;
|
|
@@ -46,6 +47,10 @@ export function parseArgs(argv) {
|
|
|
46
47
|
restart = true;
|
|
47
48
|
continue;
|
|
48
49
|
}
|
|
50
|
+
if (arg === "-q" || arg === "--quit") {
|
|
51
|
+
quit = true;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
49
54
|
if (arg === "-u" ||
|
|
50
55
|
arg === "-a" ||
|
|
51
56
|
arg === "--unity-hub-entry" ||
|
|
@@ -111,6 +116,7 @@ export function parseArgs(argv) {
|
|
|
111
116
|
unityArgs,
|
|
112
117
|
searchMaxDepth: maxDepth,
|
|
113
118
|
restart,
|
|
119
|
+
quit,
|
|
114
120
|
addUnityHub,
|
|
115
121
|
favoriteUnityHub,
|
|
116
122
|
};
|
|
@@ -393,9 +399,11 @@ export async function handleStaleLockfile(projectPath) {
|
|
|
393
399
|
const message = error instanceof Error ? error.message : String(error);
|
|
394
400
|
console.warn(`Failed to delete UnityLockfile: ${message}`);
|
|
395
401
|
}
|
|
402
|
+
console.log();
|
|
396
403
|
}
|
|
397
404
|
const KILL_POLL_INTERVAL_MS = 100;
|
|
398
405
|
const KILL_TIMEOUT_MS = 10000;
|
|
406
|
+
const GRACEFUL_QUIT_TIMEOUT_MS = 10000;
|
|
399
407
|
function isProcessAlive(pid) {
|
|
400
408
|
try {
|
|
401
409
|
process.kill(pid, 0);
|
|
@@ -413,9 +421,9 @@ function killProcess(pid) {
|
|
|
413
421
|
// Process already exited
|
|
414
422
|
}
|
|
415
423
|
}
|
|
416
|
-
async function waitForProcessExit(pid) {
|
|
424
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
417
425
|
const start = Date.now();
|
|
418
|
-
while (Date.now() - start <
|
|
426
|
+
while (Date.now() - start < timeoutMs) {
|
|
419
427
|
if (!isProcessAlive(pid)) {
|
|
420
428
|
return true;
|
|
421
429
|
}
|
|
@@ -427,16 +435,80 @@ export async function killRunningUnity(projectPath) {
|
|
|
427
435
|
const processInfo = await findRunningUnityProcess(projectPath);
|
|
428
436
|
if (!processInfo) {
|
|
429
437
|
console.log("No running Unity process found for this project.");
|
|
438
|
+
console.log();
|
|
430
439
|
return;
|
|
431
440
|
}
|
|
432
441
|
const pid = processInfo.pid;
|
|
433
442
|
console.log(`Killing Unity (PID: ${pid})...`);
|
|
434
443
|
killProcess(pid);
|
|
435
|
-
const exited = await waitForProcessExit(pid);
|
|
444
|
+
const exited = await waitForProcessExit(pid, KILL_TIMEOUT_MS);
|
|
436
445
|
if (!exited) {
|
|
437
446
|
throw new Error(`Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1000}s.`);
|
|
438
447
|
}
|
|
439
448
|
console.log("Unity killed.");
|
|
449
|
+
console.log();
|
|
450
|
+
}
|
|
451
|
+
async function sendGracefulQuitMac(pid) {
|
|
452
|
+
// System Events quit and "tell application to quit" leave UnityLockfile behind,
|
|
453
|
+
// so we send Cmd+Q keystroke to trigger Unity's normal user-initiated shutdown flow
|
|
454
|
+
const script = [
|
|
455
|
+
'tell application "System Events"',
|
|
456
|
+
` set frontmost of (first process whose unix id is ${pid}) to true`,
|
|
457
|
+
' keystroke "q" using {command down}',
|
|
458
|
+
"end tell",
|
|
459
|
+
].join("\n");
|
|
460
|
+
try {
|
|
461
|
+
await execFileAsync("osascript", ["-e", script]);
|
|
462
|
+
}
|
|
463
|
+
catch {
|
|
464
|
+
// Process may have already exited
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
async function sendGracefulQuitWindows(pid) {
|
|
468
|
+
// process.kill(pid, "SIGTERM") forcefully kills on Windows, so use CloseMainWindow() to send WM_CLOSE
|
|
469
|
+
const scriptLines = [
|
|
470
|
+
"$ErrorActionPreference = 'Stop'",
|
|
471
|
+
`try { $proc = Get-Process -Id ${pid} -ErrorAction Stop; $proc.CloseMainWindow() | Out-Null } catch { }`,
|
|
472
|
+
];
|
|
473
|
+
try {
|
|
474
|
+
await execFileAsync(WINDOWS_POWERSHELL, ["-NoProfile", "-Command", scriptLines.join("\n")]);
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
// Process may have already exited
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
async function sendGracefulQuit(pid) {
|
|
481
|
+
if (process.platform === "darwin") {
|
|
482
|
+
await sendGracefulQuitMac(pid);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
if (process.platform === "win32") {
|
|
486
|
+
await sendGracefulQuitWindows(pid);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
export async function quitRunningUnity(projectPath) {
|
|
491
|
+
const processInfo = await findRunningUnityProcess(projectPath);
|
|
492
|
+
if (!processInfo) {
|
|
493
|
+
console.log("No running Unity process found for this project.");
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const pid = processInfo.pid;
|
|
497
|
+
console.log(`Quitting Unity (PID: ${pid})...`);
|
|
498
|
+
await sendGracefulQuit(pid);
|
|
499
|
+
console.log(`Sent graceful quit signal. Waiting up to ${GRACEFUL_QUIT_TIMEOUT_MS / 1000}s...`);
|
|
500
|
+
const exitedGracefully = await waitForProcessExit(pid, GRACEFUL_QUIT_TIMEOUT_MS);
|
|
501
|
+
if (exitedGracefully) {
|
|
502
|
+
console.log("Unity quit gracefully.");
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
console.log("Unity did not respond to graceful quit. Force killing...");
|
|
506
|
+
killProcess(pid);
|
|
507
|
+
const exitedAfterKill = await waitForProcessExit(pid, KILL_TIMEOUT_MS);
|
|
508
|
+
if (!exitedAfterKill) {
|
|
509
|
+
throw new Error(`Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1000}s.`);
|
|
510
|
+
}
|
|
511
|
+
console.log("Unity force killed.");
|
|
440
512
|
}
|
|
441
513
|
function hasBuildTargetArg(unityArgs) {
|
|
442
514
|
for (const arg of unityArgs) {
|
|
@@ -533,25 +605,56 @@ export function findUnityProjectBfs(rootDir, maxDepth) {
|
|
|
533
605
|
}
|
|
534
606
|
return undefined;
|
|
535
607
|
}
|
|
536
|
-
export function launch(opts) {
|
|
608
|
+
export async function launch(opts) {
|
|
537
609
|
const { projectPath, platform, unityArgs, unityVersion } = opts;
|
|
538
610
|
const unityPath = getUnityPath(unityVersion);
|
|
539
|
-
console.log(`Detected Unity version: ${unityVersion}`);
|
|
540
611
|
if (!existsSync(unityPath)) {
|
|
541
612
|
throw new Error(`Unity ${unityVersion} not found at ${unityPath}. Please install Unity through Unity Hub.`);
|
|
542
613
|
}
|
|
543
614
|
console.log("Opening Unity...");
|
|
544
615
|
console.log(`Project Path: ${projectPath}`);
|
|
616
|
+
console.log(`Detected Unity version: ${unityVersion}`);
|
|
545
617
|
const args = ["-projectPath", projectPath];
|
|
546
618
|
const unityArgsContainBuildTarget = hasBuildTargetArg(unityArgs);
|
|
547
619
|
if (platform && platform.length > 0 && !unityArgsContainBuildTarget) {
|
|
548
620
|
args.push("-buildTarget", platform);
|
|
549
621
|
}
|
|
622
|
+
const hubCliArgs = await getProjectCliArgs(projectPath);
|
|
623
|
+
if (hubCliArgs.length > 0) {
|
|
624
|
+
console.log("Unity Hub launch options:");
|
|
625
|
+
for (const line of groupCliArgs(hubCliArgs)) {
|
|
626
|
+
console.log(` ${line}`);
|
|
627
|
+
}
|
|
628
|
+
args.push(...hubCliArgs);
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
console.log("Unity Hub launch options: none");
|
|
632
|
+
}
|
|
550
633
|
if (unityArgs.length > 0) {
|
|
551
634
|
args.push(...unityArgs);
|
|
552
635
|
}
|
|
553
|
-
|
|
554
|
-
|
|
636
|
+
return new Promise((resolve, reject) => {
|
|
637
|
+
const child = spawn(unityPath, args, {
|
|
638
|
+
stdio: "ignore",
|
|
639
|
+
detached: true,
|
|
640
|
+
// Git Bash (MSYS) がWindows パスをUnix 形式に自動変換するのを防ぐ
|
|
641
|
+
env: {
|
|
642
|
+
...process.env,
|
|
643
|
+
MSYS_NO_PATHCONV: "1",
|
|
644
|
+
},
|
|
645
|
+
});
|
|
646
|
+
const handleError = (error) => {
|
|
647
|
+
child.removeListener("spawn", handleSpawn);
|
|
648
|
+
reject(new Error(`Failed to launch Unity: ${error.message}`));
|
|
649
|
+
};
|
|
650
|
+
const handleSpawn = () => {
|
|
651
|
+
child.removeListener("error", handleError);
|
|
652
|
+
child.unref();
|
|
653
|
+
resolve();
|
|
654
|
+
};
|
|
655
|
+
child.once("error", handleError);
|
|
656
|
+
child.once("spawn", handleSpawn);
|
|
657
|
+
});
|
|
555
658
|
}
|
|
556
659
|
// Re-export Unity Hub functions
|
|
557
|
-
export { ensureProjectEntryAndUpdate, updateLastModifiedIfExists };
|
|
660
|
+
export { ensureProjectEntryAndUpdate, updateLastModifiedIfExists, getProjectCliArgs, parseCliArgs, groupCliArgs };
|
package/dist/unityHub.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
export declare const ensureProjectEntryAndUpdate: (projectPath: string, version: string, when: Date, setFavorite?: boolean) => Promise<void>;
|
|
2
2
|
export declare const updateLastModifiedIfExists: (projectPath: string, when: Date) => Promise<void>;
|
|
3
|
+
export declare const parseCliArgs: (cliArgsString: string) => string[];
|
|
4
|
+
export declare const groupCliArgs: (args: readonly string[]) => string[];
|
|
5
|
+
export declare const getProjectCliArgs: (projectPath: string) => Promise<string[]>;
|
|
3
6
|
//# sourceMappingURL=unityHub.d.ts.map
|
package/dist/unityHub.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unityHub.d.ts","sourceRoot":"","sources":["../src/unityHub.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"unityHub.d.ts","sourceRoot":"","sources":["../src/unityHub.ts"],"names":[],"mappings":"AAwFA,eAAO,MAAM,2BAA2B,GACtC,aAAa,MAAM,EACnB,SAAS,MAAM,EACf,MAAM,IAAI,EACV,qBAAmB,KAClB,OAAO,CAAC,IAAI,CAgEd,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,aAAa,MAAM,EACnB,MAAM,IAAI,KACT,OAAO,CAAC,IAAI,CAuDd,CAAC;AAoBF,eAAO,MAAM,YAAY,GAAI,eAAe,MAAM,KAAG,MAAM,EA6C1D,CAAC;AAGF,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,EAAE,KAAG,MAAM,EAiB5D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,aAAa,MAAM,KAAG,OAAO,CAAC,MAAM,EAAE,CA8C7E,CAAC"}
|
package/dist/unityHub.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { realpathSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
+
import assert from "node:assert";
|
|
4
5
|
const resolveUnityHubProjectFiles = () => {
|
|
5
6
|
if (process.platform === "darwin") {
|
|
6
7
|
const home = process.env.HOME;
|
|
@@ -168,3 +169,120 @@ export const updateLastModifiedIfExists = async (projectPath, when) => {
|
|
|
168
169
|
return;
|
|
169
170
|
}
|
|
170
171
|
};
|
|
172
|
+
const resolveUnityHubProjectsInfoFile = () => {
|
|
173
|
+
if (process.platform === "darwin") {
|
|
174
|
+
const home = process.env.HOME;
|
|
175
|
+
if (!home) {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
return join(home, "Library", "Application Support", "UnityHub", "projectsInfo.json");
|
|
179
|
+
}
|
|
180
|
+
if (process.platform === "win32") {
|
|
181
|
+
const appData = process.env.APPDATA;
|
|
182
|
+
if (!appData) {
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
return join(appData, "UnityHub", "projectsInfo.json");
|
|
186
|
+
}
|
|
187
|
+
return undefined;
|
|
188
|
+
};
|
|
189
|
+
export const parseCliArgs = (cliArgsString) => {
|
|
190
|
+
assert(cliArgsString !== null && cliArgsString !== undefined, "cliArgsString must not be null");
|
|
191
|
+
const trimmed = cliArgsString.trim();
|
|
192
|
+
if (trimmed.length === 0) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
const tokens = [];
|
|
196
|
+
let current = "";
|
|
197
|
+
let inQuote = null;
|
|
198
|
+
for (const char of trimmed) {
|
|
199
|
+
if (inQuote !== null) {
|
|
200
|
+
if (char === inQuote) {
|
|
201
|
+
tokens.push(current);
|
|
202
|
+
current = "";
|
|
203
|
+
inQuote = null;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
current += char;
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (char === '"' || char === "'") {
|
|
211
|
+
inQuote = char;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (char === " ") {
|
|
215
|
+
if (current.length > 0) {
|
|
216
|
+
tokens.push(current);
|
|
217
|
+
current = "";
|
|
218
|
+
}
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
current += char;
|
|
222
|
+
}
|
|
223
|
+
if (current.length > 0) {
|
|
224
|
+
tokens.push(current);
|
|
225
|
+
}
|
|
226
|
+
return tokens;
|
|
227
|
+
};
|
|
228
|
+
// "-flag value" pairs are grouped into single strings for display (e.g. ["-foo", "bar", "-baz", "qux"] -> ["-foo bar", "-baz qux"])
|
|
229
|
+
export const groupCliArgs = (args) => {
|
|
230
|
+
const groups = [];
|
|
231
|
+
let current = "";
|
|
232
|
+
for (const arg of args) {
|
|
233
|
+
if (arg.startsWith("-") && current.length > 0) {
|
|
234
|
+
groups.push(current);
|
|
235
|
+
current = arg;
|
|
236
|
+
}
|
|
237
|
+
else if (current.length === 0) {
|
|
238
|
+
current = arg;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
current += ` ${arg}`;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (current.length > 0) {
|
|
245
|
+
groups.push(current);
|
|
246
|
+
}
|
|
247
|
+
return groups;
|
|
248
|
+
};
|
|
249
|
+
export const getProjectCliArgs = async (projectPath) => {
|
|
250
|
+
assert(projectPath !== null && projectPath !== undefined, "projectPath must not be null");
|
|
251
|
+
const infoFilePath = resolveUnityHubProjectsInfoFile();
|
|
252
|
+
if (!infoFilePath) {
|
|
253
|
+
logDebug("projectsInfo.json path could not be resolved.");
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
logDebug(`Reading projectsInfo.json: ${infoFilePath}`);
|
|
257
|
+
let content;
|
|
258
|
+
try {
|
|
259
|
+
content = await readFile(infoFilePath, "utf8");
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
logDebug("projectsInfo.json not found or not readable.");
|
|
263
|
+
return [];
|
|
264
|
+
}
|
|
265
|
+
let json;
|
|
266
|
+
try {
|
|
267
|
+
json = JSON.parse(content);
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
logDebug("projectsInfo.json parse failed.");
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
const normalizedProjectPath = normalizePath(projectPath);
|
|
274
|
+
const projectKey = Object.keys(json).find((key) => pathsEqual(key, normalizedProjectPath));
|
|
275
|
+
if (!projectKey) {
|
|
276
|
+
logDebug(`No entry found for project: ${normalizedProjectPath}`);
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
const projectInfo = json[projectKey];
|
|
280
|
+
const cliArgsString = projectInfo?.cliArgs;
|
|
281
|
+
if (!cliArgsString || cliArgsString.trim().length === 0) {
|
|
282
|
+
logDebug("cliArgs is empty or not defined.");
|
|
283
|
+
return [];
|
|
284
|
+
}
|
|
285
|
+
const parsed = parseCliArgs(cliArgsString);
|
|
286
|
+
logDebug(`Parsed Unity Hub cliArgs: ${JSON.stringify(parsed)}`);
|
|
287
|
+
return parsed;
|
|
288
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "launch-unity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Open a Unity project with the matching Editor version (macOS/Windows)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -45,16 +45,16 @@
|
|
|
45
45
|
"node": ">=18"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@types/node": "25.0
|
|
49
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
50
|
-
"@typescript-eslint/parser": "8.
|
|
48
|
+
"@types/node": "25.2.0",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "8.54.0",
|
|
50
|
+
"@typescript-eslint/parser": "8.54.0",
|
|
51
51
|
"eslint": "9.39.2",
|
|
52
52
|
"eslint-config-prettier": "10.1.8",
|
|
53
53
|
"prettier": "3.8.1",
|
|
54
54
|
"typescript": "5.9.3"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"typescript-eslint": "8.
|
|
57
|
+
"typescript-eslint": "8.54.0"
|
|
58
58
|
},
|
|
59
59
|
"overrides": {
|
|
60
60
|
"js-yaml": "4.1.1"
|