@uofx/cli 1.0.2 → 1.1.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 (240) hide show
  1. package/README.md +159 -3
  2. package/THIRD-PARTY-NOTICES.txt +84 -2
  3. package/dist/application/dtos/config/index.js +22 -0
  4. package/dist/application/dtos/config/request/index.js +19 -0
  5. package/dist/application/dtos/config/request/set-config.request.dto.js +3 -0
  6. package/dist/application/dtos/config/response/get-config.response.dto.js +8 -0
  7. package/dist/application/dtos/config/response/index.js +21 -0
  8. package/dist/application/dtos/dev/index.js +24 -0
  9. package/dist/application/dtos/dev/request/generate-component.request.dto.js +3 -0
  10. package/dist/application/dtos/dev/request/index.js +25 -0
  11. package/dist/application/dtos/dev/request/install-template.request.dto.js +3 -0
  12. package/dist/application/dtos/dev/request/new-project.request.dto.js +3 -0
  13. package/dist/application/dtos/dev/request/publish-plugin.request.dto.js +3 -0
  14. package/dist/application/dtos/dev/request/uninstall-template.request.dto.js +3 -0
  15. package/dist/application/dtos/dev/response/generate-component.response.dto.js +3 -0
  16. package/dist/application/dtos/dev/response/index.js +24 -0
  17. package/dist/application/dtos/dev/response/new-project.response.dto.js +3 -0
  18. package/dist/application/dtos/dev/response/publish-plugin.response.dto.js +3 -0
  19. package/dist/application/dtos/dev/response/template-info.response.dto.js +3 -0
  20. package/dist/application/dtos/env/index.js +24 -0
  21. package/dist/application/dtos/{request → env/request}/index.js +1 -3
  22. package/dist/application/dtos/env/request/list-running-instances.request.dto.js +3 -0
  23. package/dist/application/dtos/{response → env/response}/index.js +1 -1
  24. package/dist/application/dtos/env/response/list-running-instances.response.dto.js +3 -0
  25. package/dist/application/dtos/index.js +9 -2
  26. package/dist/application/dtos/logs/index.js +22 -0
  27. package/dist/application/dtos/logs/request/index.js +18 -0
  28. package/dist/application/dtos/logs/response/index.js +18 -0
  29. package/dist/application/index.js +1 -0
  30. package/dist/application/services/env/environment-validator.service.js +120 -0
  31. package/dist/application/services/env/index.js +11 -0
  32. package/dist/application/services/env/instance-cleanup.service.js +79 -0
  33. package/dist/application/services/index.js +21 -0
  34. package/dist/application/use-cases/config/get-all-config.use-case.js +54 -0
  35. package/dist/application/use-cases/config/get-config.use-case.js +7 -17
  36. package/dist/application/use-cases/config/index.js +23 -0
  37. package/dist/application/use-cases/config/set-config.use-case.js +49 -3
  38. package/dist/application/use-cases/dev/generate-component.use-case.js +138 -0
  39. package/dist/application/use-cases/dev/index.js +28 -0
  40. package/dist/application/use-cases/dev/install-template.use-case.js +60 -0
  41. package/dist/application/use-cases/dev/list-templates.use-case.js +45 -0
  42. package/dist/application/use-cases/dev/new-project.use-case.js +130 -0
  43. package/dist/application/use-cases/dev/publish-plugin.use-case.js +243 -0
  44. package/dist/application/use-cases/dev/uninstall-template.use-case.js +50 -0
  45. package/dist/application/use-cases/{instance → env}/delete-instance.use-case.js +2 -2
  46. package/dist/application/use-cases/{credentials → env}/get-credentials.use-case.js +1 -1
  47. package/dist/application/use-cases/{instance → env}/index.js +11 -0
  48. package/dist/application/use-cases/{instance → env}/install-instance.use-case.js +25 -136
  49. package/dist/application/use-cases/env/list-running-instances.use-case.js +47 -0
  50. package/dist/application/use-cases/{setup → env}/setup-environment.use-case.js +35 -4
  51. package/dist/application/use-cases/{instance → env}/start-instance.use-case.js +53 -41
  52. package/dist/application/use-cases/index.js +9 -6
  53. package/dist/application/use-cases/logs/index.js +21 -0
  54. package/dist/cli.js +175 -26
  55. package/dist/constants/defaults.js +8 -1
  56. package/dist/constants/oci-artifacts.js +4 -0
  57. package/dist/constants/paths.js +0 -4
  58. package/dist/constants/timeouts.js +5 -0
  59. package/dist/di/modules/application.module.js +13 -44
  60. package/dist/di/modules/config.module.js +19 -0
  61. package/dist/di/modules/dev.module.js +45 -0
  62. package/dist/di/modules/env.module.js +42 -0
  63. package/dist/di/modules/index.js +30 -0
  64. package/dist/di/modules/infrastructure.module.js +65 -82
  65. package/dist/di/modules/logs.module.js +15 -0
  66. package/dist/di/modules/presentation.module.js +18 -7
  67. package/dist/di/tokens.js +42 -30
  68. package/dist/domain/entities/credentials-resolver.entity.js +4 -1
  69. package/dist/domain/entities/credentials.entity.js +2 -5
  70. package/dist/domain/entities/delete-instance-validation.entity.js +4 -1
  71. package/dist/domain/entities/deployment-parameters.entity.js +11 -8
  72. package/dist/domain/entities/index.js +5 -1
  73. package/dist/domain/entities/instance-list-aggregator.entity.js +2 -2
  74. package/dist/domain/entities/instance-metadata.entity.js +2 -3
  75. package/dist/domain/entities/instance.entity.js +2 -1
  76. package/dist/domain/entities/log-filter.entity.js +6 -6
  77. package/dist/domain/entities/template-info.entity.js +63 -0
  78. package/dist/{infrastructure/utils/error-formatter.util.js → domain/errors/error-utils.js} +1 -1
  79. package/dist/domain/errors/index.js +19 -0
  80. package/dist/domain/index.js +6 -0
  81. package/dist/domain/interfaces/index.js +21 -0
  82. package/dist/domain/ports/dotnet-publisher.port.js +9 -0
  83. package/dist/{infrastructure/http/interfaces/http-client.interface.js → domain/ports/file-system.port.js} +1 -1
  84. package/dist/domain/ports/http-client.port.js +3 -0
  85. package/dist/domain/ports/index.js +10 -0
  86. package/dist/domain/ports/logger.port.js +3 -3
  87. package/dist/domain/ports/progress.port.js +10 -0
  88. package/dist/domain/ports/project-scaffolder.port.js +9 -0
  89. package/dist/domain/ports/schematics-runner.port.js +9 -0
  90. package/dist/domain/ports/template-manager.port.js +9 -0
  91. package/dist/domain/ports/wsl-setup.port.js +3 -0
  92. package/dist/domain/types/index.js +1 -0
  93. package/dist/domain/value-objects/acr-credentials.value-object.js +13 -1
  94. package/dist/domain/value-objects/chart-version.value-object.js +20 -3
  95. package/dist/domain/value-objects/config-log-level.value-object.js +2 -1
  96. package/dist/domain/value-objects/index.js +3 -1
  97. package/dist/domain/value-objects/instance-name.value-object.js +6 -3
  98. package/dist/domain/value-objects/jwt-key.value-object.js +27 -5
  99. package/dist/domain/value-objects/mssql-password.value-object.js +27 -5
  100. package/dist/domain/value-objects/output-path.value-object.js +85 -0
  101. package/dist/domain/value-objects/rsa-key-pair.value-object.js +29 -3
  102. package/dist/index.js +6 -1
  103. package/dist/infrastructure/config/{app-config.service.js → app-config.adapter.js} +29 -17
  104. package/dist/infrastructure/config/{config-validator.js → config-validator.util.js} +1 -1
  105. package/dist/infrastructure/config/index.js +14 -0
  106. package/dist/infrastructure/config/interfaces/index.js +3 -0
  107. package/dist/infrastructure/config/{crypto.service.js → services/crypto.service.js} +4 -1
  108. package/dist/infrastructure/config/services/index.js +9 -0
  109. package/dist/infrastructure/deployment/deployment.adapter.js +5 -5
  110. package/dist/infrastructure/deployment/index.js +9 -0
  111. package/dist/infrastructure/deployment/interfaces/index.js +3 -0
  112. package/dist/infrastructure/deployment/services/acr-credential-manager.service.js +18 -7
  113. package/dist/infrastructure/deployment/services/app-manager.service.js +3 -3
  114. package/dist/infrastructure/deployment/services/base-helm-deployment.service.js +13 -5
  115. package/dist/infrastructure/deployment/services/helm-registry.service.js +10 -3
  116. package/dist/infrastructure/deployment/services/index.js +35 -0
  117. package/dist/infrastructure/deployment/services/infra-manager.service.js +19 -15
  118. package/dist/infrastructure/deployment/services/k8s-job-runner.service.js +24 -6
  119. package/dist/infrastructure/deployment/services/mssql-database-init.service.js +75 -11
  120. package/dist/infrastructure/deployment/services/mssql-helm-deployment.service.js +17 -5
  121. package/dist/infrastructure/deployment/services/mssql-storage.service.js +5 -1
  122. package/dist/infrastructure/deployment/services/mssql-user-manager.service.js +7 -3
  123. package/dist/infrastructure/deployment/services/oci-artifact.service.js +8 -3
  124. package/dist/infrastructure/deployment/services/secret-manager.service.js +14 -5
  125. package/dist/infrastructure/deployment/services/service-manager.service.js +1 -1
  126. package/dist/infrastructure/deployment/services/version-compatibility.service.js +9 -5
  127. package/dist/infrastructure/dotnet/dotnet-publisher.adapter.js +143 -0
  128. package/dist/infrastructure/dotnet/index.js +9 -0
  129. package/dist/infrastructure/environment/index.js +11 -0
  130. package/dist/infrastructure/environment/interfaces/index.js +3 -0
  131. package/dist/infrastructure/{platform-detector.js → environment/platform-detector.util.js} +1 -1
  132. package/dist/infrastructure/environment/services/hardware-info.service.js +8 -8
  133. package/dist/infrastructure/environment/services/index.js +11 -0
  134. package/dist/infrastructure/errors/{error-handler.js → error-handler.adapter.js} +17 -17
  135. package/dist/infrastructure/errors/index.js +5 -21
  136. package/dist/infrastructure/execution/builders/base-command.builder.js +32 -11
  137. package/dist/infrastructure/execution/builders/index.js +26 -0
  138. package/dist/infrastructure/execution/builders/wsl-command.builder.js +39 -1
  139. package/dist/infrastructure/execution/command-builder.util.js +94 -0
  140. package/dist/infrastructure/execution/environments/index.js +23 -0
  141. package/dist/infrastructure/execution/environments/wsl-execution.environment.js +22 -7
  142. package/dist/infrastructure/execution/index.js +1 -2
  143. package/dist/infrastructure/execution/services/command-executor.service.js +389 -0
  144. package/dist/infrastructure/execution/services/index.js +8 -0
  145. package/dist/infrastructure/execution/{script-executor.service.js → services/script-executor.service.js} +12 -15
  146. package/dist/infrastructure/filesystem/filesystem.adapter.js +86 -0
  147. package/dist/infrastructure/filesystem/index.js +23 -0
  148. package/dist/infrastructure/http/{http-client.service.js → http-client.adapter.js} +20 -13
  149. package/dist/infrastructure/http/index.js +1 -1
  150. package/dist/infrastructure/interceptors/decorators/index.js +23 -0
  151. package/dist/infrastructure/interceptors/index.js +2 -2
  152. package/dist/infrastructure/interceptors/interceptor.factory.js +3 -3
  153. package/dist/infrastructure/interceptors/interfaces/index.js +3 -0
  154. package/dist/infrastructure/interceptors/services/index.js +6 -0
  155. package/dist/infrastructure/interceptors/{logging.interceptor.js → services/logging-interceptor.service.js} +4 -4
  156. package/dist/infrastructure/logger/services/file-log-reader.repository.js +1 -1
  157. package/dist/infrastructure/logger/services/file-log-writer.repository.js +1 -1
  158. package/dist/infrastructure/persistence/instance-metadata.adapter.js +2 -1
  159. package/dist/infrastructure/persistence/services/file-system-config.repository.js +10 -4
  160. package/dist/infrastructure/persistence/services/file-system-instance.repository.js +2 -2
  161. package/dist/infrastructure/platforms/index.js +18 -0
  162. package/dist/infrastructure/platforms/windows/index.js +13 -0
  163. package/dist/infrastructure/platforms/windows/interfaces/index.js +3 -0
  164. package/dist/infrastructure/platforms/windows/parsers/index.js +9 -0
  165. package/dist/infrastructure/platforms/windows/services/index.js +33 -0
  166. package/dist/infrastructure/platforms/windows/services/microk8s.service.js +28 -10
  167. package/dist/infrastructure/platforms/windows/services/rootfs-manager.service.js +7 -3
  168. package/dist/infrastructure/platforms/windows/services/windows-features.service.js +22 -8
  169. package/dist/infrastructure/platforms/windows/services/windows-info.service.js +10 -6
  170. package/dist/infrastructure/platforms/windows/services/wsl-config.service.js +15 -6
  171. package/dist/infrastructure/platforms/windows/services/wsl-info.service.js +12 -12
  172. package/dist/infrastructure/platforms/windows/services/wsl-instance-inspection.service.js +3 -3
  173. package/dist/infrastructure/platforms/windows/services/wsl-instance-lifecycle.service.js +76 -22
  174. package/dist/infrastructure/platforms/windows/services/wsl-updater.service.js +20 -15
  175. package/dist/infrastructure/platforms/windows/services/wslconfig-parser.service.js +3 -3
  176. package/dist/infrastructure/platforms/windows/wsl-instance-manager.adapter.js +8 -3
  177. package/dist/infrastructure/platforms/windows/wsl-setup.adapter.js +100 -0
  178. package/dist/infrastructure/schematics/index.js +11 -0
  179. package/dist/infrastructure/schematics/project-scaffolder.adapter.js +314 -0
  180. package/dist/infrastructure/schematics/schematics-runner.adapter.js +175 -0
  181. package/dist/infrastructure/template/index.js +25 -0
  182. package/dist/infrastructure/template/interfaces/index.js +22 -0
  183. package/dist/infrastructure/template/interfaces/template-downloader.interface.js +6 -0
  184. package/dist/infrastructure/template/interfaces/template-registry.interface.js +6 -0
  185. package/dist/infrastructure/template/services/index.js +24 -0
  186. package/dist/infrastructure/template/services/template-downloader.service.js +319 -0
  187. package/dist/infrastructure/template/services/template-registry.service.js +175 -0
  188. package/dist/infrastructure/template/template-manager.adapter.js +196 -0
  189. package/dist/infrastructure/utils/index.js +23 -0
  190. package/dist/infrastructure/utils/input-validator.util.js +7 -6
  191. package/dist/presentation/controllers/base.controller.js +36 -0
  192. package/dist/presentation/controllers/{config.controller.js → config/config.controller.js} +17 -62
  193. package/dist/presentation/controllers/config/index.js +21 -0
  194. package/dist/presentation/controllers/dev/dev.controller.js +202 -0
  195. package/dist/presentation/controllers/dev/index.js +23 -0
  196. package/dist/presentation/controllers/dev/template.controller.js +158 -0
  197. package/dist/presentation/controllers/{credentials.controller.js → env/credentials.controller.js} +8 -14
  198. package/dist/presentation/controllers/env/index.js +23 -0
  199. package/dist/presentation/controllers/{instance.controller.js → env/instance.controller.js} +35 -92
  200. package/dist/presentation/controllers/{setup.controller.js → env/setup.controller.js} +33 -66
  201. package/dist/presentation/controllers/index.js +9 -5
  202. package/dist/presentation/controllers/logs/index.js +21 -0
  203. package/dist/presentation/controllers/{logs.controller.js → logs/logs.controller.js} +8 -14
  204. package/dist/presentation/interfaces/index.js +21 -0
  205. package/dist/presentation/prompts/acr-credentials.prompt.js +37 -9
  206. package/dist/presentation/ui/constants/index.js +23 -0
  207. package/dist/presentation/ui/interaction.service.js +4 -4
  208. package/dist/presentation/ui/interfaces/cli-progress.interface.js +0 -6
  209. package/dist/presentation/ui/interfaces/index.js +6 -0
  210. package/package.json +6 -1
  211. package/dist/application/dtos/request/set-config.request.dto.js +0 -16
  212. package/dist/infrastructure/errors/error-handler.interface.js +0 -3
  213. package/dist/infrastructure/execution/command-builder.js +0 -252
  214. package/dist/infrastructure/execution/command-executor.service.js +0 -230
  215. /package/dist/application/dtos/{request → config/request}/get-config.request.dto.js +0 -0
  216. /package/dist/application/dtos/{request → env/request}/delete-instance.request.dto.js +0 -0
  217. /package/dist/application/dtos/{request → env/request}/get-credentials.request.dto.js +0 -0
  218. /package/dist/application/dtos/{request → env/request}/install-instance.request.dto.js +0 -0
  219. /package/dist/application/dtos/{request → env/request}/list-charts.request.dto.js +0 -0
  220. /package/dist/application/dtos/{request → env/request}/setup-environment.request.dto.js +0 -0
  221. /package/dist/application/dtos/{request → env/request}/start-instance.request.dto.js +0 -0
  222. /package/dist/application/dtos/{request → env/request}/stop-instance.request.dto.js +0 -0
  223. /package/dist/application/dtos/{response → env/response}/credentials.response.dto.js +0 -0
  224. /package/dist/application/dtos/{response → env/response}/delete-instance.response.dto.js +0 -0
  225. /package/dist/application/dtos/{response → env/response}/install-instance.response.dto.js +0 -0
  226. /package/dist/application/dtos/{response → env/response}/instance-list.response.dto.js +0 -0
  227. /package/dist/application/dtos/{response → env/response}/instance-status.response.dto.js +0 -0
  228. /package/dist/application/dtos/{response → env/response}/setup-result.response.dto.js +0 -0
  229. /package/dist/application/dtos/{response → env/response}/start-instance.response.dto.js +0 -0
  230. /package/dist/application/dtos/{response → env/response}/stop-instance.response.dto.js +0 -0
  231. /package/dist/application/dtos/{request → logs/request}/show-logs.request.dto.js +0 -0
  232. /package/dist/application/dtos/{response → logs/response}/show-logs.response.dto.js +0 -0
  233. /package/dist/application/use-cases/{instance → env}/list-charts.use-case.js +0 -0
  234. /package/dist/application/use-cases/{instance → env}/list-instances.use-case.js +0 -0
  235. /package/dist/application/use-cases/{instance → env}/stop-instance.use-case.js +0 -0
  236. /package/dist/{infrastructure → domain}/errors/app-error.js +0 -0
  237. /package/dist/{infrastructure → domain}/errors/exit-codes.js +0 -0
  238. /package/dist/infrastructure/config/{app-config.interface.js → interfaces/app-config.interface.js} +0 -0
  239. /package/dist/{domain → infrastructure/interceptors}/decorators/sensitive.decorator.js +0 -0
  240. /package/dist/infrastructure/interceptors/{interceptor.interface.js → interfaces/interceptor.interface.js} +0 -0
@@ -15,8 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.HardwareInfoService = void 0;
16
16
  const tsyringe_1 = require("tsyringe");
17
17
  const tokens_1 = require("../../../di/tokens");
18
- const command_builder_1 = require("../../execution/command-builder");
19
- const errors_1 = require("../../errors");
18
+ const command_builder_util_1 = require("../../execution/command-builder.util");
19
+ const errors_1 = require("../../../domain/errors");
20
20
  /**
21
21
  * 硬體資訊服務
22
22
  *
@@ -32,9 +32,9 @@ let HardwareInfoService = class HardwareInfoService {
32
32
  */
33
33
  async getTotalMemoryGB() {
34
34
  try {
35
- const builder = command_builder_1.CommandBuilder.create('powershell')
35
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
36
36
  .powershell('(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB');
37
- const result = await builder.exec(this.commandExecutor);
37
+ const result = await builder.exec();
38
38
  const output = result.stdout.trim();
39
39
  const memoryGB = Math.round(parseFloat(output));
40
40
  if (isNaN(memoryGB) || memoryGB <= 0) {
@@ -67,9 +67,9 @@ let HardwareInfoService = class HardwareInfoService {
67
67
  // FreePhysicalMemory 單位是 KB
68
68
  // PowerShell 的 1MB = 1024 * 1024 = 1048576
69
69
  // KB / 1048576 = GB(因為 1GB = 1048576 KB)
70
- const builder = command_builder_1.CommandBuilder.create('powershell')
70
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
71
71
  .powershell('(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB');
72
- const result = await builder.exec(this.commandExecutor);
72
+ const result = await builder.exec();
73
73
  const output = result.stdout.trim();
74
74
  const memoryGB = Math.round(parseFloat(output) * 100) / 100;
75
75
  if (isNaN(memoryGB) || memoryGB < 0) {
@@ -99,9 +99,9 @@ let HardwareInfoService = class HardwareInfoService {
99
99
  */
100
100
  async getAvailableDiskGB() {
101
101
  try {
102
- const builder = command_builder_1.CommandBuilder.create('powershell')
102
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
103
103
  .powershell('(Get-PSDrive C).Free / 1GB');
104
- const result = await builder.exec(this.commandExecutor);
104
+ const result = await builder.exec();
105
105
  const output = result.stdout.trim();
106
106
  const diskGB = Math.round(parseFloat(output));
107
107
  if (isNaN(diskGB) || diskGB < 0) {
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NetworkCheckerService = exports.HardwareInfoService = void 0;
4
+ /**
5
+ * Environment 模組服務匯出
6
+ */
7
+ var hardware_info_service_1 = require("./hardware-info.service");
8
+ Object.defineProperty(exports, "HardwareInfoService", { enumerable: true, get: function () { return hardware_info_service_1.HardwareInfoService; } });
9
+ var network_checker_service_1 = require("./network-checker.service");
10
+ Object.defineProperty(exports, "NetworkCheckerService", { enumerable: true, get: function () { return network_checker_service_1.NetworkCheckerService; } });
11
+ //# sourceMappingURL=index.js.map
@@ -17,16 +17,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
17
17
  return function (target, key) { decorator(target, key, paramIndex); }
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.ErrorHandler = void 0;
20
+ exports.ErrorHandlerAdapter = void 0;
21
21
  const tsyringe_1 = require("tsyringe");
22
22
  const tokens_1 = require("../../di/tokens");
23
- const app_error_1 = require("./app-error");
24
- const exit_codes_1 = require("./exit-codes");
25
- const error_formatter_util_1 = require("../utils/error-formatter.util");
23
+ const errors_1 = require("../../domain/errors");
26
24
  /**
27
25
  * 錯誤處理器實作
28
26
  */
29
- let ErrorHandler = class ErrorHandler {
27
+ let ErrorHandlerAdapter = class ErrorHandlerAdapter {
30
28
  constructor(logger, process) {
31
29
  this.logger = logger;
32
30
  this.process = process;
@@ -48,7 +46,8 @@ let ErrorHandler = class ErrorHandler {
48
46
  }
49
47
  const debug = this.isDebugMode();
50
48
  // 顯示錯誤
51
- console.error(this.formatError(appError, debug));
49
+ // 輸出錯誤訊息至 stderr
50
+ process.stderr.write(this.formatError(appError, debug) + '\n');
52
51
  // 記錄日誌
53
52
  this.logError(appError);
54
53
  // 退出
@@ -60,7 +59,8 @@ let ErrorHandler = class ErrorHandler {
60
59
  handleWarning(error, context) {
61
60
  const appError = this.normalizeError(error, context);
62
61
  const debug = this.isDebugMode();
63
- console.error(this.formatError(appError, debug));
62
+ // 輸出警告訊息至 stderr
63
+ process.stderr.write(this.formatError(appError, debug) + '\n');
64
64
  this.logError(appError);
65
65
  }
66
66
  /**
@@ -105,7 +105,7 @@ let ErrorHandler = class ErrorHandler {
105
105
  output?.success('Cleanup completed').flush();
106
106
  }
107
107
  catch (error) {
108
- output?.warning(`Cleanup failed: ${(0, error_formatter_util_1.formatErrorMessage)(error)}`).flush();
108
+ output?.warning(`Cleanup failed: ${(0, errors_1.formatErrorMessage)(error)}`).flush();
109
109
  }
110
110
  }
111
111
  output?.newline().success('Exiting...').newline().flush();
@@ -143,17 +143,17 @@ let ErrorHandler = class ErrorHandler {
143
143
  * 將未知錯誤轉換為 AppError
144
144
  */
145
145
  normalizeError(error, context) {
146
- if (error instanceof app_error_1.AppError) {
146
+ if (error instanceof errors_1.AppError) {
147
147
  return error;
148
148
  }
149
149
  if (error instanceof Error) {
150
- return new app_error_1.AppError(context ? `[${context}] ${error.message}` : error.message, {
150
+ return new errors_1.AppError(context ? `[${context}] ${error.message}` : error.message, {
151
151
  cause: error,
152
- exitCode: exit_codes_1.EXIT_CODES.UNKNOWN_ERROR,
152
+ exitCode: errors_1.EXIT_CODES.UNKNOWN_ERROR,
153
153
  });
154
154
  }
155
- return new app_error_1.AppError(context ? `[${context}] ${String(error)}` : String(error), {
156
- exitCode: exit_codes_1.EXIT_CODES.UNKNOWN_ERROR,
155
+ return new errors_1.AppError(context ? `[${context}] ${String(error)}` : String(error), {
156
+ exitCode: errors_1.EXIT_CODES.UNKNOWN_ERROR,
157
157
  });
158
158
  }
159
159
  /**
@@ -208,11 +208,11 @@ let ErrorHandler = class ErrorHandler {
208
208
  process.env.UOFX_LOG_LEVEL === 'debug');
209
209
  }
210
210
  };
211
- exports.ErrorHandler = ErrorHandler;
212
- exports.ErrorHandler = ErrorHandler = __decorate([
211
+ exports.ErrorHandlerAdapter = ErrorHandlerAdapter;
212
+ exports.ErrorHandlerAdapter = ErrorHandlerAdapter = __decorate([
213
213
  (0, tsyringe_1.injectable)(),
214
214
  __param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.ILoggerPort)),
215
215
  __param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.Process)),
216
216
  __metadata("design:paramtypes", [Object, Object])
217
- ], ErrorHandler);
218
- //# sourceMappingURL=error-handler.js.map
217
+ ], ErrorHandlerAdapter);
218
+ //# sourceMappingURL=error-handler.adapter.js.map
@@ -1,25 +1,9 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ErrorHandlerAdapter = void 0;
2
4
  /**
3
- * 統一錯誤系統匯出
4
- *
5
- * 這是整個應用程式錯誤處理的單一匯出點
6
- * 使用方式:
7
- *
8
- * import {
9
- * ErrorHandler,
10
- * AppError,
11
- * EXIT_CODES
12
- * } from '@/infrastructure/errors';
5
+ * Infrastructure 錯誤處理模組
13
6
  */
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.EXIT_CODES = exports.ErrorHandler = exports.AppError = void 0;
16
- // 錯誤類別
17
- var app_error_1 = require("./app-error");
18
- Object.defineProperty(exports, "AppError", { enumerable: true, get: function () { return app_error_1.AppError; } });
19
- // 錯誤處理器
20
- var error_handler_1 = require("./error-handler");
21
- Object.defineProperty(exports, "ErrorHandler", { enumerable: true, get: function () { return error_handler_1.ErrorHandler; } });
22
- // 退出碼
23
- var exit_codes_1 = require("./exit-codes");
24
- Object.defineProperty(exports, "EXIT_CODES", { enumerable: true, get: function () { return exit_codes_1.EXIT_CODES; } });
7
+ var error_handler_adapter_1 = require("./error-handler.adapter");
8
+ Object.defineProperty(exports, "ErrorHandlerAdapter", { enumerable: true, get: function () { return error_handler_adapter_1.ErrorHandlerAdapter; } });
25
9
  //# sourceMappingURL=index.js.map
@@ -12,6 +12,7 @@ class BaseCommandBuilder {
12
12
  this.executable = '';
13
13
  this.commandArgs = [];
14
14
  this.isSensitiveInput = false;
15
+ this.extraOptions = {};
15
16
  }
16
17
  /**
17
18
  * 設定可執行檔名稱
@@ -53,23 +54,42 @@ class BaseCommandBuilder {
53
54
  this.isSensitiveInput = true;
54
55
  return this;
55
56
  }
57
+ /**
58
+ * 設定額外執行選項(如 timeout、cwd 等)
59
+ * @param options 部分命令執行選項
60
+ */
61
+ withOptions(options) {
62
+ this.extraOptions = { ...this.extraOptions, ...options };
63
+ return this;
64
+ }
56
65
  /**
57
66
  * 建構用於記錄的安全命令字串
58
67
  */
59
68
  buildSafe() {
60
- let cmd = this.buildCommandString(true);
61
- // 子類別可能會覆寫此方法來加入額外的包裝
62
- cmd = this.wrapCommand(cmd, true);
69
+ const cmd = this.buildCommandString(true);
63
70
  if (this.isSensitiveInput) {
64
- cmd += ' < [STDIN: ***REDACTED***]';
71
+ return cmd + ' < [STDIN: ***REDACTED***]';
65
72
  }
66
73
  return cmd;
67
74
  }
68
75
  /**
69
- * 包裝命令(子類別可覆寫)
76
+ * 取得參數陣列(用於 spawnProcess 模式)
77
+ * @returns 參數值的扁平陣列
70
78
  */
71
- wrapCommand(command, _maskSensitive) {
72
- return command;
79
+ getArgsArray() {
80
+ const result = [];
81
+ for (const arg of this.commandArgs) {
82
+ if (arg.flag && arg.value !== undefined) {
83
+ result.push(arg.flag, arg.value);
84
+ }
85
+ else if (arg.flag) {
86
+ result.push(arg.flag);
87
+ }
88
+ else if (arg.value !== undefined) {
89
+ result.push(arg.value);
90
+ }
91
+ }
92
+ return result;
73
93
  }
74
94
  /**
75
95
  * 建構命令字串
@@ -105,17 +125,18 @@ class BaseCommandBuilder {
105
125
  options: {
106
126
  shell: true,
107
127
  ...(this.stdinInput && { input: this.stdinInput }),
128
+ ...this.extraOptions,
108
129
  },
109
130
  safeCommand: this.buildSafe(),
110
131
  };
111
132
  }
112
133
  execSync(showOutput = false, suppressStderr = false) {
113
- const { command, options, safeCommand } = this.getExecutionOptions();
114
- return this.commandExecutor.execSync(command, options, showOutput, suppressStderr, safeCommand);
134
+ const ctx = this.getExecutionOptions();
135
+ return this.commandExecutor.execSync(ctx, { showOutput, suppressStderr });
115
136
  }
116
137
  async exec(onStdout, onStderr) {
117
- const { command, options, safeCommand } = this.getExecutionOptions();
118
- return this.commandExecutor.exec(command, onStdout, onStderr, options, safeCommand);
138
+ const ctx = this.getExecutionOptions();
139
+ return this.commandExecutor.exec(ctx, { onStdout, onStderr });
119
140
  }
120
141
  }
121
142
  exports.BaseCommandBuilder = BaseCommandBuilder;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * 命令建構器模組
19
+ *
20
+ * 匯出所有命令建構器,包含基礎建構器與各平台特定實作
21
+ */
22
+ __exportStar(require("./base-command.builder"), exports);
23
+ __exportStar(require("./host-command.builder"), exports);
24
+ __exportStar(require("./windows-host-command.builder"), exports);
25
+ __exportStar(require("./wsl-command.builder"), exports);
26
+ //# sourceMappingURL=index.js.map
@@ -2,15 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WslCommandBuilder = void 0;
4
4
  const base_command_builder_1 = require("./base-command.builder");
5
+ const errors_1 = require("../../../domain/errors");
6
+ const value_objects_1 = require("../../../domain/value-objects");
5
7
  /**
6
8
  * WSL 命令建構器
7
9
  *
8
- * 自動將命令包裝為 `wsl -d <instanceName> -- <command>` 格式
10
+ * 自動將命令包裝為 `wsl -d <instanceName> -- <command>` 格式。
11
+ * 使用 spawnProcess 直接執行 wsl.exe(不經由 cmd.exe),
12
+ * 從根本消除 Windows shell 引號解析問題。
9
13
  */
10
14
  class WslCommandBuilder extends base_command_builder_1.BaseCommandBuilder {
11
15
  constructor(instanceName, commandExecutor) {
12
16
  super(commandExecutor);
13
17
  this.instanceName = instanceName;
18
+ // 防禦性驗證:防止命令注入
19
+ if (!value_objects_1.InstanceName.isValid(instanceName)) {
20
+ throw new errors_1.AppError(`Invalid WSL instance name: "${instanceName}". Name must contain only alphanumeric characters and hyphens.`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
21
+ }
14
22
  }
15
23
  buildActual() {
16
24
  const innerCmd = this.buildCommandString(false);
@@ -24,6 +32,36 @@ class WslCommandBuilder extends base_command_builder_1.BaseCommandBuilder {
24
32
  }
25
33
  return cmd;
26
34
  }
35
+ /**
36
+ * 取得 spawnProcess 的參數陣列
37
+ * @returns wsl.exe 的完整參數陣列
38
+ */
39
+ getSpawnArgs() {
40
+ return ['-d', this.instanceName, '--', this.executable, ...this.getArgsArray()];
41
+ }
42
+ /**
43
+ * 同步執行 WSL 命令(透過 spawnProcess,不經由 cmd.exe)
44
+ * @param showOutput - 是否顯示輸出
45
+ * @param suppressStderr - 是否隱藏 stderr
46
+ * @returns 命令執行結果
47
+ */
48
+ execSync(showOutput = false, suppressStderr = false) {
49
+ return this.commandExecutor.spawnProcessSync('wsl', this.getSpawnArgs(), {
50
+ showOutput,
51
+ suppressStderr,
52
+ options: this.stdinInput ? { input: this.stdinInput } : undefined,
53
+ safeCommand: this.buildSafe(),
54
+ });
55
+ }
56
+ /**
57
+ * 非同步執行 WSL 命令(透過 spawnProcess,不經由 cmd.exe)
58
+ * @param onStdout - stdout 回調函式
59
+ * @param onStderr - stderr 回調函式
60
+ * @returns 命令執行結果
61
+ */
62
+ async exec(onStdout, onStderr) {
63
+ return this.commandExecutor.spawnProcess('wsl', this.getSpawnArgs(), { onStdout, onStderr }, this.stdinInput ? { input: this.stdinInput } : undefined);
64
+ }
27
65
  }
28
66
  exports.WslCommandBuilder = WslCommandBuilder;
29
67
  //# sourceMappingURL=wsl-command.builder.js.map
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CommandBuilder = void 0;
4
+ const host_command_builder_1 = require("./builders/host-command.builder");
5
+ /**
6
+ * 命令建構器 - 支援安全的命令建構與執行
7
+ *
8
+ * 繼承 HostCommand,額外提供 PowerShell / WSL 管理命令 / inheritStdio 等輔助方法。
9
+ *
10
+ * 注意:此類別用於非 DI 場景(如環境檢查服務)。
11
+ * 對於 WSL 實例內的命令執行,請使用 IExecutionEnvironmentFactory。
12
+ *
13
+ * @example
14
+ * // 基本使用
15
+ * const result = await CommandBuilder
16
+ * .create('wsl', this.commandExecutor)
17
+ * .arg('--list')
18
+ * .arg('--verbose')
19
+ * .exec();
20
+ *
21
+ * @example
22
+ * // PowerShell 命令
23
+ * const result = await CommandBuilder
24
+ * .create('powershell', this.commandExecutor)
25
+ * .powershell('Get-Process')
26
+ * .exec();
27
+ */
28
+ class CommandBuilder extends host_command_builder_1.HostCommand {
29
+ constructor() {
30
+ super(...arguments);
31
+ this._inheritStdio = false;
32
+ }
33
+ // ========== 工廠方法 (Factory Methods) ==========
34
+ /**
35
+ * 建立一般命令
36
+ * @param executable 可執行檔名稱或路徑
37
+ * @param executor 命令執行器實例
38
+ * @returns CommandBuilder 實例
39
+ * @example CommandBuilder.create('wsl', this.commandExecutor).arg('--list').arg('--verbose')
40
+ */
41
+ static create(executable, executor) {
42
+ const builder = new CommandBuilder(executor);
43
+ builder.setExecutable(executable);
44
+ return builder;
45
+ }
46
+ // ========== 命令輔助方法 (Command Helper Methods) ==========
47
+ /**
48
+ * PowerShell 命令 (Windows 專用)
49
+ * @param command PowerShell 命令字串
50
+ * @returns this (支援方法鏈)
51
+ * @example CommandBuilder.create('powershell', executor).powershell('Get-Process')
52
+ */
53
+ powershell(command) {
54
+ this.setExecutable('powershell');
55
+ this.arg('-NoProfile');
56
+ this.arg('-NoLogo');
57
+ this.arg('-Command');
58
+ this.arg(command);
59
+ return this;
60
+ }
61
+ /**
62
+ * WSL 管理命令 (不包裝實例)
63
+ * @param subcommand WSL 子命令
64
+ * @returns this (支援方法鏈)
65
+ * @example CommandBuilder.create('wsl.exe', executor).wslCmd('--list').arg('--verbose')
66
+ */
67
+ wslCmd(subcommand) {
68
+ // 使用 wsl.exe 而非 wsl,因為當 WSL 未安裝時 wsl 只是 stub
69
+ this.setExecutable('wsl.exe');
70
+ this.arg(subcommand);
71
+ return this;
72
+ }
73
+ /**
74
+ * 設定直接繼承終端的 stdio
75
+ * 用於需要終端訪問的命令(如 WSL 安裝)
76
+ * @returns this (支援方法鏈)
77
+ */
78
+ inheritStdio() {
79
+ this._inheritStdio = true;
80
+ return this;
81
+ }
82
+ /**
83
+ * 取得執行選項(覆寫以支援 inheritStdio)
84
+ */
85
+ getExecutionOptions() {
86
+ const base = super.getExecutionOptions();
87
+ if (this._inheritStdio) {
88
+ base.options = { ...base.options, inheritStdio: true };
89
+ }
90
+ return base;
91
+ }
92
+ }
93
+ exports.CommandBuilder = CommandBuilder;
94
+ //# sourceMappingURL=command-builder.util.js.map
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * 執行環境模組
19
+ *
20
+ * 匯出所有執行環境實作(如 WSL 執行環境)
21
+ */
22
+ __exportStar(require("./wsl-execution.environment"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -16,15 +16,24 @@ class WslExecutionEnvironment {
16
16
  this.type = execution_environment_interface_1.EXECUTION_ENVIRONMENT_TYPES.WSL;
17
17
  }
18
18
  helm(subcommand) {
19
- const builder = new wsl_command_builder_1.WslCommandBuilder(this.identifier, this.commandExecutor);
20
- builder.setExecutable(paths_1.LINUX_PATHS.MICROK8S_HELM);
21
- builder.arg(subcommand);
22
- return builder;
19
+ return this.createMicrok8sCommand('helm3', subcommand);
23
20
  }
24
21
  kubectl(subcommand) {
22
+ return this.createMicrok8sCommand('kubectl', subcommand);
23
+ }
24
+ /**
25
+ * 建立 microk8s 命令建構器
26
+ * @param command - microk8s 子命令(如 'helm3', 'kubectl')
27
+ * @param subcommand - 要執行的子命令字串
28
+ * @returns 命令建構器
29
+ */
30
+ createMicrok8sCommand(command, subcommand) {
25
31
  const builder = new wsl_command_builder_1.WslCommandBuilder(this.identifier, this.commandExecutor);
26
- builder.setExecutable(paths_1.LINUX_PATHS.KUBECTL_BIN);
27
- builder.arg(subcommand);
32
+ builder.setExecutable(paths_1.LINUX_PATHS.MICROK8S_BIN);
33
+ builder.arg(command);
34
+ for (const part of subcommand.split(' ')) {
35
+ builder.arg(part);
36
+ }
28
37
  return builder;
29
38
  }
30
39
  /**
@@ -41,6 +50,10 @@ class WslExecutionEnvironment {
41
50
  }
42
51
  /**
43
52
  * 執行 shell 腳本(支援重定向、管道等 shell 特性)
53
+ *
54
+ * WslCommandBuilder 使用 spawnProcess 直接執行 wsl.exe(不經由 cmd.exe),
55
+ * 每個 arg 是獨立的 OS 級參數,不需要引號包裹。
56
+ * sh -c 收到 bare script 後會正確解析 >、| 等 shell 特殊字元。
44
57
  * @param script 完整的 shell 腳本字串
45
58
  * @returns 命令建構器
46
59
  * @example env.shellScript('cat > /tmp/file').stdin(content)
@@ -50,7 +63,9 @@ class WslExecutionEnvironment {
50
63
  const builder = new wsl_command_builder_1.WslCommandBuilder(this.identifier, this.commandExecutor);
51
64
  builder.setExecutable('sh');
52
65
  builder.arg('-c');
53
- builder.arg(`"${script}"`);
66
+ // spawnProcess 直接傳遞參數給 wsl.exe → sh,不經由任何 shell
67
+ // 不需要引號包裹:每個 arg 已是獨立的 OS 級參數,sh -c 會正確解析 shell 特殊字元
68
+ builder.arg(script);
54
69
  return builder;
55
70
  }
56
71
  async isAvailable() {
@@ -14,8 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./command-executor.service"), exports);
18
- __exportStar(require("./script-executor.service"), exports);
17
+ __exportStar(require("./services"), exports);
19
18
  __exportStar(require("./execution-environment.factory"), exports);
20
19
  __exportStar(require("./builders/base-command.builder"), exports);
21
20
  __exportStar(require("./builders/host-command.builder"), exports);