@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.
- package/LICENSE +40 -0
- package/README.md +444 -0
- package/THIRD-PARTY-NOTICES.txt +894 -0
- package/dist/application/dtos/index.js +24 -0
- package/dist/application/dtos/request/delete-instance.request.dto.js +3 -0
- package/dist/application/dtos/request/get-config.request.dto.js +3 -0
- package/dist/application/dtos/request/get-credentials.request.dto.js +3 -0
- package/dist/application/dtos/request/index.js +27 -0
- package/dist/application/dtos/request/install-instance.request.dto.js +3 -0
- package/dist/application/dtos/request/list-charts.request.dto.js +3 -0
- package/dist/application/dtos/request/set-config.request.dto.js +16 -0
- package/dist/application/dtos/request/setup-environment.request.dto.js +16 -0
- package/dist/application/dtos/request/show-logs.request.dto.js +19 -0
- package/dist/application/dtos/request/start-instance.request.dto.js +3 -0
- package/dist/application/dtos/request/stop-instance.request.dto.js +3 -0
- package/dist/application/dtos/response/credentials.response.dto.js +3 -0
- package/dist/application/dtos/response/delete-instance.response.dto.js +3 -0
- package/dist/application/dtos/response/index.js +26 -0
- package/dist/application/dtos/response/install-instance.response.dto.js +3 -0
- package/dist/application/dtos/response/instance-list.response.dto.js +3 -0
- package/dist/application/dtos/response/instance-status.response.dto.js +3 -0
- package/dist/application/dtos/response/setup-result.response.dto.js +3 -0
- package/dist/application/dtos/response/show-logs.response.dto.js +3 -0
- package/dist/application/dtos/response/start-instance.response.dto.js +3 -0
- package/dist/application/dtos/response/stop-instance.response.dto.js +3 -0
- package/dist/application/index.js +25 -0
- package/dist/application/interfaces/index.js +24 -0
- package/dist/application/interfaces/use-case.interface.js +3 -0
- package/dist/application/use-cases/config/get-config.use-case.js +66 -0
- package/dist/application/use-cases/config/set-config.use-case.js +49 -0
- package/dist/application/use-cases/credentials/get-credentials.use-case.js +57 -0
- package/dist/application/use-cases/index.js +28 -0
- package/dist/application/use-cases/instance/delete-instance.use-case.js +81 -0
- package/dist/application/use-cases/instance/index.js +23 -0
- package/dist/application/use-cases/instance/install-instance.use-case.js +424 -0
- package/dist/application/use-cases/instance/list-charts.use-case.js +43 -0
- package/dist/application/use-cases/instance/list-instances.use-case.js +62 -0
- package/dist/application/use-cases/instance/start-instance.use-case.js +154 -0
- package/dist/application/use-cases/instance/stop-instance.use-case.js +55 -0
- package/dist/application/use-cases/logs/show-logs.use-case.js +66 -0
- package/dist/application/use-cases/setup/setup-environment.use-case.js +53 -0
- package/dist/cli.js +286 -0
- package/dist/constants/config-defaults.js +23 -0
- package/dist/constants/defaults.js +89 -0
- package/dist/constants/deployment.js +39 -0
- package/dist/constants/environments.js +93 -0
- package/dist/constants/index.js +53 -0
- package/dist/constants/oci-artifacts.js +25 -0
- package/dist/constants/paths.js +92 -0
- package/dist/constants/timeouts.js +60 -0
- package/dist/di/container.js +34 -0
- package/dist/di/index.js +22 -0
- package/dist/di/modules/application.module.js +54 -0
- package/dist/di/modules/infrastructure.module.js +206 -0
- package/dist/di/modules/interceptor.module.js +68 -0
- package/dist/di/modules/presentation.module.js +31 -0
- package/dist/di/tokens.js +149 -0
- package/dist/domain/decorators/sensitive.decorator.js +39 -0
- package/dist/domain/entities/credentials-resolver.entity.js +127 -0
- package/dist/domain/entities/credentials.entity.js +65 -0
- package/dist/domain/entities/delete-instance-validation.entity.js +100 -0
- package/dist/domain/entities/deployment-parameters.entity.js +120 -0
- package/dist/domain/entities/environment-validation.entity.js +125 -0
- package/dist/domain/entities/index.js +29 -0
- package/dist/domain/entities/instance-lifecycle-state.entity.js +100 -0
- package/dist/domain/entities/instance-list-aggregator.entity.js +104 -0
- package/dist/domain/entities/instance-metadata.entity.js +86 -0
- package/dist/domain/entities/instance-status.entity.js +79 -0
- package/dist/domain/entities/instance.entity.js +128 -0
- package/dist/domain/entities/log-filter.entity.js +141 -0
- package/dist/domain/index.js +29 -0
- package/dist/domain/interfaces/safe-loggable.interface.js +3 -0
- package/dist/domain/ports/app-config.port.js +3 -0
- package/dist/domain/ports/base-image.port.js +3 -0
- package/dist/domain/ports/chart-version.port.js +3 -0
- package/dist/domain/ports/correlation-id.port.js +3 -0
- package/dist/domain/ports/credentials.port.js +3 -0
- package/dist/domain/ports/deployment.port.js +3 -0
- package/dist/domain/ports/error-handler.port.js +3 -0
- package/dist/domain/ports/index.js +46 -0
- package/dist/domain/ports/instance-manager.port.js +3 -0
- package/dist/domain/ports/instance-metadata.port.js +8 -0
- package/dist/domain/ports/instance-storage.port.js +3 -0
- package/dist/domain/ports/k8s-deployer.port.js +3 -0
- package/dist/domain/ports/logger.port.js +14 -0
- package/dist/domain/ports/output.port.js +3 -0
- package/dist/domain/ports/runtime-environment.port.js +6 -0
- package/dist/domain/ports/user-interaction.port.js +9 -0
- package/dist/domain/ports/user-settings.port.js +3 -0
- package/dist/domain/types/index.js +22 -0
- package/dist/domain/types/logger.types.js +29 -0
- package/dist/domain/types/validation.types.js +9 -0
- package/dist/domain/value-objects/acr-credentials.value-object.js +92 -0
- package/dist/domain/value-objects/chart-version.value-object.js +124 -0
- package/dist/domain/value-objects/config-log-level.value-object.js +84 -0
- package/dist/domain/value-objects/connection-info.value-object.js +65 -0
- package/dist/domain/value-objects/index.js +25 -0
- package/dist/domain/value-objects/instance-name.value-object.js +91 -0
- package/dist/domain/value-objects/jwt-key.value-object.js +97 -0
- package/dist/domain/value-objects/mssql-password.value-object.js +140 -0
- package/dist/domain/value-objects/rsa-key-pair.value-object.js +181 -0
- package/dist/index.js +6 -0
- package/dist/infrastructure/config/app-config.interface.js +3 -0
- package/dist/infrastructure/config/app-config.service.js +280 -0
- package/dist/infrastructure/config/config-validator.js +31 -0
- package/dist/infrastructure/config/crypto.service.js +125 -0
- package/dist/infrastructure/deployment/deployment.adapter.js +118 -0
- package/dist/infrastructure/deployment/interfaces/acr-credential-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/app-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/helm-registry.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/infra-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/k8s-job-runner.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-database-init.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-helm-deployment.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-storage.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-user-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/oci-artifact.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/secret-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/service-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/version-compatibility.interface.js +3 -0
- package/dist/infrastructure/deployment/services/acr-credential-manager.service.js +144 -0
- package/dist/infrastructure/deployment/services/app-manager.service.js +193 -0
- package/dist/infrastructure/deployment/services/base-helm-deployment.service.js +163 -0
- package/dist/infrastructure/deployment/services/helm-registry.service.js +126 -0
- package/dist/infrastructure/deployment/services/infra-manager.service.js +130 -0
- package/dist/infrastructure/deployment/services/k8s-job-runner.service.js +194 -0
- package/dist/infrastructure/deployment/services/mssql-database-init.service.js +139 -0
- package/dist/infrastructure/deployment/services/mssql-helm-deployment.service.js +100 -0
- package/dist/infrastructure/deployment/services/mssql-storage.service.js +54 -0
- package/dist/infrastructure/deployment/services/mssql-user-manager.service.js +66 -0
- package/dist/infrastructure/deployment/services/oci-artifact.service.js +289 -0
- package/dist/infrastructure/deployment/services/secret-manager.service.js +179 -0
- package/dist/infrastructure/deployment/services/service-manager.service.js +82 -0
- package/dist/infrastructure/deployment/services/version-compatibility.service.js +291 -0
- package/dist/infrastructure/environment/interfaces/hardware-info.interface.js +3 -0
- package/dist/infrastructure/environment/interfaces/network-checker.interface.js +3 -0
- package/dist/infrastructure/environment/services/hardware-info.service.js +135 -0
- package/dist/infrastructure/environment/services/network-checker.service.js +142 -0
- package/dist/infrastructure/environment/windows-environment.adapter.js +162 -0
- package/dist/infrastructure/errors/app-error.js +73 -0
- package/dist/infrastructure/errors/error-handler.interface.js +3 -0
- package/dist/infrastructure/errors/error-handler.js +218 -0
- package/dist/infrastructure/errors/exit-codes.js +27 -0
- package/dist/infrastructure/errors/index.js +25 -0
- package/dist/infrastructure/execution/builders/base-command.builder.js +122 -0
- package/dist/infrastructure/execution/builders/host-command.builder.js +58 -0
- package/dist/infrastructure/execution/builders/windows-host-command.builder.js +50 -0
- package/dist/infrastructure/execution/builders/wsl-command.builder.js +29 -0
- package/dist/infrastructure/execution/command-builder.js +252 -0
- package/dist/infrastructure/execution/command-executor.service.js +230 -0
- package/dist/infrastructure/execution/environments/wsl-execution.environment.js +70 -0
- package/dist/infrastructure/execution/execution-environment.factory.js +53 -0
- package/dist/infrastructure/execution/index.js +25 -0
- package/dist/infrastructure/execution/interfaces/command-builder.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/command-executor.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/execution-environment-factory.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/execution-environment.interface.js +7 -0
- package/dist/infrastructure/execution/interfaces/host-command-builder.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/index.js +23 -0
- package/dist/infrastructure/execution/interfaces/script-executor.interface.js +3 -0
- package/dist/infrastructure/execution/script-executor.service.js +171 -0
- package/dist/infrastructure/http/http-client.service.js +176 -0
- package/dist/infrastructure/http/index.js +18 -0
- package/dist/infrastructure/http/interfaces/http-client.interface.js +3 -0
- package/dist/infrastructure/interceptors/index.js +8 -0
- package/dist/infrastructure/interceptors/interceptor.factory.js +44 -0
- package/dist/infrastructure/interceptors/interceptor.interface.js +3 -0
- package/dist/infrastructure/interceptors/logging.interceptor.js +171 -0
- package/dist/infrastructure/logger/correlation-id.adapter.js +68 -0
- package/dist/infrastructure/logger/index.js +23 -0
- package/dist/infrastructure/logger/interfaces/index.js +22 -0
- package/dist/infrastructure/logger/interfaces/log-reader.repository.interface.js +7 -0
- package/dist/infrastructure/logger/interfaces/log-writer.repository.interface.js +7 -0
- package/dist/infrastructure/logger/logger.adapter.js +274 -0
- package/dist/infrastructure/logger/services/file-log-reader.repository.js +148 -0
- package/dist/infrastructure/logger/services/file-log-writer.repository.js +307 -0
- package/dist/infrastructure/logger/services/index.js +22 -0
- package/dist/infrastructure/persistence/index.js +25 -0
- package/dist/infrastructure/persistence/instance-metadata.adapter.js +100 -0
- package/dist/infrastructure/persistence/instance-storage.adapter.js +64 -0
- package/dist/infrastructure/persistence/interfaces/config.repository.interface.js +3 -0
- package/dist/infrastructure/persistence/interfaces/index.js +22 -0
- package/dist/infrastructure/persistence/interfaces/instance.repository.interface.js +3 -0
- package/dist/infrastructure/persistence/services/file-system-config.repository.js +168 -0
- package/dist/infrastructure/persistence/services/file-system-instance.repository.js +170 -0
- package/dist/infrastructure/persistence/services/index.js +22 -0
- package/dist/infrastructure/persistence/user-settings.adapter.js +55 -0
- package/dist/infrastructure/platform-detector.js +71 -0
- package/dist/infrastructure/platforms/windows/interfaces/microk8s.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/rootfs-manager.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/windows-features.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/windows-info.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-config.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-info.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-inspection.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-lifecycle.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-naming.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-manager.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-resources.interface.js +8 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-updater.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wslconfig-parser.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/parsers/wsl-version.parser.js +133 -0
- package/dist/infrastructure/platforms/windows/services/microk8s.service.js +168 -0
- package/dist/infrastructure/platforms/windows/services/rootfs-manager.service.js +336 -0
- package/dist/infrastructure/platforms/windows/services/windows-features.service.js +191 -0
- package/dist/infrastructure/platforms/windows/services/windows-info.service.js +138 -0
- package/dist/infrastructure/platforms/windows/services/wsl-config.service.js +171 -0
- package/dist/infrastructure/platforms/windows/services/wsl-info.service.js +226 -0
- package/dist/infrastructure/platforms/windows/services/wsl-instance-inspection.service.js +325 -0
- package/dist/infrastructure/platforms/windows/services/wsl-instance-lifecycle.service.js +442 -0
- package/dist/infrastructure/platforms/windows/services/wsl-instance-naming.service.js +93 -0
- package/dist/infrastructure/platforms/windows/services/wsl-updater.service.js +273 -0
- package/dist/infrastructure/platforms/windows/services/wslconfig-parser.service.js +222 -0
- package/dist/infrastructure/platforms/windows/wsl-base-image.adapter.js +41 -0
- package/dist/infrastructure/platforms/windows/wsl-instance-manager.adapter.js +150 -0
- package/dist/infrastructure/utils/error-formatter.util.js +29 -0
- package/dist/infrastructure/utils/file-operations.util.js +201 -0
- package/dist/infrastructure/utils/input-validator.util.js +152 -0
- package/dist/infrastructure/utils/retry.util.js +98 -0
- package/dist/presentation/controllers/config.controller.js +146 -0
- package/dist/presentation/controllers/credentials.controller.js +105 -0
- package/dist/presentation/controllers/index.js +25 -0
- package/dist/presentation/controllers/instance.controller.js +363 -0
- package/dist/presentation/controllers/logs.controller.js +103 -0
- package/dist/presentation/controllers/setup.controller.js +175 -0
- package/dist/presentation/interfaces/cli-options.interface.js +8 -0
- package/dist/presentation/prompts/acr-credentials.prompt.js +76 -0
- package/dist/presentation/prompts/index.js +21 -0
- package/dist/presentation/ui/cli-progress.service.js +193 -0
- package/dist/presentation/ui/constants/output-symbols.js +42 -0
- package/dist/presentation/ui/index.js +27 -0
- package/dist/presentation/ui/interaction.service.js +276 -0
- package/dist/presentation/ui/interfaces/cli-progress.interface.js +9 -0
- package/dist/presentation/ui/interfaces/output-formatter.interface.js +23 -0
- package/dist/presentation/ui/log-level.enum.js +66 -0
- package/dist/presentation/ui/output-builder.service.js +378 -0
- package/dist/presentation/ui/output-formatter.service.js +393 -0
- package/package.json +65 -0
|
@@ -0,0 +1,154 @@
|
|
|
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.StartInstanceUseCase = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const tokens_1 = require("../../../di/tokens");
|
|
18
|
+
const instance_name_value_object_1 = require("../../../domain/value-objects/instance-name.value-object");
|
|
19
|
+
const connection_info_value_object_1 = require("../../../domain/value-objects/connection-info.value-object");
|
|
20
|
+
const instance_lifecycle_state_entity_1 = require("../../../domain/entities/instance-lifecycle-state.entity");
|
|
21
|
+
const app_error_1 = require("../../../infrastructure/errors/app-error");
|
|
22
|
+
const exit_codes_1 = require("../../../infrastructure/errors/exit-codes");
|
|
23
|
+
/**
|
|
24
|
+
* 啟動實例 Use Case
|
|
25
|
+
*/
|
|
26
|
+
let StartInstanceUseCase = class StartInstanceUseCase {
|
|
27
|
+
constructor(instanceManager) {
|
|
28
|
+
this.instanceManager = instanceManager;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 啟動實例
|
|
32
|
+
* @param request - 啟動請求
|
|
33
|
+
* @param output - 輸出介面
|
|
34
|
+
* @returns 啟動結果與連線資訊
|
|
35
|
+
*/
|
|
36
|
+
async execute(request, output) {
|
|
37
|
+
const { name, waitForReady = true } = request;
|
|
38
|
+
const instanceName = instance_name_value_object_1.InstanceName.create(name);
|
|
39
|
+
// 驗證實例存在
|
|
40
|
+
await this.instanceManager.requireExists(instanceName);
|
|
41
|
+
// 檢查是否有其他實例正在運行
|
|
42
|
+
await this.ensureNoOtherRunningInstances(instanceName);
|
|
43
|
+
// 取得生命週期狀態
|
|
44
|
+
// 重要:必須先檢查 WSL 狀態,再檢查 MicroK8s 狀態
|
|
45
|
+
// 因為 isMicroK8sRunning 會執行 wsl -d xxx -- ... 命令,這會觸發 WSL 自動啟動
|
|
46
|
+
const lifecycleState = await this.getLifecycleState(instanceName);
|
|
47
|
+
// 若已完全運行,直接返回連線資訊
|
|
48
|
+
if (lifecycleState.isFullyRunning) {
|
|
49
|
+
const connectionInfo = await this.getConnectionInfo(instanceName);
|
|
50
|
+
return {
|
|
51
|
+
success: true,
|
|
52
|
+
instanceName: instanceName.fullName,
|
|
53
|
+
alreadyRunning: true,
|
|
54
|
+
podsReady: true,
|
|
55
|
+
connectionInfo,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// 啟動實例 (WSL + MicroK8s)
|
|
59
|
+
await this.instanceManager.start(instanceName, output);
|
|
60
|
+
// 等待 Pod 就緒
|
|
61
|
+
let podsReady = false;
|
|
62
|
+
if (waitForReady) {
|
|
63
|
+
output?.item('arrow', 'Waiting for all pods to be ready...').flush();
|
|
64
|
+
podsReady = await this.instanceManager.waitForPodsReady(instanceName, 5 * 60 * 1000);
|
|
65
|
+
if (podsReady) {
|
|
66
|
+
output?.success('All pods are ready').flush();
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
output?.warning('Some pods may not be ready yet').flush();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// 取得連線資訊
|
|
73
|
+
const connectionInfo = await this.getConnectionInfo(instanceName);
|
|
74
|
+
return {
|
|
75
|
+
success: true,
|
|
76
|
+
instanceName: instanceName.fullName,
|
|
77
|
+
alreadyRunning: false,
|
|
78
|
+
podsReady,
|
|
79
|
+
connectionInfo,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 取得實例生命週期狀態
|
|
84
|
+
*/
|
|
85
|
+
async getLifecycleState(instanceName) {
|
|
86
|
+
const status = await this.instanceManager.getStatus(instanceName);
|
|
87
|
+
// 若 WSL 未運行,直接返回停止狀態
|
|
88
|
+
if (!status.isRunning) {
|
|
89
|
+
return instance_lifecycle_state_entity_1.InstanceLifecycleState.stopped();
|
|
90
|
+
}
|
|
91
|
+
// WSL 運行中,檢查 K8s 狀態
|
|
92
|
+
const k8sRunning = await this.instanceManager.isMicroK8sRunning(instanceName);
|
|
93
|
+
return instance_lifecycle_state_entity_1.InstanceLifecycleState.fromStatus(status, k8sRunning);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 列出其他運行中的 UOFX 實例
|
|
97
|
+
* @param excludeName - 要排除的實例名稱
|
|
98
|
+
* @returns 其他運行中實例的名稱陣列
|
|
99
|
+
*/
|
|
100
|
+
async listOtherRunningInstances(excludeName) {
|
|
101
|
+
const instanceName = instance_name_value_object_1.InstanceName.create(excludeName);
|
|
102
|
+
const runningInstances = await this.instanceManager.listRunningInstances();
|
|
103
|
+
return runningInstances.filter(name => name !== instanceName.fullName);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 停止指定實例
|
|
107
|
+
* @param name - 要停止的實例名稱(完整名稱)
|
|
108
|
+
* @param output - 輸出介面
|
|
109
|
+
*/
|
|
110
|
+
async stopInstance(fullName, output) {
|
|
111
|
+
// 直接使用完整名稱建立 InstanceName
|
|
112
|
+
const instanceName = instance_name_value_object_1.InstanceName.createFromFullName(fullName);
|
|
113
|
+
await this.instanceManager.stop(instanceName, true, output);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 取得連線資訊
|
|
117
|
+
*/
|
|
118
|
+
async getConnectionInfo(instanceName) {
|
|
119
|
+
const instanceIp = await this.instanceManager.getInstanceIP(instanceName);
|
|
120
|
+
const connectionInfo = connection_info_value_object_1.ConnectionInfo.create(instanceIp);
|
|
121
|
+
return connectionInfo.toDto();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 確保沒有其他實例正在運行
|
|
125
|
+
* 同時只能有一個實例運行
|
|
126
|
+
* @param currentInstance - 當前要啟動的實例
|
|
127
|
+
* @throws AppError 若有其他運行中的實例
|
|
128
|
+
*/
|
|
129
|
+
async ensureNoOtherRunningInstances(currentInstance) {
|
|
130
|
+
const otherRunning = await this.listOtherRunningInstances(currentInstance.toString());
|
|
131
|
+
if (otherRunning.length > 0) {
|
|
132
|
+
// 將全名轉換為顯示名稱(移除 uofx- 前綴)
|
|
133
|
+
const displayNames = otherRunning.map(name => name.replace('uofx-', ''));
|
|
134
|
+
const instanceList = displayNames
|
|
135
|
+
.map(name => ` - ${name}`)
|
|
136
|
+
.join('\n');
|
|
137
|
+
const stopCommand = displayNames.length === 1
|
|
138
|
+
? `uofx env stop --name ${displayNames[0]}`
|
|
139
|
+
: 'uofx env stop --name <instance-name>';
|
|
140
|
+
throw new app_error_1.AppError(`Cannot start: another instance is already running:\n${instanceList}`, {
|
|
141
|
+
exitCode: exit_codes_1.EXIT_CODES.BUSINESS_ERROR,
|
|
142
|
+
solution: `Only one instance can run at a time.\nRun: ${stopCommand}`,
|
|
143
|
+
context: { otherRunning }
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
exports.StartInstanceUseCase = StartInstanceUseCase;
|
|
149
|
+
exports.StartInstanceUseCase = StartInstanceUseCase = __decorate([
|
|
150
|
+
(0, tsyringe_1.injectable)(),
|
|
151
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.IInstanceManagerPort)),
|
|
152
|
+
__metadata("design:paramtypes", [Object])
|
|
153
|
+
], StartInstanceUseCase);
|
|
154
|
+
//# sourceMappingURL=start-instance.use-case.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
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.StopInstanceUseCase = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const tokens_1 = require("../../../di/tokens");
|
|
18
|
+
const instance_name_value_object_1 = require("../../../domain/value-objects/instance-name.value-object");
|
|
19
|
+
/**
|
|
20
|
+
* 停止實例 Use Case
|
|
21
|
+
*/
|
|
22
|
+
let StopInstanceUseCase = class StopInstanceUseCase {
|
|
23
|
+
constructor(instanceManager) {
|
|
24
|
+
this.instanceManager = instanceManager;
|
|
25
|
+
}
|
|
26
|
+
async execute(request, output) {
|
|
27
|
+
const { name, force = false } = request;
|
|
28
|
+
const instanceName = instance_name_value_object_1.InstanceName.create(name);
|
|
29
|
+
// 驗證實例存在
|
|
30
|
+
await this.instanceManager.requireExists(instanceName);
|
|
31
|
+
// 檢查實例是否已停止
|
|
32
|
+
const status = await this.instanceManager.getStatus(instanceName);
|
|
33
|
+
if (!status.isRunning) {
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
alreadyStopped: true,
|
|
37
|
+
instanceName: instanceName.fullName,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// 停止實例
|
|
41
|
+
await this.instanceManager.stop(instanceName, force, output);
|
|
42
|
+
return {
|
|
43
|
+
success: true,
|
|
44
|
+
alreadyStopped: false,
|
|
45
|
+
instanceName: instanceName.fullName,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
exports.StopInstanceUseCase = StopInstanceUseCase;
|
|
50
|
+
exports.StopInstanceUseCase = StopInstanceUseCase = __decorate([
|
|
51
|
+
(0, tsyringe_1.injectable)(),
|
|
52
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.IInstanceManagerPort)),
|
|
53
|
+
__metadata("design:paramtypes", [Object])
|
|
54
|
+
], StopInstanceUseCase);
|
|
55
|
+
//# sourceMappingURL=stop-instance.use-case.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
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.ShowLogsUseCase = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const tokens_1 = require("../../../di/tokens");
|
|
18
|
+
const log_filter_entity_1 = require("../../../domain/entities/log-filter.entity");
|
|
19
|
+
/**
|
|
20
|
+
* 顯示日誌 Use Case
|
|
21
|
+
*
|
|
22
|
+
* 讀取並過濾應用程式日誌
|
|
23
|
+
*/
|
|
24
|
+
let ShowLogsUseCase = class ShowLogsUseCase {
|
|
25
|
+
constructor(loggerPort) {
|
|
26
|
+
this.loggerPort = loggerPort;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 執行顯示日誌
|
|
30
|
+
* @param request - 請求參數
|
|
31
|
+
*/
|
|
32
|
+
async execute(request) {
|
|
33
|
+
// 讀取日誌
|
|
34
|
+
const entries = await this.loggerPort.readLogs(request.lines || 50);
|
|
35
|
+
// 建立過濾器並過濾日誌
|
|
36
|
+
const filter = log_filter_entity_1.LogFilter.create({
|
|
37
|
+
level: request.level,
|
|
38
|
+
correlation: request.correlation,
|
|
39
|
+
command: request.command,
|
|
40
|
+
commandGroup: request.commandGroup,
|
|
41
|
+
since: request.since,
|
|
42
|
+
});
|
|
43
|
+
const filtered = filter.filter(entries);
|
|
44
|
+
// 轉換為 DTO
|
|
45
|
+
const logEntries = filtered.map(entry => ({
|
|
46
|
+
timestamp: new Date(entry.timestamp).toISOString(),
|
|
47
|
+
level: entry.levelName,
|
|
48
|
+
message: entry.message,
|
|
49
|
+
correlationId: entry.correlationId,
|
|
50
|
+
command: entry.context?.command,
|
|
51
|
+
errorStack: entry.error?.stack,
|
|
52
|
+
}));
|
|
53
|
+
return {
|
|
54
|
+
entries: logEntries,
|
|
55
|
+
total: logEntries.length,
|
|
56
|
+
isFollowing: request.follow || false,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.ShowLogsUseCase = ShowLogsUseCase;
|
|
61
|
+
exports.ShowLogsUseCase = ShowLogsUseCase = __decorate([
|
|
62
|
+
(0, tsyringe_1.injectable)(),
|
|
63
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.ILoggerPort)),
|
|
64
|
+
__metadata("design:paramtypes", [Object])
|
|
65
|
+
], ShowLogsUseCase);
|
|
66
|
+
//# sourceMappingURL=show-logs.use-case.js.map
|
|
@@ -0,0 +1,53 @@
|
|
|
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.SetupEnvironmentUseCase = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const tokens_1 = require("../../../di/tokens");
|
|
18
|
+
const environment_validation_entity_1 = require("../../../domain/entities/environment-validation.entity");
|
|
19
|
+
/**
|
|
20
|
+
* 設置環境 Use Case
|
|
21
|
+
*
|
|
22
|
+
* 檢查系統環境是否符合 UOFX 運行需求
|
|
23
|
+
*/
|
|
24
|
+
let SetupEnvironmentUseCase = class SetupEnvironmentUseCase {
|
|
25
|
+
constructor(runtimeEnv) {
|
|
26
|
+
this.runtimeEnv = runtimeEnv;
|
|
27
|
+
}
|
|
28
|
+
async execute() {
|
|
29
|
+
// 並行執行所有檢查
|
|
30
|
+
const [osInfo, runtimeInfo, systemResources, networkStatus] = await Promise.all([
|
|
31
|
+
this.runtimeEnv.getOsInfo(),
|
|
32
|
+
this.runtimeEnv.getRuntimeInfo(),
|
|
33
|
+
this.runtimeEnv.getSystemResources(),
|
|
34
|
+
this.runtimeEnv.checkNetworkConnectivity(),
|
|
35
|
+
]);
|
|
36
|
+
// 使用 Entity 進行驗證
|
|
37
|
+
const validation = environment_validation_entity_1.EnvironmentValidation.create(osInfo, runtimeInfo, systemResources, networkStatus);
|
|
38
|
+
return {
|
|
39
|
+
osInfo,
|
|
40
|
+
runtimeInfo,
|
|
41
|
+
systemResources,
|
|
42
|
+
networkStatus,
|
|
43
|
+
allChecksPassed: validation.allChecksPassed,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
exports.SetupEnvironmentUseCase = SetupEnvironmentUseCase;
|
|
48
|
+
exports.SetupEnvironmentUseCase = SetupEnvironmentUseCase = __decorate([
|
|
49
|
+
(0, tsyringe_1.injectable)(),
|
|
50
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.IRuntimeEnvironmentPort)),
|
|
51
|
+
__metadata("design:paramtypes", [Object])
|
|
52
|
+
], SetupEnvironmentUseCase);
|
|
53
|
+
//# sourceMappingURL=setup-environment.use-case.js.map
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* UOFX CLI - Commander.js 主程式
|
|
4
|
+
* 註冊所有指令並處理 CLI 路由
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.createProgram = createProgram;
|
|
41
|
+
exports.run = run;
|
|
42
|
+
const commander_1 = require("commander");
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const di_1 = require("./di");
|
|
46
|
+
const tokens_1 = require("./di/tokens");
|
|
47
|
+
const output_builder_service_1 = require("./presentation/ui/output-builder.service");
|
|
48
|
+
const log_level_enum_1 = require("./presentation/ui/log-level.enum");
|
|
49
|
+
const logger_types_1 = require("./domain/types/logger.types");
|
|
50
|
+
// 載入 package.json 以獲取版本資訊
|
|
51
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
52
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
53
|
+
function createProgram() {
|
|
54
|
+
// 設定全域錯誤處理器以處理未被捕獲的錯誤
|
|
55
|
+
// 注意:必須在 DI 容器完全初始化後才能解析
|
|
56
|
+
di_1.container.resolve(tokens_1.TOKENS.IErrorHandlerPort).setupGlobalHandlers();
|
|
57
|
+
// 確保 CLI 啟動時使用者設定目錄存在
|
|
58
|
+
di_1.container.resolve(tokens_1.TOKENS.IAppConfigPort).ensureUserConfigDir();
|
|
59
|
+
const program = new commander_1.Command();
|
|
60
|
+
// 從 DI 容器獲取 Controllers
|
|
61
|
+
const instanceController = di_1.container.resolve(tokens_1.TOKENS.InstanceController);
|
|
62
|
+
const setupController = di_1.container.resolve(tokens_1.TOKENS.SetupController);
|
|
63
|
+
const configController = di_1.container.resolve(tokens_1.TOKENS.ConfigController);
|
|
64
|
+
const logsController = di_1.container.resolve(tokens_1.TOKENS.LogsController);
|
|
65
|
+
const credentialsController = di_1.container.resolve(tokens_1.TOKENS.CredentialsController);
|
|
66
|
+
program
|
|
67
|
+
.name('uofx')
|
|
68
|
+
.description('CLI tool for installing and managing the UOFX development environment on WSL2')
|
|
69
|
+
.version(packageJson.version, '-v, --version', 'display the current version')
|
|
70
|
+
.helpCommand(false);
|
|
71
|
+
// 在指令執行前配置 OutputBuilder 和 AppLogger 的 Hook
|
|
72
|
+
program.hook('preAction', (thisCommand) => {
|
|
73
|
+
const outputBuilder = di_1.container.resolve(output_builder_service_1.OutputBuilder);
|
|
74
|
+
const appConfig = di_1.container.resolve(tokens_1.TOKENS.IAppConfigPort);
|
|
75
|
+
const appLogger = di_1.container.resolve(tokens_1.TOKENS.ILoggerPort);
|
|
76
|
+
const correlationIdService = di_1.container.resolve(tokens_1.TOKENS.ICorrelationIdPort);
|
|
77
|
+
// 只在第一次執行 (根命令) 時設定日誌等級
|
|
78
|
+
if (thisCommand.name() === 'uofx') {
|
|
79
|
+
// 從設定檔載入日誌等級
|
|
80
|
+
const config = appConfig.getConfig();
|
|
81
|
+
// 設定 OutputBuilder 日誌等級
|
|
82
|
+
const outputLevel = (0, log_level_enum_1.parseOutputLogLevel)(config.logLevel);
|
|
83
|
+
if (outputLevel !== undefined) {
|
|
84
|
+
outputBuilder.setLogLevel(outputLevel);
|
|
85
|
+
}
|
|
86
|
+
// 設定 AppLogger 日誌等級
|
|
87
|
+
let loggerLevel;
|
|
88
|
+
switch (config.logLevel) {
|
|
89
|
+
case 'debug':
|
|
90
|
+
loggerLevel = logger_types_1.LogLevel.DEBUG;
|
|
91
|
+
break;
|
|
92
|
+
case 'info':
|
|
93
|
+
loggerLevel = logger_types_1.LogLevel.INFO;
|
|
94
|
+
break;
|
|
95
|
+
case 'error':
|
|
96
|
+
loggerLevel = logger_types_1.LogLevel.ERROR;
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
loggerLevel = logger_types_1.LogLevel.ERROR;
|
|
100
|
+
}
|
|
101
|
+
appLogger.setLogLevel(loggerLevel);
|
|
102
|
+
}
|
|
103
|
+
// 設定日誌執行上下文(命令追蹤)
|
|
104
|
+
// 注意:program.hook('preAction') 只會執行一次(在根命令),所以無法直接獲取子命令
|
|
105
|
+
// 我們需要從 process.argv 解析實際執行的命令
|
|
106
|
+
const argv = process.argv;
|
|
107
|
+
// 解析命令路徑(例如:['node', 'uofx', 'env', 'list'] -> 'env.list')
|
|
108
|
+
const commandParts = [];
|
|
109
|
+
for (let i = 2; i < argv.length; i++) {
|
|
110
|
+
const arg = argv[i];
|
|
111
|
+
// 跳過選項參數
|
|
112
|
+
if (arg.startsWith('-'))
|
|
113
|
+
break;
|
|
114
|
+
// 跳過 uofx 自身
|
|
115
|
+
if (arg === 'uofx' || arg.endsWith('uofx'))
|
|
116
|
+
continue;
|
|
117
|
+
commandParts.push(arg);
|
|
118
|
+
}
|
|
119
|
+
const commandPath = commandParts.join('.');
|
|
120
|
+
if (commandPath) {
|
|
121
|
+
const commandGroup = commandPath.split('.')[0];
|
|
122
|
+
const correlationId = correlationIdService.generate();
|
|
123
|
+
appLogger.setExecutionContext({
|
|
124
|
+
command: commandPath,
|
|
125
|
+
commandGroup: commandGroup,
|
|
126
|
+
correlationId: correlationId,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
// 註冊指令群組
|
|
131
|
+
// ============================================================================
|
|
132
|
+
// CONFIG 指令群組 - 設定管理
|
|
133
|
+
// ============================================================================
|
|
134
|
+
const configCommand = program
|
|
135
|
+
.command('config')
|
|
136
|
+
.description('Manage CLI configuration');
|
|
137
|
+
// config list
|
|
138
|
+
configCommand
|
|
139
|
+
.command('list')
|
|
140
|
+
.description('List all configuration values')
|
|
141
|
+
.option('--format <format>', 'Output format: json or table', 'table')
|
|
142
|
+
.action(async (options) => {
|
|
143
|
+
await configController.list(options.format);
|
|
144
|
+
});
|
|
145
|
+
// config set
|
|
146
|
+
configCommand
|
|
147
|
+
.command('set')
|
|
148
|
+
.description('Set configuration values using option flags')
|
|
149
|
+
.option('--log-level <level>', 'Set log level (debug or info or error)')
|
|
150
|
+
.option('--acr.name <name>', 'Set ACR name')
|
|
151
|
+
.option('--acr.account <account>', 'Set ACR account')
|
|
152
|
+
.option('--acr.password <password>', 'Set ACR password')
|
|
153
|
+
.action(async (options) => {
|
|
154
|
+
await configController.set(options);
|
|
155
|
+
});
|
|
156
|
+
// ============================================================================
|
|
157
|
+
// ENV 指令群組 - 環境管理
|
|
158
|
+
// ============================================================================
|
|
159
|
+
const envCommand = program
|
|
160
|
+
.command('env')
|
|
161
|
+
.description('Manage UOFX development environments');
|
|
162
|
+
// env delete
|
|
163
|
+
envCommand
|
|
164
|
+
.command('delete')
|
|
165
|
+
.description('Delete a UOFX instance')
|
|
166
|
+
.requiredOption('--name <name>', 'Instance name to delete')
|
|
167
|
+
.option('-f, --force', 'Skip confirmation prompt')
|
|
168
|
+
.action(async (options) => {
|
|
169
|
+
await instanceController.delete(options.name, options.force || false);
|
|
170
|
+
});
|
|
171
|
+
// env install
|
|
172
|
+
envCommand
|
|
173
|
+
.command('install')
|
|
174
|
+
.description('Install and deploy all services')
|
|
175
|
+
.option('--name <name>', 'Instance name to install', 'dev')
|
|
176
|
+
.option('--chart-version <version>', 'Helm chart version')
|
|
177
|
+
// .option('--pull-secret <file>', 'ACR pull secret file path')
|
|
178
|
+
.action(async (options) => {
|
|
179
|
+
await instanceController.install(options);
|
|
180
|
+
});
|
|
181
|
+
// env list - 統一的查詢入口
|
|
182
|
+
envCommand
|
|
183
|
+
.command('list [type]')
|
|
184
|
+
.description('Display information about instances, credentials, or compatibility')
|
|
185
|
+
.option('--name <name>', 'Instance name (required for credentials type)')
|
|
186
|
+
.option('--reveal', 'Show full credentials (use with credentials type)')
|
|
187
|
+
.addHelpText('after', `
|
|
188
|
+
Types:
|
|
189
|
+
instances List all UOFX instances (default)
|
|
190
|
+
charts List compatible chart versions
|
|
191
|
+
credentials Display instance credentials (requires --name)
|
|
192
|
+
|
|
193
|
+
Examples:
|
|
194
|
+
$ uofx env list
|
|
195
|
+
$ uofx env list instances
|
|
196
|
+
$ uofx env list charts
|
|
197
|
+
$ uofx env list credentials --name dev
|
|
198
|
+
$ uofx env list credentials --name dev --reveal
|
|
199
|
+
`)
|
|
200
|
+
.action(async (type = 'instances', options) => {
|
|
201
|
+
if (type === 'credentials') {
|
|
202
|
+
if (!options.name) {
|
|
203
|
+
console.error('Error: --name is required for credentials type');
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
await credentialsController.get(options.name, options.reveal || false);
|
|
207
|
+
}
|
|
208
|
+
else if (type === 'charts') {
|
|
209
|
+
await instanceController.listCharts();
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
await instanceController.list();
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
// env setup
|
|
216
|
+
envCommand
|
|
217
|
+
.command('setup')
|
|
218
|
+
.description('Check and validate system environment')
|
|
219
|
+
.action(async (options) => {
|
|
220
|
+
await setupController.setup(options);
|
|
221
|
+
});
|
|
222
|
+
// env start
|
|
223
|
+
envCommand
|
|
224
|
+
.command('start')
|
|
225
|
+
.description('Start a UOFX instance')
|
|
226
|
+
.requiredOption('--name <name>', 'Instance name to start')
|
|
227
|
+
.action(async (options) => {
|
|
228
|
+
await instanceController.start(options.name);
|
|
229
|
+
});
|
|
230
|
+
// env stop
|
|
231
|
+
envCommand
|
|
232
|
+
.command('stop')
|
|
233
|
+
.description('Stop a UOFX instance')
|
|
234
|
+
.requiredOption('--name <name>', 'Instance name to stop')
|
|
235
|
+
.action(async (options) => {
|
|
236
|
+
await instanceController.stop(options.name, { force: options.force || false });
|
|
237
|
+
});
|
|
238
|
+
// ============================================================================
|
|
239
|
+
// LOGS 指令 - 日誌檢視與過濾
|
|
240
|
+
// ============================================================================
|
|
241
|
+
program
|
|
242
|
+
.command('logs')
|
|
243
|
+
.description('View and filter logs')
|
|
244
|
+
.option('--lines <number>', 'Number of lines to show', '50')
|
|
245
|
+
.option('--level <level>', 'Filter by log level (DEBUG, INFO, ERROR)')
|
|
246
|
+
.option('--since <range>', 'Show logs since time range (e.g., 1h, 2d, 30m)')
|
|
247
|
+
.option('--correlation <id>', 'Filter by correlation ID')
|
|
248
|
+
.option('--command <command>', 'Filter by command (e.g., env.install)')
|
|
249
|
+
.option('--command-group <group>', 'Filter by command group (e.g., env)')
|
|
250
|
+
.addHelpText('after', `
|
|
251
|
+
Examples:
|
|
252
|
+
$ uofx logs
|
|
253
|
+
$ uofx logs --level error
|
|
254
|
+
$ uofx logs --since 1h
|
|
255
|
+
$ uofx logs --command env.install
|
|
256
|
+
`)
|
|
257
|
+
.action(async (options) => {
|
|
258
|
+
const parsedOptions = {
|
|
259
|
+
lines: options.lines ? parseInt(options.lines, 10) : 50,
|
|
260
|
+
follow: options.follow,
|
|
261
|
+
level: options.level,
|
|
262
|
+
since: options.since,
|
|
263
|
+
correlation: options.correlation,
|
|
264
|
+
command: options.command,
|
|
265
|
+
commandGroup: options.commandGroup,
|
|
266
|
+
};
|
|
267
|
+
await logsController.show(parsedOptions);
|
|
268
|
+
});
|
|
269
|
+
// 處理未知指令
|
|
270
|
+
program.on('command:*', (operands) => {
|
|
271
|
+
const unknownCommand = operands[0];
|
|
272
|
+
console.error(`\n✗ Error: Unknown command '${unknownCommand}'`);
|
|
273
|
+
console.log('\nAvailable command groups:');
|
|
274
|
+
console.log(' env Manage UOFX development environments');
|
|
275
|
+
console.log(' config Manage CLI configuration');
|
|
276
|
+
console.log(' logs View and filter logs');
|
|
277
|
+
console.log('\nUse "uofx --help" for more information.\n');
|
|
278
|
+
process.exit(1);
|
|
279
|
+
});
|
|
280
|
+
return program;
|
|
281
|
+
}
|
|
282
|
+
function run(argv) {
|
|
283
|
+
const program = createProgram();
|
|
284
|
+
program.parse(argv);
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_TIMEOUTS = exports.DEFAULT_CONFIG_VALUES = void 0;
|
|
4
|
+
exports.DEFAULT_CONFIG_VALUES = {
|
|
5
|
+
INSTANCE_NAME: 'dev',
|
|
6
|
+
NTP_SERVERS: [
|
|
7
|
+
'time.stdtime.gov.tw',
|
|
8
|
+
'clock.stdtime.gov.tw',
|
|
9
|
+
'time.google.com',
|
|
10
|
+
'time.cloudflare.com',
|
|
11
|
+
],
|
|
12
|
+
TIMEOUTS: {
|
|
13
|
+
NETWORK: 30000,
|
|
14
|
+
MICROK8S: 600000,
|
|
15
|
+
PODS: 300000,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
exports.MAX_TIMEOUTS = {
|
|
19
|
+
NETWORK: 300000,
|
|
20
|
+
MICROK8S: 1800000,
|
|
21
|
+
PODS: 1800000,
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=config-defaults.js.map
|