@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
|
@@ -16,7 +16,8 @@ exports.K8sJobRunnerService = void 0;
|
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
18
|
const deployment_parameters_entity_1 = require("../../../domain/entities/deployment-parameters.entity");
|
|
19
|
-
const sensitive_decorator_1 = require("
|
|
19
|
+
const sensitive_decorator_1 = require("../../interceptors/decorators/sensitive.decorator");
|
|
20
|
+
const errors_1 = require("../../../domain/errors");
|
|
20
21
|
/**
|
|
21
22
|
* Kubernetes Job 執行服務
|
|
22
23
|
*
|
|
@@ -35,6 +36,13 @@ let K8sJobRunnerService = class K8sJobRunnerService {
|
|
|
35
36
|
*/
|
|
36
37
|
async createImagePullSecret(instanceName, params) {
|
|
37
38
|
const { name: acrName, account: acrAccount, password: acrPassword } = params.acrCredentials;
|
|
39
|
+
// 防禦性驗證:確保 ACR 名稱與帳號僅包含安全字元
|
|
40
|
+
if (!/^[a-zA-Z0-9-]+$/.test(acrName)) {
|
|
41
|
+
throw new errors_1.AppError(`Invalid ACR name: "${acrName}"`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
|
|
42
|
+
}
|
|
43
|
+
if (!/^[a-zA-Z0-9-]+$/.test(acrAccount)) {
|
|
44
|
+
throw new errors_1.AppError(`Invalid ACR account: "${acrAccount}"`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
|
|
45
|
+
}
|
|
38
46
|
const registry = `${acrName}.azurecr.io`;
|
|
39
47
|
const env = this.envFactory.getForInstance(instanceName);
|
|
40
48
|
const builder = env.kubectl('create secret docker-registry')
|
|
@@ -51,7 +59,10 @@ let K8sJobRunnerService = class K8sJobRunnerService {
|
|
|
51
59
|
await deleteBuilder.exec();
|
|
52
60
|
const result = await builder.exec();
|
|
53
61
|
if (result.exitCode !== 0) {
|
|
54
|
-
|
|
62
|
+
this.logger.debug('kubectl create secret failed', { stderr: result.stderr });
|
|
63
|
+
throw new errors_1.AppError('Failed to create image pull secret', {
|
|
64
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
65
|
+
});
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
68
|
/**
|
|
@@ -121,7 +132,10 @@ let K8sJobRunnerService = class K8sJobRunnerService {
|
|
|
121
132
|
.sensitiveStdin(JSON.stringify(jobYaml));
|
|
122
133
|
const applyResult = await applyBuilder.exec();
|
|
123
134
|
if (applyResult.exitCode !== 0) {
|
|
124
|
-
|
|
135
|
+
this.logger.debug(`kubectl apply job failed for ${jobName}`, { stderr: applyResult.stderr });
|
|
136
|
+
throw new errors_1.AppError(`Failed to start job ${jobName}`, {
|
|
137
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
138
|
+
});
|
|
125
139
|
}
|
|
126
140
|
// 等待完成
|
|
127
141
|
const waitBuilder = env.kubectl('wait')
|
|
@@ -136,9 +150,13 @@ let K8sJobRunnerService = class K8sJobRunnerService {
|
|
|
136
150
|
.arg(`job/${jobName}`)
|
|
137
151
|
.arg('-n', 'mssql');
|
|
138
152
|
const logs = await logsBuilder.exec();
|
|
139
|
-
this.logger.error(new Error(`Job ${jobName}
|
|
140
|
-
|
|
141
|
-
|
|
153
|
+
this.logger.error(new Error(`Job ${jobName} failed`), {
|
|
154
|
+
jobName,
|
|
155
|
+
logs: logs.stdout,
|
|
156
|
+
});
|
|
157
|
+
throw new errors_1.AppError(`Job ${jobName} failed or timed out`, {
|
|
158
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
159
|
+
});
|
|
142
160
|
}
|
|
143
161
|
// 清理 Job
|
|
144
162
|
const cleanupBuilder = env.kubectl('delete')
|
|
@@ -16,14 +16,17 @@ exports.MssqlDatabaseInitService = void 0;
|
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
18
|
const paths_1 = require("../../../constants/paths");
|
|
19
|
+
const oci_artifacts_1 = require("../../../constants/oci-artifacts");
|
|
20
|
+
const errors_1 = require("../../../domain/errors");
|
|
19
21
|
/**
|
|
20
22
|
* MSSQL 資料庫初始化服務
|
|
21
23
|
*
|
|
22
24
|
* 負責等待 MSSQL Pod 就緒和建立初始資料庫
|
|
23
25
|
*/
|
|
24
26
|
let MssqlDatabaseInitService = class MssqlDatabaseInitService {
|
|
25
|
-
constructor(envFactory, logger) {
|
|
27
|
+
constructor(envFactory, ociArtifact, logger) {
|
|
26
28
|
this.envFactory = envFactory;
|
|
29
|
+
this.ociArtifact = ociArtifact;
|
|
27
30
|
this.logger = logger;
|
|
28
31
|
}
|
|
29
32
|
/**
|
|
@@ -40,7 +43,10 @@ let MssqlDatabaseInitService = class MssqlDatabaseInitService {
|
|
|
40
43
|
.arg('--timeout=300s');
|
|
41
44
|
const result = await builder.exec();
|
|
42
45
|
if (result.exitCode !== 0) {
|
|
43
|
-
|
|
46
|
+
this.logger.debug('MSSQL Pod not ready', { stderr: result.stderr });
|
|
47
|
+
throw new errors_1.AppError('MSSQL Pod not ready', {
|
|
48
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
49
|
+
});
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
52
|
/**
|
|
@@ -57,7 +63,10 @@ let MssqlDatabaseInitService = class MssqlDatabaseInitService {
|
|
|
57
63
|
.arg('-o', "jsonpath='{.items[0].metadata.name}'");
|
|
58
64
|
const result = await builder.exec();
|
|
59
65
|
if (result.exitCode !== 0 || !result.stdout.trim()) {
|
|
60
|
-
|
|
66
|
+
this.logger.debug('Failed to get MSSQL Pod name', { stderr: result.stderr });
|
|
67
|
+
throw new errors_1.AppError('Failed to get MSSQL Pod name', {
|
|
68
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
69
|
+
});
|
|
61
70
|
}
|
|
62
71
|
return result.stdout.trim();
|
|
63
72
|
}
|
|
@@ -82,9 +91,9 @@ let MssqlDatabaseInitService = class MssqlDatabaseInitService {
|
|
|
82
91
|
.arg(paths_1.LINUX_PATHS.SQLCMD_BIN)
|
|
83
92
|
.arg('-S', 'localhost')
|
|
84
93
|
.arg('-U', 'sa')
|
|
85
|
-
.sensitiveArg('-P',
|
|
94
|
+
.sensitiveArg('-P', saPassword)
|
|
86
95
|
.arg('-C')
|
|
87
|
-
.arg('-Q', '
|
|
96
|
+
.arg('-Q', 'SELECT 1');
|
|
88
97
|
const result = await builder.exec();
|
|
89
98
|
if (result.exitCode === 0) {
|
|
90
99
|
this.logger.debug('[Mssql] SQL Server is ready');
|
|
@@ -95,7 +104,9 @@ let MssqlDatabaseInitService = class MssqlDatabaseInitService {
|
|
|
95
104
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
96
105
|
}
|
|
97
106
|
}
|
|
98
|
-
throw new
|
|
107
|
+
throw new errors_1.AppError('SQL Server failed to start accepting connections after 60 seconds', {
|
|
108
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
109
|
+
});
|
|
99
110
|
}
|
|
100
111
|
/**
|
|
101
112
|
* 建立初始資料庫 (uofx_dev, uofx_search)
|
|
@@ -119,13 +130,65 @@ let MssqlDatabaseInitService = class MssqlDatabaseInitService {
|
|
|
119
130
|
.arg(paths_1.LINUX_PATHS.SQLCMD_BIN)
|
|
120
131
|
.arg('-S', 'localhost')
|
|
121
132
|
.arg('-U', 'sa')
|
|
122
|
-
.sensitiveArg('-P',
|
|
133
|
+
.sensitiveArg('-P', saPassword)
|
|
123
134
|
.arg('-C')
|
|
124
|
-
.arg('-Q', '
|
|
135
|
+
.arg('-Q', 'CREATE DATABASE uofx_dev; CREATE DATABASE uofx_search;');
|
|
125
136
|
this.logger.debug(`[Mssql] Creating databases uofx_dev, uofx_search...`);
|
|
126
137
|
const result = await builder.exec();
|
|
127
138
|
if (result.exitCode !== 0) {
|
|
128
|
-
|
|
139
|
+
this.logger.debug('Failed to create initial databases', { stderr: result.stderr });
|
|
140
|
+
throw new errors_1.AppError('Failed to create initial databases', {
|
|
141
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* 安裝 Northwind 範例資料庫
|
|
147
|
+
* @param instanceName WSL 實例名稱
|
|
148
|
+
* @param saPassword SA 密碼
|
|
149
|
+
* @param acrCredentials ACR 憑證(用於下載 SQL 腳本)
|
|
150
|
+
*/
|
|
151
|
+
async installNorthwindDatabase(instanceName, saPassword, acrCredentials) {
|
|
152
|
+
this.logger.debug('[Mssql] Installing Northwind sample database...');
|
|
153
|
+
const podName = await this.getMssqlPodName(instanceName);
|
|
154
|
+
const env = this.envFactory.getForInstance(instanceName);
|
|
155
|
+
const remoteScriptPath = '/tmp/instnwnd.sql';
|
|
156
|
+
// 1. 建立 Northwind 資料庫
|
|
157
|
+
const createDbBuilder = env.kubectl('exec')
|
|
158
|
+
.arg('-n', 'mssql')
|
|
159
|
+
.arg(podName)
|
|
160
|
+
.arg('--')
|
|
161
|
+
.arg(paths_1.LINUX_PATHS.SQLCMD_BIN)
|
|
162
|
+
.arg('-S', 'localhost')
|
|
163
|
+
.arg('-U', 'sa')
|
|
164
|
+
.sensitiveArg('-P', saPassword)
|
|
165
|
+
.arg('-C')
|
|
166
|
+
.arg('-Q', 'CREATE DATABASE Northwind;');
|
|
167
|
+
const createResult = await createDbBuilder.exec();
|
|
168
|
+
if (createResult.exitCode !== 0) {
|
|
169
|
+
this.logger.debug('Failed to create Northwind database', { stderr: createResult.stderr });
|
|
170
|
+
throw new errors_1.AppError('Failed to create Northwind database', {
|
|
171
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// 2. 從 ACR 下載 SQL 腳本到 WSL /tmp/
|
|
175
|
+
await this.ociArtifact.downloadToInstance(instanceName, oci_artifacts_1.OCI_ARTIFACTS.NORTHWIND_SQL, oci_artifacts_1.OCI_ARTIFACT_TAGS.NORTHWIND_SQL, remoteScriptPath, acrCredentials);
|
|
176
|
+
// 3. 透過 shell pipeline 執行 SQL 腳本並清理暫存檔
|
|
177
|
+
const passB64 = Buffer.from(saPassword).toString('base64');
|
|
178
|
+
const kubectlPath = paths_1.LINUX_PATHS.MICROK8S_KUBECTL;
|
|
179
|
+
const sqlcmdPath = paths_1.LINUX_PATHS.SQLCMD_BIN;
|
|
180
|
+
const pipelineScript = [
|
|
181
|
+
'set -e',
|
|
182
|
+
`PASS=$(echo '${passB64}' | base64 -d)`,
|
|
183
|
+
`cat ${remoteScriptPath} | ${kubectlPath} exec -i -n mssql ${podName} -- ${sqlcmdPath} -S localhost -U sa -P "\${PASS}" -d Northwind -C`,
|
|
184
|
+
`rm -f ${remoteScriptPath}`,
|
|
185
|
+
].join('\n');
|
|
186
|
+
const result = await env.shell('bash').sensitiveStdin(pipelineScript).exec();
|
|
187
|
+
if (result.exitCode !== 0) {
|
|
188
|
+
this.logger.debug('Failed to execute Northwind SQL script', { stderr: result.stderr });
|
|
189
|
+
throw new errors_1.AppError('Failed to install Northwind sample database', {
|
|
190
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
191
|
+
});
|
|
129
192
|
}
|
|
130
193
|
}
|
|
131
194
|
};
|
|
@@ -133,7 +196,8 @@ exports.MssqlDatabaseInitService = MssqlDatabaseInitService;
|
|
|
133
196
|
exports.MssqlDatabaseInitService = MssqlDatabaseInitService = __decorate([
|
|
134
197
|
(0, tsyringe_1.injectable)(),
|
|
135
198
|
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IExecutionEnvironmentFactory)),
|
|
136
|
-
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.
|
|
137
|
-
|
|
199
|
+
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IOciArtifactService)),
|
|
200
|
+
__param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.ILoggerPort)),
|
|
201
|
+
__metadata("design:paramtypes", [Object, Object, Object])
|
|
138
202
|
], MssqlDatabaseInitService);
|
|
139
203
|
//# sourceMappingURL=mssql-database-init.service.js.map
|
|
@@ -16,6 +16,7 @@ exports.MssqlHelmDeploymentService = void 0;
|
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
18
|
const base_helm_deployment_service_1 = require("./base-helm-deployment.service");
|
|
19
|
+
const errors_1 = require("../../../domain/errors");
|
|
19
20
|
/**
|
|
20
21
|
* MSSQL Helm 部署服務
|
|
21
22
|
*
|
|
@@ -66,9 +67,9 @@ let MssqlHelmDeploymentService = class MssqlHelmDeploymentService extends base_h
|
|
|
66
67
|
.arg('--timeout', '10m')
|
|
67
68
|
.arg('-n', 'mssql')
|
|
68
69
|
.arg('database')
|
|
69
|
-
.arg(
|
|
70
|
+
.arg(chartPath)
|
|
70
71
|
.arg('--create-namespace')
|
|
71
|
-
.sensitiveArg('--set', `sa_password
|
|
72
|
+
.sensitiveArg('--set', `sa_password=${params.saPassword}`);
|
|
72
73
|
this.logger.debug('[Mssql] Installing MSSQL chart', {
|
|
73
74
|
chart: 'mssql-latest',
|
|
74
75
|
chartPath: chartPath,
|
|
@@ -77,14 +78,25 @@ let MssqlHelmDeploymentService = class MssqlHelmDeploymentService extends base_h
|
|
|
77
78
|
});
|
|
78
79
|
const result = await builder.exec();
|
|
79
80
|
if (result.exitCode !== 0) {
|
|
80
|
-
|
|
81
|
+
this.logger.debug('Failed to deploy MSSQL', { stderr: result.stderr });
|
|
82
|
+
throw new errors_1.AppError('Failed to deploy MSSQL', {
|
|
83
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
84
|
+
});
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
/**
|
|
84
|
-
*
|
|
88
|
+
* 安裝後處理:建立初始資料庫與 Northwind 範例資料庫
|
|
85
89
|
*/
|
|
86
|
-
async postInstall(instanceName, params,
|
|
90
|
+
async postInstall(instanceName, params, output) {
|
|
87
91
|
await this.dbInitService.createInitialDatabases(instanceName, params.saPassword.toString());
|
|
92
|
+
if (params.skipNorthwind) {
|
|
93
|
+
output?.item('bullet', 'Skipping Northwind sample database (--no-northwind)').flush();
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
output?.item('arrow', 'Installing Northwind sample database...').flush();
|
|
97
|
+
await this.dbInitService.installNorthwindDatabase(instanceName, params.saPassword.toString(), params.acrCredentials);
|
|
98
|
+
output?.item('check', 'Northwind database installed').flush();
|
|
99
|
+
}
|
|
88
100
|
}
|
|
89
101
|
};
|
|
90
102
|
exports.MssqlHelmDeploymentService = MssqlHelmDeploymentService;
|
|
@@ -16,6 +16,7 @@ exports.MssqlStorageService = void 0;
|
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
18
|
const paths_1 = require("../../../constants/paths");
|
|
19
|
+
const errors_1 = require("../../../domain/errors");
|
|
19
20
|
/**
|
|
20
21
|
* MSSQL 存儲服務
|
|
21
22
|
*
|
|
@@ -39,7 +40,10 @@ let MssqlStorageService = class MssqlStorageService {
|
|
|
39
40
|
.args(...directories);
|
|
40
41
|
const result = await builder.exec();
|
|
41
42
|
if (result.exitCode !== 0) {
|
|
42
|
-
|
|
43
|
+
this.logger.debug('Failed to create MSSQL directories', { stderr: result.stderr });
|
|
44
|
+
throw new errors_1.AppError('Failed to create MSSQL directories', {
|
|
45
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
46
|
+
});
|
|
43
47
|
}
|
|
44
48
|
this.logger.debug('[Mssql] Directories created successfully');
|
|
45
49
|
}
|
|
@@ -16,6 +16,7 @@ exports.MssqlUserManagerService = void 0;
|
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
18
|
const paths_1 = require("../../../constants/paths");
|
|
19
|
+
const errors_1 = require("../../../domain/errors");
|
|
19
20
|
/**
|
|
20
21
|
* MSSQL 使用者管理服務
|
|
21
22
|
*
|
|
@@ -45,13 +46,16 @@ let MssqlUserManagerService = class MssqlUserManagerService {
|
|
|
45
46
|
.arg(paths_1.LINUX_PATHS.SQLCMD_BIN)
|
|
46
47
|
.arg('-S', 'localhost')
|
|
47
48
|
.arg('-U', 'sa')
|
|
48
|
-
.sensitiveArg('-P',
|
|
49
|
+
.sensitiveArg('-P', params.saPassword.toString())
|
|
49
50
|
.arg('-d', 'uofx_dev')
|
|
50
51
|
.arg('-C')
|
|
51
|
-
.sensitiveArg('-Q',
|
|
52
|
+
.sensitiveArg('-Q', query);
|
|
52
53
|
const result = await builder.exec();
|
|
53
54
|
if (result.exitCode !== 0) {
|
|
54
|
-
|
|
55
|
+
this.logger.debug('Failed to create admin user', { stderr: result.stderr });
|
|
56
|
+
throw new errors_1.AppError('Failed to create admin user', {
|
|
57
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
58
|
+
});
|
|
55
59
|
}
|
|
56
60
|
}
|
|
57
61
|
};
|
|
@@ -15,7 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.OciArtifactService = void 0;
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
|
-
const sensitive_decorator_1 = require("
|
|
18
|
+
const sensitive_decorator_1 = require("../../interceptors/decorators/sensitive.decorator");
|
|
19
|
+
const errors_1 = require("../../../domain/errors");
|
|
19
20
|
/**
|
|
20
21
|
* OCI Artifact 下載服務
|
|
21
22
|
*
|
|
@@ -49,7 +50,9 @@ let OciArtifactService = class OciArtifactService {
|
|
|
49
50
|
// 3. 取得 Blob Digest
|
|
50
51
|
const digest = this.extractDigest(manifestResponse);
|
|
51
52
|
if (!digest) {
|
|
52
|
-
throw new
|
|
53
|
+
throw new errors_1.AppError(`Could not find digest in manifest for ${repo}:${tag}`, {
|
|
54
|
+
exitCode: errors_1.EXIT_CODES.NETWORK_ERROR,
|
|
55
|
+
});
|
|
53
56
|
}
|
|
54
57
|
// 4. 下載 Blob
|
|
55
58
|
const blobUrl = `https://${registry}/v2/${repo}/blobs/${digest}`;
|
|
@@ -84,7 +87,9 @@ let OciArtifactService = class OciArtifactService {
|
|
|
84
87
|
repo,
|
|
85
88
|
tag
|
|
86
89
|
});
|
|
87
|
-
throw new
|
|
90
|
+
throw new errors_1.AppError(`Failed to download OCI artifact: ${errorDetail}`, {
|
|
91
|
+
exitCode: errors_1.EXIT_CODES.NETWORK_ERROR,
|
|
92
|
+
});
|
|
88
93
|
}
|
|
89
94
|
this.logger.debug(`Successfully downloaded OCI artifact to instance: ${targetPath}`);
|
|
90
95
|
}
|
|
@@ -15,7 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.SecretManagerService = void 0;
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
|
-
const sensitive_decorator_1 = require("
|
|
18
|
+
const sensitive_decorator_1 = require("../../interceptors/decorators/sensitive.decorator");
|
|
19
|
+
const errors_1 = require("../../../domain/errors");
|
|
19
20
|
/**
|
|
20
21
|
* Secret 管理服務
|
|
21
22
|
*
|
|
@@ -53,7 +54,10 @@ let SecretManagerService = class SecretManagerService {
|
|
|
53
54
|
.arg(namespace);
|
|
54
55
|
const result = await builder.exec();
|
|
55
56
|
if (result.exitCode !== 0) {
|
|
56
|
-
|
|
57
|
+
this.logger.debug('kubectl create namespace failed', { stderr: result.stderr });
|
|
58
|
+
throw new errors_1.AppError('Failed to create Kubernetes namespace', {
|
|
59
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
60
|
+
});
|
|
57
61
|
}
|
|
58
62
|
}
|
|
59
63
|
/**
|
|
@@ -100,7 +104,10 @@ let SecretManagerService = class SecretManagerService {
|
|
|
100
104
|
.sensitiveStdin(JSON.stringify(secretManifest));
|
|
101
105
|
const result = await builder.exec();
|
|
102
106
|
if (result.exitCode !== 0) {
|
|
103
|
-
|
|
107
|
+
this.logger.debug('kubectl apply secret failed', { stderr: result.stderr });
|
|
108
|
+
throw new errors_1.AppError('Failed to create global config secret', {
|
|
109
|
+
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
110
|
+
});
|
|
104
111
|
}
|
|
105
112
|
output?.success(`Global config secret created in ${namespace}`).flush();
|
|
106
113
|
}
|
|
@@ -120,8 +127,10 @@ let SecretManagerService = class SecretManagerService {
|
|
|
120
127
|
.arg('-o', 'json');
|
|
121
128
|
const result = await builder.exec();
|
|
122
129
|
if (result.exitCode !== 0) {
|
|
123
|
-
this.logger.error(new Error(
|
|
124
|
-
|
|
130
|
+
this.logger.error(new Error('kubectl get secret failed'), {
|
|
131
|
+
exitCode: result.exitCode,
|
|
132
|
+
stderr: result.stderr,
|
|
133
|
+
});
|
|
125
134
|
return null;
|
|
126
135
|
}
|
|
127
136
|
const secret = JSON.parse(result.stdout);
|
|
@@ -16,7 +16,7 @@ exports.ServiceManagerService = void 0;
|
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const tokens_1 = require("../../../di/tokens");
|
|
18
18
|
const deployment_parameters_entity_1 = require("../../../domain/entities/deployment-parameters.entity");
|
|
19
|
-
const sensitive_decorator_1 = require("
|
|
19
|
+
const sensitive_decorator_1 = require("../../interceptors/decorators/sensitive.decorator");
|
|
20
20
|
const base_helm_deployment_service_1 = require("./base-helm-deployment.service");
|
|
21
21
|
/**
|
|
22
22
|
* Service Manager Service
|
|
@@ -49,8 +49,8 @@ exports.VersionCompatibilityService = void 0;
|
|
|
49
49
|
const tsyringe_1 = require("tsyringe");
|
|
50
50
|
const semver = __importStar(require("semver"));
|
|
51
51
|
const tokens_1 = require("../../../di/tokens");
|
|
52
|
-
const sensitive_decorator_1 = require("
|
|
53
|
-
const errors_1 = require("
|
|
52
|
+
const sensitive_decorator_1 = require("../../interceptors/decorators/sensitive.decorator");
|
|
53
|
+
const errors_1 = require("../../../domain/errors");
|
|
54
54
|
const index_1 = require("../../../constants/index");
|
|
55
55
|
/**
|
|
56
56
|
* 版本相容性檢查服務
|
|
@@ -189,7 +189,9 @@ let VersionCompatibilityService = class VersionCompatibilityService {
|
|
|
189
189
|
}
|
|
190
190
|
const creds = this.acrCreds.getDefaultCredentials();
|
|
191
191
|
if (!creds) {
|
|
192
|
-
throw new
|
|
192
|
+
throw new errors_1.AppError('ACR credentials not found', {
|
|
193
|
+
exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
|
|
194
|
+
});
|
|
193
195
|
}
|
|
194
196
|
const registry = `${creds.name}.azurecr.io`;
|
|
195
197
|
const scope = `repository:${repo}:pull`;
|
|
@@ -217,7 +219,9 @@ let VersionCompatibilityService = class VersionCompatibilityService {
|
|
|
217
219
|
digest = manifestResponse.config.digest;
|
|
218
220
|
}
|
|
219
221
|
if (!digest) {
|
|
220
|
-
throw new
|
|
222
|
+
throw new errors_1.AppError('Could not find digest in manifest', {
|
|
223
|
+
exitCode: errors_1.EXIT_CODES.NETWORK_ERROR,
|
|
224
|
+
});
|
|
221
225
|
}
|
|
222
226
|
const blobUrl = `https://${registry}/v2/${repo}/blobs/${digest}`;
|
|
223
227
|
const blob = await this.httpClient.getJson(blobUrl, {
|
|
@@ -283,7 +287,7 @@ __decorate([
|
|
|
283
287
|
exports.VersionCompatibilityService = VersionCompatibilityService = __decorate([
|
|
284
288
|
(0, tsyringe_1.injectable)(),
|
|
285
289
|
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IHttpClient)),
|
|
286
|
-
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.
|
|
290
|
+
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.IAppConfigPort)),
|
|
287
291
|
__param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IAcrCredentialManager)),
|
|
288
292
|
__param(3, (0, tsyringe_1.inject)(tokens_1.TOKENS.ILoggerPort)),
|
|
289
293
|
__metadata("design:paramtypes", [Object, Object, Object, Object])
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dotnet Publisher Adapter
|
|
4
|
+
*
|
|
5
|
+
* 實作 IDotnetPublisherPort 介面
|
|
6
|
+
* 透過 dotnet publish 建置 .NET 專案
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
25
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
26
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
27
|
+
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;
|
|
28
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
29
|
+
};
|
|
30
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
31
|
+
var ownKeys = function(o) {
|
|
32
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
33
|
+
var ar = [];
|
|
34
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
35
|
+
return ar;
|
|
36
|
+
};
|
|
37
|
+
return ownKeys(o);
|
|
38
|
+
};
|
|
39
|
+
return function (mod) {
|
|
40
|
+
if (mod && mod.__esModule) return mod;
|
|
41
|
+
var result = {};
|
|
42
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
48
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
49
|
+
};
|
|
50
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
51
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
52
|
+
};
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.DotnetPublisherAdapter = void 0;
|
|
55
|
+
const tsyringe_1 = require("tsyringe");
|
|
56
|
+
const fs = __importStar(require("fs"));
|
|
57
|
+
const os = __importStar(require("os"));
|
|
58
|
+
const path = __importStar(require("path"));
|
|
59
|
+
const tokens_1 = require("../../di/tokens");
|
|
60
|
+
let DotnetPublisherAdapter = class DotnetPublisherAdapter {
|
|
61
|
+
constructor(logger, commandExecutor) {
|
|
62
|
+
this.logger = logger;
|
|
63
|
+
this.commandExecutor = commandExecutor;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 執行 dotnet publish 建置 .NET 專案
|
|
67
|
+
*
|
|
68
|
+
* 使用暫存目錄作為 dotnet publish 的輸出目標,避免 Microsoft.NET.Sdk.Web
|
|
69
|
+
* 將專案目錄內已存在的其他目錄當作 Content 複製進輸出。
|
|
70
|
+
*
|
|
71
|
+
* @param options - 發布選項
|
|
72
|
+
* @param output - 輸出端口,用於回報進度
|
|
73
|
+
* @returns 發布結果
|
|
74
|
+
*/
|
|
75
|
+
async publish(options, output) {
|
|
76
|
+
const configuration = options.configuration || 'Release';
|
|
77
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'uofx-publish-'));
|
|
78
|
+
try {
|
|
79
|
+
const args = [
|
|
80
|
+
'publish',
|
|
81
|
+
'-c', configuration,
|
|
82
|
+
'-o', tempDir,
|
|
83
|
+
];
|
|
84
|
+
this.logger.debug(`Executing: dotnet ${args.join(' ')}`, {
|
|
85
|
+
cwd: options.projectPath,
|
|
86
|
+
});
|
|
87
|
+
output
|
|
88
|
+
?.item('arrow', `Running: dotnet publish -c ${configuration}`)
|
|
89
|
+
.flush();
|
|
90
|
+
output?.divider().flush();
|
|
91
|
+
const result = await this.commandExecutor.spawnProcess('dotnet', args, undefined, { cwd: options.projectPath, inheritStdio: true });
|
|
92
|
+
output?.divider().flush();
|
|
93
|
+
if (result.exitCode === 0) {
|
|
94
|
+
// cpSync 支援跨磁碟,避免 renameSync 的 EXDEV 錯誤
|
|
95
|
+
fs.mkdirSync(options.outputPath, { recursive: true });
|
|
96
|
+
fs.cpSync(tempDir, options.outputPath, { recursive: true });
|
|
97
|
+
return {
|
|
98
|
+
success: true,
|
|
99
|
+
message: 'Dotnet publish completed successfully.',
|
|
100
|
+
outputPath: options.outputPath,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
const errorMsg = `dotnet publish exited with code ${result.exitCode}`;
|
|
105
|
+
output?.error(errorMsg).flush();
|
|
106
|
+
return {
|
|
107
|
+
success: false,
|
|
108
|
+
message: errorMsg,
|
|
109
|
+
outputPath: options.outputPath,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
const errorMsg = `Failed to execute dotnet publish: ${err instanceof Error ? err.message : String(err)}`;
|
|
115
|
+
this.logger.error(new Error(errorMsg));
|
|
116
|
+
output?.error(errorMsg).flush();
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
message: errorMsg,
|
|
120
|
+
outputPath: options.outputPath,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 從 ClientApp 路徑推算專案根目錄
|
|
129
|
+
* @param clientAppPath - ClientApp 目錄路徑
|
|
130
|
+
* @returns 專案根目錄路徑(ClientApp 的上層目錄)
|
|
131
|
+
*/
|
|
132
|
+
findProjectDir(clientAppPath) {
|
|
133
|
+
return path.dirname(clientAppPath);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
exports.DotnetPublisherAdapter = DotnetPublisherAdapter;
|
|
137
|
+
exports.DotnetPublisherAdapter = DotnetPublisherAdapter = __decorate([
|
|
138
|
+
(0, tsyringe_1.injectable)(),
|
|
139
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.ILoggerPort)),
|
|
140
|
+
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.ICommandExecutor)),
|
|
141
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
142
|
+
], DotnetPublisherAdapter);
|
|
143
|
+
//# sourceMappingURL=dotnet-publisher.adapter.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DotnetPublisherAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Infrastructure Dotnet 模組匯出
|
|
6
|
+
*/
|
|
7
|
+
var dotnet_publisher_adapter_1 = require("./dotnet-publisher.adapter");
|
|
8
|
+
Object.defineProperty(exports, "DotnetPublisherAdapter", { enumerable: true, get: function () { return dotnet_publisher_adapter_1.DotnetPublisherAdapter; } });
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectPlatform = exports.WindowsEnvironmentAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Infrastructure Environment 模組匯出
|
|
6
|
+
*/
|
|
7
|
+
var windows_environment_adapter_1 = require("./windows-environment.adapter");
|
|
8
|
+
Object.defineProperty(exports, "WindowsEnvironmentAdapter", { enumerable: true, get: function () { return windows_environment_adapter_1.WindowsEnvironmentAdapter; } });
|
|
9
|
+
var platform_detector_util_1 = require("./platform-detector.util");
|
|
10
|
+
Object.defineProperty(exports, "detectPlatform", { enumerable: true, get: function () { return platform_detector_util_1.detectPlatform; } });
|
|
11
|
+
//# sourceMappingURL=index.js.map
|