@uofx/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/LICENSE +40 -0
  2. package/README.md +444 -0
  3. package/THIRD-PARTY-NOTICES.txt +894 -0
  4. package/dist/application/dtos/index.js +24 -0
  5. package/dist/application/dtos/request/delete-instance.request.dto.js +3 -0
  6. package/dist/application/dtos/request/get-config.request.dto.js +3 -0
  7. package/dist/application/dtos/request/get-credentials.request.dto.js +3 -0
  8. package/dist/application/dtos/request/index.js +27 -0
  9. package/dist/application/dtos/request/install-instance.request.dto.js +3 -0
  10. package/dist/application/dtos/request/list-charts.request.dto.js +3 -0
  11. package/dist/application/dtos/request/set-config.request.dto.js +16 -0
  12. package/dist/application/dtos/request/setup-environment.request.dto.js +16 -0
  13. package/dist/application/dtos/request/show-logs.request.dto.js +19 -0
  14. package/dist/application/dtos/request/start-instance.request.dto.js +3 -0
  15. package/dist/application/dtos/request/stop-instance.request.dto.js +3 -0
  16. package/dist/application/dtos/response/credentials.response.dto.js +3 -0
  17. package/dist/application/dtos/response/delete-instance.response.dto.js +3 -0
  18. package/dist/application/dtos/response/index.js +26 -0
  19. package/dist/application/dtos/response/install-instance.response.dto.js +3 -0
  20. package/dist/application/dtos/response/instance-list.response.dto.js +3 -0
  21. package/dist/application/dtos/response/instance-status.response.dto.js +3 -0
  22. package/dist/application/dtos/response/setup-result.response.dto.js +3 -0
  23. package/dist/application/dtos/response/show-logs.response.dto.js +3 -0
  24. package/dist/application/dtos/response/start-instance.response.dto.js +3 -0
  25. package/dist/application/dtos/response/stop-instance.response.dto.js +3 -0
  26. package/dist/application/index.js +25 -0
  27. package/dist/application/interfaces/index.js +24 -0
  28. package/dist/application/interfaces/use-case.interface.js +3 -0
  29. package/dist/application/use-cases/config/get-config.use-case.js +66 -0
  30. package/dist/application/use-cases/config/set-config.use-case.js +49 -0
  31. package/dist/application/use-cases/credentials/get-credentials.use-case.js +57 -0
  32. package/dist/application/use-cases/index.js +28 -0
  33. package/dist/application/use-cases/instance/delete-instance.use-case.js +81 -0
  34. package/dist/application/use-cases/instance/index.js +23 -0
  35. package/dist/application/use-cases/instance/install-instance.use-case.js +424 -0
  36. package/dist/application/use-cases/instance/list-charts.use-case.js +43 -0
  37. package/dist/application/use-cases/instance/list-instances.use-case.js +62 -0
  38. package/dist/application/use-cases/instance/start-instance.use-case.js +154 -0
  39. package/dist/application/use-cases/instance/stop-instance.use-case.js +55 -0
  40. package/dist/application/use-cases/logs/show-logs.use-case.js +66 -0
  41. package/dist/application/use-cases/setup/setup-environment.use-case.js +53 -0
  42. package/dist/cli.js +286 -0
  43. package/dist/constants/config-defaults.js +23 -0
  44. package/dist/constants/defaults.js +89 -0
  45. package/dist/constants/deployment.js +39 -0
  46. package/dist/constants/environments.js +93 -0
  47. package/dist/constants/index.js +53 -0
  48. package/dist/constants/oci-artifacts.js +25 -0
  49. package/dist/constants/paths.js +92 -0
  50. package/dist/constants/timeouts.js +60 -0
  51. package/dist/di/container.js +34 -0
  52. package/dist/di/index.js +22 -0
  53. package/dist/di/modules/application.module.js +54 -0
  54. package/dist/di/modules/infrastructure.module.js +206 -0
  55. package/dist/di/modules/interceptor.module.js +68 -0
  56. package/dist/di/modules/presentation.module.js +31 -0
  57. package/dist/di/tokens.js +149 -0
  58. package/dist/domain/decorators/sensitive.decorator.js +39 -0
  59. package/dist/domain/entities/credentials-resolver.entity.js +127 -0
  60. package/dist/domain/entities/credentials.entity.js +65 -0
  61. package/dist/domain/entities/delete-instance-validation.entity.js +100 -0
  62. package/dist/domain/entities/deployment-parameters.entity.js +120 -0
  63. package/dist/domain/entities/environment-validation.entity.js +125 -0
  64. package/dist/domain/entities/index.js +29 -0
  65. package/dist/domain/entities/instance-lifecycle-state.entity.js +100 -0
  66. package/dist/domain/entities/instance-list-aggregator.entity.js +104 -0
  67. package/dist/domain/entities/instance-metadata.entity.js +86 -0
  68. package/dist/domain/entities/instance-status.entity.js +79 -0
  69. package/dist/domain/entities/instance.entity.js +128 -0
  70. package/dist/domain/entities/log-filter.entity.js +141 -0
  71. package/dist/domain/index.js +29 -0
  72. package/dist/domain/interfaces/safe-loggable.interface.js +3 -0
  73. package/dist/domain/ports/app-config.port.js +3 -0
  74. package/dist/domain/ports/base-image.port.js +3 -0
  75. package/dist/domain/ports/chart-version.port.js +3 -0
  76. package/dist/domain/ports/correlation-id.port.js +3 -0
  77. package/dist/domain/ports/credentials.port.js +3 -0
  78. package/dist/domain/ports/deployment.port.js +3 -0
  79. package/dist/domain/ports/error-handler.port.js +3 -0
  80. package/dist/domain/ports/index.js +46 -0
  81. package/dist/domain/ports/instance-manager.port.js +3 -0
  82. package/dist/domain/ports/instance-metadata.port.js +8 -0
  83. package/dist/domain/ports/instance-storage.port.js +3 -0
  84. package/dist/domain/ports/k8s-deployer.port.js +3 -0
  85. package/dist/domain/ports/logger.port.js +14 -0
  86. package/dist/domain/ports/output.port.js +3 -0
  87. package/dist/domain/ports/runtime-environment.port.js +6 -0
  88. package/dist/domain/ports/user-interaction.port.js +9 -0
  89. package/dist/domain/ports/user-settings.port.js +3 -0
  90. package/dist/domain/types/index.js +22 -0
  91. package/dist/domain/types/logger.types.js +29 -0
  92. package/dist/domain/types/validation.types.js +9 -0
  93. package/dist/domain/value-objects/acr-credentials.value-object.js +92 -0
  94. package/dist/domain/value-objects/chart-version.value-object.js +124 -0
  95. package/dist/domain/value-objects/config-log-level.value-object.js +84 -0
  96. package/dist/domain/value-objects/connection-info.value-object.js +65 -0
  97. package/dist/domain/value-objects/index.js +25 -0
  98. package/dist/domain/value-objects/instance-name.value-object.js +91 -0
  99. package/dist/domain/value-objects/jwt-key.value-object.js +97 -0
  100. package/dist/domain/value-objects/mssql-password.value-object.js +140 -0
  101. package/dist/domain/value-objects/rsa-key-pair.value-object.js +181 -0
  102. package/dist/index.js +6 -0
  103. package/dist/infrastructure/config/app-config.interface.js +3 -0
  104. package/dist/infrastructure/config/app-config.service.js +280 -0
  105. package/dist/infrastructure/config/config-validator.js +31 -0
  106. package/dist/infrastructure/config/crypto.service.js +125 -0
  107. package/dist/infrastructure/deployment/deployment.adapter.js +118 -0
  108. package/dist/infrastructure/deployment/interfaces/acr-credential-manager.interface.js +3 -0
  109. package/dist/infrastructure/deployment/interfaces/app-manager.interface.js +3 -0
  110. package/dist/infrastructure/deployment/interfaces/helm-registry.interface.js +3 -0
  111. package/dist/infrastructure/deployment/interfaces/infra-manager.interface.js +3 -0
  112. package/dist/infrastructure/deployment/interfaces/k8s-job-runner.interface.js +3 -0
  113. package/dist/infrastructure/deployment/interfaces/mssql-database-init.interface.js +3 -0
  114. package/dist/infrastructure/deployment/interfaces/mssql-helm-deployment.interface.js +3 -0
  115. package/dist/infrastructure/deployment/interfaces/mssql-storage.interface.js +3 -0
  116. package/dist/infrastructure/deployment/interfaces/mssql-user-manager.interface.js +3 -0
  117. package/dist/infrastructure/deployment/interfaces/oci-artifact.interface.js +3 -0
  118. package/dist/infrastructure/deployment/interfaces/secret-manager.interface.js +3 -0
  119. package/dist/infrastructure/deployment/interfaces/service-manager.interface.js +3 -0
  120. package/dist/infrastructure/deployment/interfaces/version-compatibility.interface.js +3 -0
  121. package/dist/infrastructure/deployment/services/acr-credential-manager.service.js +144 -0
  122. package/dist/infrastructure/deployment/services/app-manager.service.js +193 -0
  123. package/dist/infrastructure/deployment/services/base-helm-deployment.service.js +163 -0
  124. package/dist/infrastructure/deployment/services/helm-registry.service.js +126 -0
  125. package/dist/infrastructure/deployment/services/infra-manager.service.js +130 -0
  126. package/dist/infrastructure/deployment/services/k8s-job-runner.service.js +194 -0
  127. package/dist/infrastructure/deployment/services/mssql-database-init.service.js +139 -0
  128. package/dist/infrastructure/deployment/services/mssql-helm-deployment.service.js +100 -0
  129. package/dist/infrastructure/deployment/services/mssql-storage.service.js +54 -0
  130. package/dist/infrastructure/deployment/services/mssql-user-manager.service.js +66 -0
  131. package/dist/infrastructure/deployment/services/oci-artifact.service.js +289 -0
  132. package/dist/infrastructure/deployment/services/secret-manager.service.js +179 -0
  133. package/dist/infrastructure/deployment/services/service-manager.service.js +82 -0
  134. package/dist/infrastructure/deployment/services/version-compatibility.service.js +291 -0
  135. package/dist/infrastructure/environment/interfaces/hardware-info.interface.js +3 -0
  136. package/dist/infrastructure/environment/interfaces/network-checker.interface.js +3 -0
  137. package/dist/infrastructure/environment/services/hardware-info.service.js +135 -0
  138. package/dist/infrastructure/environment/services/network-checker.service.js +142 -0
  139. package/dist/infrastructure/environment/windows-environment.adapter.js +162 -0
  140. package/dist/infrastructure/errors/app-error.js +73 -0
  141. package/dist/infrastructure/errors/error-handler.interface.js +3 -0
  142. package/dist/infrastructure/errors/error-handler.js +218 -0
  143. package/dist/infrastructure/errors/exit-codes.js +27 -0
  144. package/dist/infrastructure/errors/index.js +25 -0
  145. package/dist/infrastructure/execution/builders/base-command.builder.js +122 -0
  146. package/dist/infrastructure/execution/builders/host-command.builder.js +58 -0
  147. package/dist/infrastructure/execution/builders/windows-host-command.builder.js +50 -0
  148. package/dist/infrastructure/execution/builders/wsl-command.builder.js +29 -0
  149. package/dist/infrastructure/execution/command-builder.js +252 -0
  150. package/dist/infrastructure/execution/command-executor.service.js +230 -0
  151. package/dist/infrastructure/execution/environments/wsl-execution.environment.js +70 -0
  152. package/dist/infrastructure/execution/execution-environment.factory.js +53 -0
  153. package/dist/infrastructure/execution/index.js +25 -0
  154. package/dist/infrastructure/execution/interfaces/command-builder.interface.js +3 -0
  155. package/dist/infrastructure/execution/interfaces/command-executor.interface.js +3 -0
  156. package/dist/infrastructure/execution/interfaces/execution-environment-factory.interface.js +3 -0
  157. package/dist/infrastructure/execution/interfaces/execution-environment.interface.js +7 -0
  158. package/dist/infrastructure/execution/interfaces/host-command-builder.interface.js +3 -0
  159. package/dist/infrastructure/execution/interfaces/index.js +23 -0
  160. package/dist/infrastructure/execution/interfaces/script-executor.interface.js +3 -0
  161. package/dist/infrastructure/execution/script-executor.service.js +171 -0
  162. package/dist/infrastructure/http/http-client.service.js +176 -0
  163. package/dist/infrastructure/http/index.js +18 -0
  164. package/dist/infrastructure/http/interfaces/http-client.interface.js +3 -0
  165. package/dist/infrastructure/interceptors/index.js +8 -0
  166. package/dist/infrastructure/interceptors/interceptor.factory.js +44 -0
  167. package/dist/infrastructure/interceptors/interceptor.interface.js +3 -0
  168. package/dist/infrastructure/interceptors/logging.interceptor.js +171 -0
  169. package/dist/infrastructure/logger/correlation-id.adapter.js +68 -0
  170. package/dist/infrastructure/logger/index.js +23 -0
  171. package/dist/infrastructure/logger/interfaces/index.js +22 -0
  172. package/dist/infrastructure/logger/interfaces/log-reader.repository.interface.js +7 -0
  173. package/dist/infrastructure/logger/interfaces/log-writer.repository.interface.js +7 -0
  174. package/dist/infrastructure/logger/logger.adapter.js +274 -0
  175. package/dist/infrastructure/logger/services/file-log-reader.repository.js +148 -0
  176. package/dist/infrastructure/logger/services/file-log-writer.repository.js +307 -0
  177. package/dist/infrastructure/logger/services/index.js +22 -0
  178. package/dist/infrastructure/persistence/index.js +25 -0
  179. package/dist/infrastructure/persistence/instance-metadata.adapter.js +100 -0
  180. package/dist/infrastructure/persistence/instance-storage.adapter.js +64 -0
  181. package/dist/infrastructure/persistence/interfaces/config.repository.interface.js +3 -0
  182. package/dist/infrastructure/persistence/interfaces/index.js +22 -0
  183. package/dist/infrastructure/persistence/interfaces/instance.repository.interface.js +3 -0
  184. package/dist/infrastructure/persistence/services/file-system-config.repository.js +168 -0
  185. package/dist/infrastructure/persistence/services/file-system-instance.repository.js +170 -0
  186. package/dist/infrastructure/persistence/services/index.js +22 -0
  187. package/dist/infrastructure/persistence/user-settings.adapter.js +55 -0
  188. package/dist/infrastructure/platform-detector.js +71 -0
  189. package/dist/infrastructure/platforms/windows/interfaces/microk8s.interface.js +3 -0
  190. package/dist/infrastructure/platforms/windows/interfaces/rootfs-manager.interface.js +3 -0
  191. package/dist/infrastructure/platforms/windows/interfaces/windows-features.interface.js +3 -0
  192. package/dist/infrastructure/platforms/windows/interfaces/windows-info.interface.js +3 -0
  193. package/dist/infrastructure/platforms/windows/interfaces/wsl-config.interface.js +3 -0
  194. package/dist/infrastructure/platforms/windows/interfaces/wsl-info.interface.js +3 -0
  195. package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-inspection.interface.js +3 -0
  196. package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-lifecycle.interface.js +3 -0
  197. package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-naming.interface.js +3 -0
  198. package/dist/infrastructure/platforms/windows/interfaces/wsl-manager.interface.js +3 -0
  199. package/dist/infrastructure/platforms/windows/interfaces/wsl-resources.interface.js +8 -0
  200. package/dist/infrastructure/platforms/windows/interfaces/wsl-updater.interface.js +3 -0
  201. package/dist/infrastructure/platforms/windows/interfaces/wslconfig-parser.interface.js +3 -0
  202. package/dist/infrastructure/platforms/windows/parsers/wsl-version.parser.js +133 -0
  203. package/dist/infrastructure/platforms/windows/services/microk8s.service.js +168 -0
  204. package/dist/infrastructure/platforms/windows/services/rootfs-manager.service.js +336 -0
  205. package/dist/infrastructure/platforms/windows/services/windows-features.service.js +191 -0
  206. package/dist/infrastructure/platforms/windows/services/windows-info.service.js +138 -0
  207. package/dist/infrastructure/platforms/windows/services/wsl-config.service.js +171 -0
  208. package/dist/infrastructure/platforms/windows/services/wsl-info.service.js +226 -0
  209. package/dist/infrastructure/platforms/windows/services/wsl-instance-inspection.service.js +325 -0
  210. package/dist/infrastructure/platforms/windows/services/wsl-instance-lifecycle.service.js +442 -0
  211. package/dist/infrastructure/platforms/windows/services/wsl-instance-naming.service.js +93 -0
  212. package/dist/infrastructure/platforms/windows/services/wsl-updater.service.js +273 -0
  213. package/dist/infrastructure/platforms/windows/services/wslconfig-parser.service.js +222 -0
  214. package/dist/infrastructure/platforms/windows/wsl-base-image.adapter.js +41 -0
  215. package/dist/infrastructure/platforms/windows/wsl-instance-manager.adapter.js +150 -0
  216. package/dist/infrastructure/utils/error-formatter.util.js +29 -0
  217. package/dist/infrastructure/utils/file-operations.util.js +201 -0
  218. package/dist/infrastructure/utils/input-validator.util.js +152 -0
  219. package/dist/infrastructure/utils/retry.util.js +98 -0
  220. package/dist/presentation/controllers/config.controller.js +146 -0
  221. package/dist/presentation/controllers/credentials.controller.js +105 -0
  222. package/dist/presentation/controllers/index.js +25 -0
  223. package/dist/presentation/controllers/instance.controller.js +363 -0
  224. package/dist/presentation/controllers/logs.controller.js +103 -0
  225. package/dist/presentation/controllers/setup.controller.js +175 -0
  226. package/dist/presentation/interfaces/cli-options.interface.js +8 -0
  227. package/dist/presentation/prompts/acr-credentials.prompt.js +76 -0
  228. package/dist/presentation/prompts/index.js +21 -0
  229. package/dist/presentation/ui/cli-progress.service.js +193 -0
  230. package/dist/presentation/ui/constants/output-symbols.js +42 -0
  231. package/dist/presentation/ui/index.js +27 -0
  232. package/dist/presentation/ui/interaction.service.js +276 -0
  233. package/dist/presentation/ui/interfaces/cli-progress.interface.js +9 -0
  234. package/dist/presentation/ui/interfaces/output-formatter.interface.js +23 -0
  235. package/dist/presentation/ui/log-level.enum.js +66 -0
  236. package/dist/presentation/ui/output-builder.service.js +378 -0
  237. package/dist/presentation/ui/output-formatter.service.js +393 -0
  238. package/package.json +65 -0
@@ -0,0 +1,273 @@
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.WslUpdaterService = void 0;
16
+ const tsyringe_1 = require("tsyringe");
17
+ const tokens_1 = require("../../../../di/tokens");
18
+ const errors_1 = require("../../../errors");
19
+ const command_builder_1 = require("../../../execution/command-builder");
20
+ const error_formatter_util_1 = require("../../../utils/error-formatter.util");
21
+ /**
22
+ * WSL 更新服務
23
+ *
24
+ * 負責 WSL 的安裝與更新操作,包含:
25
+ * - WSL 安裝狀態檢查
26
+ * - WSL 2 預設版本設定
27
+ * - WSL 更新執行
28
+ * - 使用者互動提示
29
+ */
30
+ let WslUpdaterService = class WslUpdaterService {
31
+ constructor(commandExecutor, appLogger, userInteraction) {
32
+ this.commandExecutor = commandExecutor;
33
+ this.appLogger = appLogger;
34
+ this.userInteraction = userInteraction;
35
+ }
36
+ /**
37
+ * 格式化 WSL 設定提示訊息
38
+ * @param requirement - 更新需求資訊
39
+ * @returns 格式化後的提示訊息
40
+ */
41
+ formatWslSetupPrompt(requirement) {
42
+ const lines = [];
43
+ lines.push('⚠ WSL 2 setup required');
44
+ lines.push('');
45
+ lines.push('Kubernetes requires WSL 2 with up-to-date software version.');
46
+ lines.push('');
47
+ lines.push('Current status:');
48
+ if (requirement.needsUpdate && requirement.currentVersion) {
49
+ lines.push(` • WSL version: ${requirement.currentVersion} (update available)`);
50
+ }
51
+ else if (requirement.currentVersion) {
52
+ lines.push(` • WSL version: ${requirement.currentVersion} ✓`);
53
+ }
54
+ else {
55
+ lines.push(' • WSL version: Unknown (update recommended)');
56
+ }
57
+ if (requirement.needsDefaultVersion && requirement.currentDefaultVersion !== undefined) {
58
+ lines.push(` • Default WSL version: WSL ${requirement.currentDefaultVersion}`);
59
+ }
60
+ else if (requirement.currentDefaultVersion !== undefined) {
61
+ lines.push(` • Default WSL version: WSL ${requirement.currentDefaultVersion} ✓`);
62
+ }
63
+ else {
64
+ lines.push(' • Default WSL version: Unknown');
65
+ }
66
+ lines.push('');
67
+ lines.push('The following steps will be performed:');
68
+ requirement.steps.forEach((step, index) => {
69
+ lines.push(` ${index + 1}. ${step}`);
70
+ });
71
+ if (requirement.needsDefaultVersion) {
72
+ lines.push('');
73
+ lines.push('WSL 2 uses a real Linux kernel and provides full system call');
74
+ lines.push('compatibility required by Kubernetes.');
75
+ }
76
+ return lines.join('\n');
77
+ }
78
+ /**
79
+ * 提示使用者是否進行 WSL 設定
80
+ * @param requirement - 更新需求資訊
81
+ * @param progress - 進度通知回調
82
+ * @returns 若使用者同意則回傳 true
83
+ */
84
+ async promptWslSetup(requirement, output) {
85
+ output?.info(this.formatWslSetupPrompt(requirement)).flush();
86
+ const questionText = requirement.needsUpdate && requirement.needsDefaultVersion
87
+ ? 'Do you want to proceed with WSL 2 setup?'
88
+ : requirement.needsUpdate
89
+ ? 'Do you want to proceed with WSL update?'
90
+ : 'Do you want to proceed with WSL 2 setup?';
91
+ if (!this.userInteraction)
92
+ return false;
93
+ return this.userInteraction.confirm(questionText, true);
94
+ }
95
+ /**
96
+ * 提示使用者安裝 WSL
97
+ * @param output - 輸出介面
98
+ */
99
+ async promptWslInstall(output) {
100
+ output?.info('WSL is not installed on this system.').flush();
101
+ output?.info('This process will install WSL and automatically enable required Windows features.').flush();
102
+ if (!this.userInteraction)
103
+ return false;
104
+ return this.userInteraction.confirm('Do you want to install WSL now?', true);
105
+ }
106
+ /**
107
+ * 檢查當前程序是否具有管理員權限
108
+ */
109
+ async checkAdmin() {
110
+ try {
111
+ const builder = command_builder_1.CommandBuilder.create('powershell')
112
+ .powershell("([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')");
113
+ const result = await builder.exec(this.commandExecutor);
114
+ return result.stdout.trim() === 'True';
115
+ }
116
+ catch {
117
+ return false;
118
+ }
119
+ }
120
+ /**
121
+ * 安裝或更新 WSL
122
+ * 統一使用 wsl --update 命令,適用於所有 Windows 版本
123
+ * 如果以管理員身分執行,則在當前控制台中執行
124
+ * 否則,提示用戶以管理員身份重新執行
125
+ *
126
+ * @param action 'install' 或 'update'(統一執行 --update)
127
+ * @param output - 輸出介面
128
+ * @returns 物件指示是否需要重新啟動
129
+ */
130
+ async installWsl(action = 'install', output) {
131
+ const isAdmin = await this.checkAdmin();
132
+ const actionDescription = action === 'install' ? 'installation' : 'update';
133
+ this.appLogger?.info(`Starting WSL ${actionDescription}`, { isAdmin, action });
134
+ if (isAdmin) {
135
+ output?.info(`Running WSL ${actionDescription} in the current console...`).flush();
136
+ try {
137
+ // 統一使用 --update,適用於所有 Windows 版本
138
+ const builder = command_builder_1.CommandBuilder.create('wsl')
139
+ .wslCmd('--update');
140
+ const result = await builder.exec(this.commandExecutor);
141
+ const cmdOutput = result.stdout + result.stderr;
142
+ if (result.exitCode !== 0) {
143
+ // 即使命令 "失敗",也可能已經成功但需要重新啟動
144
+ // Windows 經常在需要重新啟動時返回非零退出碼
145
+ if (/restart|reboot|重新啟動/i.test(cmdOutput)) {
146
+ output?.success(`WSL ${actionDescription} completed (restart required).`).flush();
147
+ return { needsRestart: true };
148
+ }
149
+ throw new Error('Command failed');
150
+ }
151
+ // 根據輸出檢查是否需要重新啟動
152
+ const needsRestart = /restart|reboot|重新啟動/i.test(cmdOutput);
153
+ if (needsRestart) {
154
+ output?.success(`WSL ${actionDescription} completed.`).flush();
155
+ output?.warning('A system restart is required.').flush();
156
+ }
157
+ else {
158
+ output?.success(`WSL ${actionDescription} completed.`).flush();
159
+ }
160
+ return { needsRestart };
161
+ }
162
+ catch (error) {
163
+ // 檢查錯誤訊息中是否包含重啟提示
164
+ const errorMessage = (0, error_formatter_util_1.formatErrorMessage)(error);
165
+ if (/restart|reboot|重新啟動/i.test(errorMessage)) {
166
+ output?.success(`WSL ${actionDescription} completed (restart required).`).flush();
167
+ return { needsRestart: true };
168
+ }
169
+ this.appLogger?.error(error instanceof Error ? error : new Error(String(error)), {
170
+ operation: 'installWsl',
171
+ action,
172
+ isAdmin: true
173
+ });
174
+ throw new errors_1.AppError(`Failed to execute WSL ${actionDescription}`, {
175
+ exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
176
+ solution: 'Try running the command as administrator or check Windows Event Viewer for details',
177
+ });
178
+ }
179
+ }
180
+ else {
181
+ // 沒有管理員權限,需要用戶重新以管理員身份開啟終端
182
+ output?.error('Administrator privileges required.').flush();
183
+ output?.info(`WSL ${actionDescription} requires administrator privileges.`).flush();
184
+ output?.info('Please reopen this terminal as Administrator and run the setup command again.').flush();
185
+ output?.info('How to run as Administrator:').flush();
186
+ output?.info(' 1. Right-click your terminal (Command Prompt, PowerShell, or Windows Terminal)').flush();
187
+ output?.info(' 2. Select "Run as administrator"').flush();
188
+ output?.info(` 3. Run: uofx env setup`).flush();
189
+ // 拋出簡單錯誤以便記錄,但不顯示冗長的錯誤詳情
190
+ this.appLogger?.error(new Error(`Administrator privileges required for WSL ${actionDescription}`), {
191
+ operation: 'installWsl',
192
+ action,
193
+ isAdmin: false
194
+ });
195
+ throw new errors_1.AppError(`Failed to launch WSL ${actionDescription}`, {
196
+ exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
197
+ solution: 'Run the command as administrator or check your Windows permissions',
198
+ });
199
+ }
200
+ }
201
+ /**
202
+ * 設定 WSL 預設版本為 2 (wsl --set-default-version 2)
203
+ * @param progress - 進度通知回調
204
+ * @throws AppSystemError 若設定失敗
205
+ */
206
+ async setDefaultVersion(output) {
207
+ try {
208
+ output?.info('Setting WSL 2 as default version...').flush();
209
+ this.appLogger?.debug('Running wsl --set-default-version 2');
210
+ const builder = command_builder_1.CommandBuilder.create('wsl')
211
+ .arg('--set-default-version')
212
+ .arg('2');
213
+ const result = await builder.exec(this.commandExecutor, (data) => output?.info(`${data.trim()}`).flush(), (data) => output?.info(`${data.trim()}`).flush());
214
+ if (result.exitCode !== 0) {
215
+ throw new Error(result.stderr || 'Command failed');
216
+ }
217
+ output?.success('WSL 2 set as default version').flush();
218
+ }
219
+ catch (error) {
220
+ this.appLogger?.error(error instanceof Error ? error : new Error(String(error)), {
221
+ operation: 'setDefaultVersion',
222
+ });
223
+ throw new errors_1.AppError('Failed to set WSL default version', {
224
+ exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
225
+ solution: 'Try running: wsl --set-default-version 2',
226
+ });
227
+ }
228
+ }
229
+ /**
230
+ * 格式化設定取消錯誤訊息
231
+ * @param requirement - 更新需求資訊
232
+ * @returns 格式化後的錯誤訊息
233
+ */
234
+ formatSetupCancelledError(requirement) {
235
+ const lines = [];
236
+ lines.push('✗ Setup cancelled: WSL 2 is required for Kubernetes');
237
+ lines.push('');
238
+ lines.push('To continue setup manually, please run:');
239
+ if (requirement.needsUpdate) {
240
+ lines.push(' wsl --update');
241
+ }
242
+ if (requirement.needsDefaultVersion) {
243
+ lines.push(' wsl --set-default-version 2');
244
+ }
245
+ lines.push('');
246
+ lines.push("Then run 'uofx setup' again");
247
+ lines.push('');
248
+ lines.push('For more information: https://docs.microsoft.com/en-us/windows/wsl/');
249
+ return lines.join('\n');
250
+ }
251
+ /**
252
+ * 處理設定取消事件,顯示錯誤訊息並拋出異常
253
+ * @param requirement - 更新需求資訊
254
+ * @param progress - 進度通知回調
255
+ * @throws AppBusinessError 總是拋出 SETUP_CANCELLED 錯誤
256
+ */
257
+ handleSetupCancelled(requirement, output) {
258
+ output?.info(this.formatSetupCancelledError(requirement)).flush();
259
+ throw new errors_1.AppError('Setup cancelled: WSL 2 is required for Kubernetes', {
260
+ exitCode: errors_1.EXIT_CODES.BUSINESS_ERROR,
261
+ solution: 'Install WSL 2 to continue. Run: uofx setup',
262
+ });
263
+ }
264
+ };
265
+ exports.WslUpdaterService = WslUpdaterService;
266
+ exports.WslUpdaterService = WslUpdaterService = __decorate([
267
+ (0, tsyringe_1.injectable)(),
268
+ __param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.ICommandExecutor)),
269
+ __param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.ILoggerPort)),
270
+ __param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.IUserInteractionPort)),
271
+ __metadata("design:paramtypes", [Object, Object, Object])
272
+ ], WslUpdaterService);
273
+ //# sourceMappingURL=wsl-updater.service.js.map
@@ -0,0 +1,222 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ 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;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
45
+ return function (target, key) { decorator(target, key, paramIndex); }
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.WslConfigParserService = void 0;
49
+ const tsyringe_1 = require("tsyringe");
50
+ const fs = __importStar(require("fs"));
51
+ const path = __importStar(require("path"));
52
+ const os = __importStar(require("os"));
53
+ const tokens_1 = require("../../../../di/tokens");
54
+ const command_builder_1 = require("../../../execution/command-builder");
55
+ /**
56
+ * WSL 配置檔案解析服務
57
+ *
58
+ * 負責讀取和解析 .wslconfig 設定檔以及查詢 WSL 記憶體使用狀態
59
+ */
60
+ let WslConfigParserService = class WslConfigParserService {
61
+ constructor(hardwareInfo, wslInfo, commandExecutor) {
62
+ this.hardwareInfo = hardwareInfo;
63
+ this.wslInfo = wslInfo;
64
+ this.commandExecutor = commandExecutor;
65
+ }
66
+ /**
67
+ * 解析記憶體值字串
68
+ * @param value 記憶體值 (如 "16GB", "16384MB")
69
+ * @returns 記憶體大小 (GB)
70
+ */
71
+ parseMemoryValue(value) {
72
+ if (typeof value === 'number') {
73
+ return value;
74
+ }
75
+ const trimmed = value.trim().toUpperCase();
76
+ if (trimmed.endsWith('GB')) {
77
+ return parseInt(trimmed.replace('GB', ''), 10);
78
+ }
79
+ if (trimmed.endsWith('MB')) {
80
+ return Math.round(parseInt(trimmed.replace('MB', ''), 10) / 1024);
81
+ }
82
+ return parseInt(trimmed, 10);
83
+ }
84
+ /**
85
+ * 取得 WSL2 預設記憶體限制
86
+ * - WSL 2.0+: 總記憶體的 50%(無上限)
87
+ * - WSL < 2.0 或無法取得版本: min(50%, 8GB)
88
+ * @returns 預設記憶體限制 (GB)
89
+ */
90
+ async getWsl2DefaultMemory() {
91
+ const totalMemoryGB = await this.hardwareInfo.getTotalMemoryGB();
92
+ const halfMemory = Math.floor(totalMemoryGB / 2);
93
+ // 取得 WSL 版本
94
+ const versionInfo = await this.wslInfo.getWslVersionInfo();
95
+ // WSL 2.0+ 沒有 8GB 上限
96
+ if (versionInfo.wslVersion && this.isWsl2OrLater(versionInfo.wslVersion)) {
97
+ return halfMemory;
98
+ }
99
+ // 舊版或無法取得版本:使用保守值 min(50%, 8GB)
100
+ return Math.min(halfMemory, 8);
101
+ }
102
+ /**
103
+ * 檢查 WSL 版本是否為 2.0 或更新
104
+ * @param version WSL 版本字串 (如 "2.0.9.0")
105
+ * @returns 是否為 2.0+
106
+ */
107
+ isWsl2OrLater(version) {
108
+ const parts = version.split('.').map(Number);
109
+ return parts[0] >= 2;
110
+ }
111
+ /**
112
+ * 讀取 .wslconfig 設定
113
+ * @returns WSL 配置記憶體資訊
114
+ */
115
+ async readWslConfig() {
116
+ const wslConfigPath = path.join(os.homedir(), '.wslconfig');
117
+ if (!fs.existsSync(wslConfigPath)) {
118
+ return {
119
+ exists: false,
120
+ memoryGB: await this.getWsl2DefaultMemory(),
121
+ configured: false
122
+ };
123
+ }
124
+ try {
125
+ const content = fs.readFileSync(wslConfigPath, 'utf-8');
126
+ const lines = content.split('\n');
127
+ let inWsl2Section = false;
128
+ let memoryValue;
129
+ for (const line of lines) {
130
+ const trimmed = line.trim();
131
+ if (trimmed === '[wsl2]') {
132
+ inWsl2Section = true;
133
+ continue;
134
+ }
135
+ if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
136
+ inWsl2Section = false;
137
+ continue;
138
+ }
139
+ if (inWsl2Section && trimmed.startsWith('memory')) {
140
+ const match = trimmed.match(/memory\s*=\s*(.+)/i);
141
+ if (match) {
142
+ memoryValue = match[1].trim();
143
+ break;
144
+ }
145
+ }
146
+ }
147
+ if (memoryValue) {
148
+ const memoryGB = this.parseMemoryValue(memoryValue);
149
+ return {
150
+ exists: true,
151
+ memoryGB,
152
+ configured: true,
153
+ rawValue: memoryValue
154
+ };
155
+ }
156
+ return {
157
+ exists: true,
158
+ memoryGB: await this.getWsl2DefaultMemory(),
159
+ configured: false
160
+ };
161
+ }
162
+ catch {
163
+ return {
164
+ exists: true,
165
+ memoryGB: await this.getWsl2DefaultMemory(),
166
+ configured: false
167
+ };
168
+ }
169
+ }
170
+ /**
171
+ * 取得 WSL2 目前使用的記憶體 (GB)
172
+ * 透過查詢 vmmem 程序取得
173
+ * @returns WSL 目前使用的記憶體 (GB)
174
+ */
175
+ async getWslCurrentMemoryUsageGB() {
176
+ try {
177
+ const builder = command_builder_1.CommandBuilder.create('powershell')
178
+ .arg('-NoProfile')
179
+ .arg('-Command')
180
+ .arg('(Get-Process vmmemWSL -ErrorAction SilentlyContinue).WorkingSet64');
181
+ const result = await builder.exec(this.commandExecutor);
182
+ const bytes = parseInt(result.stdout.trim(), 10);
183
+ if (isNaN(bytes))
184
+ return 0;
185
+ return Math.round(bytes / (1024 * 1024 * 1024) * 100) / 100;
186
+ }
187
+ catch {
188
+ return 0; // 如果查詢失敗,回傳 0(WSL 可能未運行)
189
+ }
190
+ }
191
+ /**
192
+ * 取得記憶體可用性資訊
193
+ * 綜合計算系統剩餘記憶體、WSL 限制、WSL 使用量
194
+ * @returns 記憶體可用性資訊
195
+ */
196
+ async getMemoryAvailability() {
197
+ const systemAvailableGB = await this.hardwareInfo.getAvailableMemoryGB();
198
+ const wslConfig = await this.readWslConfig();
199
+ const wslLimitGB = wslConfig.memoryGB;
200
+ const wslCurrentUsageGB = await this.getWslCurrentMemoryUsageGB();
201
+ const wslAvailableGB = Math.max(0, wslLimitGB - wslCurrentUsageGB);
202
+ // 取系統剩餘和 WSL 可用的較小值
203
+ const availableForUofxGB = Math.min(systemAvailableGB, wslAvailableGB);
204
+ return {
205
+ systemAvailableGB,
206
+ wslLimitGB,
207
+ wslCurrentUsageGB,
208
+ wslAvailableGB,
209
+ availableForUofxGB,
210
+ wslLimitSource: wslConfig.configured ? 'wslconfig' : 'default'
211
+ };
212
+ }
213
+ };
214
+ exports.WslConfigParserService = WslConfigParserService;
215
+ exports.WslConfigParserService = WslConfigParserService = __decorate([
216
+ (0, tsyringe_1.injectable)(),
217
+ __param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IHardwareInfo)),
218
+ __param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.WslInfoService)),
219
+ __param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.ICommandExecutor)),
220
+ __metadata("design:paramtypes", [Object, Object, Object])
221
+ ], WslConfigParserService);
222
+ //# sourceMappingURL=wslconfig-parser.service.js.map
@@ -0,0 +1,41 @@
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.WslBaseImageAdapter = void 0;
16
+ const tsyringe_1 = require("tsyringe");
17
+ const tokens_1 = require("../../../di/tokens");
18
+ /**
19
+ * WSL Base Image Adapter
20
+ *
21
+ * implements IBaseImagePort for Windows/WSL platform
22
+ * 管理 Ubuntu rootfs 下載與快取
23
+ */
24
+ let WslBaseImageAdapter = class WslBaseImageAdapter {
25
+ constructor(rootfsManager) {
26
+ this.rootfsManager = rootfsManager;
27
+ }
28
+ checkCache() {
29
+ return this.rootfsManager.checkCache();
30
+ }
31
+ async getOrDownload(output) {
32
+ return await this.rootfsManager.getOrDownloadRootfs(output);
33
+ }
34
+ };
35
+ exports.WslBaseImageAdapter = WslBaseImageAdapter;
36
+ exports.WslBaseImageAdapter = WslBaseImageAdapter = __decorate([
37
+ (0, tsyringe_1.injectable)(),
38
+ __param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.RootfsManagerService)),
39
+ __metadata("design:paramtypes", [Object])
40
+ ], WslBaseImageAdapter);
41
+ //# sourceMappingURL=wsl-base-image.adapter.js.map
@@ -0,0 +1,150 @@
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.WslInstanceManagerAdapter = void 0;
16
+ const tsyringe_1 = require("tsyringe");
17
+ const tokens_1 = require("../../../di/tokens");
18
+ const instance_status_entity_1 = require("../../../domain/entities/instance-status.entity");
19
+ /**
20
+ * WSL Instance Manager Adapter
21
+ *
22
+ * implements IInstanceManagerPort for Windows/WSL platform
23
+ * 橋接 Infrastructure 層的 WSL Services 與 Domain 層的 Port
24
+ */
25
+ let WslInstanceManagerAdapter = class WslInstanceManagerAdapter {
26
+ constructor(naming, lifecycle, inspection, wslConfig, scriptExecutor, envFactory) {
27
+ this.naming = naming;
28
+ this.lifecycle = lifecycle;
29
+ this.inspection = inspection;
30
+ this.wslConfig = wslConfig;
31
+ this.scriptExecutor = scriptExecutor;
32
+ this.envFactory = envFactory;
33
+ }
34
+ async create(name, config, output) {
35
+ await this.lifecycle.createInstance(name.toString(), // 短名稱 "dev"
36
+ config.installPath, // 安裝路徑
37
+ config.chartVersion, // Chart 版本
38
+ config.rootfsPath, output);
39
+ }
40
+ async delete(name, output) {
41
+ // 先 unregister WSL(釋放 VHDX 檔案鎖定)
42
+ await this.lifecycle.deleteInstance(name.fullName);
43
+ // 再刪除資料夾
44
+ await this.lifecycle.removeInstanceDirectory(name.toString(), output);
45
+ }
46
+ async start(name, output) {
47
+ await this.lifecycle.startInstance(name.fullName, output);
48
+ }
49
+ async stop(name, force, output) {
50
+ await this.lifecycle.stopInstance(name.fullName, force, output);
51
+ }
52
+ async exists(name) {
53
+ return await this.inspection.checkInstanceExists(name.fullName);
54
+ }
55
+ async getStatus(name) {
56
+ const infraStatus = await this.inspection.getInstanceStatus(name.fullName);
57
+ if (infraStatus.running) {
58
+ return instance_status_entity_1.InstanceStatus.createRunning(name.toString(), infraStatus.uptime);
59
+ }
60
+ else {
61
+ return instance_status_entity_1.InstanceStatus.createStopped(name.toString());
62
+ }
63
+ }
64
+ async list() {
65
+ return await this.inspection.scanAllInstances();
66
+ }
67
+ async listUofx() {
68
+ const result = await this.inspection.scanUofxInstances();
69
+ return result.instances;
70
+ }
71
+ async verify(name) {
72
+ return await this.inspection.verifyInstance(name.fullName);
73
+ }
74
+ async initialize(name, params, environmentVersion, output) {
75
+ await this.scriptExecutor.runSystemInitialization(name.fullName, params, environmentVersion, output);
76
+ }
77
+ async listRunningInstances() {
78
+ return await this.inspection.listRunningInstances();
79
+ }
80
+ async waitForPodsReady(name, timeoutMs) {
81
+ return await this.lifecycle.waitForPodsReady(name.fullName, timeoutMs);
82
+ }
83
+ async initDBusSession(name, output) {
84
+ await this.lifecycle.initDBusSession(name.fullName, output);
85
+ }
86
+ async isMicroK8sRunning(name) {
87
+ return await this.lifecycle.isMicroK8sRunning(name.fullName);
88
+ }
89
+ async getInstanceDetails(name) {
90
+ const exists = await this.inspection.checkInstanceExists(name.fullName);
91
+ if (!exists) {
92
+ return null;
93
+ }
94
+ const status = await this.inspection.getInstanceStatus(name.fullName);
95
+ const installPath = this.naming.getInstallPath(name.toString());
96
+ const metadata = this.lifecycle.loadMetadata(installPath);
97
+ const diskUsage = await this.lifecycle.getDirectorySize(installPath);
98
+ return {
99
+ name: name.fullName,
100
+ isRunning: status.running,
101
+ chartVersion: metadata?.chartVersion || null,
102
+ installedAt: metadata?.createdAt || null,
103
+ diskUsage,
104
+ diskUsageFormatted: this.lifecycle.formatSize(diskUsage),
105
+ };
106
+ }
107
+ async getInstanceIP(name) {
108
+ try {
109
+ const env = this.envFactory.getForInstance(name.fullName);
110
+ const builder = env.shell('hostname')
111
+ .arg('-I');
112
+ const result = await builder.exec();
113
+ if (!result || result.exitCode !== 0 || !result.stdout) {
114
+ return null;
115
+ }
116
+ // 解析第一個 IP 位址
117
+ const ipAddr = result.stdout.trim().split(' ')[0];
118
+ // 驗證 IP 格式
119
+ const ipPattern = /^\d+\.\d+\.\d+\.\d+$/;
120
+ return ipPattern.test(ipAddr) ? ipAddr : null;
121
+ }
122
+ catch {
123
+ return null;
124
+ }
125
+ }
126
+ async requireExists(name) {
127
+ const exists = await this.exists(name);
128
+ if (!exists) {
129
+ throw new Error(`Instance "${name.toString()}" not found`);
130
+ }
131
+ }
132
+ async requireNotExists(name) {
133
+ const exists = await this.exists(name);
134
+ if (exists) {
135
+ throw new Error(`Instance "${name.toString()}" already exists`);
136
+ }
137
+ }
138
+ };
139
+ exports.WslInstanceManagerAdapter = WslInstanceManagerAdapter;
140
+ exports.WslInstanceManagerAdapter = WslInstanceManagerAdapter = __decorate([
141
+ (0, tsyringe_1.injectable)(),
142
+ __param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IWslInstanceNaming)),
143
+ __param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IWslInstanceLifecycle)),
144
+ __param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IWslInstanceInspection)),
145
+ __param(3, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.WslConfigService)),
146
+ __param(4, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.ScriptExecutorService)),
147
+ __param(5, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IExecutionEnvironmentFactory)),
148
+ __metadata("design:paramtypes", [Object, Object, Object, Object, Object, Object])
149
+ ], WslInstanceManagerAdapter);
150
+ //# sourceMappingURL=wsl-instance-manager.adapter.js.map