uloop-cli 1.7.0 → 1.7.2
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 +65 -25
- package/dist/cli.bundle.cjs.map +3 -3
- package/package.json +3 -3
- package/src/__tests__/busy-state-order.test.ts +120 -0
- package/src/__tests__/cli-project-error.test.ts +33 -0
- package/src/__tests__/cli-update.test.ts +129 -0
- package/src/cli-project-error.ts +26 -0
- package/src/cli.ts +13 -21
- package/src/default-tools.json +1 -1
- package/src/execute-tool.ts +14 -3
- package/src/project-root.ts +1 -1
- package/src/version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uloop-cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"//version": "x-release-please-version",
|
|
5
5
|
"description": "CLI tool for Unity Editor communication via Unity CLI Loop",
|
|
6
6
|
"main": "dist/cli.bundle.cjs",
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
"eslint-plugin-prettier": "5.5.5",
|
|
58
58
|
"eslint-plugin-security": "4.0.0",
|
|
59
59
|
"jest": "30.3.0",
|
|
60
|
-
"knip": "6.3.
|
|
60
|
+
"knip": "6.3.1",
|
|
61
61
|
"prettier": "3.8.1",
|
|
62
62
|
"ts-jest": "29.4.9",
|
|
63
63
|
"typescript": "5.9.3",
|
|
64
|
-
"typescript-eslint": "8.58.
|
|
64
|
+
"typescript-eslint": "8.58.1"
|
|
65
65
|
},
|
|
66
66
|
"overrides": {
|
|
67
67
|
"minimatch": "10.2.4"
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const mockResolveUnityPort = jest.fn<Promise<number>, [number | undefined, string | undefined]>();
|
|
2
|
+
const mockValidateProjectPath = jest.fn<string, [string]>();
|
|
3
|
+
const mockFindUnityProjectRoot = jest.fn<string | null, []>();
|
|
4
|
+
const mockExistsSync = jest.fn<boolean, [string]>();
|
|
5
|
+
|
|
6
|
+
jest.mock('../port-resolver.js', () => ({
|
|
7
|
+
resolveUnityPort: (explicitPort?: number, projectPath?: string): Promise<number> =>
|
|
8
|
+
mockResolveUnityPort(explicitPort, projectPath),
|
|
9
|
+
validateProjectPath: (projectPath: string): string => mockValidateProjectPath(projectPath),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
jest.mock('../project-root.js', () => ({
|
|
13
|
+
findUnityProjectRoot: (): string | null => mockFindUnityProjectRoot(),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
jest.mock('fs', () => ({
|
|
17
|
+
existsSync: (path: string): boolean => mockExistsSync(path),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
import { executeToolCommand, listAvailableTools, syncTools } from '../execute-tool.js';
|
|
21
|
+
|
|
22
|
+
describe('busy state detection order', () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
mockResolveUnityPort.mockReset();
|
|
25
|
+
mockResolveUnityPort.mockRejectedValue(new Error('RESOLVE_CALLED_BEFORE_BUSY_CHECK'));
|
|
26
|
+
|
|
27
|
+
mockValidateProjectPath.mockReset();
|
|
28
|
+
mockValidateProjectPath.mockReturnValue('/project');
|
|
29
|
+
|
|
30
|
+
mockFindUnityProjectRoot.mockReset();
|
|
31
|
+
mockFindUnityProjectRoot.mockReturnValue('/project');
|
|
32
|
+
|
|
33
|
+
mockExistsSync.mockReset();
|
|
34
|
+
mockExistsSync.mockImplementation((path: string) => path.endsWith('serverstarting.lock'));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('checks busy state before resolving port for tool execution', async () => {
|
|
38
|
+
await expect(executeToolCommand('get-logs', {}, { projectPath: '/project' })).rejects.toThrow(
|
|
39
|
+
'UNITY_SERVER_STARTING',
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
expect(mockResolveUnityPort).not.toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('checks busy state before resolving port for list', async () => {
|
|
46
|
+
await expect(listAvailableTools({ projectPath: '/project' })).rejects.toThrow(
|
|
47
|
+
'UNITY_SERVER_STARTING',
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
expect(mockResolveUnityPort).not.toHaveBeenCalled();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('checks busy state before resolving port for sync', async () => {
|
|
54
|
+
await expect(syncTools({ projectPath: '/project' })).rejects.toThrow('UNITY_SERVER_STARTING');
|
|
55
|
+
|
|
56
|
+
expect(mockResolveUnityPort).not.toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('skips busy state checks when an explicit port is provided for tool execution', async () => {
|
|
60
|
+
mockResolveUnityPort.mockRejectedValue(new Error('EXPLICIT_PORT_RESOLVED'));
|
|
61
|
+
|
|
62
|
+
await expect(executeToolCommand('get-logs', {}, { port: '8711' })).rejects.toThrow(
|
|
63
|
+
'EXPLICIT_PORT_RESOLVED',
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
expect(mockResolveUnityPort).toHaveBeenCalledWith(8711, undefined);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('preserves usage errors before busy state checks for tool execution', async () => {
|
|
70
|
+
mockResolveUnityPort.mockRejectedValue(
|
|
71
|
+
new Error('Cannot specify both --port and --project-path. Use one or the other.'),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
await expect(
|
|
75
|
+
executeToolCommand('get-logs', {}, { port: '8711', projectPath: '/project' }),
|
|
76
|
+
).rejects.toThrow('Cannot specify both --port and --project-path. Use one or the other.');
|
|
77
|
+
|
|
78
|
+
expect(mockResolveUnityPort).toHaveBeenCalledWith(8711, '/project');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('skips busy state checks when an explicit port is provided for list', async () => {
|
|
82
|
+
mockResolveUnityPort.mockRejectedValue(new Error('EXPLICIT_PORT_RESOLVED'));
|
|
83
|
+
|
|
84
|
+
await expect(listAvailableTools({ port: '8711' })).rejects.toThrow('EXPLICIT_PORT_RESOLVED');
|
|
85
|
+
|
|
86
|
+
expect(mockResolveUnityPort).toHaveBeenCalledWith(8711, undefined);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('preserves usage errors before busy state checks for list', async () => {
|
|
90
|
+
mockResolveUnityPort.mockRejectedValue(
|
|
91
|
+
new Error('Cannot specify both --port and --project-path. Use one or the other.'),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
await expect(listAvailableTools({ port: '8711', projectPath: '/project' })).rejects.toThrow(
|
|
95
|
+
'Cannot specify both --port and --project-path. Use one or the other.',
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
expect(mockResolveUnityPort).toHaveBeenCalledWith(8711, '/project');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('skips busy state checks when an explicit port is provided for sync', async () => {
|
|
102
|
+
mockResolveUnityPort.mockRejectedValue(new Error('EXPLICIT_PORT_RESOLVED'));
|
|
103
|
+
|
|
104
|
+
await expect(syncTools({ port: '8711' })).rejects.toThrow('EXPLICIT_PORT_RESOLVED');
|
|
105
|
+
|
|
106
|
+
expect(mockResolveUnityPort).toHaveBeenCalledWith(8711, undefined);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('preserves usage errors before busy state checks for sync', async () => {
|
|
110
|
+
mockResolveUnityPort.mockRejectedValue(
|
|
111
|
+
new Error('Cannot specify both --port and --project-path. Use one or the other.'),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
await expect(syncTools({ port: '8711', projectPath: '/project' })).rejects.toThrow(
|
|
115
|
+
'Cannot specify both --port and --project-path. Use one or the other.',
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
expect(mockResolveUnityPort).toHaveBeenCalledWith(8711, '/project');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getProjectResolutionErrorLines } from '../cli-project-error.js';
|
|
2
|
+
import { UnityNotRunningError } from '../port-resolver.js';
|
|
3
|
+
import { ProjectMismatchError } from '../project-validator.js';
|
|
4
|
+
|
|
5
|
+
describe('getProjectResolutionErrorLines', () => {
|
|
6
|
+
it('returns not-running guidance for UnityNotRunningError', () => {
|
|
7
|
+
const lines = getProjectResolutionErrorLines(new UnityNotRunningError('/project/root'));
|
|
8
|
+
|
|
9
|
+
expect(lines).toEqual([
|
|
10
|
+
'Error: Unity Editor for this project is not running.',
|
|
11
|
+
'',
|
|
12
|
+
' Project: /project/root',
|
|
13
|
+
'',
|
|
14
|
+
'Start the Unity Editor for this project and try again.',
|
|
15
|
+
]);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('returns mismatch guidance for ProjectMismatchError', () => {
|
|
19
|
+
const lines = getProjectResolutionErrorLines(
|
|
20
|
+
new ProjectMismatchError('/expected/project', '/connected/project'),
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
expect(lines).toEqual([
|
|
24
|
+
'Error: Connected Unity instance belongs to a different project.',
|
|
25
|
+
'',
|
|
26
|
+
' Project: /expected/project',
|
|
27
|
+
' Connected to: /connected/project',
|
|
28
|
+
'',
|
|
29
|
+
'Another Unity instance was found, but it belongs to a different project.',
|
|
30
|
+
'Start the Unity Editor for this project, or use --project-path to specify the target.',
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
type SpawnArgs = [string, string[], Record<string, unknown>?];
|
|
2
|
+
|
|
3
|
+
const mockSpawn = jest.fn<unknown, SpawnArgs>();
|
|
4
|
+
|
|
5
|
+
jest.mock('child_process', () => ({
|
|
6
|
+
spawn: (...args: SpawnArgs): unknown => mockSpawn(...args),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
jest.mock(
|
|
10
|
+
'launch-unity',
|
|
11
|
+
() => ({
|
|
12
|
+
orchestrateLaunch: jest.fn(),
|
|
13
|
+
}),
|
|
14
|
+
{ virtual: true },
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
import { getInstalledVersion, updateCli } from '../cli.js';
|
|
18
|
+
|
|
19
|
+
type CloseHandler = (code: number | null) => void;
|
|
20
|
+
type ErrorHandler = (error: Error) => void;
|
|
21
|
+
type DataHandler = (chunk: Buffer) => void;
|
|
22
|
+
|
|
23
|
+
interface MockChildProcess {
|
|
24
|
+
stdout: {
|
|
25
|
+
on: jest.Mock<void, [string, DataHandler]>;
|
|
26
|
+
};
|
|
27
|
+
on: jest.Mock<void, [string, CloseHandler | ErrorHandler]>;
|
|
28
|
+
emitStdout: (chunk: string) => void;
|
|
29
|
+
emitClose: (code: number | null) => void;
|
|
30
|
+
emitError: (error: Error) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function createMockChildProcess(): MockChildProcess {
|
|
34
|
+
let closeHandler: CloseHandler | undefined;
|
|
35
|
+
let errorHandler: ErrorHandler | undefined;
|
|
36
|
+
let dataHandler: DataHandler | undefined;
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
stdout: {
|
|
40
|
+
on: jest.fn((event: string, handler: DataHandler) => {
|
|
41
|
+
if (event === 'data') {
|
|
42
|
+
dataHandler = handler;
|
|
43
|
+
}
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
on: jest.fn((event: string, handler: CloseHandler | ErrorHandler) => {
|
|
47
|
+
if (event === 'close') {
|
|
48
|
+
closeHandler = handler as CloseHandler;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (event === 'error') {
|
|
52
|
+
errorHandler = handler as ErrorHandler;
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
emitStdout: (chunk: string): void => {
|
|
56
|
+
dataHandler?.(Buffer.from(chunk));
|
|
57
|
+
},
|
|
58
|
+
emitClose: (code: number | null): void => {
|
|
59
|
+
closeHandler?.(code);
|
|
60
|
+
},
|
|
61
|
+
emitError: (error: Error): void => {
|
|
62
|
+
errorHandler?.(error);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
describe('CLI update npm invocation', () => {
|
|
68
|
+
const expectedNpmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
69
|
+
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
mockSpawn.mockReset();
|
|
72
|
+
jest.spyOn(console, 'log').mockImplementation(() => {});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
afterEach(() => {
|
|
76
|
+
jest.restoreAllMocks();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('gets installed version without enabling shell mode', () => {
|
|
80
|
+
const child = createMockChildProcess();
|
|
81
|
+
const callback = jest.fn();
|
|
82
|
+
mockSpawn.mockReturnValue(child);
|
|
83
|
+
|
|
84
|
+
getInstalledVersion(callback);
|
|
85
|
+
|
|
86
|
+
expect(mockSpawn).toHaveBeenCalledWith(expectedNpmCommand, [
|
|
87
|
+
'list',
|
|
88
|
+
'-g',
|
|
89
|
+
'uloop-cli',
|
|
90
|
+
'--json',
|
|
91
|
+
]);
|
|
92
|
+
expect(mockSpawn.mock.calls[0]).toHaveLength(2);
|
|
93
|
+
|
|
94
|
+
child.emitStdout(JSON.stringify({ dependencies: { 'uloop-cli': { version: '1.8.0' } } }));
|
|
95
|
+
child.emitClose(0);
|
|
96
|
+
|
|
97
|
+
expect(callback).toHaveBeenCalledWith('1.8.0');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('updates the CLI without enabling shell mode', () => {
|
|
101
|
+
const updateChild = createMockChildProcess();
|
|
102
|
+
const listChild = createMockChildProcess();
|
|
103
|
+
mockSpawn.mockReturnValueOnce(updateChild).mockReturnValueOnce(listChild);
|
|
104
|
+
|
|
105
|
+
updateCli();
|
|
106
|
+
|
|
107
|
+
expect(mockSpawn).toHaveBeenNthCalledWith(
|
|
108
|
+
1,
|
|
109
|
+
expectedNpmCommand,
|
|
110
|
+
['install', '-g', 'uloop-cli@latest'],
|
|
111
|
+
{ stdio: 'inherit' },
|
|
112
|
+
);
|
|
113
|
+
const installOptions = mockSpawn.mock.calls[0]?.[2];
|
|
114
|
+
expect(installOptions?.['shell']).toBeUndefined();
|
|
115
|
+
|
|
116
|
+
updateChild.emitClose(0);
|
|
117
|
+
|
|
118
|
+
expect(mockSpawn).toHaveBeenNthCalledWith(2, expectedNpmCommand, [
|
|
119
|
+
'list',
|
|
120
|
+
'-g',
|
|
121
|
+
'uloop-cli',
|
|
122
|
+
'--json',
|
|
123
|
+
]);
|
|
124
|
+
expect(mockSpawn.mock.calls[1]).toHaveLength(2);
|
|
125
|
+
|
|
126
|
+
listChild.emitStdout(JSON.stringify({ dependencies: { 'uloop-cli': { version: '1.7.1' } } }));
|
|
127
|
+
listChild.emitClose(0);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { UnityNotRunningError } from './port-resolver.js';
|
|
2
|
+
import { ProjectMismatchError } from './project-validator.js';
|
|
3
|
+
|
|
4
|
+
export function getProjectResolutionErrorLines(
|
|
5
|
+
error: UnityNotRunningError | ProjectMismatchError,
|
|
6
|
+
): string[] {
|
|
7
|
+
if (error instanceof UnityNotRunningError) {
|
|
8
|
+
return [
|
|
9
|
+
'Error: Unity Editor for this project is not running.',
|
|
10
|
+
'',
|
|
11
|
+
` Project: ${error.projectRoot}`,
|
|
12
|
+
'',
|
|
13
|
+
'Start the Unity Editor for this project and try again.',
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [
|
|
18
|
+
'Error: Connected Unity instance belongs to a different project.',
|
|
19
|
+
'',
|
|
20
|
+
` Project: ${error.expectedProjectRoot}`,
|
|
21
|
+
` Connected to: ${error.connectedProjectRoot}`,
|
|
22
|
+
'',
|
|
23
|
+
'Another Unity instance was found, but it belongs to a different project.',
|
|
24
|
+
'Start the Unity Editor for this project, or use --project-path to specify the target.',
|
|
25
|
+
];
|
|
26
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -39,6 +39,7 @@ import { findUnityProjectRoot } from './project-root.js';
|
|
|
39
39
|
import { validateProjectPath, UnityNotRunningError } from './port-resolver.js';
|
|
40
40
|
import { ProjectMismatchError } from './project-validator.js';
|
|
41
41
|
import { filterEnabledTools, isToolEnabled } from './tool-settings-loader.js';
|
|
42
|
+
import { getProjectResolutionErrorLines } from './cli-project-error.js';
|
|
42
43
|
|
|
43
44
|
interface CliOptions extends GlobalOptions {
|
|
44
45
|
[key: string]: unknown;
|
|
@@ -430,24 +431,16 @@ async function runWithErrorHandling(fn: () => Promise<void>): Promise<void> {
|
|
|
430
431
|
await fn();
|
|
431
432
|
} catch (error) {
|
|
432
433
|
if (error instanceof UnityNotRunningError) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
console.error('');
|
|
437
|
-
console.error('Start the Unity Editor for this project and try again.');
|
|
434
|
+
for (const line of getProjectResolutionErrorLines(error)) {
|
|
435
|
+
console.error(line.startsWith('Error: ') ? `\x1b[31m${line}\x1b[0m` : line);
|
|
436
|
+
}
|
|
438
437
|
process.exit(1);
|
|
439
438
|
}
|
|
440
439
|
|
|
441
440
|
if (error instanceof ProjectMismatchError) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
console.error(` Connected to: ${error.connectedProjectRoot}`);
|
|
446
|
-
console.error('');
|
|
447
|
-
console.error('Another Unity instance was found, but it belongs to a different project.');
|
|
448
|
-
console.error(
|
|
449
|
-
'Start the Unity Editor for this project, or use --project-path to specify the target.',
|
|
450
|
-
);
|
|
441
|
+
for (const line of getProjectResolutionErrorLines(error)) {
|
|
442
|
+
console.error(line.startsWith('Error: ') ? `\x1b[31m${line}\x1b[0m` : line);
|
|
443
|
+
}
|
|
451
444
|
process.exit(1);
|
|
452
445
|
}
|
|
453
446
|
|
|
@@ -604,11 +597,9 @@ compdef _uloop uloop`;
|
|
|
604
597
|
/**
|
|
605
598
|
* Get the currently installed version of uloop-cli from npm.
|
|
606
599
|
*/
|
|
607
|
-
function getInstalledVersion(callback: (version: string | null) => void): void {
|
|
600
|
+
export function getInstalledVersion(callback: (version: string | null) => void): void {
|
|
608
601
|
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
609
|
-
const child = spawn(npmCommand, ['list', '-g', 'uloop-cli', '--json']
|
|
610
|
-
shell: true,
|
|
611
|
-
});
|
|
602
|
+
const child = spawn(npmCommand, ['list', '-g', 'uloop-cli', '--json']);
|
|
612
603
|
|
|
613
604
|
let stdout = '';
|
|
614
605
|
child.stdout.on('data', (data: Buffer) => {
|
|
@@ -663,14 +654,13 @@ function getInstalledVersion(callback: (version: string | null) => void): void {
|
|
|
663
654
|
/**
|
|
664
655
|
* Update uloop CLI to the latest version using npm.
|
|
665
656
|
*/
|
|
666
|
-
function updateCli(): void {
|
|
657
|
+
export function updateCli(): void {
|
|
667
658
|
const previousVersion = VERSION;
|
|
668
659
|
console.log('Updating uloop-cli to the latest version...');
|
|
669
660
|
|
|
670
661
|
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
671
662
|
const child = spawn(npmCommand, ['install', '-g', 'uloop-cli@latest'], {
|
|
672
663
|
stdio: 'inherit',
|
|
673
|
-
shell: true,
|
|
674
664
|
});
|
|
675
665
|
|
|
676
666
|
child.on('close', (code) => {
|
|
@@ -1039,4 +1029,6 @@ async function main(): Promise<void> {
|
|
|
1039
1029
|
program.parse();
|
|
1040
1030
|
}
|
|
1041
1031
|
|
|
1042
|
-
|
|
1032
|
+
if (process.env.JEST_WORKER_ID === undefined) {
|
|
1033
|
+
void main();
|
|
1034
|
+
}
|
package/src/default-tools.json
CHANGED
package/src/execute-tool.ts
CHANGED
|
@@ -188,6 +188,14 @@ function checkUnityBusyState(projectPath?: string): void {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
function checkUnityBusyStateBeforeProjectResolution(globalOptions: GlobalOptions): void {
|
|
192
|
+
if (globalOptions.port !== undefined) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
checkUnityBusyState(globalOptions.projectPath);
|
|
197
|
+
}
|
|
198
|
+
|
|
191
199
|
export async function executeToolCommand(
|
|
192
200
|
toolName: string,
|
|
193
201
|
params: Record<string, unknown>,
|
|
@@ -201,6 +209,7 @@ export async function executeToolCommand(
|
|
|
201
209
|
}
|
|
202
210
|
portNumber = parsed;
|
|
203
211
|
}
|
|
212
|
+
checkUnityBusyStateBeforeProjectResolution(globalOptions);
|
|
204
213
|
const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
|
|
205
214
|
const compileOptions = getCompileExecutionOptions(toolName, params);
|
|
206
215
|
const shouldWaitForDomainReload = compileOptions.waitForDomainReload;
|
|
@@ -228,7 +237,7 @@ export async function executeToolCommand(
|
|
|
228
237
|
let requestDispatched = false;
|
|
229
238
|
|
|
230
239
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
231
|
-
|
|
240
|
+
checkUnityBusyStateBeforeProjectResolution(globalOptions);
|
|
232
241
|
|
|
233
242
|
const client = new DirectUnityClient(port);
|
|
234
243
|
try {
|
|
@@ -391,6 +400,7 @@ export async function listAvailableTools(globalOptions: GlobalOptions): Promise<
|
|
|
391
400
|
}
|
|
392
401
|
portNumber = parsed;
|
|
393
402
|
}
|
|
403
|
+
checkUnityBusyStateBeforeProjectResolution(globalOptions);
|
|
394
404
|
const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
|
|
395
405
|
const projectRoot =
|
|
396
406
|
globalOptions.projectPath !== undefined
|
|
@@ -403,7 +413,7 @@ export async function listAvailableTools(globalOptions: GlobalOptions): Promise<
|
|
|
403
413
|
|
|
404
414
|
let lastError: unknown;
|
|
405
415
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
406
|
-
|
|
416
|
+
checkUnityBusyStateBeforeProjectResolution(globalOptions);
|
|
407
417
|
|
|
408
418
|
const client = new DirectUnityClient(port);
|
|
409
419
|
try {
|
|
@@ -488,6 +498,7 @@ export async function syncTools(globalOptions: GlobalOptions): Promise<void> {
|
|
|
488
498
|
}
|
|
489
499
|
portNumber = parsed;
|
|
490
500
|
}
|
|
501
|
+
checkUnityBusyStateBeforeProjectResolution(globalOptions);
|
|
491
502
|
const port = await resolveUnityPort(portNumber, globalOptions.projectPath);
|
|
492
503
|
const projectRoot =
|
|
493
504
|
globalOptions.projectPath !== undefined
|
|
@@ -500,7 +511,7 @@ export async function syncTools(globalOptions: GlobalOptions): Promise<void> {
|
|
|
500
511
|
|
|
501
512
|
let lastError: unknown;
|
|
502
513
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
503
|
-
|
|
514
|
+
checkUnityBusyStateBeforeProjectResolution(globalOptions);
|
|
504
515
|
|
|
505
516
|
const client = new DirectUnityClient(port);
|
|
506
517
|
try {
|
package/src/project-root.ts
CHANGED
|
@@ -34,7 +34,7 @@ export function getUnitySettingsCandidatePaths(dirPath: string): string[] {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export function hasUloopInstalled(dirPath: string): boolean {
|
|
37
|
-
return getUnitySettingsCandidatePaths(dirPath).some(path => existsSync(path));
|
|
37
|
+
return getUnitySettingsCandidatePaths(dirPath).some((path) => existsSync(path));
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function isUnityProjectWithUloop(dirPath: string): boolean {
|
package/src/version.ts
CHANGED