@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
@@ -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
+ * 匯出敏感資料標記等裝飾器,用於方法參數與回傳值的安全處理
21
+ */
22
+ __exportStar(require("./sensitive.decorator"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InterceptorFactory = exports.LoggingInterceptor = void 0;
4
- var logging_interceptor_1 = require("./logging.interceptor");
5
- Object.defineProperty(exports, "LoggingInterceptor", { enumerable: true, get: function () { return logging_interceptor_1.LoggingInterceptor; } });
4
+ var services_1 = require("./services");
5
+ Object.defineProperty(exports, "LoggingInterceptor", { enumerable: true, get: function () { return services_1.LoggingInterceptor; } });
6
6
  var interceptor_factory_1 = require("./interceptor.factory");
7
7
  Object.defineProperty(exports, "InterceptorFactory", { enumerable: true, get: function () { return interceptor_factory_1.InterceptorFactory; } });
8
8
  //# sourceMappingURL=index.js.map
@@ -14,7 +14,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.InterceptorFactory = void 0;
16
16
  const tsyringe_1 = require("tsyringe");
17
- const logging_interceptor_1 = require("./logging.interceptor");
17
+ const services_1 = require("./services");
18
18
  /**
19
19
  * 攔截器工廠
20
20
  *
@@ -38,7 +38,7 @@ let InterceptorFactory = class InterceptorFactory {
38
38
  exports.InterceptorFactory = InterceptorFactory;
39
39
  exports.InterceptorFactory = InterceptorFactory = __decorate([
40
40
  (0, tsyringe_1.injectable)(),
41
- __param(0, (0, tsyringe_1.inject)(logging_interceptor_1.LoggingInterceptor)),
42
- __metadata("design:paramtypes", [logging_interceptor_1.LoggingInterceptor])
41
+ __param(0, (0, tsyringe_1.inject)(services_1.LoggingInterceptor)),
42
+ __metadata("design:paramtypes", [services_1.LoggingInterceptor])
43
43
  ], InterceptorFactory);
44
44
  //# sourceMappingURL=interceptor.factory.js.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoggingInterceptor = void 0;
4
+ var logging_interceptor_service_1 = require("./logging-interceptor.service");
5
+ Object.defineProperty(exports, "LoggingInterceptor", { enumerable: true, get: function () { return logging_interceptor_service_1.LoggingInterceptor; } });
6
+ //# sourceMappingURL=index.js.map
@@ -16,8 +16,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.LoggingInterceptor = void 0;
17
17
  const tsyringe_1 = require("tsyringe");
18
18
  require("reflect-metadata");
19
- const tokens_1 = require("../../di/tokens");
20
- const sensitive_decorator_1 = require("../../domain/decorators/sensitive.decorator");
19
+ const tokens_1 = require("../../../di/tokens");
20
+ const sensitive_decorator_1 = require("../decorators/sensitive.decorator");
21
21
  /**
22
22
  * 日誌攔截器
23
23
  *
@@ -165,7 +165,7 @@ LoggingInterceptor.EXCLUDED_METHODS = new Set([
165
165
  exports.LoggingInterceptor = LoggingInterceptor = LoggingInterceptor_1 = __decorate([
166
166
  (0, tsyringe_1.injectable)(),
167
167
  __param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.ILoggerPort)),
168
- __param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.IAppConfig)),
168
+ __param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.IAppConfigPort)),
169
169
  __metadata("design:paramtypes", [Object, Object])
170
170
  ], LoggingInterceptor);
171
- //# sourceMappingURL=logging.interceptor.js.map
171
+ //# sourceMappingURL=logging-interceptor.service.js.map
@@ -65,7 +65,7 @@ const DEFAULT_CONFIG = {
65
65
  let FileLogReaderRepository = class FileLogReaderRepository {
66
66
  constructor() {
67
67
  // 使用默認配置
68
- // 如果未來需要自定義配置,應該從 IAppConfig 注入
68
+ // 如果未來需要自定義配置,應該從 IAppConfigPort 注入
69
69
  this.config = DEFAULT_CONFIG;
70
70
  }
71
71
  /**
@@ -82,7 +82,7 @@ let FileLogWriterRepository = class FileLogWriterRepository {
82
82
  this.currentDate = '';
83
83
  this.currentFilePath = '';
84
84
  // 使用默認配置
85
- // 如果未來需要自定義配置,應該從 IAppConfig 注入
85
+ // 如果未來需要自定義配置,應該從 IAppConfigPort 注入
86
86
  this.config = DEFAULT_CONFIG;
87
87
  this.baseDir = path.dirname(this.config.path);
88
88
  this.updateCurrentFilePath();
@@ -61,7 +61,8 @@ let InstanceMetadataAdapter = class InstanceMetadataAdapter {
61
61
  if (!fs.existsSync(installPath)) {
62
62
  fs.mkdirSync(installPath, { recursive: true });
63
63
  }
64
- fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
64
+ // 限制檔案權限為擁有者可讀寫
65
+ fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), { encoding: 'utf8', mode: 0o600 });
65
66
  }
66
67
  /**
67
68
  * 載入實例 metadata
@@ -48,6 +48,7 @@ const fs = __importStar(require("fs/promises"));
48
48
  const path = __importStar(require("path"));
49
49
  const os = __importStar(require("os"));
50
50
  const value_objects_1 = require("../../../domain/value-objects");
51
+ const crypto_service_1 = require("../../config/services/crypto.service");
51
52
  /**
52
53
  * 檔案系統配置 Repository
53
54
  *
@@ -66,7 +67,11 @@ let FileSystemConfigRepository = class FileSystemConfigRepository {
66
67
  const config = await this.loadConfig();
67
68
  if (config.acr) {
68
69
  try {
69
- return value_objects_1.AcrCredentials.create(config.acr.name, config.acr.account, config.acr.password);
70
+ // 解密密碼(相容未加密的舊資料)
71
+ const password = crypto_service_1.CryptoService.isEncrypted(config.acr.password)
72
+ ? crypto_service_1.CryptoService.decrypt(config.acr.password)
73
+ : config.acr.password;
74
+ return value_objects_1.AcrCredentials.create(config.acr.name, config.acr.account, password);
70
75
  }
71
76
  catch {
72
77
  return null;
@@ -80,10 +85,11 @@ let FileSystemConfigRepository = class FileSystemConfigRepository {
80
85
  */
81
86
  async saveDefaultAcrCredentials(credentials) {
82
87
  const config = await this.loadConfig();
88
+ // 加密密碼後再儲存
83
89
  config.acr = {
84
90
  name: credentials.name,
85
91
  account: credentials.account,
86
- password: credentials.password,
92
+ password: crypto_service_1.CryptoService.encrypt(credentials.password),
87
93
  };
88
94
  await this.saveConfig(config);
89
95
  }
@@ -155,9 +161,9 @@ let FileSystemConfigRepository = class FileSystemConfigRepository {
155
161
  const dir = path.dirname(this.configPath);
156
162
  // 確保目錄存在
157
163
  await fs.mkdir(dir, { recursive: true });
158
- // 寫入配置
164
+ // 寫入配置(限制檔案權限為擁有者可讀寫)
159
165
  const data = JSON.stringify(config, null, 2);
160
- await fs.writeFile(this.configPath, data, 'utf8');
166
+ await fs.writeFile(this.configPath, data, { encoding: 'utf8', mode: 0o600 });
161
167
  }
162
168
  };
163
169
  exports.FileSystemConfigRepository = FileSystemConfigRepository;
@@ -67,9 +67,9 @@ let FileSystemInstanceRepository = class FileSystemInstanceRepository {
67
67
  const dir = path.dirname(metadataPath);
68
68
  // 確保目錄存在
69
69
  await fs.mkdir(dir, { recursive: true });
70
- // 寫入 metadata
70
+ // 寫入 metadata(限制檔案權限為擁有者可讀寫)
71
71
  const data = JSON.stringify(metadata.toObject(), null, 2);
72
- await fs.writeFile(metadataPath, data, 'utf8');
72
+ await fs.writeFile(metadataPath, data, { encoding: 'utf8', mode: 0o600 });
73
73
  }
74
74
  /**
75
75
  * 載入實例 metadata
@@ -0,0 +1,18 @@
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
+ __exportStar(require("./windows"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WslSetupAdapter = exports.WslBaseImageAdapter = exports.WslInstanceManagerAdapter = void 0;
4
+ /**
5
+ * Infrastructure Windows 平台模組匯出
6
+ */
7
+ var wsl_instance_manager_adapter_1 = require("./wsl-instance-manager.adapter");
8
+ Object.defineProperty(exports, "WslInstanceManagerAdapter", { enumerable: true, get: function () { return wsl_instance_manager_adapter_1.WslInstanceManagerAdapter; } });
9
+ var wsl_base_image_adapter_1 = require("./wsl-base-image.adapter");
10
+ Object.defineProperty(exports, "WslBaseImageAdapter", { enumerable: true, get: function () { return wsl_base_image_adapter_1.WslBaseImageAdapter; } });
11
+ var wsl_setup_adapter_1 = require("./wsl-setup.adapter");
12
+ Object.defineProperty(exports, "WslSetupAdapter", { enumerable: true, get: function () { return wsl_setup_adapter_1.WslSetupAdapter; } });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WslVersionParser = void 0;
4
+ /**
5
+ * Windows 平台模組解析器匯出
6
+ */
7
+ var wsl_version_parser_1 = require("./wsl-version.parser");
8
+ Object.defineProperty(exports, "WslVersionParser", { enumerable: true, get: function () { return wsl_version_parser_1.WslVersionParser; } });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WslUpdaterService = exports.WslInstanceNamingService = exports.WslInstanceLifecycleService = exports.WslInstanceInspectionService = exports.WslInfoService = exports.WslConfigParserService = exports.WslConfigService = exports.MIN_WIN11_BUILD = exports.MIN_WIN10_BUILD = exports.WindowsInfoService = exports.VM_PLATFORM_FEATURE_NAME = exports.WSL_FEATURE_NAME = exports.WindowsFeaturesService = exports.RootfsManagerService = exports.MicroK8sService = void 0;
4
+ /**
5
+ * Windows 平台模組服務匯出
6
+ */
7
+ var microk8s_service_1 = require("./microk8s.service");
8
+ Object.defineProperty(exports, "MicroK8sService", { enumerable: true, get: function () { return microk8s_service_1.MicroK8sService; } });
9
+ var rootfs_manager_service_1 = require("./rootfs-manager.service");
10
+ Object.defineProperty(exports, "RootfsManagerService", { enumerable: true, get: function () { return rootfs_manager_service_1.RootfsManagerService; } });
11
+ var windows_features_service_1 = require("./windows-features.service");
12
+ Object.defineProperty(exports, "WindowsFeaturesService", { enumerable: true, get: function () { return windows_features_service_1.WindowsFeaturesService; } });
13
+ Object.defineProperty(exports, "WSL_FEATURE_NAME", { enumerable: true, get: function () { return windows_features_service_1.WSL_FEATURE_NAME; } });
14
+ Object.defineProperty(exports, "VM_PLATFORM_FEATURE_NAME", { enumerable: true, get: function () { return windows_features_service_1.VM_PLATFORM_FEATURE_NAME; } });
15
+ var windows_info_service_1 = require("./windows-info.service");
16
+ Object.defineProperty(exports, "WindowsInfoService", { enumerable: true, get: function () { return windows_info_service_1.WindowsInfoService; } });
17
+ Object.defineProperty(exports, "MIN_WIN10_BUILD", { enumerable: true, get: function () { return windows_info_service_1.MIN_WIN10_BUILD; } });
18
+ Object.defineProperty(exports, "MIN_WIN11_BUILD", { enumerable: true, get: function () { return windows_info_service_1.MIN_WIN11_BUILD; } });
19
+ var wsl_config_service_1 = require("./wsl-config.service");
20
+ Object.defineProperty(exports, "WslConfigService", { enumerable: true, get: function () { return wsl_config_service_1.WslConfigService; } });
21
+ var wslconfig_parser_service_1 = require("./wslconfig-parser.service");
22
+ Object.defineProperty(exports, "WslConfigParserService", { enumerable: true, get: function () { return wslconfig_parser_service_1.WslConfigParserService; } });
23
+ var wsl_info_service_1 = require("./wsl-info.service");
24
+ Object.defineProperty(exports, "WslInfoService", { enumerable: true, get: function () { return wsl_info_service_1.WslInfoService; } });
25
+ var wsl_instance_inspection_service_1 = require("./wsl-instance-inspection.service");
26
+ Object.defineProperty(exports, "WslInstanceInspectionService", { enumerable: true, get: function () { return wsl_instance_inspection_service_1.WslInstanceInspectionService; } });
27
+ var wsl_instance_lifecycle_service_1 = require("./wsl-instance-lifecycle.service");
28
+ Object.defineProperty(exports, "WslInstanceLifecycleService", { enumerable: true, get: function () { return wsl_instance_lifecycle_service_1.WslInstanceLifecycleService; } });
29
+ var wsl_instance_naming_service_1 = require("./wsl-instance-naming.service");
30
+ Object.defineProperty(exports, "WslInstanceNamingService", { enumerable: true, get: function () { return wsl_instance_naming_service_1.WslInstanceNamingService; } });
31
+ var wsl_updater_service_1 = require("./wsl-updater.service");
32
+ Object.defineProperty(exports, "WslUpdaterService", { enumerable: true, get: function () { return wsl_updater_service_1.WslUpdaterService; } });
33
+ //# sourceMappingURL=index.js.map
@@ -143,19 +143,37 @@ let MicroK8sService = class MicroK8sService {
143
143
  return false;
144
144
  }
145
145
  /**
146
- * 重啟 containerd 服務
146
+ * 清理 containerd stale state
147
+ *
148
+ * WSL terminate 後 containerd 的 task state 殘留在磁碟,
149
+ * 重啟後 kubelet 逐一嘗試清理 stale containers 會卡住數分鐘。
150
+ * 在 microk8s start 前清理 stale tasks 可實現秒級恢復。
151
+ * @param instanceName - WSL 實例名稱
147
152
  */
148
- async restartContainerd(instanceName) {
153
+ async cleanStaleState(instanceName) {
149
154
  (0, input_validator_util_1.requireValidInstanceName)(instanceName);
150
- this.logger.debug('[MicroK8s] Restarting containerd', { instanceName });
155
+ this.logger.debug('[MicroK8s] Cleaning stale containerd state', { instanceName });
151
156
  const env = this.envFactory.getForInstance(instanceName);
152
- // 停止
153
- const restartBuilder = env.shell('sudo')
154
- .arg('systemctl')
155
- .arg('restart')
156
- .arg('snap.microk8s.daemon-containerd');
157
- await restartBuilder.exec();
158
- await new Promise(resolve => setTimeout(resolve, 3000));
157
+ const staleTaskDir = '/var/snap/microk8s/common/run/containerd/io.containerd.runtime.v2.task/k8s.io';
158
+ try {
159
+ // 先停止所有 microk8s 服務(kubelite + containerd 等),
160
+ // 避免只停 containerd 導致 kubelet 報 connection error
161
+ const stopBuilder = env.shell(index_1.LINUX_PATHS.MICROK8S_BIN)
162
+ .arg('stop');
163
+ await stopBuilder.exec();
164
+ // lazy unmount stale rootfs(kernel 可能仍持有 overlay mount)
165
+ const unmountBuilder = env.shellScript(`mount | grep 'containerd.*k8s.io' | awk '{print $3}' | xargs -r umount -l 2>/dev/null; true`);
166
+ await unmountBuilder.exec();
167
+ // 清除 stale task 目錄
168
+ const cleanBuilder = env.shell('sudo')
169
+ .arg('rm')
170
+ .arg('-rf')
171
+ .arg(staleTaskDir);
172
+ await cleanBuilder.exec();
173
+ }
174
+ catch (error) {
175
+ this.logger.warn('[MicroK8s] Failed to clean stale state, continuing...', { error });
176
+ }
159
177
  }
160
178
  };
161
179
  exports.MicroK8sService = MicroK8sService;
@@ -52,7 +52,7 @@ const path = __importStar(require("path"));
52
52
  const os = __importStar(require("os"));
53
53
  const crypto = __importStar(require("crypto"));
54
54
  const tokens_1 = require("../../../../di/tokens");
55
- const errors_1 = require("../../../errors");
55
+ const errors_1 = require("../../../../domain/errors");
56
56
  const index_1 = require("../../../../constants/index");
57
57
  /**
58
58
  * Rootfs 管理相關常數
@@ -193,7 +193,9 @@ let RootfsManagerService = class RootfsManagerService {
193
193
  const rootfsFilename = path.basename(this.rootfsUrl);
194
194
  const hash = sums.get(rootfsFilename);
195
195
  if (!hash) {
196
- throw new Error(`SHA256 hash not found for ${rootfsFilename}`);
196
+ throw new errors_1.AppError(`SHA256 hash not found for ${rootfsFilename}`, {
197
+ exitCode: errors_1.EXIT_CODES.NETWORK_ERROR,
198
+ });
197
199
  }
198
200
  return hash;
199
201
  }
@@ -221,7 +223,9 @@ let RootfsManagerService = class RootfsManagerService {
221
223
  if (!verified) {
222
224
  // 清理無效檔案
223
225
  fs.unlinkSync(tempPath);
224
- throw new Error('SHA256 verification failed - downloaded file may be corrupted');
226
+ throw new errors_1.AppError('SHA256 verification failed - downloaded file may be corrupted', {
227
+ exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
228
+ });
225
229
  }
226
230
  // 移動臨時檔案到最終位置
227
231
  if (fs.existsSync(this.cachePath)) {
@@ -15,8 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.WindowsFeaturesService = exports.VM_PLATFORM_FEATURE_NAME = exports.WSL_FEATURE_NAME = void 0;
16
16
  const tsyringe_1 = require("tsyringe");
17
17
  const tokens_1 = require("../../../../di/tokens");
18
- const errors_1 = require("../../../errors");
19
- const command_builder_1 = require("../../../execution/command-builder");
18
+ const errors_1 = require("../../../../domain/errors");
19
+ const command_builder_util_1 = require("../../../execution/command-builder.util");
20
20
  /**
21
21
  * Windows 功能管理服務
22
22
  *
@@ -32,6 +32,16 @@ let WindowsFeaturesService = class WindowsFeaturesService {
32
32
  constructor(commandExecutor) {
33
33
  this.commandExecutor = commandExecutor;
34
34
  }
35
+ /**
36
+ * 驗證 Windows 功能名稱僅包含安全字元
37
+ * @param name - Windows 功能名稱
38
+ * @throws AppError 若名稱包含不安全字元
39
+ */
40
+ validateFeatureName(name) {
41
+ if (!/^[a-zA-Z0-9-]+$/.test(name)) {
42
+ throw new errors_1.AppError(`Invalid Windows feature name: "${name}"`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
43
+ }
44
+ }
35
45
  /**
36
46
  * 檢查單一 Windows 功能的狀態
37
47
  * @param featureName - Windows 功能名稱
@@ -39,10 +49,12 @@ let WindowsFeaturesService = class WindowsFeaturesService {
39
49
  * @throws AppSystemError 若查詢失敗
40
50
  */
41
51
  async checkFeatureState(featureName) {
52
+ // 防禦性驗證:確保 featureName 僅包含安全字元
53
+ this.validateFeatureName(featureName);
42
54
  try {
43
- const builder = command_builder_1.CommandBuilder.create('powershell')
55
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
44
56
  .powershell(`[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; $feature = Get-WindowsOptionalFeature -Online -FeatureName ${featureName}; $feature.State`);
45
- const result = await builder.exec(this.commandExecutor);
57
+ const result = await builder.exec();
46
58
  const output = result.stdout.trim();
47
59
  if (output.includes('Enable')) {
48
60
  return 'Enabled';
@@ -103,9 +115,9 @@ let WindowsFeaturesService = class WindowsFeaturesService {
103
115
  */
104
116
  async checkAdminPrivileges() {
105
117
  try {
106
- const builder = command_builder_1.CommandBuilder.create('powershell')
118
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
107
119
  .powershell("([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')");
108
- const result = await builder.exec(this.commandExecutor);
120
+ const result = await builder.exec();
109
121
  const output = result.stdout.trim();
110
122
  return output === 'True';
111
123
  }
@@ -127,14 +139,16 @@ let WindowsFeaturesService = class WindowsFeaturesService {
127
139
  async enableWSLFeatures(features) {
128
140
  let enabledCount = 0;
129
141
  for (const feature of features) {
142
+ // 防禦性驗證:確保 feature name 僅包含安全字元
143
+ this.validateFeatureName(feature.name);
130
144
  try {
131
- const builder = command_builder_1.CommandBuilder.create('dism.exe')
145
+ const builder = command_builder_util_1.CommandBuilder.create('dism.exe', this.commandExecutor)
132
146
  .arg('/online')
133
147
  .arg('/enable-feature')
134
148
  .arg(`/featurename:${feature.name}`)
135
149
  .arg('/all')
136
150
  .arg('/norestart');
137
- await builder.exec(this.commandExecutor);
151
+ await builder.exec();
138
152
  enabledCount++;
139
153
  }
140
154
  catch (error) {
@@ -15,8 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.WindowsInfoService = exports.MIN_WIN11_BUILD = exports.MIN_WIN10_BUILD = 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
  * Windows 支援的最低 Build 號碼
22
22
  */
@@ -40,19 +40,23 @@ let WindowsInfoService = class WindowsInfoService {
40
40
  });
41
41
  }
42
42
  try {
43
- const builder = command_builder_1.CommandBuilder.create('powershell')
43
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
44
44
  .arg('-NoProfile')
45
45
  .arg('-NoLogo')
46
46
  .arg('-Command')
47
47
  .arg(`"${PS_QUERY_COMMAND}"`);
48
- const result = await builder.exec(this.commandExecutor);
48
+ const result = await builder.exec();
49
49
  const info = JSON.parse(result.stdout.trim());
50
50
  if (!info.Caption || !info.Version || !info.BuildNumber) {
51
- throw new Error('Invalid PowerShell output format');
51
+ throw new errors_1.AppError('Invalid PowerShell output format', {
52
+ exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
53
+ });
52
54
  }
53
55
  const buildNumber = parseInt(info.BuildNumber, 10);
54
56
  if (isNaN(buildNumber)) {
55
- throw new Error(`Invalid build number: ${info.BuildNumber}`);
57
+ throw new errors_1.AppError(`Invalid build number: ${info.BuildNumber}`, {
58
+ exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
59
+ });
56
60
  }
57
61
  const isWindows11 = buildNumber >= exports.MIN_WIN11_BUILD;
58
62
  const isSupported = buildNumber >= exports.MIN_WIN10_BUILD;
@@ -17,6 +17,7 @@ const tsyringe_1 = require("tsyringe");
17
17
  const tokens_1 = require("../../../../di/tokens");
18
18
  const index_1 = require("../../../../constants/index");
19
19
  const input_validator_util_1 = require("../../../utils/input-validator.util");
20
+ const errors_1 = require("../../../../domain/errors");
20
21
  /**
21
22
  * 延遲執行輔助函式
22
23
  */
@@ -86,7 +87,8 @@ appendWindowsPath=false`;
86
87
  .stdin(configContent);
87
88
  const result = await builder.exec();
88
89
  if (result.exitCode !== 0) {
89
- throw new Error(`Failed to create wsl.conf in instance '${instanceName}': ${result.stderr}`);
90
+ this.appLogger?.debug('Failed to create wsl.conf', { stderr: result.stderr });
91
+ throw new errors_1.AppError(`Failed to create wsl.conf in instance '${instanceName}'`, { exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR });
90
92
  }
91
93
  return true;
92
94
  }
@@ -97,7 +99,8 @@ appendWindowsPath=false`;
97
99
  .arg(instanceName);
98
100
  const terminateResult = await terminateBuilder.exec();
99
101
  if (terminateResult.exitCode !== 0) {
100
- throw new Error(`Failed to terminate instance '${instanceName}': ${terminateResult.stderr}`);
102
+ this.appLogger?.debug('Failed to terminate instance', { stderr: terminateResult.stderr });
103
+ throw new errors_1.AppError(`Failed to terminate instance '${instanceName}'`, { exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR });
101
104
  }
102
105
  await sleep(index_1.TIMEOUTS.WSL_CONFIG_APPLY);
103
106
  // 重啟實例
@@ -105,7 +108,10 @@ appendWindowsPath=false`;
105
108
  const restartBuilder = env.shell('exit');
106
109
  const restartResult = await restartBuilder.exec();
107
110
  if (restartResult.exitCode !== 0) {
108
- throw new Error(`Failed to restart instance '${instanceName}': ${restartResult.stderr}`);
111
+ this.appLogger?.debug('Failed to restart instance', { stderr: restartResult.stderr });
112
+ throw new errors_1.AppError(`Failed to restart instance '${instanceName}'`, {
113
+ exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
114
+ });
109
115
  }
110
116
  await sleep(index_1.TIMEOUTS.WSL_SHUTDOWN_DELAY);
111
117
  }
@@ -139,7 +145,8 @@ appendWindowsPath=false`;
139
145
  .arg(username);
140
146
  const createResult = await createBuilder.exec();
141
147
  if (createResult.exitCode !== 0) {
142
- throw new Error(`Failed to create user '${username}' in instance '${instanceName}': ${createResult.stderr}`);
148
+ this.appLogger?.debug('Failed to create user', { stderr: createResult.stderr });
149
+ throw new errors_1.AppError(`Failed to create user '${username}' in instance '${instanceName}'`, { exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR });
143
150
  }
144
151
  // 加入 sudo 群組
145
152
  const sudoGroupBuilder = env.shell('usermod')
@@ -148,7 +155,8 @@ appendWindowsPath=false`;
148
155
  .arg(username);
149
156
  const sudoGroupResult = await sudoGroupBuilder.exec();
150
157
  if (sudoGroupResult.exitCode !== 0) {
151
- throw new Error(`Failed to add user '${username}' to sudo group: ${sudoGroupResult.stderr}`);
158
+ this.appLogger?.debug('Failed to add user to sudo group', { stderr: sudoGroupResult.stderr });
159
+ throw new errors_1.AppError(`Failed to add user '${username}' to sudo group`, { exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR });
152
160
  }
153
161
  // 設定 sudoers 權限 - 使用 stdin 傳遞內容,避免命令注入
154
162
  const sudoersContent = `${username} ALL=(ALL) NOPASSWD:ALL\n`;
@@ -156,7 +164,8 @@ appendWindowsPath=false`;
156
164
  .stdin(sudoersContent);
157
165
  const sudoersResult = await sudoersBuilder.exec();
158
166
  if (sudoersResult.exitCode !== 0) {
159
- throw new Error(`Failed to configure passwordless sudo for '${username}': ${sudoersResult.stderr}`);
167
+ this.appLogger?.debug('Failed to configure passwordless sudo', { stderr: sudoersResult.stderr });
168
+ throw new errors_1.AppError(`Failed to configure passwordless sudo for '${username}'`, { exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR });
160
169
  }
161
170
  return true;
162
171
  }
@@ -13,10 +13,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.WslInfoService = void 0;
16
- const errors_1 = require("../../../errors");
16
+ const errors_1 = require("../../../../domain/errors");
17
17
  const tsyringe_1 = require("tsyringe");
18
18
  const tokens_1 = require("../../../../di/tokens");
19
- const command_builder_1 = require("../../../execution/command-builder");
19
+ const command_builder_util_1 = require("../../../execution/command-builder.util");
20
20
  const wsl_version_parser_1 = require("../parsers/wsl-version.parser");
21
21
  /**
22
22
  * 最低建議 WSL 版本
@@ -33,9 +33,9 @@ let WslInfoService = class WslInfoService {
33
33
  async isWslInstalled() {
34
34
  try {
35
35
  // 使用 where.exe 檢查 wsl.exe 是否存在,這不會觸發 WSL 的彈窗
36
- const builder = command_builder_1.CommandBuilder.create('where.exe')
36
+ const builder = command_builder_util_1.CommandBuilder.create('where.exe', this.commandExecutor)
37
37
  .arg('wsl.exe');
38
- const result = await builder.exec(this.commandExecutor);
38
+ const result = await builder.exec();
39
39
  return result.exitCode === 0 && result.stdout.trim().length > 0;
40
40
  }
41
41
  catch {
@@ -55,11 +55,11 @@ let WslInfoService = class WslInfoService {
55
55
  try {
56
56
  // 檢查 LxssManager 服務是否存在並正在執行
57
57
  // 這個服務只有在 WSL 完全安裝後才會存在
58
- const builder = command_builder_1.CommandBuilder.create('powershell')
58
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
59
59
  .arg('-NoProfile')
60
60
  .arg('-Command')
61
61
  .arg('Get-Service LxssManager -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Status');
62
- const result = await builder.exec(this.commandExecutor);
62
+ const result = await builder.exec();
63
63
  const status = result.stdout.trim();
64
64
  // 服務狀態應該是 Running 或 Stopped
65
65
  return status === 'Running' || status === 'Stopped';
@@ -74,11 +74,11 @@ let WslInfoService = class WslInfoService {
74
74
  */
75
75
  async isStoreVersionInstalled() {
76
76
  try {
77
- const builder = command_builder_1.CommandBuilder.create('powershell')
77
+ const builder = command_builder_util_1.CommandBuilder.create('powershell', this.commandExecutor)
78
78
  .arg('-NoProfile')
79
79
  .arg('-Command')
80
80
  .arg('Get-AppxPackage -Name MicrosoftCorporationII.WindowsSubsystemForLinux');
81
- const result = await builder.exec(this.commandExecutor);
81
+ const result = await builder.exec();
82
82
  return result.stdout.trim().length > 0;
83
83
  }
84
84
  catch {
@@ -110,9 +110,9 @@ let WslInfoService = class WslInfoService {
110
110
  if (await this.isStoreVersionInstalled()) {
111
111
  try {
112
112
  // 使用 --version 檢查版本
113
- const versionBuilder = command_builder_1.CommandBuilder.create('wsl')
113
+ const versionBuilder = command_builder_util_1.CommandBuilder.create('wsl', this.commandExecutor)
114
114
  .arg('--version');
115
- const versionResult = await versionBuilder.exec(this.commandExecutor);
115
+ const versionResult = await versionBuilder.exec();
116
116
  const versionOutput = versionResult.stdout;
117
117
  // 使用 Parser 解析版本資訊(支援多語系)
118
118
  wslVersion = wsl_version_parser_1.WslVersionParser.parseWslVersion(versionOutput) ?? undefined;
@@ -125,9 +125,9 @@ let WslInfoService = class WslInfoService {
125
125
  // 執行 wsl --status 取得預設版本
126
126
  let defaultVersion;
127
127
  try {
128
- const statusBuilder = command_builder_1.CommandBuilder.create('wsl')
128
+ const statusBuilder = command_builder_util_1.CommandBuilder.create('wsl', this.commandExecutor)
129
129
  .arg('--status');
130
- const statusResult = await statusBuilder.exec(this.commandExecutor);
130
+ const statusResult = await statusBuilder.exec();
131
131
  const statusOutput = statusResult.stdout;
132
132
  // 使用 Parser 解析預設版本(支援多語系)
133
133
  defaultVersion = wsl_version_parser_1.WslVersionParser.parseDefaultVersion(statusOutput) ?? undefined;
@@ -50,7 +50,7 @@ const tsyringe_1 = require("tsyringe");
50
50
  const fs = __importStar(require("fs"));
51
51
  const path = __importStar(require("path"));
52
52
  const tokens_1 = require("../../../../di/tokens");
53
- const command_builder_1 = require("../../../execution/command-builder");
53
+ const command_builder_util_1 = require("../../../execution/command-builder.util");
54
54
  const paths_1 = require("../../../../constants/paths");
55
55
  const input_validator_util_1 = require("../../../utils/input-validator.util");
56
56
  /**
@@ -80,10 +80,10 @@ let WslInstanceInspectionService = class WslInstanceInspectionService {
80
80
  component: 'WslInstanceInspectionService'
81
81
  });
82
82
  try {
83
- const builder = command_builder_1.CommandBuilder.create('wsl')
83
+ const builder = command_builder_util_1.CommandBuilder.create('wsl', this.commandExecutor)
84
84
  .arg('--list')
85
85
  .arg('--verbose');
86
- const result = await builder.exec(this.commandExecutor);
86
+ const result = await builder.exec();
87
87
  const output = result.stdout;
88
88
  const lines = output.split('\n');
89
89
  const instances = [];