@notask/unity-cli-tools 1.1.2 → 2.0.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.
Files changed (58) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/CHANGELOG.md +164 -146
  3. package/LICENSE +23 -23
  4. package/README.md +809 -347
  5. package/dist/cjs/errors/Result.js +76 -0
  6. package/dist/cjs/errors/UnityError.js +77 -0
  7. package/dist/cjs/errors/index.js +18 -0
  8. package/dist/cjs/events/hubEventEmitter.js +16 -16
  9. package/dist/cjs/events/hubEventParser.js +97 -27
  10. package/dist/cjs/events/patterns/implementations/bracketModulePattern.js +57 -0
  11. package/dist/cjs/events/patterns/implementations/errorPattern.js +99 -0
  12. package/dist/cjs/events/patterns/implementations/fallbackPattern.js +63 -0
  13. package/dist/cjs/events/patterns/implementations/index.js +9 -0
  14. package/dist/cjs/events/patterns/index.js +23 -0
  15. package/dist/cjs/events/patterns/patternRegistry.js +69 -0
  16. package/dist/cjs/events/patterns/statusNormalizer.js +280 -0
  17. package/dist/cjs/events/patterns/types.js +2 -0
  18. package/dist/cjs/index.js +7 -6
  19. package/dist/cjs/unityEditor.js +162 -194
  20. package/dist/cjs/unityHub.js +82 -78
  21. package/dist/cjs/utils/commandExecutor.js +8 -9
  22. package/dist/esm/errors/Result.d.ts +21 -0
  23. package/dist/esm/errors/Result.js +63 -0
  24. package/dist/esm/errors/UnityError.d.ts +36 -0
  25. package/dist/esm/errors/UnityError.js +64 -0
  26. package/dist/esm/errors/index.d.ts +2 -0
  27. package/dist/esm/errors/index.js +2 -0
  28. package/dist/esm/events/hubEventEmitter.d.ts +1 -1
  29. package/dist/esm/events/hubEventParser.d.ts +17 -3
  30. package/dist/esm/events/hubEventParser.js +97 -27
  31. package/dist/esm/events/patterns/implementations/bracketModulePattern.d.ts +11 -0
  32. package/dist/esm/events/patterns/implementations/bracketModulePattern.js +53 -0
  33. package/dist/esm/events/patterns/implementations/errorPattern.d.ts +22 -0
  34. package/dist/esm/events/patterns/implementations/errorPattern.js +95 -0
  35. package/dist/esm/events/patterns/implementations/fallbackPattern.d.ts +13 -0
  36. package/dist/esm/events/patterns/implementations/fallbackPattern.js +59 -0
  37. package/dist/esm/events/patterns/implementations/index.d.ts +3 -0
  38. package/dist/esm/events/patterns/implementations/index.js +3 -0
  39. package/dist/esm/events/patterns/index.d.ts +4 -0
  40. package/dist/esm/events/patterns/index.js +4 -0
  41. package/dist/esm/events/patterns/patternRegistry.d.ts +14 -0
  42. package/dist/esm/events/patterns/patternRegistry.js +65 -0
  43. package/dist/esm/events/patterns/statusNormalizer.d.ts +15 -0
  44. package/dist/esm/events/patterns/statusNormalizer.js +276 -0
  45. package/dist/esm/events/patterns/types.d.ts +30 -0
  46. package/dist/esm/events/patterns/types.js +1 -0
  47. package/dist/esm/index.d.ts +5 -4
  48. package/dist/esm/index.js +1 -0
  49. package/dist/esm/unityEditor.d.ts +11 -13
  50. package/dist/esm/unityEditor.js +175 -207
  51. package/dist/esm/unityHub.d.ts +12 -11
  52. package/dist/esm/unityHub.js +80 -76
  53. package/dist/esm/utils/commandExecutor.d.ts +4 -3
  54. package/dist/esm/utils/commandExecutor.js +8 -9
  55. package/package.json +70 -70
  56. package/sandbox/index.js +51 -0
  57. package/sandbox/node_modules/.package-lock.json +10495 -0
  58. package/sandbox/package.json +13 -0
@@ -5,6 +5,7 @@ import { EditorArchitecture, } from "./types/unity.js";
5
5
  import { executeCommand } from "./utils/commandExecutor.js";
6
6
  import { getUnityChangeset } from "unity-changeset";
7
7
  import { UnityHubInstallerEvent } from "./events/hubEventEmitter.js";
8
+ import { ok, err, UnityHubNotFoundError, UnityCommandError, UnityInstallationError, UnityProjectError, InvalidArgumentError, } from "./errors/index.js";
8
9
  class UnityHub {
9
10
  static CONFIG_PATHS = {
10
11
  win32: {
@@ -51,122 +52,124 @@ class UnityHub {
51
52
  const isAvailable = await UnityHub.isUnityHubAvailable();
52
53
  if (!isAvailable) {
53
54
  console.error("Unity Hub is not available.");
54
- return {
55
- success: false,
56
- stdout: "",
57
- stderr: "Unity Hub is not available.",
58
- exitCode: -1,
59
- };
60
- }
61
- try {
62
- const hubArgs = [this.platform !== "linux" ? "--" : "", "--headless", ...args].filter(Boolean);
63
- console.debug(`Executing Unity Hub command: ${this.hubPath} ${hubArgs.join(" ")}`);
64
- return await executeCommand(this.hubPath, hubArgs, options);
65
- }
66
- catch (error) {
67
- console.error("Error executing Unity Hub command:", error);
68
- return {
69
- success: false,
70
- stdout: "",
71
- stderr: String(error),
72
- exitCode: -1,
73
- };
55
+ return err(new UnityHubNotFoundError("Unity Hub is not available", { hubPath: this.hubPath }));
74
56
  }
57
+ const hubArgs = [this.platform !== "linux" ? "--" : "", "--headless", ...args].filter(Boolean);
58
+ console.debug(`Executing Unity Hub command: ${this.hubPath} ${hubArgs.join(" ")}`);
59
+ return await executeCommand(this.hubPath, hubArgs, options);
75
60
  }
76
61
  static async getInstallPath() {
77
- const { stdout, stderr } = await this.execUnityHubCommand(["install-path", "-g"], {
62
+ const result = await this.execUnityHubCommand(["install-path", "-g"], {
78
63
  reject: false,
79
64
  });
80
- if (stderr) {
81
- throw new Error(`Error getting install path: ${stderr}`);
65
+ if (!result.success) {
66
+ return result;
67
+ }
68
+ if (result.value.stderr) {
69
+ return err(new UnityCommandError(`Error getting install path: ${result.value.stderr}`, result.value.stdout, result.value.stderr, result.value.exitCode));
82
70
  }
83
- return stdout;
71
+ return ok(result.value.stdout.trim());
84
72
  }
85
73
  static async setInstallPath(path) {
86
- const { stdout, stderr } = await this.execUnityHubCommand(["install-path", "-s", path], {
74
+ const result = await this.execUnityHubCommand(["install-path", "-s", path], {
87
75
  reject: false,
88
76
  });
89
- if (stderr) {
90
- throw new Error(`Error setting install path: ${stderr}`);
77
+ if (!result.success) {
78
+ return result;
79
+ }
80
+ if (result.value.stderr) {
81
+ return err(new UnityCommandError(`Error setting install path: ${result.value.stderr}`, result.value.stdout, result.value.stderr, result.value.exitCode));
91
82
  }
92
- console.debug(`Install path set to: ${stdout}`);
83
+ console.debug(`Install path set to: ${result.value.stdout}`);
84
+ return ok(undefined);
93
85
  }
94
86
  static async getUnityInstallations(filter = "i") {
95
87
  if (!["i", "a", "r"].includes(filter)) {
96
- throw new Error(`Invalid filter "${filter}". Use "i" for installed, "a" for all, or "r" for available releases.`);
88
+ return err(new InvalidArgumentError(`Invalid filter "${filter}". Use "i" for installed, "a" for all, or "r" for available releases.`, { filter, validFilters: ["i", "a", "r"] }));
97
89
  }
98
- const { stdout, stderr } = await this.execUnityHubCommand(["editors", `-${filter}`], {
90
+ const result = await this.execUnityHubCommand(["editors", `-${filter}`], {
99
91
  reject: false,
100
92
  });
93
+ if (!result.success) {
94
+ return result;
95
+ }
96
+ const { stdout, stderr } = result.value;
101
97
  const isSuccess = stdout.includes(", installed at");
102
- if (stderr)
103
- throw new Error(`Get installations command warning/error: ${stderr}`);
104
- if (!isSuccess)
105
- throw new Error(`Consider install a Unity version using Unity Hub.`);
98
+ if (stderr) {
99
+ return err(new UnityCommandError(`Get installations command warning/error: ${stderr}`, stdout, stderr, result.value.exitCode));
100
+ }
101
+ if (!isSuccess) {
102
+ return err(new UnityInstallationError("No Unity installations found. Consider installing a Unity version using Unity Hub.", {
103
+ filter,
104
+ }));
105
+ }
106
106
  const lines = stdout.split(/\r\n|\n/);
107
107
  const installations = {};
108
108
  lines.forEach((line) => {
109
109
  const [version, unityPath] = line.split(", installed at").map((entry) => entry.trim());
110
- installations[version] = unityPath;
110
+ if (version && unityPath) {
111
+ installations[version] = unityPath;
112
+ }
111
113
  });
112
- if (Object.keys(installations).length <= 0)
113
- throw new Error("No unity installations found.");
114
- return installations;
114
+ if (Object.keys(installations).length <= 0) {
115
+ return err(new UnityInstallationError("No Unity installations found.", { filter }));
116
+ }
117
+ return ok(installations);
115
118
  }
116
119
  static async addModule(editorVersion, modules, childModules = true) {
117
- try {
118
- console.debug(`Adding module ${modules} to Unity ${editorVersion}`);
119
- const args = ["install-modules", "-v", editorVersion];
120
- if (modules.length > 0) {
121
- args.push(...["--module", modules.join(" ")]);
122
- if (childModules) {
123
- args.push("--child-modules");
124
- }
125
- }
126
- else {
127
- throw new Error("No module IDs provided.");
128
- }
129
- const installerEmitter = new UnityHubInstallerEvent();
130
- this.execUnityHubCommand(args, {
131
- reject: false,
132
- onStdout: (data) => installerEmitter.Progress(data),
133
- }).catch((error) => {
134
- console.error(`Error adding module ${modules} to Unity ${editorVersion}:`, error);
135
- });
136
- return installerEmitter;
120
+ if (modules.length === 0) {
121
+ return err(new InvalidArgumentError("No module IDs provided.", { editorVersion, modules }));
137
122
  }
138
- catch (error) {
139
- console.error(`Error adding module ${modules} to Unity ${editorVersion}:`, error);
140
- throw error;
123
+ console.debug(`Adding module ${modules} to Unity ${editorVersion}`);
124
+ const args = ["install-modules", "-v", editorVersion, "--module", modules.join(" ")];
125
+ if (childModules) {
126
+ args.push("--child-modules");
141
127
  }
128
+ const installerEmitter = new UnityHubInstallerEvent();
129
+ this.execUnityHubCommand(args, {
130
+ reject: false,
131
+ onStdout: (data) => installerEmitter.Progress(data),
132
+ })
133
+ .then((result) => {
134
+ if (!result.success) {
135
+ console.error(`Error adding module ${modules} to Unity ${editorVersion}:`, result.error);
136
+ }
137
+ })
138
+ .catch((error) => {
139
+ console.error(`Error adding module ${modules} to Unity ${editorVersion}:`, error);
140
+ });
141
+ return ok(installerEmitter);
142
142
  }
143
143
  static async addEditor(version, modules = [], architecture) {
144
144
  try {
145
145
  const data = await getUnityChangeset(version);
146
- const args = ["install", "-v", version];
147
- args.push("--changeset", data.changeset);
146
+ const args = ["install", "-v", version, "--changeset", data.changeset];
148
147
  if (modules.length > 0) {
149
- args.push("--module");
150
- args.push(modules.join(" "));
148
+ args.push("--module", modules.join(" "));
151
149
  }
152
150
  if (!architecture) {
153
151
  const arch = os.arch() || process.arch;
154
- const defaultArchitecture = arch === "arm64" || arch === "arm" ? EditorArchitecture.arm64 : EditorArchitecture.x86_64;
155
- architecture = defaultArchitecture;
152
+ architecture = arch === "arm64" || arch === "arm" ? EditorArchitecture.arm64 : EditorArchitecture.x86_64;
156
153
  }
157
154
  args.push("--architecture", architecture);
158
155
  const installerEmitter = new UnityHubInstallerEvent();
159
156
  this.execUnityHubCommand(args, {
160
157
  reject: false,
161
158
  onStdout: (data) => installerEmitter.Progress(data),
162
- }).catch((error) => {
159
+ })
160
+ .then((result) => {
161
+ if (!result.success) {
162
+ console.error(`Error installing Unity ${version}:`, result.error);
163
+ }
164
+ })
165
+ .catch((error) => {
163
166
  console.error(`Error installing Unity ${version}:`, error);
164
167
  });
165
- return installerEmitter;
168
+ return ok(installerEmitter);
166
169
  }
167
170
  catch (error) {
168
171
  console.error(error);
169
- throw error;
172
+ return err(new UnityInstallationError(`Failed to install Unity ${version}: ${String(error)}`, { version, modules, architecture }));
170
173
  }
171
174
  }
172
175
  static async getProjects() {
@@ -174,19 +177,20 @@ class UnityHub {
174
177
  const projectsPath = this.getProjectsPath();
175
178
  if (!projectsPath || !fs.existsSync(projectsPath)) {
176
179
  console.debug(`Projects file not found at: ${projectsPath}`);
177
- return [];
180
+ return err(new UnityProjectError(`Projects file not found at: ${projectsPath}`, { projectsPath }));
178
181
  }
179
182
  const projectsData = await fs.readJson(projectsPath);
180
183
  const projects = Object.values(projectsData.data);
181
- return projects.map((project) => ({
184
+ const mappedProjects = projects.map((project) => ({
182
185
  name: project.title,
183
186
  path: project.path,
184
187
  version: project.version,
185
188
  }));
189
+ return ok(mappedProjects);
186
190
  }
187
191
  catch (error) {
188
192
  console.error("Error getting recent projects:", error);
189
- return [];
193
+ return err(new UnityProjectError(`Failed to get projects: ${String(error)}`));
190
194
  }
191
195
  }
192
196
  static async getDefaultProjectsDirectory() {
@@ -194,14 +198,14 @@ class UnityHub {
194
198
  const projectDirPath = this.getProjectDirPath();
195
199
  if (!projectDirPath || !fs.existsSync(projectDirPath)) {
196
200
  console.debug(`Project directory file not found at: ${projectDirPath}`);
197
- return null;
201
+ return ok(null);
198
202
  }
199
203
  const projectDirData = await fs.readJson(projectDirPath);
200
- return projectDirData.directoryPath ?? null;
204
+ return ok(projectDirData.directoryPath ?? null);
201
205
  }
202
206
  catch (error) {
203
207
  console.error("Error getting default project directory:", error);
204
- return null;
208
+ return err(new UnityProjectError(`Failed to get default project directory: ${String(error)}`));
205
209
  }
206
210
  }
207
211
  }
@@ -1,4 +1,6 @@
1
1
  import { Options } from "execa";
2
+ import { Result } from "../errors/index.js";
3
+ import { UnityCommandError } from "../errors/index.js";
2
4
  export interface CommandOptions extends Options {
3
5
  reject?: boolean;
4
6
  timeout?: number;
@@ -7,10 +9,9 @@ export interface CommandOptions extends Options {
7
9
  env?: Record<string, string>;
8
10
  cwd?: string;
9
11
  }
10
- export interface CommandResult {
11
- success: boolean;
12
+ export interface CommandOutput {
12
13
  stdout: string;
13
14
  stderr: string;
14
15
  exitCode?: number;
15
16
  }
16
- export declare function executeCommand(executable: string, args: string[], options?: CommandOptions): Promise<CommandResult>;
17
+ export declare function executeCommand(executable: string, args: string[], options?: CommandOptions): Promise<Result<CommandOutput, UnityCommandError>>;
@@ -1,4 +1,6 @@
1
1
  import { execa } from "execa";
2
+ import { ok, err } from "../errors/index.js";
3
+ import { UnityCommandError } from "../errors/index.js";
2
4
  export async function executeCommand(executable, args, options = {}) {
3
5
  try {
4
6
  const streamOutput = options.onStdout || options.onStderr;
@@ -37,19 +39,16 @@ export async function executeCommand(executable, args, options = {}) {
37
39
  }
38
40
  }
39
41
  const { stdout, stderr, exitCode } = await subprocess;
40
- return {
41
- success: true,
42
+ return ok({
42
43
  stdout,
43
44
  stderr,
44
45
  exitCode,
45
- };
46
+ });
46
47
  }
47
48
  catch (error) {
48
- return {
49
- success: false,
50
- stdout: error.stdout ?? "",
51
- stderr: error.stderr ?? String(error),
52
- exitCode: error.exitCode,
53
- };
49
+ const stdout = error.stdout ?? "";
50
+ const stderr = error.stderr ?? String(error);
51
+ const exitCode = error.exitCode;
52
+ return err(new UnityCommandError(`Command execution failed: ${executable} ${args.join(" ")}`, stdout, stderr, exitCode, { executable, args }));
54
53
  }
55
54
  }
package/package.json CHANGED
@@ -1,70 +1,70 @@
1
- {
2
- "name": "@notask/unity-cli-tools",
3
- "version": "1.1.2",
4
- "main": "dist/cjs/index.js",
5
- "module": "dist/esm/index.js",
6
- "types": "dist/esm/index.d.ts",
7
- "type": "module",
8
- "exports": {
9
- ".": {
10
- "import": "./dist/esm/index.js",
11
- "require": "./dist/cjs/index.js",
12
- "types": "./dist/esm/index.d.ts"
13
- }
14
- },
15
- "private": false,
16
- "publishConfig": {
17
- "access": "public"
18
- },
19
- "repository": {
20
- "type": "git",
21
- "url": "https://github.com/NoTaskStudios/unity-cli-tools.git"
22
- },
23
- "scripts": {
24
- "clean": "rimraf dist",
25
- "build": "npm run clean && npm run build:esm && npm run build:cjs",
26
- "build:esm": "tsc --project tsconfig.json",
27
- "build:cjs": "tsc --project tsconfig.cjs.json && node scripts/write-cjs-package.cjs",
28
- "test": "jest --passWithNoTests",
29
- "test:coverage": "jest --coverage",
30
- "lint": "eslint . --ext .ts",
31
- "lint:fix": "eslint . --ext .ts --fix",
32
- "format": "prettier --write \"src/**/*.ts\"",
33
- "format:check": "prettier --check \"src/**/*.ts\"",
34
- "semantic-release": "semantic-release"
35
- },
36
- "keywords": [
37
- "unity",
38
- "cli",
39
- "tools",
40
- "command line"
41
- ],
42
- "author": "NoTask Team",
43
- "license": "MIT",
44
- "description": "A tools for Unity command line development.",
45
- "dependencies": {
46
- "execa": "^9.5.2",
47
- "fs-extra": "^11.3.0",
48
- "unity-changeset": "2.5.0"
49
- },
50
- "devDependencies": {
51
- "@eslint/js": "9.24.0",
52
- "@semantic-release/changelog": "^6.0.3",
53
- "@semantic-release/git": "^10.0.1",
54
- "@semantic-release/npm": "^12.0.1",
55
- "@types/fs-extra": "^11.0.4",
56
- "@types/jest": "^29.5.14",
57
- "@types/node": "^22.13.14",
58
- "@typescript-eslint/eslint-plugin": "^8.30.1",
59
- "@typescript-eslint/parser": "^8.30.1",
60
- "eslint": "9.24.0",
61
- "jest": "^29.7.0",
62
- "prettier": "^3.5.3",
63
- "rimraf": "6.0.1",
64
- "semantic-release": "^24.2.3",
65
- "ts-jest": "^29.3.1",
66
- "tsx": "4.19.3",
67
- "typescript": "^5.8.3",
68
- "typescript-eslint": "8.30.1"
69
- }
70
- }
1
+ {
2
+ "name": "@notask/unity-cli-tools",
3
+ "version": "2.0.0",
4
+ "main": "dist/cjs/index.js",
5
+ "module": "dist/esm/index.js",
6
+ "types": "dist/esm/index.d.ts",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/esm/index.js",
11
+ "require": "./dist/cjs/index.js",
12
+ "types": "./dist/esm/index.d.ts"
13
+ }
14
+ },
15
+ "private": false,
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/NoTaskStudios/unity-cli-tools.git"
22
+ },
23
+ "scripts": {
24
+ "clean": "rimraf dist",
25
+ "build": "npm run clean && npm run build:esm && npm run build:cjs",
26
+ "build:esm": "tsc --project tsconfig.json",
27
+ "build:cjs": "tsc --project tsconfig.cjs.json && node scripts/write-cjs-package.cjs",
28
+ "test": "jest --passWithNoTests",
29
+ "test:coverage": "jest --coverage",
30
+ "lint": "eslint . --ext .ts",
31
+ "lint:fix": "eslint . --ext .ts --fix",
32
+ "format": "prettier --write \"src/**/*.ts\"",
33
+ "format:check": "prettier --check \"src/**/*.ts\"",
34
+ "semantic-release": "semantic-release"
35
+ },
36
+ "keywords": [
37
+ "unity",
38
+ "cli",
39
+ "tools",
40
+ "command line"
41
+ ],
42
+ "author": "NoTask Team",
43
+ "license": "MIT",
44
+ "description": "A tools for Unity command line development.",
45
+ "dependencies": {
46
+ "execa": "^9.5.2",
47
+ "fs-extra": "^11.3.0",
48
+ "unity-changeset": "3.1.0"
49
+ },
50
+ "devDependencies": {
51
+ "@eslint/js": "9.24.0",
52
+ "@semantic-release/changelog": "^6.0.3",
53
+ "@semantic-release/git": "^10.0.1",
54
+ "@semantic-release/npm": "^12.0.1",
55
+ "@types/fs-extra": "^11.0.4",
56
+ "@types/jest": "^29.5.14",
57
+ "@types/node": "^22.13.14",
58
+ "@typescript-eslint/eslint-plugin": "^8.30.1",
59
+ "@typescript-eslint/parser": "^8.30.1",
60
+ "eslint": "9.24.0",
61
+ "jest": "^29.7.0",
62
+ "prettier": "^3.5.3",
63
+ "rimraf": "6.0.1",
64
+ "semantic-release": "^24.2.3",
65
+ "ts-jest": "^29.3.1",
66
+ "tsx": "4.19.3",
67
+ "typescript": "^5.8.3",
68
+ "typescript-eslint": "8.30.1"
69
+ }
70
+ }
@@ -0,0 +1,51 @@
1
+ import { UnityEditor, UnityHub, InstallerEventType, UnityModules, isOk, isErr } from "@notask/unity-cli-tools";
2
+
3
+ // Check if Unity Hub is available
4
+ const isAvailable = await UnityHub.isUnityHubAvailable();
5
+
6
+ if (!isAvailable) {
7
+ console.error("Unity Hub is not available on this system.");
8
+ process.exit(1);
9
+ } else {
10
+ console.log("Unity Hub is available.");
11
+ }
12
+
13
+ // Get projects from Unity Hub
14
+ const result = await UnityHub.getProjects();
15
+
16
+ if (isOk(result)) {
17
+ const projects = result.value;
18
+ // Returns: [{ name: 'ProjectName', path: '/path/to/project', version: '2022.3.60f1' }, ...]
19
+ console.log("Projects:", projects);
20
+ }
21
+
22
+ // Get default projects directory
23
+ const dirResult = await UnityHub.getDefaultProjectsDirectory();
24
+
25
+ if (isOk(dirResult)) {
26
+ const defaultDir = dirResult.value; // string | null
27
+ console.log("Default directory:", defaultDir);
28
+ }
29
+
30
+ const addModuleEvent = await UnityHub.addModule("6000.3.2f1", UnityModules.WebGLBuildSupport);
31
+
32
+ if (!isOk(addModuleEvent)) {
33
+ console.error("Failed to start installation:", addModuleEvent.error);
34
+ }
35
+
36
+ const installer = addModuleEvent.value;
37
+ // Listen to progress events
38
+ installer.on(InstallerEventType.Progress, (events) => {
39
+ console.log(
40
+ "Progress:",
41
+ events.map((e) => `${e.module}: ${e.status} ${e.progress || 0}%`)
42
+ );
43
+ });
44
+
45
+ installer.on(InstallerEventType.Error, (errorEvents) => {
46
+ console.error("Installation error:", errorEvents);
47
+ });
48
+
49
+ installer.on(InstallerEventType.Completed, (events) => {
50
+ console.log("Installation completed!");
51
+ });