@uofx/cli 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +159 -3
  2. package/THIRD-PARTY-NOTICES.txt +84 -2
  3. package/dist/application/dtos/config/index.js +22 -0
  4. package/dist/application/dtos/config/request/index.js +19 -0
  5. package/dist/application/dtos/config/request/set-config.request.dto.js +3 -0
  6. package/dist/application/dtos/config/response/get-config.response.dto.js +8 -0
  7. package/dist/application/dtos/config/response/index.js +21 -0
  8. package/dist/application/dtos/dev/index.js +24 -0
  9. package/dist/application/dtos/dev/request/generate-component.request.dto.js +3 -0
  10. package/dist/application/dtos/dev/request/index.js +25 -0
  11. package/dist/application/dtos/dev/request/install-template.request.dto.js +3 -0
  12. package/dist/application/dtos/dev/request/new-project.request.dto.js +3 -0
  13. package/dist/application/dtos/dev/request/publish-plugin.request.dto.js +3 -0
  14. package/dist/application/dtos/dev/request/uninstall-template.request.dto.js +3 -0
  15. package/dist/application/dtos/dev/response/generate-component.response.dto.js +3 -0
  16. package/dist/application/dtos/dev/response/index.js +24 -0
  17. package/dist/application/dtos/dev/response/new-project.response.dto.js +3 -0
  18. package/dist/application/dtos/dev/response/publish-plugin.response.dto.js +3 -0
  19. package/dist/application/dtos/dev/response/template-info.response.dto.js +3 -0
  20. package/dist/application/dtos/env/index.js +24 -0
  21. package/dist/application/dtos/{request → env/request}/index.js +1 -3
  22. package/dist/application/dtos/env/request/list-running-instances.request.dto.js +3 -0
  23. package/dist/application/dtos/{response → env/response}/index.js +1 -1
  24. package/dist/application/dtos/env/response/list-running-instances.response.dto.js +3 -0
  25. package/dist/application/dtos/index.js +9 -2
  26. package/dist/application/dtos/logs/index.js +22 -0
  27. package/dist/application/dtos/logs/request/index.js +18 -0
  28. package/dist/application/dtos/logs/response/index.js +18 -0
  29. package/dist/application/index.js +1 -0
  30. package/dist/application/services/env/environment-validator.service.js +120 -0
  31. package/dist/application/services/env/index.js +11 -0
  32. package/dist/application/services/env/instance-cleanup.service.js +79 -0
  33. package/dist/application/services/index.js +21 -0
  34. package/dist/application/use-cases/config/get-all-config.use-case.js +54 -0
  35. package/dist/application/use-cases/config/get-config.use-case.js +7 -17
  36. package/dist/application/use-cases/config/index.js +23 -0
  37. package/dist/application/use-cases/config/set-config.use-case.js +49 -3
  38. package/dist/application/use-cases/dev/generate-component.use-case.js +138 -0
  39. package/dist/application/use-cases/dev/index.js +28 -0
  40. package/dist/application/use-cases/dev/install-template.use-case.js +60 -0
  41. package/dist/application/use-cases/dev/list-templates.use-case.js +45 -0
  42. package/dist/application/use-cases/dev/new-project.use-case.js +130 -0
  43. package/dist/application/use-cases/dev/publish-plugin.use-case.js +243 -0
  44. package/dist/application/use-cases/dev/uninstall-template.use-case.js +50 -0
  45. package/dist/application/use-cases/{instance → env}/delete-instance.use-case.js +2 -2
  46. package/dist/application/use-cases/{credentials → env}/get-credentials.use-case.js +1 -1
  47. package/dist/application/use-cases/{instance → env}/index.js +11 -0
  48. package/dist/application/use-cases/{instance → env}/install-instance.use-case.js +25 -136
  49. package/dist/application/use-cases/env/list-running-instances.use-case.js +47 -0
  50. package/dist/application/use-cases/{setup → env}/setup-environment.use-case.js +35 -4
  51. package/dist/application/use-cases/{instance → env}/start-instance.use-case.js +53 -41
  52. package/dist/application/use-cases/index.js +9 -6
  53. package/dist/application/use-cases/logs/index.js +21 -0
  54. package/dist/cli.js +175 -26
  55. package/dist/constants/defaults.js +8 -1
  56. package/dist/constants/oci-artifacts.js +4 -0
  57. package/dist/constants/paths.js +0 -4
  58. package/dist/constants/timeouts.js +5 -0
  59. package/dist/di/modules/application.module.js +13 -44
  60. package/dist/di/modules/config.module.js +19 -0
  61. package/dist/di/modules/dev.module.js +45 -0
  62. package/dist/di/modules/env.module.js +42 -0
  63. package/dist/di/modules/index.js +30 -0
  64. package/dist/di/modules/infrastructure.module.js +65 -82
  65. package/dist/di/modules/logs.module.js +15 -0
  66. package/dist/di/modules/presentation.module.js +18 -7
  67. package/dist/di/tokens.js +42 -30
  68. package/dist/domain/entities/credentials-resolver.entity.js +4 -1
  69. package/dist/domain/entities/credentials.entity.js +2 -5
  70. package/dist/domain/entities/delete-instance-validation.entity.js +4 -1
  71. package/dist/domain/entities/deployment-parameters.entity.js +11 -8
  72. package/dist/domain/entities/index.js +5 -1
  73. package/dist/domain/entities/instance-list-aggregator.entity.js +2 -2
  74. package/dist/domain/entities/instance-metadata.entity.js +2 -3
  75. package/dist/domain/entities/instance.entity.js +2 -1
  76. package/dist/domain/entities/log-filter.entity.js +6 -6
  77. package/dist/domain/entities/template-info.entity.js +63 -0
  78. package/dist/{infrastructure/utils/error-formatter.util.js → domain/errors/error-utils.js} +1 -1
  79. package/dist/domain/errors/index.js +19 -0
  80. package/dist/domain/index.js +6 -0
  81. package/dist/domain/interfaces/index.js +21 -0
  82. package/dist/domain/ports/dotnet-publisher.port.js +9 -0
  83. package/dist/{infrastructure/http/interfaces/http-client.interface.js → domain/ports/file-system.port.js} +1 -1
  84. package/dist/domain/ports/http-client.port.js +3 -0
  85. package/dist/domain/ports/index.js +10 -0
  86. package/dist/domain/ports/logger.port.js +3 -3
  87. package/dist/domain/ports/progress.port.js +10 -0
  88. package/dist/domain/ports/project-scaffolder.port.js +9 -0
  89. package/dist/domain/ports/schematics-runner.port.js +9 -0
  90. package/dist/domain/ports/template-manager.port.js +9 -0
  91. package/dist/domain/ports/wsl-setup.port.js +3 -0
  92. package/dist/domain/types/index.js +1 -0
  93. package/dist/domain/value-objects/acr-credentials.value-object.js +13 -1
  94. package/dist/domain/value-objects/chart-version.value-object.js +20 -3
  95. package/dist/domain/value-objects/config-log-level.value-object.js +2 -1
  96. package/dist/domain/value-objects/index.js +3 -1
  97. package/dist/domain/value-objects/instance-name.value-object.js +6 -3
  98. package/dist/domain/value-objects/jwt-key.value-object.js +27 -5
  99. package/dist/domain/value-objects/mssql-password.value-object.js +27 -5
  100. package/dist/domain/value-objects/output-path.value-object.js +85 -0
  101. package/dist/domain/value-objects/rsa-key-pair.value-object.js +29 -3
  102. package/dist/index.js +6 -1
  103. package/dist/infrastructure/config/{app-config.service.js → app-config.adapter.js} +29 -17
  104. package/dist/infrastructure/config/{config-validator.js → config-validator.util.js} +1 -1
  105. package/dist/infrastructure/config/index.js +14 -0
  106. package/dist/infrastructure/config/interfaces/index.js +3 -0
  107. package/dist/infrastructure/config/{crypto.service.js → services/crypto.service.js} +4 -1
  108. package/dist/infrastructure/config/services/index.js +9 -0
  109. package/dist/infrastructure/deployment/deployment.adapter.js +5 -5
  110. package/dist/infrastructure/deployment/index.js +9 -0
  111. package/dist/infrastructure/deployment/interfaces/index.js +3 -0
  112. package/dist/infrastructure/deployment/services/acr-credential-manager.service.js +18 -7
  113. package/dist/infrastructure/deployment/services/app-manager.service.js +3 -3
  114. package/dist/infrastructure/deployment/services/base-helm-deployment.service.js +13 -5
  115. package/dist/infrastructure/deployment/services/helm-registry.service.js +10 -3
  116. package/dist/infrastructure/deployment/services/index.js +35 -0
  117. package/dist/infrastructure/deployment/services/infra-manager.service.js +19 -15
  118. package/dist/infrastructure/deployment/services/k8s-job-runner.service.js +24 -6
  119. package/dist/infrastructure/deployment/services/mssql-database-init.service.js +75 -11
  120. package/dist/infrastructure/deployment/services/mssql-helm-deployment.service.js +17 -5
  121. package/dist/infrastructure/deployment/services/mssql-storage.service.js +5 -1
  122. package/dist/infrastructure/deployment/services/mssql-user-manager.service.js +7 -3
  123. package/dist/infrastructure/deployment/services/oci-artifact.service.js +8 -3
  124. package/dist/infrastructure/deployment/services/secret-manager.service.js +14 -5
  125. package/dist/infrastructure/deployment/services/service-manager.service.js +1 -1
  126. package/dist/infrastructure/deployment/services/version-compatibility.service.js +9 -5
  127. package/dist/infrastructure/dotnet/dotnet-publisher.adapter.js +143 -0
  128. package/dist/infrastructure/dotnet/index.js +9 -0
  129. package/dist/infrastructure/environment/index.js +11 -0
  130. package/dist/infrastructure/environment/interfaces/index.js +3 -0
  131. package/dist/infrastructure/{platform-detector.js → environment/platform-detector.util.js} +1 -1
  132. package/dist/infrastructure/environment/services/hardware-info.service.js +8 -8
  133. package/dist/infrastructure/environment/services/index.js +11 -0
  134. package/dist/infrastructure/errors/{error-handler.js → error-handler.adapter.js} +17 -17
  135. package/dist/infrastructure/errors/index.js +5 -21
  136. package/dist/infrastructure/execution/builders/base-command.builder.js +32 -11
  137. package/dist/infrastructure/execution/builders/index.js +26 -0
  138. package/dist/infrastructure/execution/builders/wsl-command.builder.js +39 -1
  139. package/dist/infrastructure/execution/command-builder.util.js +94 -0
  140. package/dist/infrastructure/execution/environments/index.js +23 -0
  141. package/dist/infrastructure/execution/environments/wsl-execution.environment.js +22 -7
  142. package/dist/infrastructure/execution/index.js +1 -2
  143. package/dist/infrastructure/execution/services/command-executor.service.js +389 -0
  144. package/dist/infrastructure/execution/services/index.js +8 -0
  145. package/dist/infrastructure/execution/{script-executor.service.js → services/script-executor.service.js} +12 -15
  146. package/dist/infrastructure/filesystem/filesystem.adapter.js +86 -0
  147. package/dist/infrastructure/filesystem/index.js +23 -0
  148. package/dist/infrastructure/http/{http-client.service.js → http-client.adapter.js} +20 -13
  149. package/dist/infrastructure/http/index.js +1 -1
  150. package/dist/infrastructure/interceptors/decorators/index.js +23 -0
  151. package/dist/infrastructure/interceptors/index.js +2 -2
  152. package/dist/infrastructure/interceptors/interceptor.factory.js +3 -3
  153. package/dist/infrastructure/interceptors/interfaces/index.js +3 -0
  154. package/dist/infrastructure/interceptors/services/index.js +6 -0
  155. package/dist/infrastructure/interceptors/{logging.interceptor.js → services/logging-interceptor.service.js} +4 -4
  156. package/dist/infrastructure/logger/services/file-log-reader.repository.js +1 -1
  157. package/dist/infrastructure/logger/services/file-log-writer.repository.js +1 -1
  158. package/dist/infrastructure/persistence/instance-metadata.adapter.js +2 -1
  159. package/dist/infrastructure/persistence/services/file-system-config.repository.js +10 -4
  160. package/dist/infrastructure/persistence/services/file-system-instance.repository.js +2 -2
  161. package/dist/infrastructure/platforms/index.js +18 -0
  162. package/dist/infrastructure/platforms/windows/index.js +13 -0
  163. package/dist/infrastructure/platforms/windows/interfaces/index.js +3 -0
  164. package/dist/infrastructure/platforms/windows/parsers/index.js +9 -0
  165. package/dist/infrastructure/platforms/windows/services/index.js +33 -0
  166. package/dist/infrastructure/platforms/windows/services/microk8s.service.js +28 -10
  167. package/dist/infrastructure/platforms/windows/services/rootfs-manager.service.js +7 -3
  168. package/dist/infrastructure/platforms/windows/services/windows-features.service.js +22 -8
  169. package/dist/infrastructure/platforms/windows/services/windows-info.service.js +10 -6
  170. package/dist/infrastructure/platforms/windows/services/wsl-config.service.js +15 -6
  171. package/dist/infrastructure/platforms/windows/services/wsl-info.service.js +12 -12
  172. package/dist/infrastructure/platforms/windows/services/wsl-instance-inspection.service.js +3 -3
  173. package/dist/infrastructure/platforms/windows/services/wsl-instance-lifecycle.service.js +76 -22
  174. package/dist/infrastructure/platforms/windows/services/wsl-updater.service.js +20 -15
  175. package/dist/infrastructure/platforms/windows/services/wslconfig-parser.service.js +3 -3
  176. package/dist/infrastructure/platforms/windows/wsl-instance-manager.adapter.js +8 -3
  177. package/dist/infrastructure/platforms/windows/wsl-setup.adapter.js +100 -0
  178. package/dist/infrastructure/schematics/index.js +11 -0
  179. package/dist/infrastructure/schematics/project-scaffolder.adapter.js +314 -0
  180. package/dist/infrastructure/schematics/schematics-runner.adapter.js +175 -0
  181. package/dist/infrastructure/template/index.js +25 -0
  182. package/dist/infrastructure/template/interfaces/index.js +22 -0
  183. package/dist/infrastructure/template/interfaces/template-downloader.interface.js +6 -0
  184. package/dist/infrastructure/template/interfaces/template-registry.interface.js +6 -0
  185. package/dist/infrastructure/template/services/index.js +24 -0
  186. package/dist/infrastructure/template/services/template-downloader.service.js +319 -0
  187. package/dist/infrastructure/template/services/template-registry.service.js +175 -0
  188. package/dist/infrastructure/template/template-manager.adapter.js +196 -0
  189. package/dist/infrastructure/utils/index.js +23 -0
  190. package/dist/infrastructure/utils/input-validator.util.js +7 -6
  191. package/dist/presentation/controllers/base.controller.js +36 -0
  192. package/dist/presentation/controllers/{config.controller.js → config/config.controller.js} +17 -62
  193. package/dist/presentation/controllers/config/index.js +21 -0
  194. package/dist/presentation/controllers/dev/dev.controller.js +202 -0
  195. package/dist/presentation/controllers/dev/index.js +23 -0
  196. package/dist/presentation/controllers/dev/template.controller.js +158 -0
  197. package/dist/presentation/controllers/{credentials.controller.js → env/credentials.controller.js} +8 -14
  198. package/dist/presentation/controllers/env/index.js +23 -0
  199. package/dist/presentation/controllers/{instance.controller.js → env/instance.controller.js} +35 -92
  200. package/dist/presentation/controllers/{setup.controller.js → env/setup.controller.js} +33 -66
  201. package/dist/presentation/controllers/index.js +9 -5
  202. package/dist/presentation/controllers/logs/index.js +21 -0
  203. package/dist/presentation/controllers/{logs.controller.js → logs/logs.controller.js} +8 -14
  204. package/dist/presentation/interfaces/index.js +21 -0
  205. package/dist/presentation/prompts/acr-credentials.prompt.js +37 -9
  206. package/dist/presentation/ui/constants/index.js +23 -0
  207. package/dist/presentation/ui/interaction.service.js +4 -4
  208. package/dist/presentation/ui/interfaces/cli-progress.interface.js +0 -6
  209. package/dist/presentation/ui/interfaces/index.js +6 -0
  210. package/package.json +6 -1
  211. package/dist/application/dtos/request/set-config.request.dto.js +0 -16
  212. package/dist/infrastructure/errors/error-handler.interface.js +0 -3
  213. package/dist/infrastructure/execution/command-builder.js +0 -252
  214. package/dist/infrastructure/execution/command-executor.service.js +0 -230
  215. /package/dist/application/dtos/{request → config/request}/get-config.request.dto.js +0 -0
  216. /package/dist/application/dtos/{request → env/request}/delete-instance.request.dto.js +0 -0
  217. /package/dist/application/dtos/{request → env/request}/get-credentials.request.dto.js +0 -0
  218. /package/dist/application/dtos/{request → env/request}/install-instance.request.dto.js +0 -0
  219. /package/dist/application/dtos/{request → env/request}/list-charts.request.dto.js +0 -0
  220. /package/dist/application/dtos/{request → env/request}/setup-environment.request.dto.js +0 -0
  221. /package/dist/application/dtos/{request → env/request}/start-instance.request.dto.js +0 -0
  222. /package/dist/application/dtos/{request → env/request}/stop-instance.request.dto.js +0 -0
  223. /package/dist/application/dtos/{response → env/response}/credentials.response.dto.js +0 -0
  224. /package/dist/application/dtos/{response → env/response}/delete-instance.response.dto.js +0 -0
  225. /package/dist/application/dtos/{response → env/response}/install-instance.response.dto.js +0 -0
  226. /package/dist/application/dtos/{response → env/response}/instance-list.response.dto.js +0 -0
  227. /package/dist/application/dtos/{response → env/response}/instance-status.response.dto.js +0 -0
  228. /package/dist/application/dtos/{response → env/response}/setup-result.response.dto.js +0 -0
  229. /package/dist/application/dtos/{response → env/response}/start-instance.response.dto.js +0 -0
  230. /package/dist/application/dtos/{response → env/response}/stop-instance.response.dto.js +0 -0
  231. /package/dist/application/dtos/{request → logs/request}/show-logs.request.dto.js +0 -0
  232. /package/dist/application/dtos/{response → logs/response}/show-logs.response.dto.js +0 -0
  233. /package/dist/application/use-cases/{instance → env}/list-charts.use-case.js +0 -0
  234. /package/dist/application/use-cases/{instance → env}/list-instances.use-case.js +0 -0
  235. /package/dist/application/use-cases/{instance → env}/stop-instance.use-case.js +0 -0
  236. /package/dist/{infrastructure → domain}/errors/app-error.js +0 -0
  237. /package/dist/{infrastructure → domain}/errors/exit-codes.js +0 -0
  238. /package/dist/infrastructure/config/{app-config.interface.js → interfaces/app-config.interface.js} +0 -0
  239. /package/dist/{domain → infrastructure/interceptors}/decorators/sensitive.decorator.js +0 -0
  240. /package/dist/infrastructure/interceptors/{interceptor.interface.js → interfaces/interceptor.interface.js} +0 -0
@@ -5,7 +5,7 @@
5
5
  * 業務核心實體,封裝業務邏輯與狀態
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.CredentialsResolver = exports.DeleteInstanceValidation = exports.InstanceListAggregator = exports.EnvironmentValidation = exports.InstanceLifecycleState = exports.LogFilter = exports.DeploymentParameters = exports.InstanceStatus = exports.InstanceMetadata = exports.Instance = void 0;
8
+ exports.TemplateInfo = exports.Credentials = exports.CredentialsResolver = exports.DeleteInstanceValidation = exports.InstanceListAggregator = exports.EnvironmentValidation = exports.InstanceLifecycleState = exports.LogFilter = exports.DeploymentParameters = exports.InstanceStatus = exports.InstanceMetadata = exports.Instance = void 0;
9
9
  var instance_entity_1 = require("./instance.entity");
10
10
  Object.defineProperty(exports, "Instance", { enumerable: true, get: function () { return instance_entity_1.Instance; } });
11
11
  var instance_metadata_entity_1 = require("./instance-metadata.entity");
@@ -26,4 +26,8 @@ var delete_instance_validation_entity_1 = require("./delete-instance-validation.
26
26
  Object.defineProperty(exports, "DeleteInstanceValidation", { enumerable: true, get: function () { return delete_instance_validation_entity_1.DeleteInstanceValidation; } });
27
27
  var credentials_resolver_entity_1 = require("./credentials-resolver.entity");
28
28
  Object.defineProperty(exports, "CredentialsResolver", { enumerable: true, get: function () { return credentials_resolver_entity_1.CredentialsResolver; } });
29
+ var credentials_entity_1 = require("./credentials.entity");
30
+ Object.defineProperty(exports, "Credentials", { enumerable: true, get: function () { return credentials_entity_1.Credentials; } });
31
+ var template_info_entity_1 = require("./template-info.entity");
32
+ Object.defineProperty(exports, "TemplateInfo", { enumerable: true, get: function () { return template_info_entity_1.TemplateInfo; } });
29
33
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InstanceListAggregator = void 0;
4
- const connection_info_value_object_1 = require("../value-objects/connection-info.value-object");
4
+ const value_objects_1 = require("../value-objects");
5
5
  /**
6
6
  * 實例列表聚合器 Entity
7
7
  *
@@ -31,7 +31,7 @@ class InstanceListAggregator {
31
31
  static mergeInstanceInfo(info, metadataList, ipMap) {
32
32
  const metadata = metadataList.find(m => m.name.fullName === info.name);
33
33
  const ip = ipMap.get(info.name) ?? null;
34
- const connectionInfo = connection_info_value_object_1.ConnectionInfo.create(ip);
34
+ const connectionInfo = value_objects_1.ConnectionInfo.create(ip);
35
35
  const connectionDto = connectionInfo.toDto();
36
36
  return {
37
37
  name: metadata?.name.toString() || this.extractNameFromFullName(info.name),
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InstanceMetadata = void 0;
4
- const instance_name_value_object_1 = require("../value-objects/instance-name.value-object");
5
- const chart_version_value_object_1 = require("../value-objects/chart-version.value-object");
4
+ const value_objects_1 = require("../value-objects");
6
5
  /**
7
6
  * 實例元資料 Entity
8
7
  *
@@ -34,7 +33,7 @@ class InstanceMetadata {
34
33
  * @returns 元資料物件
35
34
  */
36
35
  static fromObject(data) {
37
- return new InstanceMetadata(instance_name_value_object_1.InstanceName.create(data.displayName), data.displayName, new Date(data.createdAt), data.version, data.rootfsVersion, data.chartVersion ? chart_version_value_object_1.ChartVersion.create(data.chartVersion) : undefined);
36
+ return new InstanceMetadata(value_objects_1.InstanceName.create(data.displayName), data.displayName, new Date(data.createdAt), data.version, data.rootfsVersion, data.chartVersion ? value_objects_1.ChartVersion.create(data.chartVersion) : undefined);
38
37
  }
39
38
  /**
40
39
  * 更新 chart 版本
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Instance = void 0;
4
4
  const instance_status_entity_1 = require("./instance-status.entity");
5
+ const errors_1 = require("../errors");
5
6
  /**
6
7
  * WSL 實例 Entity (Aggregate Root)
7
8
  *
@@ -20,7 +21,7 @@ class Instance {
20
21
  */
21
22
  static create(metadata, status) {
22
23
  if (metadata.fullName !== status.name) {
23
- throw new Error(`Instance name mismatch: metadata.fullName="${metadata.fullName}" vs status.name="${status.name}"`);
24
+ throw new errors_1.AppError(`Instance name mismatch: metadata.fullName="${metadata.fullName}" vs status.name="${status.name}"`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
24
25
  }
25
26
  return new Instance(metadata, status);
26
27
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LogFilter = void 0;
4
- const logger_types_1 = require("../types/logger.types");
4
+ const types_1 = require("../types");
5
5
  /**
6
6
  * 日誌過濾器 Entity
7
7
  *
@@ -132,10 +132,10 @@ LogFilter.TIME_MULTIPLIERS = {
132
132
  };
133
133
  /** 日誌層級對應表 */
134
134
  LogFilter.LEVEL_MAP = {
135
- 'debug': logger_types_1.LogLevel.DEBUG,
136
- 'info': logger_types_1.LogLevel.INFO,
137
- 'warn': logger_types_1.LogLevel.WARN,
138
- 'error': logger_types_1.LogLevel.ERROR,
139
- 'fatal': logger_types_1.LogLevel.FATAL,
135
+ 'debug': types_1.LogLevel.DEBUG,
136
+ 'info': types_1.LogLevel.INFO,
137
+ 'warn': types_1.LogLevel.WARN,
138
+ 'error': types_1.LogLevel.ERROR,
139
+ 'fatal': types_1.LogLevel.FATAL,
140
140
  };
141
141
  //# sourceMappingURL=log-filter.entity.js.map
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ /**
3
+ * Template Info Entity
4
+ *
5
+ * 樣板資訊實體,包含樣板的元資料
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.TemplateInfo = void 0;
9
+ /**
10
+ * 樣板資訊實體
11
+ */
12
+ class TemplateInfo {
13
+ constructor(name, displayName, version, source, variables, schematics, installedAt, path) {
14
+ this.name = name;
15
+ this.displayName = displayName;
16
+ this.version = version;
17
+ this.source = source;
18
+ this.variables = variables;
19
+ this.schematics = schematics;
20
+ this.installedAt = installedAt;
21
+ this.path = path;
22
+ }
23
+ /**
24
+ * 從 template.json 建立實體
25
+ */
26
+ static fromJson(json, installedAt, path) {
27
+ return new TemplateInfo(json.name, json.displayName || json.name, json.version || '1.0.0', json.source || { type: 'local' }, json.variables || [], json.schematics || {}, installedAt, path);
28
+ }
29
+ /**
30
+ * 從名稱與版本建立實體
31
+ * @param name - 樣板名稱
32
+ * @param version - 樣板版本
33
+ * @param installedAt - 安裝時間
34
+ * @param templatePath - 樣板路徑
35
+ * @param sourceUrl - 來源 URL
36
+ */
37
+ static create(name, version, installedAt, templatePath, sourceUrl) {
38
+ return new TemplateInfo(name, name, version, sourceUrl ? { type: 'url', url: sourceUrl } : { type: 'local' }, [], {}, installedAt, templatePath);
39
+ }
40
+ /**
41
+ * 轉換為顯示資訊
42
+ */
43
+ toDisplayInfo() {
44
+ return {
45
+ name: this.name,
46
+ displayName: this.displayName,
47
+ version: this.version,
48
+ installedAt: this.installedAt.toISOString(),
49
+ path: this.path,
50
+ };
51
+ }
52
+ /**
53
+ * 取得 schematic 路徑
54
+ */
55
+ getSchematicPath(type, platform) {
56
+ const config = this.schematics[type];
57
+ if (!config)
58
+ return undefined;
59
+ return config[platform];
60
+ }
61
+ }
62
+ exports.TemplateInfo = TemplateInfo;
63
+ //# sourceMappingURL=template-info.entity.js.map
@@ -26,4 +26,4 @@ function toError(error, defaultMessage = 'Unknown error') {
26
26
  }
27
27
  return new Error(error ? String(error) : defaultMessage);
28
28
  }
29
- //# sourceMappingURL=error-formatter.util.js.map
29
+ //# sourceMappingURL=error-utils.js.map
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /**
3
+ * Domain 錯誤系統匯出
4
+ *
5
+ * 統一錯誤類別、退出碼與工具函式的匯出點
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.toError = exports.formatErrorMessage = exports.EXIT_CODES = exports.AppError = void 0;
9
+ // 錯誤類別
10
+ var app_error_1 = require("./app-error");
11
+ Object.defineProperty(exports, "AppError", { enumerable: true, get: function () { return app_error_1.AppError; } });
12
+ // 退出碼
13
+ var exit_codes_1 = require("./exit-codes");
14
+ Object.defineProperty(exports, "EXIT_CODES", { enumerable: true, get: function () { return exit_codes_1.EXIT_CODES; } });
15
+ // 錯誤工具函式
16
+ var error_utils_1 = require("./error-utils");
17
+ Object.defineProperty(exports, "formatErrorMessage", { enumerable: true, get: function () { return error_utils_1.formatErrorMessage; } });
18
+ Object.defineProperty(exports, "toError", { enumerable: true, get: function () { return error_utils_1.toError; } });
19
+ //# sourceMappingURL=index.js.map
@@ -26,4 +26,10 @@ __exportStar(require("./value-objects"), exports);
26
26
  __exportStar(require("./entities"), exports);
27
27
  // Ports (介面定義,供 Infrastructure 層實作)
28
28
  __exportStar(require("./ports"), exports);
29
+ // Errors (錯誤類別與退出碼)
30
+ __exportStar(require("./errors"), exports);
31
+ // Types (領域類型定義)
32
+ __exportStar(require("./types"), exports);
33
+ // Interfaces (領域介面)
34
+ __exportStar(require("./interfaces"), exports);
29
35
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,21 @@
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
+ * Domain 層介面匯出
19
+ */
20
+ __exportStar(require("./safe-loggable.interface"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Dotnet Publisher Port
4
+ *
5
+ * 定義執行 dotnet publish 的抽象介面
6
+ * 由 Infrastructure 層實作
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ //# sourceMappingURL=dotnet-publisher.port.js.map
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=http-client.interface.js.map
3
+ //# sourceMappingURL=file-system.port.js.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=http-client.port.js.map
@@ -43,4 +43,14 @@ __exportStar(require("./base-image.port"), exports);
43
43
  __exportStar(require("./app-config.port"), exports);
44
44
  __exportStar(require("./error-handler.port"), exports);
45
45
  __exportStar(require("./correlation-id.port"), exports);
46
+ __exportStar(require("./http-client.port"), exports);
47
+ __exportStar(require("./output.port"), exports);
48
+ __exportStar(require("./user-interaction.port"), exports);
49
+ __exportStar(require("./template-manager.port"), exports);
50
+ __exportStar(require("./project-scaffolder.port"), exports);
51
+ __exportStar(require("./schematics-runner.port"), exports);
52
+ __exportStar(require("./dotnet-publisher.port"), exports);
53
+ __exportStar(require("./wsl-setup.port"), exports);
54
+ __exportStar(require("./progress.port"), exports);
55
+ __exportStar(require("./file-system.port"), exports);
46
56
  //# sourceMappingURL=index.js.map
@@ -8,7 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.LogLevelNames = exports.LogLevel = void 0;
10
10
  // Re-export 類型供外部使用
11
- var logger_types_1 = require("../types/logger.types");
12
- Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_types_1.LogLevel; } });
13
- Object.defineProperty(exports, "LogLevelNames", { enumerable: true, get: function () { return logger_types_1.LogLevelNames; } });
11
+ var types_1 = require("../types");
12
+ Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return types_1.LogLevel; } });
13
+ Object.defineProperty(exports, "LogLevelNames", { enumerable: true, get: function () { return types_1.LogLevelNames; } });
14
14
  //# sourceMappingURL=logger.port.js.map
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Progress Port (進度條介面定義)
4
+ *
5
+ * 定義 Progress Bar(進度條)進度指示器的介面
6
+ * 用於可預估進度的長時間操作
7
+ * 由 Presentation 層實作
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ //# sourceMappingURL=progress.port.js.map
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Project Scaffolder Port
4
+ *
5
+ * 定義建立新專案的抽象介面
6
+ * 由 Infrastructure 層實作,從已安裝的樣板複製並初始化專案
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ //# sourceMappingURL=project-scaffolder.port.js.map
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Schematics Runner Port
4
+ *
5
+ * 定義執行 Angular schematics 的抽象介面
6
+ * 由 Infrastructure 層實作,透過 npx ng generate 呼叫 @uofx/plugin-schematics
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ //# sourceMappingURL=schematics-runner.port.js.map
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Template Manager Port
4
+ *
5
+ * 定義樣板管理能力的抽象介面
6
+ * 由 Infrastructure 層實作
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ //# sourceMappingURL=template-manager.port.js.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=wsl-setup.port.js.map
@@ -19,4 +19,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  __exportStar(require("./logger.types"), exports);
22
+ __exportStar(require("./validation.types"), exports);
22
23
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AcrCredentials = void 0;
4
+ const errors_1 = require("../errors");
4
5
  /**
5
6
  * Azure Container Registry 憑證 Value Object
6
7
  *
@@ -22,7 +23,7 @@ class AcrCredentials {
22
23
  */
23
24
  static create(name, account, password) {
24
25
  if (!this.isValid(name, account, password)) {
25
- throw new Error('Invalid ACR credentials: name, account, and password are required');
26
+ throw new errors_1.AppError('Invalid ACR credentials: name, account, and password are required', { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
26
27
  }
27
28
  return new AcrCredentials(name, account, password);
28
29
  }
@@ -63,6 +64,17 @@ class AcrCredentials {
63
64
  password: this.password,
64
65
  };
65
66
  }
67
+ /**
68
+ * 防止 JSON.stringify 意外洩露密碼,回傳遮罩值
69
+ * @returns 遮罩後的物件
70
+ */
71
+ toJSON() {
72
+ return {
73
+ name: this.name,
74
+ account: this.account,
75
+ password: '***MASKED***',
76
+ };
77
+ }
66
78
  /**
67
79
  * 比較兩個憑證是否相等
68
80
  * @param other - 另一個憑證
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.ChartVersion = void 0;
37
37
  const semver = __importStar(require("semver"));
38
+ const errors_1 = require("../errors");
38
39
  /**
39
40
  * Chart 版本 Value Object
40
41
  *
@@ -55,8 +56,8 @@ class ChartVersion {
55
56
  */
56
57
  static create(version) {
57
58
  if (!this.isValid(version)) {
58
- throw new Error(`Invalid chart version: "${version}". ` +
59
- `Version must be a valid SemVer format (e.g., 1.0.0) or "latest".`);
59
+ throw new errors_1.AppError(`Invalid chart version: "${version}". ` +
60
+ `Version must be a valid SemVer format (e.g., 1.0.0) or "latest".`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
60
61
  }
61
62
  return new ChartVersion(version);
62
63
  }
@@ -105,6 +106,20 @@ class ChartVersion {
105
106
  equals(other) {
106
107
  return this.value === other.value;
107
108
  }
109
+ /**
110
+ * 取得版本類型
111
+ * @returns 'Beta' 或 'Stable'
112
+ */
113
+ getType() {
114
+ const parts = this.value.split('.');
115
+ if (parts.length >= 3) {
116
+ const patch = parts[2];
117
+ if (patch.startsWith('2')) {
118
+ return 'Beta';
119
+ }
120
+ }
121
+ return 'Stable';
122
+ }
108
123
  /**
109
124
  * 比較版本大小
110
125
  * @param other - 另一個版本
@@ -113,7 +128,9 @@ class ChartVersion {
113
128
  */
114
129
  compare(other) {
115
130
  if (this.isLatest || other.isLatest) {
116
- throw new Error('Cannot compare versions when either is "latest"');
131
+ throw new errors_1.AppError('Cannot compare versions when either is "latest"', {
132
+ exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
133
+ });
117
134
  }
118
135
  const result = semver.compare(this.value, other.value);
119
136
  return result;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ConfigLogLevelValue = void 0;
4
+ const errors_1 = require("../errors");
4
5
  /**
5
6
  * 配置日誌級別 Value Object
6
7
  *
@@ -19,7 +20,7 @@ class ConfigLogLevelValue {
19
20
  */
20
21
  static create(level) {
21
22
  if (!this.isValid(level)) {
22
- throw new Error(`Invalid log level: "${level}". Valid values: ${this.VALID_LEVELS.join(', ')}`);
23
+ throw new errors_1.AppError(`Invalid log level: "${level}". Valid values: ${this.VALID_LEVELS.join(', ')}`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
23
24
  }
24
25
  return new ConfigLogLevelValue(level);
25
26
  }
@@ -5,7 +5,7 @@
5
5
  * 不可變物件,封裝驗證規則與轉換邏輯
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.ConfigLogLevelValue = exports.ConnectionInfo = exports.AcrCredentials = exports.RsaKeyPair = exports.JwtKey = exports.MssqlPassword = exports.ChartVersion = exports.InstanceName = void 0;
8
+ exports.OutputPath = exports.ConfigLogLevelValue = exports.ConnectionInfo = exports.AcrCredentials = exports.RsaKeyPair = exports.JwtKey = exports.MssqlPassword = exports.ChartVersion = exports.InstanceName = void 0;
9
9
  var instance_name_value_object_1 = require("./instance-name.value-object");
10
10
  Object.defineProperty(exports, "InstanceName", { enumerable: true, get: function () { return instance_name_value_object_1.InstanceName; } });
11
11
  var chart_version_value_object_1 = require("./chart-version.value-object");
@@ -22,4 +22,6 @@ var connection_info_value_object_1 = require("./connection-info.value-object");
22
22
  Object.defineProperty(exports, "ConnectionInfo", { enumerable: true, get: function () { return connection_info_value_object_1.ConnectionInfo; } });
23
23
  var config_log_level_value_object_1 = require("./config-log-level.value-object");
24
24
  Object.defineProperty(exports, "ConfigLogLevelValue", { enumerable: true, get: function () { return config_log_level_value_object_1.ConfigLogLevelValue; } });
25
+ var output_path_value_object_1 = require("./output-path.value-object");
26
+ Object.defineProperty(exports, "OutputPath", { enumerable: true, get: function () { return output_path_value_object_1.OutputPath; } });
25
27
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InstanceName = void 0;
4
+ const errors_1 = require("../errors");
4
5
  /**
5
6
  * 實例名稱 Value Object
6
7
  *
@@ -27,9 +28,9 @@ class InstanceName {
27
28
  ? name.substring(prefix.length)
28
29
  : name;
29
30
  if (!this.isValid(normalizedName)) {
30
- throw new Error(`Invalid instance name: "${name}". ` +
31
+ throw new errors_1.AppError(`Invalid instance name: "${name}". ` +
31
32
  `Name must be ${this.MIN_LENGTH}-${this.MAX_LENGTH} characters, ` +
32
- `start and end with alphanumeric characters, and may contain hyphens.`);
33
+ `start and end with alphanumeric characters, and may contain hyphens.`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
33
34
  }
34
35
  return new InstanceName(normalizedName);
35
36
  }
@@ -42,7 +43,9 @@ class InstanceName {
42
43
  static createFromFullName(fullName) {
43
44
  const prefix = 'uofx-';
44
45
  if (!fullName.startsWith(prefix)) {
45
- throw new Error(`Invalid full instance name: "${fullName}". Expected format: uofx-{name}`);
46
+ throw new errors_1.AppError(`Invalid full instance name: "${fullName}". Expected format: uofx-{name}`, {
47
+ exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
48
+ });
46
49
  }
47
50
  const name = fullName.substring(prefix.length);
48
51
  return this.create(name);
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.JwtKey = void 0;
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
+ const errors_1 = require("../errors");
8
9
  /**
9
10
  * JWT 簽署金鑰 Value Object
10
11
  *
@@ -25,7 +26,9 @@ class JwtKey {
25
26
  */
26
27
  static generate(length = 63) {
27
28
  if (length < this.MIN_LENGTH) {
28
- throw new Error(`JWT key length must be at least ${this.MIN_LENGTH} characters`);
29
+ throw new errors_1.AppError(`JWT key length must be at least ${this.MIN_LENGTH} characters`, {
30
+ exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
31
+ });
29
32
  }
30
33
  try {
31
34
  let key = '';
@@ -35,12 +38,14 @@ class JwtKey {
35
38
  }
36
39
  // 驗證生成的金鑰
37
40
  if (!this.isValid(key)) {
38
- throw new Error('Generated JWT key validation failed');
41
+ throw new errors_1.AppError('Generated JWT key validation failed', {
42
+ exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
43
+ });
39
44
  }
40
45
  return new JwtKey(key);
41
46
  }
42
47
  catch (error) {
43
- throw new Error(`Failed to generate JWT signing key: ${error instanceof Error ? error.message : String(error)}`);
48
+ throw new errors_1.AppError(`Failed to generate JWT signing key: ${error instanceof Error ? error.message : String(error)}`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
44
49
  }
45
50
  }
46
51
  /**
@@ -51,8 +56,8 @@ class JwtKey {
51
56
  */
52
57
  static create(key) {
53
58
  if (!this.isValid(key)) {
54
- throw new Error(`Invalid JWT signing key. Must be at least ${this.MIN_LENGTH} characters ` +
55
- `and contain only alphanumeric characters.`);
59
+ throw new errors_1.AppError(`Invalid JWT signing key. Must be at least ${this.MIN_LENGTH} characters ` +
60
+ `and contain only alphanumeric characters.`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
56
61
  }
57
62
  return new JwtKey(key);
58
63
  }
@@ -82,6 +87,23 @@ class JwtKey {
82
87
  toBase64() {
83
88
  return Buffer.from(this.value, 'utf8').toString('base64');
84
89
  }
90
+ /**
91
+ * 防止 JSON.stringify 意外洩露金鑰,回傳遮罩值
92
+ * @returns 遮罩後的金鑰字串
93
+ */
94
+ toJSON() {
95
+ return '***MASKED***';
96
+ }
97
+ /**
98
+ * 回傳可安全記錄到日志的物件
99
+ * 金鑰欄位將被遮罩
100
+ * @returns 遮罩後的物件,可安全寫入日志
101
+ */
102
+ toSafeLog() {
103
+ return {
104
+ key: '***MASKED***',
105
+ };
106
+ }
85
107
  /**
86
108
  * 比較兩個金鑰是否相等
87
109
  * @param other - 另一個金鑰
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.MssqlPassword = void 0;
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
+ const errors_1 = require("../errors");
8
9
  /**
9
10
  * MSSQL 密碼 Value Object
10
11
  *
@@ -26,7 +27,9 @@ class MssqlPassword {
26
27
  */
27
28
  static generate(length = 16) {
28
29
  if (length < this.MIN_LENGTH) {
29
- throw new Error(`Password length must be at least ${this.MIN_LENGTH} characters`);
30
+ throw new errors_1.AppError(`Password length must be at least ${this.MIN_LENGTH} characters`, {
31
+ exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
32
+ });
30
33
  }
31
34
  try {
32
35
  // 確保包含所有必要字元類型
@@ -44,12 +47,14 @@ class MssqlPassword {
44
47
  const shuffled = this.shuffleString(password);
45
48
  // 驗證生成的密碼
46
49
  if (!this.isValid(shuffled)) {
47
- throw new Error('Generated password does not meet MSSQL complexity requirements');
50
+ throw new errors_1.AppError('Generated password does not meet MSSQL complexity requirements', {
51
+ exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR,
52
+ });
48
53
  }
49
54
  return new MssqlPassword(shuffled);
50
55
  }
51
56
  catch (error) {
52
- throw new Error(`Failed to generate MSSQL password: ${error instanceof Error ? error.message : String(error)}`);
57
+ throw new errors_1.AppError(`Failed to generate MSSQL password: ${error instanceof Error ? error.message : String(error)}`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
53
58
  }
54
59
  }
55
60
  /**
@@ -60,8 +65,8 @@ class MssqlPassword {
60
65
  */
61
66
  static create(password) {
62
67
  if (!this.isValid(password)) {
63
- throw new Error(`Invalid MSSQL password. Must be at least ${this.MIN_LENGTH} characters ` +
64
- `and contain at least 3 of: uppercase, lowercase, numbers, special characters.`);
68
+ throw new errors_1.AppError(`Invalid MSSQL password. Must be at least ${this.MIN_LENGTH} characters ` +
69
+ `and contain at least 3 of: uppercase, lowercase, numbers, special characters.`, { exitCode: errors_1.EXIT_CODES.VALIDATION_ERROR });
65
70
  }
66
71
  return new MssqlPassword(password);
67
72
  }
@@ -122,6 +127,23 @@ class MssqlPassword {
122
127
  const suffix = this.value.substring(this.value.length - 4);
123
128
  return `${prefix}******${suffix}`;
124
129
  }
130
+ /**
131
+ * 防止 JSON.stringify 意外洩露密碼,回傳遮罩值
132
+ * @returns 遮罩後的密碼字串
133
+ */
134
+ toJSON() {
135
+ return '***MASKED***';
136
+ }
137
+ /**
138
+ * 回傳可安全記錄到日志的物件
139
+ * 密碼欄位將被遮罩
140
+ * @returns 遮罩後的物件,可安全寫入日志
141
+ */
142
+ toSafeLog() {
143
+ return {
144
+ password: '***MASKED***',
145
+ };
146
+ }
125
147
  /**
126
148
  * 比較兩個密碼是否相等
127
149
  * @param other - 另一個密碼