@friggframework/devtools 2.0.0-next.60 → 2.0.0-next.62

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 (305) hide show
  1. package/package.json +14 -7
  2. package/.eslintrc.json +0 -3
  3. package/CHANGELOG.md +0 -132
  4. package/infrastructure/ARCHITECTURE.md +0 -487
  5. package/infrastructure/CLAUDE.md +0 -481
  6. package/infrastructure/HEALTH.md +0 -468
  7. package/infrastructure/README.md +0 -522
  8. package/infrastructure/__tests__/fixtures/mock-aws-resources.js +0 -391
  9. package/infrastructure/__tests__/helpers/test-utils.js +0 -277
  10. package/infrastructure/__tests__/postgres-config.test.js +0 -914
  11. package/infrastructure/__tests__/template-generation.test.js +0 -687
  12. package/infrastructure/create-frigg-infrastructure.js +0 -147
  13. package/infrastructure/docs/POSTGRES-CONFIGURATION.md +0 -630
  14. package/infrastructure/docs/PRE-DEPLOYMENT-HEALTH-CHECK-SPEC.md +0 -1317
  15. package/infrastructure/docs/WEBSOCKET-CONFIGURATION.md +0 -105
  16. package/infrastructure/docs/deployment-instructions.md +0 -268
  17. package/infrastructure/docs/generate-iam-command.md +0 -278
  18. package/infrastructure/docs/iam-policy-templates.md +0 -193
  19. package/infrastructure/domains/database/aurora-builder.js +0 -809
  20. package/infrastructure/domains/database/aurora-builder.test.js +0 -950
  21. package/infrastructure/domains/database/aurora-discovery.js +0 -87
  22. package/infrastructure/domains/database/aurora-discovery.test.js +0 -188
  23. package/infrastructure/domains/database/aurora-resolver.js +0 -210
  24. package/infrastructure/domains/database/aurora-resolver.test.js +0 -347
  25. package/infrastructure/domains/database/migration-builder.js +0 -701
  26. package/infrastructure/domains/database/migration-builder.test.js +0 -321
  27. package/infrastructure/domains/database/migration-resolver.js +0 -163
  28. package/infrastructure/domains/database/migration-resolver.test.js +0 -337
  29. package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +0 -164
  30. package/infrastructure/domains/health/application/ports/IResourceDetector.js +0 -129
  31. package/infrastructure/domains/health/application/ports/IResourceImporter.js +0 -142
  32. package/infrastructure/domains/health/application/ports/IStackRepository.js +0 -131
  33. package/infrastructure/domains/health/application/ports/index.js +0 -26
  34. package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +0 -679
  35. package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +0 -167
  36. package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +0 -1130
  37. package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +0 -221
  38. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +0 -152
  39. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +0 -343
  40. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +0 -535
  41. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +0 -376
  42. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +0 -213
  43. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +0 -441
  44. package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +0 -267
  45. package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +0 -324
  46. package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +0 -386
  47. package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +0 -1419
  48. package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +0 -391
  49. package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +0 -551
  50. package/infrastructure/domains/health/domain/entities/issue.js +0 -299
  51. package/infrastructure/domains/health/domain/entities/issue.test.js +0 -528
  52. package/infrastructure/domains/health/domain/entities/property-mismatch.js +0 -108
  53. package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +0 -275
  54. package/infrastructure/domains/health/domain/entities/resource.js +0 -159
  55. package/infrastructure/domains/health/domain/entities/resource.test.js +0 -432
  56. package/infrastructure/domains/health/domain/entities/stack-health-report.js +0 -306
  57. package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +0 -601
  58. package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +0 -380
  59. package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +0 -971
  60. package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +0 -1150
  61. package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +0 -672
  62. package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +0 -496
  63. package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +0 -419
  64. package/infrastructure/domains/health/domain/services/health-score-calculator.js +0 -248
  65. package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +0 -504
  66. package/infrastructure/domains/health/domain/services/import-progress-monitor.js +0 -195
  67. package/infrastructure/domains/health/domain/services/import-template-generator.js +0 -435
  68. package/infrastructure/domains/health/domain/services/logical-id-mapper.js +0 -345
  69. package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +0 -234
  70. package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +0 -431
  71. package/infrastructure/domains/health/domain/services/property-mutability-config.js +0 -382
  72. package/infrastructure/domains/health/domain/services/template-parser.js +0 -245
  73. package/infrastructure/domains/health/domain/services/update-progress-monitor.js +0 -192
  74. package/infrastructure/domains/health/domain/value-objects/health-score.js +0 -138
  75. package/infrastructure/domains/health/domain/value-objects/health-score.test.js +0 -267
  76. package/infrastructure/domains/health/domain/value-objects/property-mutability.js +0 -161
  77. package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +0 -198
  78. package/infrastructure/domains/health/domain/value-objects/resource-state.js +0 -167
  79. package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +0 -196
  80. package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +0 -192
  81. package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +0 -262
  82. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +0 -312
  83. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +0 -367
  84. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +0 -432
  85. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +0 -784
  86. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +0 -1133
  87. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +0 -565
  88. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +0 -554
  89. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +0 -318
  90. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +0 -398
  91. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +0 -777
  92. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +0 -580
  93. package/infrastructure/domains/integration/integration-builder.js +0 -404
  94. package/infrastructure/domains/integration/integration-builder.test.js +0 -690
  95. package/infrastructure/domains/integration/integration-resolver.js +0 -170
  96. package/infrastructure/domains/integration/integration-resolver.test.js +0 -369
  97. package/infrastructure/domains/integration/websocket-builder.js +0 -69
  98. package/infrastructure/domains/integration/websocket-builder.test.js +0 -195
  99. package/infrastructure/domains/networking/vpc-builder.js +0 -2051
  100. package/infrastructure/domains/networking/vpc-builder.test.js +0 -1960
  101. package/infrastructure/domains/networking/vpc-discovery.js +0 -177
  102. package/infrastructure/domains/networking/vpc-discovery.test.js +0 -350
  103. package/infrastructure/domains/networking/vpc-resolver.js +0 -505
  104. package/infrastructure/domains/networking/vpc-resolver.test.js +0 -801
  105. package/infrastructure/domains/parameters/ssm-builder.js +0 -79
  106. package/infrastructure/domains/parameters/ssm-builder.test.js +0 -189
  107. package/infrastructure/domains/parameters/ssm-discovery.js +0 -84
  108. package/infrastructure/domains/parameters/ssm-discovery.test.js +0 -210
  109. package/infrastructure/domains/security/iam-generator.js +0 -816
  110. package/infrastructure/domains/security/iam-generator.test.js +0 -204
  111. package/infrastructure/domains/security/kms-builder.js +0 -415
  112. package/infrastructure/domains/security/kms-builder.test.js +0 -392
  113. package/infrastructure/domains/security/kms-discovery.js +0 -80
  114. package/infrastructure/domains/security/kms-discovery.test.js +0 -177
  115. package/infrastructure/domains/security/kms-resolver.js +0 -96
  116. package/infrastructure/domains/security/kms-resolver.test.js +0 -216
  117. package/infrastructure/domains/security/templates/frigg-deployment-iam-stack.yaml +0 -401
  118. package/infrastructure/domains/security/templates/iam-policy-basic.json +0 -218
  119. package/infrastructure/domains/security/templates/iam-policy-full.json +0 -288
  120. package/infrastructure/domains/shared/base-builder.js +0 -112
  121. package/infrastructure/domains/shared/base-resolver.js +0 -186
  122. package/infrastructure/domains/shared/base-resolver.test.js +0 -305
  123. package/infrastructure/domains/shared/builder-orchestrator.js +0 -212
  124. package/infrastructure/domains/shared/builder-orchestrator.test.js +0 -213
  125. package/infrastructure/domains/shared/cloudformation-discovery-v2.js +0 -334
  126. package/infrastructure/domains/shared/cloudformation-discovery.js +0 -672
  127. package/infrastructure/domains/shared/cloudformation-discovery.test.js +0 -985
  128. package/infrastructure/domains/shared/environment-builder.js +0 -119
  129. package/infrastructure/domains/shared/environment-builder.test.js +0 -247
  130. package/infrastructure/domains/shared/providers/aws-provider-adapter.js +0 -579
  131. package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +0 -416
  132. package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +0 -93
  133. package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +0 -136
  134. package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +0 -82
  135. package/infrastructure/domains/shared/providers/provider-factory.js +0 -108
  136. package/infrastructure/domains/shared/providers/provider-factory.test.js +0 -170
  137. package/infrastructure/domains/shared/resource-discovery.enhanced.test.js +0 -306
  138. package/infrastructure/domains/shared/resource-discovery.js +0 -233
  139. package/infrastructure/domains/shared/resource-discovery.test.js +0 -588
  140. package/infrastructure/domains/shared/types/app-definition.js +0 -205
  141. package/infrastructure/domains/shared/types/discovery-result.js +0 -106
  142. package/infrastructure/domains/shared/types/discovery-result.test.js +0 -258
  143. package/infrastructure/domains/shared/types/index.js +0 -46
  144. package/infrastructure/domains/shared/types/resource-ownership.js +0 -108
  145. package/infrastructure/domains/shared/types/resource-ownership.test.js +0 -101
  146. package/infrastructure/domains/shared/utilities/base-definition-factory.js +0 -394
  147. package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +0 -338
  148. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +0 -291
  149. package/infrastructure/domains/shared/utilities/handler-path-resolver.js +0 -134
  150. package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +0 -268
  151. package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +0 -159
  152. package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +0 -444
  153. package/infrastructure/domains/shared/validation/env-validator.js +0 -78
  154. package/infrastructure/domains/shared/validation/env-validator.test.js +0 -173
  155. package/infrastructure/domains/shared/validation/plugin-validator.js +0 -187
  156. package/infrastructure/domains/shared/validation/plugin-validator.test.js +0 -323
  157. package/infrastructure/esbuild.config.js +0 -53
  158. package/infrastructure/index.js +0 -4
  159. package/infrastructure/infrastructure-composer.js +0 -117
  160. package/infrastructure/infrastructure-composer.test.js +0 -1895
  161. package/infrastructure/integration.test.js +0 -383
  162. package/infrastructure/scripts/build-prisma-layer.js +0 -701
  163. package/infrastructure/scripts/build-prisma-layer.test.js +0 -170
  164. package/infrastructure/scripts/build-time-discovery.js +0 -238
  165. package/infrastructure/scripts/build-time-discovery.test.js +0 -379
  166. package/infrastructure/scripts/run-discovery.js +0 -110
  167. package/infrastructure/scripts/verify-prisma-layer.js +0 -72
  168. package/layers/prisma/.build-complete +0 -3
  169. package/layers/prisma/nodejs/package.json +0 -8
  170. package/management-ui/.eslintrc.js +0 -22
  171. package/management-ui/components.json +0 -21
  172. package/management-ui/docs/phase2-integration-guide.md +0 -320
  173. package/management-ui/index.html +0 -13
  174. package/management-ui/package.json +0 -76
  175. package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +0 -302
  176. package/management-ui/postcss.config.js +0 -6
  177. package/management-ui/server/api/backend.js +0 -256
  178. package/management-ui/server/api/cli.js +0 -315
  179. package/management-ui/server/api/codegen.js +0 -663
  180. package/management-ui/server/api/connections.js +0 -857
  181. package/management-ui/server/api/discovery.js +0 -185
  182. package/management-ui/server/api/environment/index.js +0 -1
  183. package/management-ui/server/api/environment/router.js +0 -378
  184. package/management-ui/server/api/environment.js +0 -328
  185. package/management-ui/server/api/integrations.js +0 -876
  186. package/management-ui/server/api/logs.js +0 -248
  187. package/management-ui/server/api/monitoring.js +0 -282
  188. package/management-ui/server/api/open-ide.js +0 -31
  189. package/management-ui/server/api/project.js +0 -1029
  190. package/management-ui/server/api/users/sessions.js +0 -371
  191. package/management-ui/server/api/users/simulation.js +0 -254
  192. package/management-ui/server/api/users.js +0 -362
  193. package/management-ui/server/api-contract.md +0 -275
  194. package/management-ui/server/index.js +0 -873
  195. package/management-ui/server/middleware/errorHandler.js +0 -93
  196. package/management-ui/server/middleware/security.js +0 -32
  197. package/management-ui/server/processManager.js +0 -296
  198. package/management-ui/server/server.js +0 -346
  199. package/management-ui/server/services/aws-monitor.js +0 -413
  200. package/management-ui/server/services/npm-registry.js +0 -347
  201. package/management-ui/server/services/template-engine.js +0 -538
  202. package/management-ui/server/utils/cliIntegration.js +0 -220
  203. package/management-ui/server/utils/environment/auditLogger.js +0 -471
  204. package/management-ui/server/utils/environment/awsParameterStore.js +0 -275
  205. package/management-ui/server/utils/environment/encryption.js +0 -278
  206. package/management-ui/server/utils/environment/envFileManager.js +0 -286
  207. package/management-ui/server/utils/import-commonjs.js +0 -28
  208. package/management-ui/server/utils/response.js +0 -83
  209. package/management-ui/server/websocket/handler.js +0 -325
  210. package/management-ui/src/App.jsx +0 -25
  211. package/management-ui/src/assets/FriggLogo.svg +0 -1
  212. package/management-ui/src/components/AppRouter.jsx +0 -65
  213. package/management-ui/src/components/Button.jsx +0 -70
  214. package/management-ui/src/components/Card.jsx +0 -97
  215. package/management-ui/src/components/EnvironmentCompare.jsx +0 -400
  216. package/management-ui/src/components/EnvironmentEditor.jsx +0 -372
  217. package/management-ui/src/components/EnvironmentImportExport.jsx +0 -469
  218. package/management-ui/src/components/EnvironmentSchema.jsx +0 -491
  219. package/management-ui/src/components/EnvironmentSecurity.jsx +0 -463
  220. package/management-ui/src/components/ErrorBoundary.jsx +0 -73
  221. package/management-ui/src/components/IntegrationCard.jsx +0 -481
  222. package/management-ui/src/components/IntegrationCardEnhanced.jsx +0 -770
  223. package/management-ui/src/components/IntegrationExplorer.jsx +0 -379
  224. package/management-ui/src/components/IntegrationStatus.jsx +0 -336
  225. package/management-ui/src/components/Layout.jsx +0 -716
  226. package/management-ui/src/components/LoadingSpinner.jsx +0 -113
  227. package/management-ui/src/components/RepositoryPicker.jsx +0 -248
  228. package/management-ui/src/components/SessionMonitor.jsx +0 -350
  229. package/management-ui/src/components/StatusBadge.jsx +0 -208
  230. package/management-ui/src/components/UserContextSwitcher.jsx +0 -212
  231. package/management-ui/src/components/UserSimulation.jsx +0 -327
  232. package/management-ui/src/components/Welcome.jsx +0 -434
  233. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +0 -637
  234. package/management-ui/src/components/codegen/APIModuleSelector.jsx +0 -227
  235. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +0 -247
  236. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +0 -316
  237. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +0 -271
  238. package/management-ui/src/components/codegen/FormBuilder.jsx +0 -737
  239. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +0 -855
  240. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +0 -797
  241. package/management-ui/src/components/codegen/SchemaBuilder.jsx +0 -303
  242. package/management-ui/src/components/codegen/TemplateSelector.jsx +0 -586
  243. package/management-ui/src/components/codegen/index.js +0 -10
  244. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +0 -362
  245. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +0 -182
  246. package/management-ui/src/components/connections/ConnectionTester.jsx +0 -200
  247. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +0 -292
  248. package/management-ui/src/components/connections/OAuthFlow.jsx +0 -204
  249. package/management-ui/src/components/connections/index.js +0 -5
  250. package/management-ui/src/components/index.js +0 -21
  251. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +0 -222
  252. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +0 -169
  253. package/management-ui/src/components/monitoring/MetricsChart.jsx +0 -197
  254. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +0 -393
  255. package/management-ui/src/components/monitoring/SQSMetrics.jsx +0 -246
  256. package/management-ui/src/components/monitoring/index.js +0 -6
  257. package/management-ui/src/components/monitoring/monitoring.css +0 -218
  258. package/management-ui/src/components/theme-provider.jsx +0 -52
  259. package/management-ui/src/components/theme-toggle.jsx +0 -39
  260. package/management-ui/src/components/ui/badge.tsx +0 -36
  261. package/management-ui/src/components/ui/button.test.jsx +0 -56
  262. package/management-ui/src/components/ui/button.tsx +0 -57
  263. package/management-ui/src/components/ui/card.tsx +0 -76
  264. package/management-ui/src/components/ui/dropdown-menu.tsx +0 -199
  265. package/management-ui/src/components/ui/select.tsx +0 -157
  266. package/management-ui/src/components/ui/skeleton.jsx +0 -15
  267. package/management-ui/src/hooks/useFrigg.jsx +0 -387
  268. package/management-ui/src/hooks/useSocket.jsx +0 -58
  269. package/management-ui/src/index.css +0 -193
  270. package/management-ui/src/lib/utils.ts +0 -6
  271. package/management-ui/src/main.jsx +0 -10
  272. package/management-ui/src/pages/CodeGeneration.jsx +0 -14
  273. package/management-ui/src/pages/Connections.jsx +0 -252
  274. package/management-ui/src/pages/ConnectionsEnhanced.jsx +0 -633
  275. package/management-ui/src/pages/Dashboard.jsx +0 -311
  276. package/management-ui/src/pages/Environment.jsx +0 -314
  277. package/management-ui/src/pages/IntegrationConfigure.jsx +0 -669
  278. package/management-ui/src/pages/IntegrationDiscovery.jsx +0 -567
  279. package/management-ui/src/pages/IntegrationTest.jsx +0 -742
  280. package/management-ui/src/pages/Integrations.jsx +0 -253
  281. package/management-ui/src/pages/Monitoring.jsx +0 -17
  282. package/management-ui/src/pages/Simulation.jsx +0 -155
  283. package/management-ui/src/pages/Users.jsx +0 -492
  284. package/management-ui/src/services/api.js +0 -41
  285. package/management-ui/src/services/apiModuleService.js +0 -193
  286. package/management-ui/src/services/websocket-handlers.js +0 -120
  287. package/management-ui/src/test/api/project.test.js +0 -273
  288. package/management-ui/src/test/components/Welcome.test.jsx +0 -378
  289. package/management-ui/src/test/mocks/server.js +0 -178
  290. package/management-ui/src/test/setup.js +0 -61
  291. package/management-ui/src/test/utils/test-utils.jsx +0 -134
  292. package/management-ui/src/utils/repository.js +0 -98
  293. package/management-ui/src/utils/repository.test.js +0 -118
  294. package/management-ui/src/workflows/phase2-integration-workflows.js +0 -884
  295. package/management-ui/tailwind.config.js +0 -63
  296. package/management-ui/tsconfig.json +0 -37
  297. package/management-ui/tsconfig.node.json +0 -10
  298. package/management-ui/vite.config.js +0 -26
  299. package/management-ui/vitest.config.js +0 -38
  300. package/test/auther-definition-method-tester.js +0 -45
  301. package/test/index.js +0 -9
  302. package/test/integration-validator.js +0 -2
  303. package/test/mock-api-readme.md +0 -102
  304. package/test/mock-api.js +0 -284
  305. package/test/mock-integration.js +0 -78
@@ -1,784 +0,0 @@
1
- /**
2
- * AWSPropertyReconciler - AWS Property Drift Reconciliation Adapter
3
- *
4
- * Infrastructure Adapter - Hexagonal Architecture
5
- *
6
- * Implements IPropertyReconciler port for AWS.
7
- * Handles property drift reconciliation via template or resource updates.
8
- *
9
- * Lazy-loads AWS SDK to minimize cold start time and memory usage.
10
- */
11
-
12
- const IPropertyReconciler = require('../../application/ports/IPropertyReconciler');
13
-
14
- // Lazy-loaded AWS SDK clients
15
- let CloudFormationClient, UpdateStackCommand, GetTemplateCommand;
16
- let EC2Client, ModifyVpcAttributeCommand;
17
- let LambdaClient, UpdateFunctionConfigurationCommand;
18
-
19
- /**
20
- * Lazy load CloudFormation SDK
21
- */
22
- function loadCloudFormation() {
23
- if (!CloudFormationClient) {
24
- const cfModule = require('@aws-sdk/client-cloudformation');
25
- CloudFormationClient = cfModule.CloudFormationClient;
26
- UpdateStackCommand = cfModule.UpdateStackCommand;
27
- GetTemplateCommand = cfModule.GetTemplateCommand;
28
- }
29
- }
30
-
31
- /**
32
- * Lazy load EC2 SDK
33
- */
34
- function loadEC2() {
35
- if (!EC2Client) {
36
- const ec2Module = require('@aws-sdk/client-ec2');
37
- EC2Client = ec2Module.EC2Client;
38
- ModifyVpcAttributeCommand = ec2Module.ModifyVpcAttributeCommand;
39
- }
40
- }
41
-
42
- /**
43
- * Lazy load Lambda SDK
44
- */
45
- function loadLambda() {
46
- if (!LambdaClient) {
47
- const lambdaModule = require('@aws-sdk/client-lambda');
48
- LambdaClient = lambdaModule.LambdaClient;
49
- UpdateFunctionConfigurationCommand = lambdaModule.UpdateFunctionConfigurationCommand;
50
- }
51
- }
52
-
53
- class AWSPropertyReconciler extends IPropertyReconciler {
54
- /**
55
- * Resource types that support reconciliation
56
- * @private
57
- */
58
- static SUPPORTED_TYPES = {
59
- 'AWS::EC2::VPC': {
60
- templateUpdate: true,
61
- resourceUpdate: true,
62
- recommendedMode: 'template',
63
- limitations: ['Some VPC properties require resource replacement (e.g., CidrBlock)'],
64
- },
65
- 'AWS::EC2::Subnet': {
66
- templateUpdate: true,
67
- resourceUpdate: false,
68
- recommendedMode: 'template',
69
- limitations: ['Most Subnet properties are immutable'],
70
- },
71
- 'AWS::EC2::SecurityGroup': {
72
- templateUpdate: true,
73
- resourceUpdate: true,
74
- recommendedMode: 'template',
75
- limitations: ['Rule changes may cause brief connectivity interruption'],
76
- },
77
- 'AWS::EC2::RouteTable': {
78
- templateUpdate: true,
79
- resourceUpdate: false,
80
- recommendedMode: 'template',
81
- limitations: ['Route changes require CloudFormation update'],
82
- },
83
- 'AWS::RDS::DBCluster': {
84
- templateUpdate: true,
85
- resourceUpdate: false,
86
- recommendedMode: 'template',
87
- limitations: ['Many DBCluster properties require specific update windows'],
88
- },
89
- 'AWS::KMS::Key': {
90
- templateUpdate: true,
91
- resourceUpdate: false,
92
- recommendedMode: 'template',
93
- limitations: ['Key policy changes must be done via CloudFormation'],
94
- },
95
- 'AWS::Lambda::Function': {
96
- templateUpdate: true,
97
- resourceUpdate: true,
98
- recommendedMode: 'template',
99
- limitations: [
100
- 'VpcConfig changes may take several minutes to propagate',
101
- 'Code updates are handled separately via UpdateFunctionCode',
102
- 'Environment variable changes may cause brief invocation errors during update',
103
- ],
104
- },
105
- };
106
-
107
- /**
108
- * Create AWS Property Reconciler
109
- *
110
- * @param {Object} [config={}]
111
- * @param {string} [config.region] - AWS region (defaults to AWS_REGION env var)
112
- * @param {Object} [config.cloudFormationRepository] - CloudFormation repository for monitoring
113
- */
114
- constructor(config = {}) {
115
- super();
116
- this.region = config.region || process.env.AWS_REGION || 'us-east-1';
117
- this.cfClient = null;
118
- this.ec2Client = null;
119
- this.lambdaClient = null;
120
- this.cfRepo = config.cloudFormationRepository || null;
121
- }
122
-
123
- /**
124
- * Get or create CloudFormation client
125
- * @private
126
- */
127
- _getCFClient() {
128
- if (!this.cfClient) {
129
- loadCloudFormation();
130
- this.cfClient = new CloudFormationClient({ region: this.region });
131
- }
132
- return this.cfClient;
133
- }
134
-
135
- /**
136
- * Get or create EC2 client
137
- * @private
138
- */
139
- _getEC2Client() {
140
- if (!this.ec2Client) {
141
- loadEC2();
142
- this.ec2Client = new EC2Client({ region: this.region });
143
- }
144
- return this.ec2Client;
145
- }
146
-
147
- /**
148
- * Get or create Lambda client
149
- * @private
150
- */
151
- _getLambdaClient() {
152
- if (!this.lambdaClient) {
153
- loadLambda();
154
- this.lambdaClient = new LambdaClient({ region: this.region });
155
- }
156
- return this.lambdaClient;
157
- }
158
-
159
- /**
160
- * Check if a property mismatch can be auto-fixed
161
- */
162
- async canReconcile(mismatch) {
163
- // Immutable properties cannot be reconciled (require replacement)
164
- if (mismatch.requiresReplacement()) {
165
- return false;
166
- }
167
-
168
- // Mutable and conditional properties can be reconciled
169
- // Note: CONDITIONAL may require additional validation, but we treat it as reconcilable
170
- return true;
171
- }
172
-
173
- /**
174
- * Reconcile a single property mismatch
175
- */
176
- async reconcileProperty({ stackIdentifier, logicalId, mismatch, mode = 'template' }) {
177
- if (mode === 'template') {
178
- return await this._reconcileViaTemplate({
179
- stackIdentifier,
180
- logicalId,
181
- mismatch,
182
- });
183
- } else {
184
- return await this._reconcileViaResource({
185
- stackIdentifier,
186
- logicalId,
187
- mismatch,
188
- });
189
- }
190
- }
191
-
192
- /**
193
- * Reconcile multiple property mismatches for a resource
194
- *
195
- * IMPORTANT: Batches all property updates into a SINGLE UpdateStack call
196
- * to avoid "stack is already updating" errors from CloudFormation.
197
- *
198
- * MONITORING: After calling UpdateStack, monitors the stack until UPDATE_COMPLETE
199
- * or UPDATE_FAILED to ensure the update actually succeeded.
200
- */
201
- async reconcileMultipleProperties({
202
- stackIdentifier,
203
- logicalId,
204
- physicalId,
205
- resourceType,
206
- mismatches,
207
- mode = 'template',
208
- progressMonitor = null, // Optional UpdateProgressMonitor for async tracking
209
- }) {
210
- // Route to appropriate reconciliation method based on mode
211
- if (mode === 'resource') {
212
- return await this._reconcileMultiplePropertiesViaResource({
213
- stackIdentifier,
214
- logicalId,
215
- physicalId,
216
- resourceType,
217
- mismatches,
218
- });
219
- }
220
-
221
- // Template mode (original implementation)
222
- const results = [];
223
- let reconciledCount = 0;
224
- let failedCount = 0;
225
-
226
- try {
227
- const client = this._getCFClient();
228
-
229
- // 1. Get current template ONCE
230
- const getTemplateCommand = new GetTemplateCommand({
231
- StackName: stackIdentifier.stackName,
232
- TemplateStage: 'Original',
233
- });
234
-
235
- const templateResponse = await client.send(getTemplateCommand);
236
- const template = JSON.parse(templateResponse.TemplateBody);
237
-
238
- // 2. Apply ALL property changes to the template
239
- for (const mismatch of mismatches) {
240
- try {
241
- // Navigate to the property in the template
242
- // AWS drift detection returns paths without 'Properties.' prefix (e.g., 'VpcConfig.SubnetIds')
243
- // But CloudFormation templates have 'Properties' section, so we need to navigate there
244
- const pathParts = mismatch.propertyPath.split('.');
245
- let current = template.Resources[logicalId];
246
-
247
- // Ensure Properties section exists
248
- if (!current.Properties) {
249
- current.Properties = {};
250
- }
251
-
252
- // Start navigation at Properties level
253
- current = current.Properties;
254
-
255
- // Create nested objects if they don't exist
256
- for (let i = 0; i < pathParts.length - 1; i++) {
257
- if (!current[pathParts[i]]) {
258
- current[pathParts[i]] = {};
259
- }
260
- current = current[pathParts[i]];
261
- }
262
-
263
- // Update the property value
264
- const lastPart = pathParts[pathParts.length - 1];
265
- current[lastPart] = mismatch.actualValue;
266
-
267
- // Track as pending (will be confirmed by monitor)
268
- results.push({
269
- success: true,
270
- mode: 'template',
271
- propertyPath: mismatch.propertyPath,
272
- oldValue: mismatch.expectedValue,
273
- newValue: mismatch.actualValue,
274
- message: 'Property updated in template',
275
- });
276
- reconciledCount++;
277
- } catch (error) {
278
- // Track as failed
279
- results.push({
280
- success: false,
281
- mode: 'template',
282
- propertyPath: mismatch.propertyPath,
283
- message: `Failed to update property: ${error.message}`,
284
- });
285
- failedCount++;
286
- }
287
- }
288
-
289
- // 3. If any properties were updated, call UpdateStack ONCE with all changes
290
- if (reconciledCount > 0) {
291
- const templateBody = JSON.stringify(template);
292
- const templateSize = templateBody.length;
293
- const TEMPLATE_SIZE_LIMIT = 51200; // CloudFormation inline template limit
294
-
295
- // Use S3 for large templates, inline for small templates
296
- const updateParams = {
297
- StackName: stackIdentifier.stackName,
298
- };
299
-
300
- if (templateSize > TEMPLATE_SIZE_LIMIT && this.cfRepo) {
301
- // Upload template to S3 and use TemplateURL
302
- const templateUrl = await this.cfRepo.uploadTemplate({
303
- stackName: stackIdentifier.stackName,
304
- templateBody,
305
- });
306
- updateParams.TemplateURL = templateUrl;
307
- } else {
308
- // Use inline template body
309
- updateParams.TemplateBody = templateBody;
310
- }
311
-
312
- // Add capabilities required for IAM resources
313
- updateParams.Capabilities = ['CAPABILITY_NAMED_IAM'];
314
-
315
- const updateCommand = new UpdateStackCommand(updateParams);
316
- await client.send(updateCommand);
317
-
318
- // 4. Monitor UpdateStack operation if CloudFormation repository available
319
- if (this.cfRepo) {
320
- const { UpdateProgressMonitor } = require('../../domain/services/update-progress-monitor');
321
- const monitor = new UpdateProgressMonitor({
322
- cloudFormationRepository: this.cfRepo,
323
- });
324
-
325
- const monitorResult = await monitor.monitorUpdate({
326
- stackIdentifier,
327
- resourceLogicalIds: [logicalId],
328
- onProgress: (progress) => {
329
- // Progress callback for UI updates (optional)
330
- if (progress.status === 'FAILED') {
331
- console.log(` ⚠ ${progress.logicalId}: Update failed - ${progress.reason}`);
332
- }
333
- },
334
- });
335
-
336
- // If monitoring detected failures, update results
337
- if (!monitorResult.success) {
338
- reconciledCount = 0;
339
- failedCount = mismatches.length;
340
- results.forEach(r => {
341
- r.success = false;
342
- r.message = 'CloudFormation update failed';
343
- });
344
-
345
- return {
346
- reconciledCount,
347
- failedCount,
348
- results,
349
- message: `Update failed: ${monitorResult.failedResources.map(f => f.reason).join(', ')}`,
350
- };
351
- }
352
- }
353
- }
354
- } catch (error) {
355
- // If UpdateStack fails, mark all as failed
356
- return {
357
- reconciledCount: 0,
358
- failedCount: mismatches.length,
359
- results: mismatches.map(m => ({
360
- success: false,
361
- mode: 'template',
362
- propertyPath: m.propertyPath,
363
- message: `UpdateStack failed: ${error.message}`,
364
- })),
365
- message: `UpdateStack failed: ${error.message}`,
366
- };
367
- }
368
-
369
- return {
370
- reconciledCount,
371
- failedCount,
372
- results,
373
- message: `Reconciled ${reconciledCount} of ${mismatches.length} properties in single UpdateStack call`,
374
- };
375
- }
376
-
377
- /**
378
- * Preview property reconciliation without applying changes
379
- */
380
- async previewReconciliation({ stackIdentifier, logicalId, mismatch, mode = 'template' }) {
381
- const canReconcile = await this.canReconcile(mismatch);
382
-
383
- const warnings = [];
384
- if (mismatch.requiresReplacement()) {
385
- warnings.push('Property is immutable - requires resource replacement');
386
- }
387
-
388
- let impact = '';
389
- if (mode === 'template') {
390
- impact = 'Will update CloudFormation template to match actual resource state';
391
- } else {
392
- impact = 'Will update cloud resource to match template definition';
393
- }
394
-
395
- return {
396
- canReconcile,
397
- mode,
398
- propertyPath: mismatch.propertyPath,
399
- currentValue: mismatch.expectedValue,
400
- proposedValue: mismatch.actualValue,
401
- impact,
402
- warnings,
403
- };
404
- }
405
-
406
- /**
407
- * Update CloudFormation template property
408
- */
409
- async updateTemplateProperty({ stackIdentifier, logicalId, propertyPath, newValue }) {
410
- const client = this._getCFClient();
411
-
412
- // Get current template
413
- const getTemplateCommand = new GetTemplateCommand({
414
- StackName: stackIdentifier.stackName,
415
- TemplateStage: 'Original',
416
- });
417
-
418
- const templateResponse = await client.send(getTemplateCommand);
419
- const template = JSON.parse(templateResponse.TemplateBody);
420
-
421
- // Update property in template
422
- const pathParts = propertyPath.split('.');
423
- let current = template.Resources[logicalId];
424
-
425
- for (let i = 0; i < pathParts.length - 1; i++) {
426
- if (!current[pathParts[i]]) {
427
- current[pathParts[i]] = {};
428
- }
429
- current = current[pathParts[i]];
430
- }
431
-
432
- const lastPart = pathParts[pathParts.length - 1];
433
- current[lastPart] = newValue;
434
-
435
- // Update stack with new template
436
- const updateCommand = new UpdateStackCommand({
437
- StackName: stackIdentifier.stackName,
438
- TemplateBody: JSON.stringify(template),
439
- Capabilities: ['CAPABILITY_NAMED_IAM'],
440
- });
441
-
442
- const updateResponse = await client.send(updateCommand);
443
-
444
- return {
445
- success: true,
446
- changeSetId: updateResponse.StackId,
447
- message: 'Template property updated successfully',
448
- };
449
- }
450
-
451
- /**
452
- * Update cloud resource property directly
453
- */
454
- async updateResourceProperty({ resourceType, physicalId, region, propertyPath, newValue }) {
455
- // Only VPC properties are supported for direct resource updates in this implementation
456
- if (resourceType === 'AWS::EC2::VPC') {
457
- return await this._updateVpcProperty({ physicalId, propertyPath, newValue });
458
- }
459
-
460
- throw new Error(`Resource type ${resourceType} updates not supported`);
461
- }
462
-
463
- /**
464
- * Get reconciliation strategy for a resource type
465
- */
466
- async getReconciliationStrategy(resourceType) {
467
- if (!(resourceType in AWSPropertyReconciler.SUPPORTED_TYPES)) {
468
- throw new Error(`Resource type ${resourceType} not supported`);
469
- }
470
-
471
- const config = AWSPropertyReconciler.SUPPORTED_TYPES[resourceType];
472
-
473
- return {
474
- supportsTemplateUpdate: config.templateUpdate,
475
- supportsResourceUpdate: config.resourceUpdate,
476
- recommendedMode: config.recommendedMode,
477
- limitations: config.limitations,
478
- };
479
- }
480
-
481
- // ========================================
482
- // Private Helper Methods
483
- // ========================================
484
-
485
- /**
486
- * Reconcile via template update
487
- * @private
488
- */
489
- async _reconcileViaTemplate({ stackIdentifier, logicalId, mismatch }) {
490
- await this.updateTemplateProperty({
491
- stackIdentifier,
492
- logicalId,
493
- propertyPath: mismatch.propertyPath,
494
- newValue: mismatch.actualValue,
495
- });
496
-
497
- return {
498
- success: true,
499
- mode: 'template',
500
- propertyPath: mismatch.propertyPath,
501
- oldValue: mismatch.expectedValue,
502
- newValue: mismatch.actualValue,
503
- message: 'Template updated to match actual resource state',
504
- };
505
- }
506
-
507
- /**
508
- * Reconcile via resource update
509
- * @private
510
- */
511
- async _reconcileViaResource({ stackIdentifier, logicalId, mismatch }) {
512
- // This is a simplified implementation
513
- // In production, would need resource type detection and proper API calls
514
-
515
- // For now, only support VPC properties
516
- if (!mismatch.propertyPath.includes('EnableDns')) {
517
- throw new Error('Resource property update not supported for this property');
518
- }
519
-
520
- // Mock resource update (in real implementation, would use EC2 API)
521
- const client = this._getEC2Client();
522
- const command = new ModifyVpcAttributeCommand({
523
- VpcId: 'vpc-placeholder',
524
- EnableDnsSupport: { Value: mismatch.expectedValue },
525
- });
526
-
527
- await client.send(command);
528
-
529
- return {
530
- success: true,
531
- mode: 'resource',
532
- propertyPath: mismatch.propertyPath,
533
- oldValue: mismatch.actualValue,
534
- newValue: mismatch.expectedValue,
535
- message: 'Resource updated to match template definition',
536
- };
537
- }
538
-
539
- /**
540
- * Update VPC property directly
541
- * @private
542
- */
543
- async _updateVpcProperty({ physicalId, propertyPath, newValue }) {
544
- const client = this._getEC2Client();
545
-
546
- // Map property paths to VPC attribute names
547
- if (propertyPath === 'Properties.EnableDnsSupport') {
548
- const command = new ModifyVpcAttributeCommand({
549
- VpcId: physicalId,
550
- EnableDnsSupport: { Value: newValue },
551
- });
552
-
553
- await client.send(command);
554
- } else if (propertyPath === 'Properties.EnableDnsHostnames') {
555
- const command = new ModifyVpcAttributeCommand({
556
- VpcId: physicalId,
557
- EnableDnsHostnames: { Value: newValue },
558
- });
559
-
560
- await client.send(command);
561
- } else {
562
- throw new Error(`Property ${propertyPath} cannot be updated directly`);
563
- }
564
-
565
- return {
566
- success: true,
567
- message: `VPC property ${propertyPath} updated successfully`,
568
- updatedAt: new Date(),
569
- };
570
- }
571
-
572
- /**
573
- * Reconcile multiple properties via resource update (resource mode)
574
- *
575
- * Domain Service - Hexagonal Architecture
576
- * Coordinates AWS API calls to update cloud resources directly
577
- *
578
- * @private
579
- */
580
- async _reconcileMultiplePropertiesViaResource({
581
- stackIdentifier,
582
- logicalId,
583
- physicalId,
584
- resourceType,
585
- mismatches,
586
- }) {
587
- // Validate resource type supports resource mode
588
- if (resourceType !== 'AWS::Lambda::Function') {
589
- throw new Error(`Resource mode reconciliation not supported for ${resourceType}`);
590
- }
591
-
592
- const results = [];
593
- let reconciledCount = 0;
594
- let failedCount = 0;
595
- let skippedCount = 0;
596
-
597
- try {
598
- // Separate mutable from immutable properties
599
- const mutableMismatches = [];
600
- const mutableIndexMap = new Map(); // Track original index for mutable properties
601
-
602
- for (let i = 0; i < mismatches.length; i++) {
603
- const mismatch = mismatches[i];
604
- if (mismatch.requiresReplacement()) {
605
- skippedCount++;
606
- } else {
607
- mutableIndexMap.set(mismatch, i);
608
- mutableMismatches.push(mismatch);
609
- }
610
- }
611
-
612
- // If no mutable properties, return early with all marked as skipped
613
- if (mutableMismatches.length === 0) {
614
- const skippedResults = mismatches.map(m => ({
615
- success: false,
616
- mode: 'resource',
617
- propertyPath: m.propertyPath,
618
- message: `Skipped: Property is immutable and cannot be updated without replacement`,
619
- }));
620
-
621
- return {
622
- reconciledCount: 0,
623
- failedCount: 0,
624
- skippedCount,
625
- results: skippedResults,
626
- message: `All ${mismatches.length} properties are immutable and cannot be reconciled in resource mode`,
627
- };
628
- }
629
-
630
- // Route to resource-specific updater
631
- let lambdaResults = [];
632
- if (resourceType === 'AWS::Lambda::Function') {
633
- const lambdaResult = await this._updateLambdaFunction({
634
- physicalId,
635
- mismatches: mutableMismatches,
636
- });
637
-
638
- reconciledCount = lambdaResult.reconciledCount;
639
- failedCount = lambdaResult.failedCount;
640
- lambdaResults = lambdaResult.results;
641
- }
642
-
643
- // Build results array in original input order
644
- for (let i = 0; i < mismatches.length; i++) {
645
- const mismatch = mismatches[i];
646
- if (mismatch.requiresReplacement()) {
647
- // Immutable - add skip result
648
- results.push({
649
- success: false,
650
- mode: 'resource',
651
- propertyPath: mismatch.propertyPath,
652
- message: `Skipped: Property is immutable and cannot be updated without replacement`,
653
- });
654
- } else {
655
- // Mutable - find corresponding result from Lambda update
656
- const lambdaResult = lambdaResults.find(r => r.propertyPath === mismatch.propertyPath);
657
- if (lambdaResult) {
658
- results.push(lambdaResult);
659
- }
660
- }
661
- }
662
- } catch (error) {
663
- // If update fails, mark all as failed
664
- return {
665
- reconciledCount: 0,
666
- failedCount: mismatches.length,
667
- skippedCount: 0,
668
- results: mismatches.map(m => ({
669
- success: false,
670
- mode: 'resource',
671
- propertyPath: m.propertyPath,
672
- message: `Failed to update Lambda: ${error.message}`,
673
- })),
674
- message: `Failed to update Lambda: ${error.message}`,
675
- };
676
- }
677
-
678
- // Determine appropriate message based on outcome
679
- let message;
680
- if (failedCount > 0 && reconciledCount === 0) {
681
- message = `Failed to update Lambda: ${results.find(r => !r.success)?.message || 'Unknown error'}`;
682
- } else if (failedCount > 0) {
683
- message = `Partially updated Lambda VpcConfig (${reconciledCount} succeeded, ${failedCount} failed)`;
684
- } else {
685
- message = `Lambda VpcConfig updated via UpdateFunctionConfiguration (${reconciledCount} properties reconciled)`;
686
- }
687
-
688
- return {
689
- reconciledCount,
690
- failedCount,
691
- skippedCount,
692
- results,
693
- message,
694
- };
695
- }
696
-
697
- /**
698
- * Update Lambda function configuration via AWS Lambda API
699
- *
700
- * Infrastructure Adapter
701
- * Translates domain mismatches to AWS Lambda UpdateFunctionConfiguration call
702
- *
703
- * @private
704
- */
705
- async _updateLambdaFunction({ physicalId, mismatches }) {
706
- const client = this._getLambdaClient();
707
- const results = [];
708
- let reconciledCount = 0;
709
- let failedCount = 0;
710
-
711
- try {
712
- // Build VpcConfig update from mismatches
713
- const vpcConfigUpdate = {};
714
- const vpcConfigMismatches = mismatches.filter(m =>
715
- m.propertyPath.startsWith('VpcConfig')
716
- );
717
-
718
- for (const mismatch of vpcConfigMismatches) {
719
- // Property path format: "VpcConfig.SubnetIds" or "VpcConfig.SecurityGroupIds"
720
- const parts = mismatch.propertyPath.split('.');
721
- if (parts.length === 2 && parts[0] === 'VpcConfig') {
722
- vpcConfigUpdate[parts[1]] = mismatch.expectedValue;
723
- }
724
- }
725
-
726
- // If we have VpcConfig updates, call UpdateFunctionConfiguration
727
- if (Object.keys(vpcConfigUpdate).length > 0) {
728
- const command = new UpdateFunctionConfigurationCommand({
729
- FunctionName: physicalId,
730
- VpcConfig: vpcConfigUpdate,
731
- });
732
-
733
- await client.send(command);
734
-
735
- // Mark all VpcConfig properties as successful
736
- for (const mismatch of vpcConfigMismatches) {
737
- results.push({
738
- success: true,
739
- mode: 'resource',
740
- propertyPath: mismatch.propertyPath,
741
- oldValue: mismatch.actualValue,
742
- newValue: mismatch.expectedValue,
743
- message: 'Lambda VpcConfig updated successfully',
744
- });
745
- reconciledCount++;
746
- }
747
- }
748
-
749
- // Handle non-VpcConfig properties (currently unsupported)
750
- const otherMismatches = mismatches.filter(m =>
751
- !m.propertyPath.startsWith('VpcConfig')
752
- );
753
- for (const mismatch of otherMismatches) {
754
- results.push({
755
- success: false,
756
- mode: 'resource',
757
- propertyPath: mismatch.propertyPath,
758
- message: `Property ${mismatch.propertyPath} updates not yet supported in resource mode`,
759
- });
760
- failedCount++;
761
- }
762
- } catch (error) {
763
- // If Lambda API call fails, mark all as failed
764
- for (const mismatch of mismatches) {
765
- results.push({
766
- success: false,
767
- mode: 'resource',
768
- propertyPath: mismatch.propertyPath,
769
- message: `Lambda update failed: ${error.message}`,
770
- });
771
- failedCount++;
772
- }
773
- reconciledCount = 0;
774
- }
775
-
776
- return {
777
- reconciledCount,
778
- failedCount,
779
- results,
780
- };
781
- }
782
- }
783
-
784
- module.exports = AWSPropertyReconciler;