uloop-cli 0.60.0 → 0.61.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/cli.bundle.cjs +176 -52
- package/dist/cli.bundle.cjs.map +3 -3
- package/package.json +2 -2
- package/src/commands/launch.ts +20 -73
- package/src/default-tools.json +1 -1
- package/src/version.ts +1 -1
package/dist/cli.bundle.cjs
CHANGED
|
@@ -5763,7 +5763,7 @@ var import_path3 = require("path");
|
|
|
5763
5763
|
|
|
5764
5764
|
// src/default-tools.json
|
|
5765
5765
|
var default_tools_default = {
|
|
5766
|
-
version: "0.
|
|
5766
|
+
version: "0.61.0",
|
|
5767
5767
|
tools: [
|
|
5768
5768
|
{
|
|
5769
5769
|
name: "compile",
|
|
@@ -6207,7 +6207,7 @@ function getCachedServerVersion() {
|
|
|
6207
6207
|
}
|
|
6208
6208
|
|
|
6209
6209
|
// src/version.ts
|
|
6210
|
-
var VERSION = "0.
|
|
6210
|
+
var VERSION = "0.61.0";
|
|
6211
6211
|
|
|
6212
6212
|
// src/spinner.ts
|
|
6213
6213
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -7464,6 +7464,24 @@ var parseCliArgs = (cliArgsString) => {
|
|
|
7464
7464
|
}
|
|
7465
7465
|
return tokens;
|
|
7466
7466
|
};
|
|
7467
|
+
var groupCliArgs = (args) => {
|
|
7468
|
+
const groups = [];
|
|
7469
|
+
let current = "";
|
|
7470
|
+
for (const arg of args) {
|
|
7471
|
+
if (arg.startsWith("-") && current.length > 0) {
|
|
7472
|
+
groups.push(current);
|
|
7473
|
+
current = arg;
|
|
7474
|
+
} else if (current.length === 0) {
|
|
7475
|
+
current = arg;
|
|
7476
|
+
} else {
|
|
7477
|
+
current += ` ${arg}`;
|
|
7478
|
+
}
|
|
7479
|
+
}
|
|
7480
|
+
if (current.length > 0) {
|
|
7481
|
+
groups.push(current);
|
|
7482
|
+
}
|
|
7483
|
+
return groups;
|
|
7484
|
+
};
|
|
7467
7485
|
var getProjectCliArgs = async (projectPath) => {
|
|
7468
7486
|
(0, import_node_assert.default)(projectPath !== null && projectPath !== void 0, "projectPath must not be null");
|
|
7469
7487
|
const infoFilePath = resolveUnityHubProjectsInfoFile();
|
|
@@ -7769,9 +7787,11 @@ async function handleStaleLockfile(projectPath) {
|
|
|
7769
7787
|
const message = error instanceof Error ? error.message : String(error);
|
|
7770
7788
|
console.warn(`Failed to delete UnityLockfile: ${message}`);
|
|
7771
7789
|
}
|
|
7790
|
+
console.log();
|
|
7772
7791
|
}
|
|
7773
7792
|
var KILL_POLL_INTERVAL_MS = 100;
|
|
7774
7793
|
var KILL_TIMEOUT_MS = 1e4;
|
|
7794
|
+
var GRACEFUL_QUIT_TIMEOUT_MS = 1e4;
|
|
7775
7795
|
function isProcessAlive(pid) {
|
|
7776
7796
|
try {
|
|
7777
7797
|
process.kill(pid, 0);
|
|
@@ -7786,9 +7806,9 @@ function killProcess(pid) {
|
|
|
7786
7806
|
} catch {
|
|
7787
7807
|
}
|
|
7788
7808
|
}
|
|
7789
|
-
async function waitForProcessExit(pid) {
|
|
7809
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
7790
7810
|
const start = Date.now();
|
|
7791
|
-
while (Date.now() - start <
|
|
7811
|
+
while (Date.now() - start < timeoutMs) {
|
|
7792
7812
|
if (!isProcessAlive(pid)) {
|
|
7793
7813
|
return true;
|
|
7794
7814
|
}
|
|
@@ -7800,16 +7820,73 @@ async function killRunningUnity(projectPath) {
|
|
|
7800
7820
|
const processInfo = await findRunningUnityProcess(projectPath);
|
|
7801
7821
|
if (!processInfo) {
|
|
7802
7822
|
console.log("No running Unity process found for this project.");
|
|
7823
|
+
console.log();
|
|
7803
7824
|
return;
|
|
7804
7825
|
}
|
|
7805
7826
|
const pid = processInfo.pid;
|
|
7806
7827
|
console.log(`Killing Unity (PID: ${pid})...`);
|
|
7807
7828
|
killProcess(pid);
|
|
7808
|
-
const exited = await waitForProcessExit(pid);
|
|
7829
|
+
const exited = await waitForProcessExit(pid, KILL_TIMEOUT_MS);
|
|
7809
7830
|
if (!exited) {
|
|
7810
7831
|
throw new Error(`Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1e3}s.`);
|
|
7811
7832
|
}
|
|
7812
7833
|
console.log("Unity killed.");
|
|
7834
|
+
console.log();
|
|
7835
|
+
}
|
|
7836
|
+
async function sendGracefulQuitMac(pid) {
|
|
7837
|
+
const script = [
|
|
7838
|
+
'tell application "System Events"',
|
|
7839
|
+
` set frontmost of (first process whose unix id is ${pid}) to true`,
|
|
7840
|
+
' keystroke "q" using {command down}',
|
|
7841
|
+
"end tell"
|
|
7842
|
+
].join("\n");
|
|
7843
|
+
try {
|
|
7844
|
+
await execFileAsync("osascript", ["-e", script]);
|
|
7845
|
+
} catch {
|
|
7846
|
+
}
|
|
7847
|
+
}
|
|
7848
|
+
async function sendGracefulQuitWindows(pid) {
|
|
7849
|
+
const scriptLines = [
|
|
7850
|
+
"$ErrorActionPreference = 'Stop'",
|
|
7851
|
+
`try { $proc = Get-Process -Id ${pid} -ErrorAction Stop; $proc.CloseMainWindow() | Out-Null } catch { }`
|
|
7852
|
+
];
|
|
7853
|
+
try {
|
|
7854
|
+
await execFileAsync(WINDOWS_POWERSHELL, ["-NoProfile", "-Command", scriptLines.join("\n")]);
|
|
7855
|
+
} catch {
|
|
7856
|
+
}
|
|
7857
|
+
}
|
|
7858
|
+
async function sendGracefulQuit(pid) {
|
|
7859
|
+
if (process.platform === "darwin") {
|
|
7860
|
+
await sendGracefulQuitMac(pid);
|
|
7861
|
+
return;
|
|
7862
|
+
}
|
|
7863
|
+
if (process.platform === "win32") {
|
|
7864
|
+
await sendGracefulQuitWindows(pid);
|
|
7865
|
+
return;
|
|
7866
|
+
}
|
|
7867
|
+
}
|
|
7868
|
+
async function quitRunningUnity(projectPath) {
|
|
7869
|
+
const processInfo = await findRunningUnityProcess(projectPath);
|
|
7870
|
+
if (!processInfo) {
|
|
7871
|
+
console.log("No running Unity process found for this project.");
|
|
7872
|
+
return;
|
|
7873
|
+
}
|
|
7874
|
+
const pid = processInfo.pid;
|
|
7875
|
+
console.log(`Quitting Unity (PID: ${pid})...`);
|
|
7876
|
+
await sendGracefulQuit(pid);
|
|
7877
|
+
console.log(`Sent graceful quit signal. Waiting up to ${GRACEFUL_QUIT_TIMEOUT_MS / 1e3}s...`);
|
|
7878
|
+
const exitedGracefully = await waitForProcessExit(pid, GRACEFUL_QUIT_TIMEOUT_MS);
|
|
7879
|
+
if (exitedGracefully) {
|
|
7880
|
+
console.log("Unity quit gracefully.");
|
|
7881
|
+
return;
|
|
7882
|
+
}
|
|
7883
|
+
console.log("Unity did not respond to graceful quit. Force killing...");
|
|
7884
|
+
killProcess(pid);
|
|
7885
|
+
const exitedAfterKill = await waitForProcessExit(pid, KILL_TIMEOUT_MS);
|
|
7886
|
+
if (!exitedAfterKill) {
|
|
7887
|
+
throw new Error(`Failed to kill Unity (PID: ${pid}) within ${KILL_TIMEOUT_MS / 1e3}s.`);
|
|
7888
|
+
}
|
|
7889
|
+
console.log("Unity force killed.");
|
|
7813
7890
|
}
|
|
7814
7891
|
function hasBuildTargetArg(unityArgs) {
|
|
7815
7892
|
for (const arg of unityArgs) {
|
|
@@ -7900,12 +7977,12 @@ function findUnityProjectBfs(rootDir, maxDepth) {
|
|
|
7900
7977
|
async function launch(opts) {
|
|
7901
7978
|
const { projectPath, platform, unityArgs, unityVersion } = opts;
|
|
7902
7979
|
const unityPath = getUnityPath(unityVersion);
|
|
7903
|
-
console.log(`Detected Unity version: ${unityVersion}`);
|
|
7904
7980
|
if (!(0, import_node_fs2.existsSync)(unityPath)) {
|
|
7905
7981
|
throw new Error(`Unity ${unityVersion} not found at ${unityPath}. Please install Unity through Unity Hub.`);
|
|
7906
7982
|
}
|
|
7907
7983
|
console.log("Opening Unity...");
|
|
7908
7984
|
console.log(`Project Path: ${projectPath}`);
|
|
7985
|
+
console.log(`Detected Unity version: ${unityVersion}`);
|
|
7909
7986
|
const args = ["-projectPath", projectPath];
|
|
7910
7987
|
const unityArgsContainBuildTarget = hasBuildTargetArg(unityArgs);
|
|
7911
7988
|
if (platform && platform.length > 0 && !unityArgsContainBuildTarget) {
|
|
@@ -7913,86 +7990,133 @@ async function launch(opts) {
|
|
|
7913
7990
|
}
|
|
7914
7991
|
const hubCliArgs = await getProjectCliArgs(projectPath);
|
|
7915
7992
|
if (hubCliArgs.length > 0) {
|
|
7993
|
+
console.log("Unity Hub launch options:");
|
|
7994
|
+
for (const line of groupCliArgs(hubCliArgs)) {
|
|
7995
|
+
console.log(` ${line}`);
|
|
7996
|
+
}
|
|
7916
7997
|
args.push(...hubCliArgs);
|
|
7998
|
+
} else {
|
|
7999
|
+
console.log("Unity Hub launch options: none");
|
|
7917
8000
|
}
|
|
7918
8001
|
if (unityArgs.length > 0) {
|
|
7919
8002
|
args.push(...unityArgs);
|
|
7920
8003
|
}
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
//
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
8004
|
+
return new Promise((resolve5, reject) => {
|
|
8005
|
+
const child = (0, import_node_child_process.spawn)(unityPath, args, {
|
|
8006
|
+
stdio: "ignore",
|
|
8007
|
+
detached: true,
|
|
8008
|
+
// Git Bash (MSYS) がWindows パスをUnix 形式に自動変換するのを防ぐ
|
|
8009
|
+
env: {
|
|
8010
|
+
...process.env,
|
|
8011
|
+
MSYS_NO_PATHCONV: "1"
|
|
8012
|
+
}
|
|
8013
|
+
});
|
|
8014
|
+
const handleError = (error) => {
|
|
8015
|
+
child.removeListener("spawn", handleSpawn);
|
|
8016
|
+
reject(new Error(`Failed to launch Unity: ${error.message}`));
|
|
8017
|
+
};
|
|
8018
|
+
const handleSpawn = () => {
|
|
8019
|
+
child.removeListener("error", handleError);
|
|
8020
|
+
child.unref();
|
|
8021
|
+
resolve5();
|
|
8022
|
+
};
|
|
8023
|
+
child.once("error", handleError);
|
|
8024
|
+
child.once("spawn", handleSpawn);
|
|
7929
8025
|
});
|
|
7930
8026
|
}
|
|
7931
|
-
function
|
|
7932
|
-
if (
|
|
7933
|
-
|
|
8027
|
+
async function orchestrateLaunch(options) {
|
|
8028
|
+
if (options.quit && options.restart) {
|
|
8029
|
+
throw new Error("--quit and --restart cannot be used together.");
|
|
7934
8030
|
}
|
|
7935
|
-
|
|
7936
|
-
if (Number.isNaN(parsed)) {
|
|
7937
|
-
console.error(`Error: Invalid --max-depth value: "${value}". Must be an integer.`);
|
|
7938
|
-
process.exit(1);
|
|
7939
|
-
}
|
|
7940
|
-
return parsed;
|
|
7941
|
-
}
|
|
7942
|
-
async function runLaunchCommand(projectPath, options) {
|
|
7943
|
-
const maxDepth = parseMaxDepth(options.maxDepth);
|
|
7944
|
-
let resolvedProjectPath = projectPath ? (0, import_path6.resolve)(projectPath) : void 0;
|
|
8031
|
+
let resolvedProjectPath = options.projectPath;
|
|
7945
8032
|
if (!resolvedProjectPath) {
|
|
7946
|
-
const
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
`No project-path provided. Searching under ${searchRoot} (max-depth: ${depthInfo})...`
|
|
7950
|
-
);
|
|
7951
|
-
const found = findUnityProjectBfs(searchRoot, maxDepth);
|
|
8033
|
+
const depthInfo = options.searchMaxDepth === -1 ? "unlimited" : String(options.searchMaxDepth);
|
|
8034
|
+
console.log(`Searching for Unity project under ${options.searchRoot} (max-depth: ${depthInfo})...`);
|
|
8035
|
+
const found = findUnityProjectBfs(options.searchRoot, options.searchMaxDepth);
|
|
7952
8036
|
if (!found) {
|
|
7953
|
-
|
|
7954
|
-
process.exit(1);
|
|
8037
|
+
throw new Error(`Unity project not found under ${options.searchRoot}.`);
|
|
7955
8038
|
}
|
|
7956
|
-
console.log(
|
|
8039
|
+
console.log();
|
|
7957
8040
|
resolvedProjectPath = found;
|
|
7958
8041
|
}
|
|
8042
|
+
if (!(0, import_node_fs2.existsSync)(resolvedProjectPath)) {
|
|
8043
|
+
throw new Error(`Project directory not found: ${resolvedProjectPath}`);
|
|
8044
|
+
}
|
|
7959
8045
|
const unityVersion = getUnityVersion(resolvedProjectPath);
|
|
7960
|
-
|
|
7961
|
-
if (unityHubOnlyMode) {
|
|
8046
|
+
if (options.addUnityHub || options.favoriteUnityHub) {
|
|
7962
8047
|
console.log(`Detected Unity version: ${unityVersion}`);
|
|
7963
8048
|
console.log(`Project Path: ${resolvedProjectPath}`);
|
|
7964
8049
|
const now2 = /* @__PURE__ */ new Date();
|
|
7965
|
-
await ensureProjectEntryAndUpdate(
|
|
7966
|
-
resolvedProjectPath,
|
|
7967
|
-
unityVersion,
|
|
7968
|
-
now2,
|
|
7969
|
-
options.favorite === true
|
|
7970
|
-
);
|
|
8050
|
+
await ensureProjectEntryAndUpdate(resolvedProjectPath, unityVersion, now2, options.favoriteUnityHub);
|
|
7971
8051
|
console.log("Unity Hub entry updated.");
|
|
7972
|
-
return;
|
|
8052
|
+
return { action: "hub-updated", projectPath: resolvedProjectPath, unityVersion };
|
|
8053
|
+
}
|
|
8054
|
+
if (options.quit) {
|
|
8055
|
+
await quitRunningUnity(resolvedProjectPath);
|
|
8056
|
+
return { action: "quit", projectPath: resolvedProjectPath };
|
|
7973
8057
|
}
|
|
7974
|
-
|
|
8058
|
+
const isRestart = options.restart;
|
|
8059
|
+
if (isRestart) {
|
|
7975
8060
|
await killRunningUnity(resolvedProjectPath);
|
|
7976
8061
|
} else {
|
|
7977
8062
|
const runningProcess = await findRunningUnityProcess(resolvedProjectPath);
|
|
7978
8063
|
if (runningProcess) {
|
|
7979
|
-
console.log(
|
|
7980
|
-
`Unity process already running for project: ${resolvedProjectPath} (PID: ${runningProcess.pid})`
|
|
7981
|
-
);
|
|
8064
|
+
console.log(`Unity process already running for project: ${resolvedProjectPath} (PID: ${runningProcess.pid})`);
|
|
7982
8065
|
await focusUnityProcess(runningProcess.pid);
|
|
7983
|
-
return;
|
|
8066
|
+
return { action: "focused", projectPath: resolvedProjectPath, pid: runningProcess.pid };
|
|
7984
8067
|
}
|
|
7985
8068
|
}
|
|
7986
8069
|
await handleStaleLockfile(resolvedProjectPath);
|
|
7987
8070
|
const resolved = {
|
|
7988
8071
|
projectPath: resolvedProjectPath,
|
|
7989
8072
|
platform: options.platform,
|
|
7990
|
-
unityArgs:
|
|
8073
|
+
unityArgs: options.unityArgs,
|
|
7991
8074
|
unityVersion
|
|
7992
8075
|
};
|
|
7993
8076
|
await launch(resolved);
|
|
7994
8077
|
const now = /* @__PURE__ */ new Date();
|
|
7995
|
-
|
|
8078
|
+
try {
|
|
8079
|
+
await updateLastModifiedIfExists(resolvedProjectPath, now);
|
|
8080
|
+
} catch (error) {
|
|
8081
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8082
|
+
console.warn(`Failed to update Unity Hub lastModified: ${message}`);
|
|
8083
|
+
}
|
|
8084
|
+
const action = isRestart ? "killed-and-launched" : "launched";
|
|
8085
|
+
return { action, projectPath: resolvedProjectPath, unityVersion };
|
|
8086
|
+
}
|
|
8087
|
+
|
|
8088
|
+
// src/commands/launch.ts
|
|
8089
|
+
function registerLaunchCommand(program3) {
|
|
8090
|
+
program3.command("launch").description(
|
|
8091
|
+
"Open a Unity project with the matching Editor version installed by Unity Hub.\nAuto-detects project path and Unity version from ProjectSettings/ProjectVersion.txt.\nRun 'uloop launch -h' for all options. Details: https://github.com/hatayama/LaunchUnityCommand"
|
|
8092
|
+
).argument("[project-path]", "Path to Unity project").option("-r, --restart", "Kill running Unity and restart").option("-q, --quit", "Gracefully quit running Unity").option("-p, --platform <platform>", "Build target (e.g., Android, iOS)").option("--max-depth <n>", "Search depth when project-path is omitted", "3").option("-a, --add-unity-hub", "Add to Unity Hub (does not launch)").option("-f, --favorite", "Add to Unity Hub as favorite (does not launch)").action(async (projectPath, options) => {
|
|
8093
|
+
await runLaunchCommand(projectPath, options);
|
|
8094
|
+
});
|
|
8095
|
+
}
|
|
8096
|
+
function parseMaxDepth(value) {
|
|
8097
|
+
if (value === void 0) {
|
|
8098
|
+
return 3;
|
|
8099
|
+
}
|
|
8100
|
+
const parsed = parseInt(value, 10);
|
|
8101
|
+
if (Number.isNaN(parsed)) {
|
|
8102
|
+
console.error(`Error: Invalid --max-depth value: "${value}". Must be an integer.`);
|
|
8103
|
+
process.exit(1);
|
|
8104
|
+
}
|
|
8105
|
+
return parsed;
|
|
8106
|
+
}
|
|
8107
|
+
async function runLaunchCommand(projectPath, options) {
|
|
8108
|
+
const maxDepth = parseMaxDepth(options.maxDepth);
|
|
8109
|
+
await orchestrateLaunch({
|
|
8110
|
+
projectPath: projectPath ? (0, import_path6.resolve)(projectPath) : void 0,
|
|
8111
|
+
searchRoot: process.cwd(),
|
|
8112
|
+
searchMaxDepth: maxDepth,
|
|
8113
|
+
platform: options.platform,
|
|
8114
|
+
unityArgs: [],
|
|
8115
|
+
restart: options.restart === true,
|
|
8116
|
+
quit: options.quit === true,
|
|
8117
|
+
addUnityHub: options.addUnityHub === true,
|
|
8118
|
+
favoriteUnityHub: options.favorite === true
|
|
8119
|
+
});
|
|
7996
8120
|
}
|
|
7997
8121
|
|
|
7998
8122
|
// src/commands/focus-window.ts
|