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