unity-hub-cli 0.5.0 → 0.6.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/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  A CLI tool that displays the same content as Unity Hub in an Ink-based TUI, allows navigation with arrow keys/`j`/`k`, and launches Unity Editor by pressing `o`.
6
6
 
7
+ <img width="1678" height="1460" alt="スクリーンショット 2025-10-27 23 44 40" src="https://github.com/user-attachments/assets/db3cc995-820e-490b-a43b-393893197ab4" />
8
+
7
9
  ## Requirements
8
10
 
9
11
  - macOS
package/dist/index.js CHANGED
@@ -347,11 +347,17 @@ var UnityHubProjectsReader = class {
347
347
  };
348
348
 
349
349
  // src/infrastructure/unityLock.ts
350
+ import { execFile } from "child_process";
350
351
  import { constants as constants2, createReadStream, createWriteStream } from "fs";
351
352
  import { access as access2, rm } from "fs/promises";
352
353
  import { join as join3 } from "path";
353
354
  import readline from "readline";
355
+ import { promisify } from "util";
354
356
  var RAW_PROMPT_MESSAGE = "Delete UnityLockfile and continue? Type 'y' to continue; anything else aborts: ";
357
+ var execFileAsync = promisify(execFile);
358
+ var buildBringToFrontScript = (pid) => {
359
+ return `tell application "System Events" to set frontmost of (first process whose unix id is ${pid}) to true`;
360
+ };
355
361
  var isRawModeSupported = () => {
356
362
  const stdin = process.stdin;
357
363
  return Boolean(stdin?.isTTY && typeof stdin.setRawMode === "function" && process.stdout.isTTY);
@@ -462,7 +468,18 @@ var pathExists = async (target) => {
462
468
  }
463
469
  };
464
470
  var UnityLockChecker = class {
471
+ constructor(unityProcessReader) {
472
+ this.unityProcessReader = unityProcessReader;
473
+ }
465
474
  async check(projectPath) {
475
+ const activeProcess = await this.unityProcessReader.findByProjectPath(projectPath);
476
+ if (activeProcess) {
477
+ console.log(
478
+ `Unity process already running for project: ${activeProcess.projectPath} (PID: ${activeProcess.pid})`
479
+ );
480
+ await this.bringUnityToFront(activeProcess.pid);
481
+ return "skip";
482
+ }
466
483
  const lockfilePath = join3(projectPath, "Temp", "UnityLockfile");
467
484
  const hasLockfile = await pathExists(lockfilePath);
468
485
  if (!hasLockfile) {
@@ -479,6 +496,18 @@ var UnityLockChecker = class {
479
496
  console.log("Deleted UnityLockfile. Continuing launch.");
480
497
  return "allow";
481
498
  }
499
+ async bringUnityToFront(pid) {
500
+ if (process.platform !== "darwin") {
501
+ return;
502
+ }
503
+ try {
504
+ const script = buildBringToFrontScript(pid);
505
+ await execFileAsync("osascript", ["-e", script]);
506
+ } catch (error) {
507
+ const message = error instanceof Error ? error.message : String(error);
508
+ console.error(`Failed to bring Unity to front: ${message}`);
509
+ }
510
+ }
482
511
  };
483
512
  var UnityLockStatusReader = class {
484
513
  async isLocked(projectPath) {
@@ -488,12 +517,12 @@ var UnityLockStatusReader = class {
488
517
  };
489
518
 
490
519
  // src/infrastructure/unityProcess.ts
491
- import { execFile } from "child_process";
520
+ import { execFile as execFile2 } from "child_process";
492
521
  import { resolve as resolve2 } from "path";
493
- import { promisify } from "util";
494
- var execFileAsync = promisify(execFile);
522
+ import { promisify as promisify2 } from "util";
523
+ var execFileAsync2 = promisify2(execFile2);
495
524
  var UNITY_EXECUTABLE_PATTERN = /Unity\.app\/Contents\/MacOS\/Unity/i;
496
- var PROJECT_PATH_PATTERN = /-(?:projectPath|projectpath)\s+("[^"]+"|'[^']+'|[^\s"']+)/i;
525
+ var PROJECT_PATH_PATTERN = /-(?:projectPath|projectpath)(?:=|\s+)("[^"]+"|'[^']+'|[^\s"']+)/i;
497
526
  var PROCESS_LIST_ARGS = ["-axo", "pid=,command=", "-ww"];
498
527
  var PROCESS_LIST_COMMAND = "ps";
499
528
  var TERMINATE_TIMEOUT_MILLIS = 5e3;
@@ -565,7 +594,7 @@ var MacUnityProcessReader = class {
565
594
  async listUnityProcesses() {
566
595
  let stdout;
567
596
  try {
568
- const result = await execFileAsync(PROCESS_LIST_COMMAND, PROCESS_LIST_ARGS);
597
+ const result = await execFileAsync2(PROCESS_LIST_COMMAND, PROCESS_LIST_ARGS);
569
598
  stdout = result.stdout;
570
599
  } catch (error) {
571
600
  throw new Error(`Failed to retrieve Unity process list: ${error instanceof Error ? error.message : String(error)}`);
@@ -1158,6 +1187,7 @@ var bootstrap = async () => {
1158
1187
  const unityHubReader = new UnityHubProjectsReader();
1159
1188
  const gitRepositoryInfoReader = new GitRepositoryInfoReader();
1160
1189
  const lockStatusReader = new UnityLockStatusReader();
1190
+ const unityProcessReader = new MacUnityProcessReader();
1161
1191
  const listProjectsUseCase = new ListProjectsUseCase(
1162
1192
  unityHubReader,
1163
1193
  gitRepositoryInfoReader,
@@ -1166,8 +1196,7 @@ var bootstrap = async () => {
1166
1196
  );
1167
1197
  const editorPathResolver = new MacEditorPathResolver();
1168
1198
  const processLauncher = new NodeProcessLauncher();
1169
- const lockChecker = new UnityLockChecker();
1170
- const unityProcessReader = new MacUnityProcessReader();
1199
+ const lockChecker = new UnityLockChecker(unityProcessReader);
1171
1200
  const unityProcessTerminator = new MacUnityProcessTerminator();
1172
1201
  const unityTempDirectoryCleaner = new UnityTempDirectoryCleaner();
1173
1202
  const launchProjectUseCase = new LaunchProjectUseCase(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unity-hub-cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "A CLI tool that reads Unity Hub's projects and launches Unity Editor with an interactive TUI",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {