@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
@@ -1,230 +0,0 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __metadata = (this && this.__metadata) || function (k, v) {
9
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
- };
11
- var __param = (this && this.__param) || function (paramIndex, decorator) {
12
- return function (target, key) { decorator(target, key, paramIndex); }
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.CommandExecutorService = void 0;
16
- const tsyringe_1 = require("tsyringe");
17
- const child_process_1 = require("child_process");
18
- const defaults_1 = require("../../constants/defaults");
19
- const sensitive_decorator_1 = require("../../domain/decorators/sensitive.decorator");
20
- /**
21
- * 命令執行器服務
22
- *
23
- * 使用 Node.js child_process 模組實作 ICommandExecutor 介面,
24
- * 提供真實的命令執行功能。支援同步和非同步執行、串流輸出、timeout 機制。
25
- */
26
- let CommandExecutorService = class CommandExecutorService {
27
- /**
28
- * 同步執行命令
29
- * @param command - 要執行的命令字串
30
- * @param options - 執行選項(如 cwd, env, timeout)
31
- * @param showOutput - 是否在 stdout 顯示輸出(預設:true)
32
- * @param suppressStderr - 是否隱藏 stderr 輸出(預設:false)
33
- * @param _safeCommandForLogging - 用於日誌記錄的安全命令字串(隱藏敏感資料)
34
- * @returns 命令執行結果,包含 stdout, stderr 和 exitCode
35
- * @throws 當命令執行嚴重失敗且無法捕捉時拋出 Error
36
- */
37
- execSync(command, options, _showOutput = true, suppressStderr = false, _safeCommandForLogging) {
38
- // 處理 shell 選項
39
- let shell;
40
- if (options?.shell === true) {
41
- shell = process.platform === 'win32' ? 'cmd.exe' : '/bin/sh';
42
- }
43
- else if (typeof options?.shell === 'string') {
44
- shell = options.shell;
45
- }
46
- const execOptions = {
47
- // encoding: 'buffer' 会導致 ERR_UNKNOWN_ENCODING,設為 undefined 則會返回 Buffer
48
- encoding: undefined,
49
- cwd: options?.cwd,
50
- env: options?.env,
51
- timeout: options?.timeout,
52
- shell,
53
- maxBuffer: defaults_1.FILE_SIZE.MAX_COMMAND_BUFFER,
54
- input: options?.input,
55
- // 總是 pipe stderr 以便正確解碼 UTF-16LE
56
- stdio: suppressStderr ? ['pipe', 'pipe', 'ignore'] : ['pipe', 'pipe', 'pipe'],
57
- };
58
- try {
59
- const stdoutBuffer = (0, child_process_1.execSync)(command, execOptions);
60
- const stdout = this.decodeBuffer(stdoutBuffer);
61
- return {
62
- stdout,
63
- stderr: '',
64
- exitCode: 0,
65
- };
66
- }
67
- catch (error) {
68
- if (error && typeof error === 'object' && 'status' in error) {
69
- const execError = error;
70
- const stdout = this.decodeBuffer(execError.stdout);
71
- const stderr = this.decodeBuffer(execError.stderr);
72
- return {
73
- stdout,
74
- stderr: stderr,
75
- exitCode: execError.status ?? 1,
76
- };
77
- }
78
- throw new Error(`Command execution failed: ${String(error)}`);
79
- }
80
- }
81
- /**
82
- * 非同步執行命令
83
- * @param command - 要執行的命令字串
84
- * @param onStdout - 標準輸出回調函式
85
- * @param onStderr - 標準錯誤回調函式
86
- * @param options - 執行選項(如 cwd, env, timeout)
87
- * @param _safeCommandForLogging - 用於日誌記錄的安全命令字串(隱藏敏感資料)
88
- * @returns 解析為命令執行結果的 Promise
89
- */
90
- async exec(command, onStdout, onStderr, options, _safeCommandForLogging) {
91
- return new Promise((resolve, reject) => {
92
- const encoding = options?.encoding ?? 'utf8';
93
- // 預設 shell 為 true 以支援命令字串
94
- let shell = true;
95
- if (options?.shell === false) {
96
- shell = false;
97
- }
98
- else if (typeof options?.shell === 'string') {
99
- shell = options.shell;
100
- }
101
- // 如果需要繼承 stdio(用於 WSL 安裝等需要終端訪問的命令)
102
- if (options?.inheritStdio) {
103
- const spawnOptions = {
104
- cwd: options?.cwd,
105
- env: options?.env,
106
- shell,
107
- stdio: 'inherit',
108
- };
109
- const childProcess = (0, child_process_1.spawn)(command, [], spawnOptions);
110
- childProcess.on('close', (code) => {
111
- resolve({
112
- stdout: '',
113
- stderr: '',
114
- exitCode: code ?? 0,
115
- });
116
- });
117
- childProcess.on('error', (error) => {
118
- reject(new Error(`Failed to execute command: ${error.message}`));
119
- });
120
- return;
121
- }
122
- const spawnOptions = {
123
- cwd: options?.cwd,
124
- env: options?.env,
125
- shell,
126
- encoding,
127
- };
128
- const childProcess = (0, child_process_1.spawn)(command, [], spawnOptions);
129
- if (options?.input && childProcess.stdin) {
130
- childProcess.stdin.write(options.input);
131
- childProcess.stdin.end();
132
- }
133
- // 累積輸出 Buffer
134
- const stdoutChunks = [];
135
- const stderrChunks = [];
136
- // 監聽標準輸出
137
- if (childProcess.stdout) {
138
- childProcess.stdout.on('data', (data) => {
139
- stdoutChunks.push(data);
140
- if (onStdout) {
141
- onStdout(this.decodeBuffer(data));
142
- }
143
- });
144
- }
145
- // 監聽標準錯誤輸出
146
- if (childProcess.stderr) {
147
- childProcess.stderr.on('data', (data) => {
148
- stderrChunks.push(data);
149
- if (onStderr) {
150
- onStderr(this.decodeBuffer(data));
151
- }
152
- });
153
- }
154
- // 設定 timeout (如果有指定)
155
- let timeoutId;
156
- if (options?.timeout) {
157
- timeoutId = setTimeout(() => {
158
- childProcess.kill('SIGTERM');
159
- reject(new Error(`Command timed out after ${options.timeout}ms`));
160
- }, options.timeout);
161
- }
162
- // 監聽進程結束
163
- childProcess.on('close', (code) => {
164
- if (timeoutId) {
165
- clearTimeout(timeoutId);
166
- }
167
- const stdoutBuffer = Buffer.concat(stdoutChunks);
168
- const stderrBuffer = Buffer.concat(stderrChunks);
169
- resolve({
170
- stdout: this.decodeBuffer(stdoutBuffer),
171
- stderr: this.decodeBuffer(stderrBuffer),
172
- exitCode: code ?? 0,
173
- });
174
- });
175
- childProcess.on('error', (error) => {
176
- if (timeoutId) {
177
- clearTimeout(timeoutId);
178
- }
179
- reject(new Error(`Failed to execute command: ${error.message}`));
180
- });
181
- });
182
- }
183
- /**
184
- * 解碼 Buffer
185
- * 嘗試偵測 UTF-16 LE (常見於 Windows/WSL 輸出),否則使用 UTF-8
186
- */
187
- decodeBuffer(buffer) {
188
- if (!buffer)
189
- return '';
190
- if (typeof buffer === 'string')
191
- return buffer;
192
- if (buffer.length === 0)
193
- return '';
194
- // 1. 檢查 UTF-16LE BOM (FF FE)
195
- if (buffer.length >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) {
196
- return buffer.toString('utf16le');
197
- }
198
- // 2. 檢查是否為 UTF-16LE (無 BOM)
199
- // WSL 輸出通常沒有 BOM,但使用 UTF-16LE 編碼
200
- const sample = buffer.subarray(0, Math.min(buffer.length, 200));
201
- let nullCount = 0;
202
- for (let i = 0; i < sample.length; i++) {
203
- if (sample[i] === 0)
204
- nullCount++;
205
- }
206
- // 如果 null bytes 超過 20%,很可能是 UTF-16LE
207
- if (nullCount > sample.length * 0.2) {
208
- return buffer.toString('utf16le');
209
- }
210
- // 3. 預設使用 UTF-8
211
- return buffer.toString('utf8');
212
- }
213
- };
214
- exports.CommandExecutorService = CommandExecutorService;
215
- __decorate([
216
- __param(1, (0, sensitive_decorator_1.Sensitive)()),
217
- __metadata("design:type", Function),
218
- __metadata("design:paramtypes", [String, Object, Boolean, Boolean, String]),
219
- __metadata("design:returntype", Object)
220
- ], CommandExecutorService.prototype, "execSync", null);
221
- __decorate([
222
- __param(3, (0, sensitive_decorator_1.Sensitive)()),
223
- __metadata("design:type", Function),
224
- __metadata("design:paramtypes", [String, Function, Function, Object, String]),
225
- __metadata("design:returntype", Promise)
226
- ], CommandExecutorService.prototype, "exec", null);
227
- exports.CommandExecutorService = CommandExecutorService = __decorate([
228
- (0, tsyringe_1.injectable)()
229
- ], CommandExecutorService);
230
- //# sourceMappingURL=command-executor.service.js.map