@friggframework/devtools 2.0.0-next.45 → 2.0.0-next.47

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 (212) hide show
  1. package/infrastructure/ARCHITECTURE.md +487 -0
  2. package/infrastructure/HEALTH.md +468 -0
  3. package/infrastructure/README.md +51 -0
  4. package/infrastructure/__tests__/postgres-config.test.js +914 -0
  5. package/infrastructure/__tests__/template-generation.test.js +687 -0
  6. package/infrastructure/create-frigg-infrastructure.js +1 -1
  7. package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
  8. package/infrastructure/{DEPLOYMENT-INSTRUCTIONS.md → docs/deployment-instructions.md} +3 -3
  9. package/infrastructure/{IAM-POLICY-TEMPLATES.md → docs/iam-policy-templates.md} +9 -10
  10. package/infrastructure/domains/database/aurora-builder.js +809 -0
  11. package/infrastructure/domains/database/aurora-builder.test.js +950 -0
  12. package/infrastructure/domains/database/aurora-discovery.js +87 -0
  13. package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
  14. package/infrastructure/domains/database/aurora-resolver.js +210 -0
  15. package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
  16. package/infrastructure/domains/database/migration-builder.js +695 -0
  17. package/infrastructure/domains/database/migration-builder.test.js +294 -0
  18. package/infrastructure/domains/database/migration-resolver.js +163 -0
  19. package/infrastructure/domains/database/migration-resolver.test.js +337 -0
  20. package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
  21. package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
  22. package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
  23. package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
  24. package/infrastructure/domains/health/application/ports/index.js +26 -0
  25. package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
  26. package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
  27. package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
  28. package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
  29. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
  30. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
  31. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
  32. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
  33. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
  34. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
  35. package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
  36. package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
  37. package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
  38. package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
  39. package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
  40. package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
  41. package/infrastructure/domains/health/domain/entities/issue.js +299 -0
  42. package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
  43. package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
  44. package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
  45. package/infrastructure/domains/health/domain/entities/resource.js +159 -0
  46. package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
  47. package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
  48. package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
  49. package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
  50. package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
  51. package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
  52. package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
  53. package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
  54. package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
  55. package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
  56. package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
  57. package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
  58. package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
  59. package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
  60. package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
  61. package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
  62. package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
  63. package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
  64. package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
  65. package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
  66. package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
  67. package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
  68. package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
  69. package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
  70. package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
  71. package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
  72. package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
  73. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
  74. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
  75. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
  76. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
  77. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
  78. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
  79. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
  80. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
  81. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
  82. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
  83. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
  84. package/infrastructure/domains/integration/integration-builder.js +397 -0
  85. package/infrastructure/domains/integration/integration-builder.test.js +593 -0
  86. package/infrastructure/domains/integration/integration-resolver.js +170 -0
  87. package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
  88. package/infrastructure/domains/integration/websocket-builder.js +69 -0
  89. package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
  90. package/infrastructure/domains/networking/vpc-builder.js +1829 -0
  91. package/infrastructure/domains/networking/vpc-builder.test.js +1262 -0
  92. package/infrastructure/domains/networking/vpc-discovery.js +177 -0
  93. package/infrastructure/domains/networking/vpc-discovery.test.js +350 -0
  94. package/infrastructure/domains/networking/vpc-resolver.js +324 -0
  95. package/infrastructure/domains/networking/vpc-resolver.test.js +501 -0
  96. package/infrastructure/domains/parameters/ssm-builder.js +79 -0
  97. package/infrastructure/domains/parameters/ssm-builder.test.js +189 -0
  98. package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
  99. package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
  100. package/infrastructure/{iam-generator.js → domains/security/iam-generator.js} +2 -2
  101. package/infrastructure/domains/security/kms-builder.js +366 -0
  102. package/infrastructure/domains/security/kms-builder.test.js +374 -0
  103. package/infrastructure/domains/security/kms-discovery.js +80 -0
  104. package/infrastructure/domains/security/kms-discovery.test.js +177 -0
  105. package/infrastructure/domains/security/kms-resolver.js +96 -0
  106. package/infrastructure/domains/security/kms-resolver.test.js +216 -0
  107. package/infrastructure/domains/shared/base-builder.js +112 -0
  108. package/infrastructure/domains/shared/base-resolver.js +186 -0
  109. package/infrastructure/domains/shared/base-resolver.test.js +305 -0
  110. package/infrastructure/domains/shared/builder-orchestrator.js +212 -0
  111. package/infrastructure/domains/shared/builder-orchestrator.test.js +213 -0
  112. package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
  113. package/infrastructure/domains/shared/cloudformation-discovery.js +375 -0
  114. package/infrastructure/domains/shared/cloudformation-discovery.test.js +590 -0
  115. package/infrastructure/domains/shared/environment-builder.js +119 -0
  116. package/infrastructure/domains/shared/environment-builder.test.js +247 -0
  117. package/infrastructure/domains/shared/providers/aws-provider-adapter.js +544 -0
  118. package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +377 -0
  119. package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
  120. package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
  121. package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
  122. package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
  123. package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
  124. package/infrastructure/domains/shared/resource-discovery.js +192 -0
  125. package/infrastructure/domains/shared/resource-discovery.test.js +552 -0
  126. package/infrastructure/domains/shared/types/app-definition.js +205 -0
  127. package/infrastructure/domains/shared/types/discovery-result.js +106 -0
  128. package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
  129. package/infrastructure/domains/shared/types/index.js +46 -0
  130. package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
  131. package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
  132. package/infrastructure/domains/shared/utilities/base-definition-factory.js +380 -0
  133. package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
  134. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +248 -0
  135. package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
  136. package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
  137. package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +55 -0
  138. package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +138 -0
  139. package/infrastructure/{env-validator.js → domains/shared/validation/env-validator.js} +2 -1
  140. package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
  141. package/infrastructure/esbuild.config.js +53 -0
  142. package/infrastructure/infrastructure-composer.js +87 -0
  143. package/infrastructure/{serverless-template.test.js → infrastructure-composer.test.js} +115 -24
  144. package/infrastructure/scripts/build-prisma-layer.js +553 -0
  145. package/infrastructure/scripts/build-prisma-layer.test.js +102 -0
  146. package/infrastructure/{build-time-discovery.js → scripts/build-time-discovery.js} +80 -48
  147. package/infrastructure/{build-time-discovery.test.js → scripts/build-time-discovery.test.js} +5 -4
  148. package/layers/prisma/nodejs/package.json +8 -0
  149. package/management-ui/server/utils/cliIntegration.js +1 -1
  150. package/management-ui/server/utils/environment/awsParameterStore.js +29 -18
  151. package/package.json +11 -11
  152. package/frigg-cli/.eslintrc.js +0 -141
  153. package/frigg-cli/__tests__/unit/commands/build.test.js +0 -251
  154. package/frigg-cli/__tests__/unit/commands/db-setup.test.js +0 -548
  155. package/frigg-cli/__tests__/unit/commands/install.test.js +0 -400
  156. package/frigg-cli/__tests__/unit/commands/ui.test.js +0 -346
  157. package/frigg-cli/__tests__/unit/utils/database-validator.test.js +0 -366
  158. package/frigg-cli/__tests__/unit/utils/error-messages.test.js +0 -304
  159. package/frigg-cli/__tests__/unit/utils/prisma-runner.test.js +0 -486
  160. package/frigg-cli/__tests__/utils/mock-factory.js +0 -270
  161. package/frigg-cli/__tests__/utils/prisma-mock.js +0 -194
  162. package/frigg-cli/__tests__/utils/test-fixtures.js +0 -463
  163. package/frigg-cli/__tests__/utils/test-setup.js +0 -287
  164. package/frigg-cli/build-command/index.js +0 -65
  165. package/frigg-cli/db-setup-command/index.js +0 -193
  166. package/frigg-cli/deploy-command/index.js +0 -175
  167. package/frigg-cli/generate-command/__tests__/generate-command.test.js +0 -301
  168. package/frigg-cli/generate-command/azure-generator.js +0 -43
  169. package/frigg-cli/generate-command/gcp-generator.js +0 -47
  170. package/frigg-cli/generate-command/index.js +0 -332
  171. package/frigg-cli/generate-command/terraform-generator.js +0 -555
  172. package/frigg-cli/generate-iam-command.js +0 -118
  173. package/frigg-cli/index.js +0 -75
  174. package/frigg-cli/index.test.js +0 -158
  175. package/frigg-cli/init-command/backend-first-handler.js +0 -756
  176. package/frigg-cli/init-command/index.js +0 -93
  177. package/frigg-cli/init-command/template-handler.js +0 -143
  178. package/frigg-cli/install-command/backend-js.js +0 -33
  179. package/frigg-cli/install-command/commit-changes.js +0 -16
  180. package/frigg-cli/install-command/environment-variables.js +0 -127
  181. package/frigg-cli/install-command/environment-variables.test.js +0 -136
  182. package/frigg-cli/install-command/index.js +0 -54
  183. package/frigg-cli/install-command/install-package.js +0 -13
  184. package/frigg-cli/install-command/integration-file.js +0 -30
  185. package/frigg-cli/install-command/logger.js +0 -12
  186. package/frigg-cli/install-command/template.js +0 -90
  187. package/frigg-cli/install-command/validate-package.js +0 -75
  188. package/frigg-cli/jest.config.js +0 -124
  189. package/frigg-cli/package.json +0 -54
  190. package/frigg-cli/start-command/index.js +0 -149
  191. package/frigg-cli/start-command/start-command.test.js +0 -297
  192. package/frigg-cli/test/init-command.test.js +0 -180
  193. package/frigg-cli/test/npm-registry.test.js +0 -319
  194. package/frigg-cli/ui-command/index.js +0 -154
  195. package/frigg-cli/utils/app-resolver.js +0 -319
  196. package/frigg-cli/utils/backend-path.js +0 -25
  197. package/frigg-cli/utils/database-validator.js +0 -161
  198. package/frigg-cli/utils/error-messages.js +0 -257
  199. package/frigg-cli/utils/npm-registry.js +0 -167
  200. package/frigg-cli/utils/prisma-runner.js +0 -280
  201. package/frigg-cli/utils/process-manager.js +0 -199
  202. package/frigg-cli/utils/repo-detection.js +0 -405
  203. package/infrastructure/aws-discovery.js +0 -1176
  204. package/infrastructure/aws-discovery.test.js +0 -1220
  205. package/infrastructure/serverless-template.js +0 -2094
  206. /package/infrastructure/{WEBSOCKET-CONFIGURATION.md → docs/WEBSOCKET-CONFIGURATION.md} +0 -0
  207. /package/infrastructure/{GENERATE-IAM-DOCS.md → docs/generate-iam-command.md} +0 -0
  208. /package/infrastructure/{iam-generator.test.js → domains/security/iam-generator.test.js} +0 -0
  209. /package/infrastructure/{frigg-deployment-iam-stack.yaml → domains/security/templates/frigg-deployment-iam-stack.yaml} +0 -0
  210. /package/infrastructure/{iam-policy-basic.json → domains/security/templates/iam-policy-basic.json} +0 -0
  211. /package/infrastructure/{iam-policy-full.json → domains/security/templates/iam-policy-full.json} +0 -0
  212. /package/infrastructure/{run-discovery.js → scripts/run-discovery.js} +0 -0
@@ -0,0 +1,306 @@
1
+ /**
2
+ * StackHealthReport Aggregate Root
3
+ *
4
+ * Represents the complete health assessment of a CloudFormation stack,
5
+ * including all resources, detected issues, and overall health score.
6
+ *
7
+ * As an aggregate root, this entity controls access to Resource and Issue entities
8
+ * and maintains consistency across the entire health report.
9
+ */
10
+
11
+ const StackIdentifier = require('../value-objects/stack-identifier');
12
+ const HealthScore = require('../value-objects/health-score');
13
+ const Resource = require('./resource');
14
+ const Issue = require('./issue');
15
+
16
+ class StackHealthReport {
17
+ /**
18
+ * Create a new StackHealthReport
19
+ *
20
+ * @param {Object} params
21
+ * @param {StackIdentifier} params.stackIdentifier - Stack identifier
22
+ * @param {HealthScore} params.healthScore - Overall health score (0-100)
23
+ * @param {Resource[]} [params.resources=[]] - Resources in the stack
24
+ * @param {Issue[]} [params.issues=[]] - Detected issues
25
+ * @param {Date} [params.timestamp=new Date()] - When the health check was performed
26
+ * @param {Object} [params.metadata={}] - Additional metadata (e.g., scan duration)
27
+ */
28
+ constructor({
29
+ stackIdentifier,
30
+ healthScore,
31
+ resources = [],
32
+ issues = [],
33
+ timestamp = new Date(),
34
+ metadata = {},
35
+ }) {
36
+ // Validate required fields
37
+ if (!stackIdentifier) {
38
+ throw new Error('stackIdentifier is required');
39
+ }
40
+
41
+ if (!healthScore) {
42
+ throw new Error('healthScore is required');
43
+ }
44
+
45
+ if (!(stackIdentifier instanceof StackIdentifier)) {
46
+ throw new Error('stackIdentifier must be a StackIdentifier instance');
47
+ }
48
+
49
+ if (!(healthScore instanceof HealthScore)) {
50
+ throw new Error('healthScore must be a HealthScore instance');
51
+ }
52
+
53
+ // Validate resources array
54
+ if (!Array.isArray(resources)) {
55
+ throw new Error('resources must be an array');
56
+ }
57
+
58
+ for (const resource of resources) {
59
+ if (!(resource instanceof Resource)) {
60
+ throw new Error('All resources must be Resource instances');
61
+ }
62
+ }
63
+
64
+ // Validate issues array
65
+ if (!Array.isArray(issues)) {
66
+ throw new Error('issues must be an array');
67
+ }
68
+
69
+ for (const issue of issues) {
70
+ if (!(issue instanceof Issue)) {
71
+ throw new Error('All issues must be Issue instances');
72
+ }
73
+ }
74
+
75
+ this.stackIdentifier = stackIdentifier;
76
+ this.healthScore = healthScore;
77
+ this.resources = [...resources]; // Copy to prevent external mutation
78
+ this.issues = [...issues]; // Copy to prevent external mutation
79
+ this.timestamp = timestamp;
80
+ this.metadata = metadata;
81
+ }
82
+
83
+ // ========================================
84
+ // Resource Queries
85
+ // ========================================
86
+
87
+ /**
88
+ * Get all orphaned resources (exist in cloud but not in stack)
89
+ * @returns {Resource[]}
90
+ */
91
+ getOrphanedResources() {
92
+ return this.resources.filter((r) => r.isOrphaned());
93
+ }
94
+
95
+ /**
96
+ * Get all missing resources (in stack but not in cloud)
97
+ * @returns {Resource[]}
98
+ */
99
+ getMissingResources() {
100
+ return this.resources.filter((r) => r.isMissing());
101
+ }
102
+
103
+ /**
104
+ * Get all drifted resources (properties differ)
105
+ * @returns {Resource[]}
106
+ */
107
+ getDriftedResources() {
108
+ return this.resources.filter((r) => r.isDrifted());
109
+ }
110
+
111
+ /**
112
+ * Get all healthy resources (in stack with no issues)
113
+ * @returns {Resource[]}
114
+ */
115
+ getHealthyResources() {
116
+ return this.resources.filter((r) => r.isInStack() && r.isHealthy());
117
+ }
118
+
119
+ /**
120
+ * Get all resources that are in the stack
121
+ * @returns {Resource[]}
122
+ */
123
+ getResourcesInStack() {
124
+ return this.resources.filter((r) => r.isInStack());
125
+ }
126
+
127
+ /**
128
+ * Get total resource count
129
+ * @returns {number}
130
+ */
131
+ getResourceCount() {
132
+ return this.resources.length;
133
+ }
134
+
135
+ /**
136
+ * Get count of orphaned resources
137
+ * @returns {number}
138
+ */
139
+ getOrphanedResourceCount() {
140
+ return this.getOrphanedResources().length;
141
+ }
142
+
143
+ /**
144
+ * Get count of missing resources
145
+ * @returns {number}
146
+ */
147
+ getMissingResourceCount() {
148
+ return this.getMissingResources().length;
149
+ }
150
+
151
+ /**
152
+ * Get count of drifted resources
153
+ * @returns {number}
154
+ */
155
+ getDriftedResourceCount() {
156
+ return this.getDriftedResources().length;
157
+ }
158
+
159
+ // ========================================
160
+ // Issue Queries
161
+ // ========================================
162
+
163
+ /**
164
+ * Get all critical issues
165
+ * @returns {Issue[]}
166
+ */
167
+ getCriticalIssues() {
168
+ return this.issues.filter((i) => i.isCritical());
169
+ }
170
+
171
+ /**
172
+ * Get all warning-level issues
173
+ * @returns {Issue[]}
174
+ */
175
+ getWarnings() {
176
+ return this.issues.filter((i) => i.isWarning());
177
+ }
178
+
179
+ /**
180
+ * Get all info-level issues
181
+ * @returns {Issue[]}
182
+ */
183
+ getInfoIssues() {
184
+ return this.issues.filter((i) => i.isInfo());
185
+ }
186
+
187
+ /**
188
+ * Get total issue count
189
+ * @returns {number}
190
+ */
191
+ getIssueCount() {
192
+ return this.issues.length;
193
+ }
194
+
195
+ /**
196
+ * Get count of critical issues
197
+ * @returns {number}
198
+ */
199
+ getCriticalIssueCount() {
200
+ return this.getCriticalIssues().length;
201
+ }
202
+
203
+ /**
204
+ * Get count of warnings
205
+ * @returns {number}
206
+ */
207
+ getWarningCount() {
208
+ return this.getWarnings().length;
209
+ }
210
+
211
+ /**
212
+ * Get count of info issues
213
+ * @returns {number}
214
+ */
215
+ getInfoIssueCount() {
216
+ return this.getInfoIssues().length;
217
+ }
218
+
219
+ /**
220
+ * Check if report has any critical issues
221
+ * @returns {boolean}
222
+ */
223
+ hasCriticalIssues() {
224
+ return this.getCriticalIssueCount() > 0;
225
+ }
226
+
227
+ // ========================================
228
+ // Health Assessment
229
+ // ========================================
230
+
231
+ /**
232
+ * Check if stack is healthy (score >= 80)
233
+ * @returns {boolean}
234
+ */
235
+ isHealthy() {
236
+ return this.healthScore.isHealthy();
237
+ }
238
+
239
+ /**
240
+ * Get qualitative health assessment
241
+ * @returns {string} 'healthy', 'degraded', or 'unhealthy'
242
+ */
243
+ getQualitativeAssessment() {
244
+ return this.healthScore.qualitativeAssessment();
245
+ }
246
+
247
+ // ========================================
248
+ // Summary
249
+ // ========================================
250
+
251
+ /**
252
+ * Get summary statistics for the health report
253
+ * @returns {Object}
254
+ */
255
+ getSummary() {
256
+ return {
257
+ stackName: this.stackIdentifier.stackName,
258
+ region: this.stackIdentifier.region,
259
+ healthScore: this.healthScore.value,
260
+ qualitativeAssessment: this.getQualitativeAssessment(),
261
+ isHealthy: this.isHealthy(),
262
+ resourceCount: this.getResourceCount(),
263
+ issueCount: this.getIssueCount(),
264
+ criticalIssueCount: this.getCriticalIssueCount(),
265
+ warningCount: this.getWarningCount(),
266
+ orphanedResourceCount: this.getOrphanedResourceCount(),
267
+ missingResourceCount: this.getMissingResourceCount(),
268
+ driftedResourceCount: this.getDriftedResourceCount(),
269
+ timestamp: this.timestamp.toISOString(),
270
+ };
271
+ }
272
+
273
+ // ========================================
274
+ // Serialization
275
+ // ========================================
276
+
277
+ /**
278
+ * Get string representation
279
+ * @returns {string}
280
+ */
281
+ toString() {
282
+ return `StackHealthReport: ${this.stackIdentifier.toString()} - Score: ${this.healthScore.value} (${this.getQualitativeAssessment()}) - Resources: ${this.getResourceCount()}, Issues: ${this.getIssueCount()}`;
283
+ }
284
+
285
+ /**
286
+ * Serialize to JSON
287
+ * @returns {Object}
288
+ */
289
+ toJSON() {
290
+ return {
291
+ stackIdentifier: this.stackIdentifier.toJSON(),
292
+ healthScore: this.healthScore.value,
293
+ qualitativeAssessment: this.getQualitativeAssessment(),
294
+ isHealthy: this.isHealthy(),
295
+ resources: this.resources.map((r) => r.toJSON()),
296
+ issues: this.issues.map((i) => i.toJSON()),
297
+ resourceCount: this.getResourceCount(),
298
+ issueCount: this.getIssueCount(),
299
+ summary: this.getSummary(),
300
+ timestamp: this.timestamp.toISOString(),
301
+ metadata: this.metadata,
302
+ };
303
+ }
304
+ }
305
+
306
+ module.exports = StackHealthReport;