@jterrats/smart-deployment 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +193 -0
- package/lib/ai/agentforce-error-handler.d.ts +81 -0
- package/lib/ai/agentforce-error-handler.js +196 -0
- package/lib/ai/agentforce-error-handler.js.map +1 -0
- package/lib/ai/agentforce-priority-service.d.ts +82 -0
- package/lib/ai/agentforce-priority-service.js +257 -0
- package/lib/ai/agentforce-priority-service.js.map +1 -0
- package/lib/ai/agentforce-service.d.ts +99 -0
- package/lib/ai/agentforce-service.js +300 -0
- package/lib/ai/agentforce-service.js.map +1 -0
- package/lib/ai/circuit-breaker.d.ts +115 -0
- package/lib/ai/circuit-breaker.js +277 -0
- package/lib/ai/circuit-breaker.js.map +1 -0
- package/lib/ai/dependency-inference-service.d.ts +76 -0
- package/lib/ai/dependency-inference-service.js +220 -0
- package/lib/ai/dependency-inference-service.js.map +1 -0
- package/lib/ai/llm-provider-factory.d.ts +15 -0
- package/lib/ai/llm-provider-factory.js +36 -0
- package/lib/ai/llm-provider-factory.js.map +1 -0
- package/lib/ai/llm-provider.d.ts +27 -0
- package/lib/ai/llm-provider.js +2 -0
- package/lib/ai/llm-provider.js.map +1 -0
- package/lib/ai/openai-service.d.ts +20 -0
- package/lib/ai/openai-service.js +89 -0
- package/lib/ai/openai-service.js.map +1 -0
- package/lib/ai/prompt-builder.d.ts +79 -0
- package/lib/ai/prompt-builder.js +180 -0
- package/lib/ai/prompt-builder.js.map +1 -0
- package/lib/ai/response-parser.d.ts +67 -0
- package/lib/ai/response-parser.js +234 -0
- package/lib/ai/response-parser.js.map +1 -0
- package/lib/ai/wave-validation-service.d.ts +111 -0
- package/lib/ai/wave-validation-service.js +381 -0
- package/lib/ai/wave-validation-service.js.map +1 -0
- package/lib/analysis/analysis-reporter.d.ts +56 -0
- package/lib/analysis/analysis-reporter.js +170 -0
- package/lib/analysis/analysis-reporter.js.map +1 -0
- package/lib/analytics/error-analytics.d.ts +80 -0
- package/lib/analytics/error-analytics.js +162 -0
- package/lib/analytics/error-analytics.js.map +1 -0
- package/lib/commands/analyze.d.ts +49 -0
- package/lib/commands/analyze.js +232 -0
- package/lib/commands/analyze.js.map +1 -0
- package/lib/commands/config.d.ts +42 -0
- package/lib/commands/config.js +219 -0
- package/lib/commands/config.js.map +1 -0
- package/lib/commands/resume.d.ts +26 -0
- package/lib/commands/resume.js +69 -0
- package/lib/commands/resume.js.map +1 -0
- package/lib/commands/start.d.ts +70 -0
- package/lib/commands/start.js +659 -0
- package/lib/commands/start.js.map +1 -0
- package/lib/commands/status.d.ts +37 -0
- package/lib/commands/status.js +69 -0
- package/lib/commands/status.js.map +1 -0
- package/lib/commands/validate.d.ts +33 -0
- package/lib/commands/validate.js +66 -0
- package/lib/commands/validate.js.map +1 -0
- package/lib/config/repo-config.d.ts +22 -0
- package/lib/config/repo-config.js +31 -0
- package/lib/config/repo-config.js.map +1 -0
- package/lib/constants/agentforce-limits.d.ts +174 -0
- package/lib/constants/agentforce-limits.js +262 -0
- package/lib/constants/agentforce-limits.js.map +1 -0
- package/lib/constants/api-version.d.ts +70 -0
- package/lib/constants/api-version.js +122 -0
- package/lib/constants/api-version.js.map +1 -0
- package/lib/constants/deployment-order.d.ts +68 -0
- package/lib/constants/deployment-order.js +162 -0
- package/lib/constants/deployment-order.js.map +1 -0
- package/lib/constants/salesforce-limits.d.ts +107 -0
- package/lib/constants/salesforce-limits.js +104 -0
- package/lib/constants/salesforce-limits.js.map +1 -0
- package/lib/dependencies/circular-dependency-detector.d.ts +137 -0
- package/lib/dependencies/circular-dependency-detector.js +329 -0
- package/lib/dependencies/circular-dependency-detector.js.map +1 -0
- package/lib/dependencies/cycle-remediation-planner.d.ts +50 -0
- package/lib/dependencies/cycle-remediation-planner.js +192 -0
- package/lib/dependencies/cycle-remediation-planner.js.map +1 -0
- package/lib/dependencies/dependency-cache.d.ts +134 -0
- package/lib/dependencies/dependency-cache.js +303 -0
- package/lib/dependencies/dependency-cache.js.map +1 -0
- package/lib/dependencies/dependency-depth-calculator.d.ts +145 -0
- package/lib/dependencies/dependency-depth-calculator.js +368 -0
- package/lib/dependencies/dependency-depth-calculator.js.map +1 -0
- package/lib/dependencies/dependency-graph-builder.d.ts +151 -0
- package/lib/dependencies/dependency-graph-builder.js +411 -0
- package/lib/dependencies/dependency-graph-builder.js.map +1 -0
- package/lib/dependencies/dependency-impact-analyzer.d.ts +145 -0
- package/lib/dependencies/dependency-impact-analyzer.js +330 -0
- package/lib/dependencies/dependency-impact-analyzer.js.map +1 -0
- package/lib/dependencies/dependency-merger.d.ts +122 -0
- package/lib/dependencies/dependency-merger.js +245 -0
- package/lib/dependencies/dependency-merger.js.map +1 -0
- package/lib/dependencies/dependency-resolver.d.ts +157 -0
- package/lib/dependencies/dependency-resolver.js +298 -0
- package/lib/dependencies/dependency-resolver.js.map +1 -0
- package/lib/dependencies/dependency-validator.d.ts +123 -0
- package/lib/dependencies/dependency-validator.js +291 -0
- package/lib/dependencies/dependency-validator.js.map +1 -0
- package/lib/dependencies/graph-visualizer.d.ts +110 -0
- package/lib/dependencies/graph-visualizer.js +262 -0
- package/lib/dependencies/graph-visualizer.js.map +1 -0
- package/lib/dependencies/heuristic-inference.d.ts +136 -0
- package/lib/dependencies/heuristic-inference.js +430 -0
- package/lib/dependencies/heuristic-inference.js.map +1 -0
- package/lib/deployment/cycle-source-editor.d.ts +34 -0
- package/lib/deployment/cycle-source-editor.js +121 -0
- package/lib/deployment/cycle-source-editor.js.map +1 -0
- package/lib/deployment/deployment-error-handler.d.ts +38 -0
- package/lib/deployment/deployment-error-handler.js +79 -0
- package/lib/deployment/deployment-error-handler.js.map +1 -0
- package/lib/deployment/deployment-reporter.d.ts +63 -0
- package/lib/deployment/deployment-reporter.js +150 -0
- package/lib/deployment/deployment-reporter.js.map +1 -0
- package/lib/deployment/deployment-state-summary.d.ts +38 -0
- package/lib/deployment/deployment-state-summary.js +209 -0
- package/lib/deployment/deployment-state-summary.js.map +1 -0
- package/lib/deployment/deployment-status-service.d.ts +36 -0
- package/lib/deployment/deployment-status-service.js +128 -0
- package/lib/deployment/deployment-status-service.js.map +1 -0
- package/lib/deployment/deployment-tracker.d.ts +42 -0
- package/lib/deployment/deployment-tracker.js +79 -0
- package/lib/deployment/deployment-tracker.js.map +1 -0
- package/lib/deployment/deployment-validation-service.d.ts +28 -0
- package/lib/deployment/deployment-validation-service.js +161 -0
- package/lib/deployment/deployment-validation-service.js.map +1 -0
- package/lib/deployment/retry-handler.d.ts +37 -0
- package/lib/deployment/retry-handler.js +86 -0
- package/lib/deployment/retry-handler.js.map +1 -0
- package/lib/deployment/sf-cli-integration.d.ts +42 -0
- package/lib/deployment/sf-cli-integration.js +105 -0
- package/lib/deployment/sf-cli-integration.js.map +1 -0
- package/lib/deployment/state-manager.d.ts +61 -0
- package/lib/deployment/state-manager.js +83 -0
- package/lib/deployment/state-manager.js.map +1 -0
- package/lib/deployment/test-executor.d.ts +41 -0
- package/lib/deployment/test-executor.js +87 -0
- package/lib/deployment/test-executor.js.map +1 -0
- package/lib/errors/base-error.d.ts +24 -0
- package/lib/errors/base-error.js +66 -0
- package/lib/errors/base-error.js.map +1 -0
- package/lib/errors/dependency-error.d.ts +37 -0
- package/lib/errors/dependency-error.js +76 -0
- package/lib/errors/dependency-error.js.map +1 -0
- package/lib/errors/deployment-error.d.ts +55 -0
- package/lib/errors/deployment-error.js +132 -0
- package/lib/errors/deployment-error.js.map +1 -0
- package/lib/errors/index.d.ts +45 -0
- package/lib/errors/index.js +71 -0
- package/lib/errors/index.js.map +1 -0
- package/lib/errors/network-error.d.ts +53 -0
- package/lib/errors/network-error.js +111 -0
- package/lib/errors/network-error.js.map +1 -0
- package/lib/errors/parsing-error.d.ts +41 -0
- package/lib/errors/parsing-error.js +69 -0
- package/lib/errors/parsing-error.js.map +1 -0
- package/lib/errors/validation-error-reporter.d.ts +34 -0
- package/lib/errors/validation-error-reporter.js +99 -0
- package/lib/errors/validation-error-reporter.js.map +1 -0
- package/lib/errors/validation-error.d.ts +58 -0
- package/lib/errors/validation-error.js +131 -0
- package/lib/errors/validation-error.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/monitoring/performance-monitor.d.ts +98 -0
- package/lib/monitoring/performance-monitor.js +260 -0
- package/lib/monitoring/performance-monitor.js.map +1 -0
- package/lib/parsers/apex-class-parser.d.ts +47 -0
- package/lib/parsers/apex-class-parser.js +368 -0
- package/lib/parsers/apex-class-parser.js.map +1 -0
- package/lib/parsers/apex-trigger-parser.d.ts +48 -0
- package/lib/parsers/apex-trigger-parser.js +229 -0
- package/lib/parsers/apex-trigger-parser.js.map +1 -0
- package/lib/parsers/aura-parser.d.ts +55 -0
- package/lib/parsers/aura-parser.js +229 -0
- package/lib/parsers/aura-parser.js.map +1 -0
- package/lib/parsers/bot-parser.d.ts +65 -0
- package/lib/parsers/bot-parser.js +225 -0
- package/lib/parsers/bot-parser.js.map +1 -0
- package/lib/parsers/custom-metadata-parser.d.ts +94 -0
- package/lib/parsers/custom-metadata-parser.js +199 -0
- package/lib/parsers/custom-metadata-parser.js.map +1 -0
- package/lib/parsers/custom-object-parser.d.ts +62 -0
- package/lib/parsers/custom-object-parser.js +297 -0
- package/lib/parsers/custom-object-parser.js.map +1 -0
- package/lib/parsers/email-template-parser.d.ts +64 -0
- package/lib/parsers/email-template-parser.js +238 -0
- package/lib/parsers/email-template-parser.js.map +1 -0
- package/lib/parsers/error-resilient-parser.d.ts +110 -0
- package/lib/parsers/error-resilient-parser.js +277 -0
- package/lib/parsers/error-resilient-parser.js.map +1 -0
- package/lib/parsers/flexipage-parser.d.ts +64 -0
- package/lib/parsers/flexipage-parser.js +196 -0
- package/lib/parsers/flexipage-parser.js.map +1 -0
- package/lib/parsers/flow-parser.d.ts +54 -0
- package/lib/parsers/flow-parser.js +287 -0
- package/lib/parsers/flow-parser.js.map +1 -0
- package/lib/parsers/genai-prompt-parser.d.ts +67 -0
- package/lib/parsers/genai-prompt-parser.js +160 -0
- package/lib/parsers/genai-prompt-parser.js.map +1 -0
- package/lib/parsers/layout-parser.d.ts +64 -0
- package/lib/parsers/layout-parser.js +267 -0
- package/lib/parsers/layout-parser.js.map +1 -0
- package/lib/parsers/lwc-parser.d.ts +60 -0
- package/lib/parsers/lwc-parser.js +264 -0
- package/lib/parsers/lwc-parser.js.map +1 -0
- package/lib/parsers/permission-set-parser.d.ts +86 -0
- package/lib/parsers/permission-set-parser.js +152 -0
- package/lib/parsers/permission-set-parser.js.map +1 -0
- package/lib/parsers/profile-parser.d.ts +81 -0
- package/lib/parsers/profile-parser.js +141 -0
- package/lib/parsers/profile-parser.js.map +1 -0
- package/lib/parsers/visualforce-parser.d.ts +47 -0
- package/lib/parsers/visualforce-parser.js +180 -0
- package/lib/parsers/visualforce-parser.js.map +1 -0
- package/lib/provisioning/data-provisioner.d.ts +88 -0
- package/lib/provisioning/data-provisioner.js +257 -0
- package/lib/provisioning/data-provisioner.js.map +1 -0
- package/lib/scanner/custom-structure-scanner.d.ts +66 -0
- package/lib/scanner/custom-structure-scanner.js +229 -0
- package/lib/scanner/custom-structure-scanner.js.map +1 -0
- package/lib/scanner/forceignore-parser.d.ts +69 -0
- package/lib/scanner/forceignore-parser.js +195 -0
- package/lib/scanner/forceignore-parser.js.map +1 -0
- package/lib/scanner/metadata-format-scanner.d.ts +77 -0
- package/lib/scanner/metadata-format-scanner.js +282 -0
- package/lib/scanner/metadata-format-scanner.js.map +1 -0
- package/lib/scanner/monorepo-scanner.d.ts +71 -0
- package/lib/scanner/monorepo-scanner.js +225 -0
- package/lib/scanner/monorepo-scanner.js.map +1 -0
- package/lib/scanner/project-validator.d.ts +55 -0
- package/lib/scanner/project-validator.js +235 -0
- package/lib/scanner/project-validator.js.map +1 -0
- package/lib/scanner/sfdx-project-detector.d.ts +86 -0
- package/lib/scanner/sfdx-project-detector.js +240 -0
- package/lib/scanner/sfdx-project-detector.js.map +1 -0
- package/lib/scanner/structure-validator.d.ts +64 -0
- package/lib/scanner/structure-validator.js +296 -0
- package/lib/scanner/structure-validator.js.map +1 -0
- package/lib/services/metadata-scanner-service.d.ts +64 -0
- package/lib/services/metadata-scanner-service.js +651 -0
- package/lib/services/metadata-scanner-service.js.map +1 -0
- package/lib/types/agentforce.d.ts +157 -0
- package/lib/types/agentforce.js +2 -0
- package/lib/types/agentforce.js.map +1 -0
- package/lib/types/dependency.d.ts +98 -0
- package/lib/types/dependency.js +5 -0
- package/lib/types/dependency.js.map +1 -0
- package/lib/types/deployment-plan.d.ts +81 -0
- package/lib/types/deployment-plan.js +6 -0
- package/lib/types/deployment-plan.js.map +1 -0
- package/lib/types/deployment.d.ts +88 -0
- package/lib/types/deployment.js +5 -0
- package/lib/types/deployment.js.map +1 -0
- package/lib/types/graph.d.ts +35 -0
- package/lib/types/graph.js +5 -0
- package/lib/types/graph.js.map +1 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.js +17 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/metadata.d.ts +101 -0
- package/lib/types/metadata.js +13 -0
- package/lib/types/metadata.js.map +1 -0
- package/lib/types/project.d.ts +156 -0
- package/lib/types/project.js +56 -0
- package/lib/types/project.js.map +1 -0
- package/lib/types/salesforce/apex.d.ts +94 -0
- package/lib/types/salesforce/apex.js +6 -0
- package/lib/types/salesforce/apex.js.map +1 -0
- package/lib/types/salesforce/aura.d.ts +150 -0
- package/lib/types/salesforce/aura.js +6 -0
- package/lib/types/salesforce/aura.js.map +1 -0
- package/lib/types/salesforce/bot.d.ts +293 -0
- package/lib/types/salesforce/bot.js +6 -0
- package/lib/types/salesforce/bot.js.map +1 -0
- package/lib/types/salesforce/common.d.ts +15 -0
- package/lib/types/salesforce/common.js +5 -0
- package/lib/types/salesforce/common.js.map +1 -0
- package/lib/types/salesforce/custom-metadata.d.ts +92 -0
- package/lib/types/salesforce/custom-metadata.js +6 -0
- package/lib/types/salesforce/custom-metadata.js.map +1 -0
- package/lib/types/salesforce/email.d.ts +56 -0
- package/lib/types/salesforce/email.js +6 -0
- package/lib/types/salesforce/email.js.map +1 -0
- package/lib/types/salesforce/flexipage.d.ts +149 -0
- package/lib/types/salesforce/flexipage.js +6 -0
- package/lib/types/salesforce/flexipage.js.map +1 -0
- package/lib/types/salesforce/flow.d.ts +516 -0
- package/lib/types/salesforce/flow.js +6 -0
- package/lib/types/salesforce/flow.js.map +1 -0
- package/lib/types/salesforce/genai.d.ts +67 -0
- package/lib/types/salesforce/genai.js +6 -0
- package/lib/types/salesforce/genai.js.map +1 -0
- package/lib/types/salesforce/index.d.ts +27 -0
- package/lib/types/salesforce/index.js +43 -0
- package/lib/types/salesforce/index.js.map +1 -0
- package/lib/types/salesforce/layout.d.ts +236 -0
- package/lib/types/salesforce/layout.js +6 -0
- package/lib/types/salesforce/layout.js.map +1 -0
- package/lib/types/salesforce/lwc.d.ts +123 -0
- package/lib/types/salesforce/lwc.js +6 -0
- package/lib/types/salesforce/lwc.js.map +1 -0
- package/lib/types/salesforce/object.d.ts +427 -0
- package/lib/types/salesforce/object.js +6 -0
- package/lib/types/salesforce/object.js.map +1 -0
- package/lib/types/salesforce/parser-types.d.ts +79 -0
- package/lib/types/salesforce/parser-types.js +80 -0
- package/lib/types/salesforce/parser-types.js.map +1 -0
- package/lib/types/salesforce/permission.d.ts +289 -0
- package/lib/types/salesforce/permission.js +6 -0
- package/lib/types/salesforce/permission.js.map +1 -0
- package/lib/types/salesforce/resource.d.ts +93 -0
- package/lib/types/salesforce/resource.js +6 -0
- package/lib/types/salesforce/resource.js.map +1 -0
- package/lib/types/salesforce/visualforce.d.ts +70 -0
- package/lib/types/salesforce/visualforce.js +6 -0
- package/lib/types/salesforce/visualforce.js.map +1 -0
- package/lib/utils/cache-manager.d.ts +158 -0
- package/lib/utils/cache-manager.js +429 -0
- package/lib/utils/cache-manager.js.map +1 -0
- package/lib/utils/deployment-plan-manager.d.ts +40 -0
- package/lib/utils/deployment-plan-manager.js +183 -0
- package/lib/utils/deployment-plan-manager.js.map +1 -0
- package/lib/utils/error-aggregator.d.ts +117 -0
- package/lib/utils/error-aggregator.js +268 -0
- package/lib/utils/error-aggregator.js.map +1 -0
- package/lib/utils/file-system.d.ts +62 -0
- package/lib/utils/file-system.js +167 -0
- package/lib/utils/file-system.js.map +1 -0
- package/lib/utils/functional.d.ts +52 -0
- package/lib/utils/functional.js +61 -0
- package/lib/utils/functional.js.map +1 -0
- package/lib/utils/graph-algorithms.d.ts +53 -0
- package/lib/utils/graph-algorithms.js +177 -0
- package/lib/utils/graph-algorithms.js.map +1 -0
- package/lib/utils/logger.d.ts +154 -0
- package/lib/utils/logger.js +327 -0
- package/lib/utils/logger.js.map +1 -0
- package/lib/utils/network-handler.d.ts +64 -0
- package/lib/utils/network-handler.js +147 -0
- package/lib/utils/network-handler.js.map +1 -0
- package/lib/utils/performance.d.ts +148 -0
- package/lib/utils/performance.js +294 -0
- package/lib/utils/performance.js.map +1 -0
- package/lib/utils/string.d.ts +197 -0
- package/lib/utils/string.js +331 -0
- package/lib/utils/string.js.map +1 -0
- package/lib/utils/xml.d.ts +97 -0
- package/lib/utils/xml.js +227 -0
- package/lib/utils/xml.js.map +1 -0
- package/lib/validators/xml-metadata-validator.d.ts +106 -0
- package/lib/validators/xml-metadata-validator.js +509 -0
- package/lib/validators/xml-metadata-validator.js.map +1 -0
- package/lib/waves/priority-wave-generator-ai.d.ts +85 -0
- package/lib/waves/priority-wave-generator-ai.js +191 -0
- package/lib/waves/priority-wave-generator-ai.js.map +1 -0
- package/lib/waves/priority-wave-generator.d.ts +47 -0
- package/lib/waves/priority-wave-generator.js +88 -0
- package/lib/waves/priority-wave-generator.js.map +1 -0
- package/lib/waves/test-optimizer.d.ts +155 -0
- package/lib/waves/test-optimizer.js +290 -0
- package/lib/waves/test-optimizer.js.map +1 -0
- package/lib/waves/wave-builder.d.ts +147 -0
- package/lib/waves/wave-builder.js +286 -0
- package/lib/waves/wave-builder.js.map +1 -0
- package/lib/waves/wave-diff-generator.d.ts +17 -0
- package/lib/waves/wave-diff-generator.js +6 -0
- package/lib/waves/wave-diff-generator.js.map +1 -0
- package/lib/waves/wave-executor.d.ts +33 -0
- package/lib/waves/wave-executor.js +50 -0
- package/lib/waves/wave-executor.js.map +1 -0
- package/lib/waves/wave-merger.d.ts +96 -0
- package/lib/waves/wave-merger.js +181 -0
- package/lib/waves/wave-merger.js.map +1 -0
- package/lib/waves/wave-metadata-generator.d.ts +13 -0
- package/lib/waves/wave-metadata-generator.js +12 -0
- package/lib/waves/wave-metadata-generator.js.map +1 -0
- package/lib/waves/wave-splitter.d.ts +154 -0
- package/lib/waves/wave-splitter.js +307 -0
- package/lib/waves/wave-splitter.js.map +1 -0
- package/lib/waves/wave-validator.d.ts +17 -0
- package/lib/waves/wave-validator.js +15 -0
- package/lib/waves/wave-validator.js.map +1 -0
- package/messages/analyze.json +18 -0
- package/messages/config.json +29 -0
- package/messages/resume.json +9 -0
- package/messages/start.json +24 -0
- package/messages/status.json +8 -0
- package/messages/validate.json +9 -0
- package/npm-shrinkwrap.json +25676 -0
- package/oclif.lock +11988 -0
- package/oclif.manifest.json +589 -0
- package/package.json +224 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Optimizer
|
|
3
|
+
* Optimizes test execution per wave to reduce deployment time
|
|
4
|
+
*
|
|
5
|
+
* @ac US-040-AC-1: Identify waves with Apex/Trigger changes
|
|
6
|
+
* @ac US-040-AC-2: Include tests only in waves with code
|
|
7
|
+
* @ac US-040-AC-3: Sync test classes with production classes
|
|
8
|
+
* @ac US-040-AC-4: Ensure trigger tests are included
|
|
9
|
+
* @ac US-040-AC-5: Calculate test coverage per wave
|
|
10
|
+
* @ac US-040-AC-6: Report test optimization savings
|
|
11
|
+
*
|
|
12
|
+
* @issue #40
|
|
13
|
+
*/
|
|
14
|
+
import { getLogger } from '../utils/logger.js';
|
|
15
|
+
const logger = getLogger('TestOptimizer');
|
|
16
|
+
/**
|
|
17
|
+
* Test Optimizer
|
|
18
|
+
*
|
|
19
|
+
* Optimizes test execution by only including tests in waves
|
|
20
|
+
* that contain Apex classes or triggers.
|
|
21
|
+
*
|
|
22
|
+
* Strategy:
|
|
23
|
+
* 1. Identify waves with code changes (ApexClass, ApexTrigger)
|
|
24
|
+
* 2. Match test classes to production classes
|
|
25
|
+
* 3. Include only relevant tests per wave
|
|
26
|
+
* 4. Skip tests for metadata-only waves
|
|
27
|
+
*
|
|
28
|
+
* Performance: O(V)
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const optimizer = new TestOptimizer({
|
|
32
|
+
* minCoverageRequired: 75,
|
|
33
|
+
* includeRelatedTests: true
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* const result = optimizer.optimizeTests(waves);
|
|
37
|
+
* console.log(`Time saved: ${result.stats.timeSaved}s`);
|
|
38
|
+
*/
|
|
39
|
+
export class TestOptimizer {
|
|
40
|
+
options;
|
|
41
|
+
constructor(options = {}) {
|
|
42
|
+
this.options = {
|
|
43
|
+
alwaysRunAllTests: options.alwaysRunAllTests ?? false,
|
|
44
|
+
minCoverageRequired: options.minCoverageRequired ?? 75,
|
|
45
|
+
includeRelatedTests: options.includeRelatedTests ?? false,
|
|
46
|
+
};
|
|
47
|
+
logger.debug('Initialized TestOptimizer', {
|
|
48
|
+
alwaysRunAllTests: this.options.alwaysRunAllTests,
|
|
49
|
+
minCoverageRequired: this.options.minCoverageRequired,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* @ac US-040-AC-1: Identify waves with Apex/Trigger changes
|
|
54
|
+
* @ac US-040-AC-2: Include tests only in waves with code
|
|
55
|
+
* @ac US-040-AC-3: Sync test classes with production classes
|
|
56
|
+
*/
|
|
57
|
+
optimizeTests(waves) {
|
|
58
|
+
const startTime = Date.now();
|
|
59
|
+
const decisions = [];
|
|
60
|
+
const optimizedWaves = [];
|
|
61
|
+
// Collect all test classes across all waves
|
|
62
|
+
const allTestClasses = this.collectAllTestClasses(waves);
|
|
63
|
+
for (const wave of waves) {
|
|
64
|
+
const codeClasses = this.getCodeClasses(wave);
|
|
65
|
+
const triggers = this.getTriggers(wave);
|
|
66
|
+
const needsTests = codeClasses.length > 0 || triggers.length > 0;
|
|
67
|
+
let testClasses = [];
|
|
68
|
+
let estimatedCoverage = 100;
|
|
69
|
+
if (this.options.alwaysRunAllTests) {
|
|
70
|
+
// Include all test classes in every wave
|
|
71
|
+
testClasses = allTestClasses;
|
|
72
|
+
decisions.push({
|
|
73
|
+
waveNumber: wave.number,
|
|
74
|
+
type: 'include-tests',
|
|
75
|
+
reason: 'alwaysRunAllTests option enabled',
|
|
76
|
+
testsAffected: allTestClasses.length,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else if (!needsTests) {
|
|
80
|
+
// No code changes, skip tests
|
|
81
|
+
testClasses = [];
|
|
82
|
+
decisions.push({
|
|
83
|
+
waveNumber: wave.number,
|
|
84
|
+
type: 'skip-tests',
|
|
85
|
+
reason: 'No Apex classes or triggers in wave',
|
|
86
|
+
testsAffected: 0,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Sync test classes with code classes
|
|
91
|
+
testClasses = this.syncTestClasses(codeClasses, triggers, allTestClasses);
|
|
92
|
+
estimatedCoverage = this.estimateCoverage(codeClasses.length, testClasses.length);
|
|
93
|
+
decisions.push({
|
|
94
|
+
waveNumber: wave.number,
|
|
95
|
+
type: 'sync-tests',
|
|
96
|
+
reason: `Matched ${testClasses.length} tests to ${codeClasses.length} classes`,
|
|
97
|
+
testsAffected: testClasses.length,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
optimizedWaves.push({
|
|
101
|
+
...wave,
|
|
102
|
+
testClasses,
|
|
103
|
+
codeClasses,
|
|
104
|
+
triggers,
|
|
105
|
+
needsTests,
|
|
106
|
+
estimatedCoverage,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Calculate statistics
|
|
110
|
+
const stats = this.calculateStats(optimizedWaves, allTestClasses.length);
|
|
111
|
+
const duration = Date.now() - startTime;
|
|
112
|
+
logger.info('Test optimization completed', {
|
|
113
|
+
totalWaves: stats.totalWaves,
|
|
114
|
+
wavesWithTests: stats.wavesWithTests,
|
|
115
|
+
testsAdded: stats.totalTestsAdded,
|
|
116
|
+
timeSaved: stats.timeSaved,
|
|
117
|
+
durationMs: duration,
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
originalWaves: waves,
|
|
121
|
+
optimizedWaves,
|
|
122
|
+
decisions,
|
|
123
|
+
stats,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Collect all test classes from all waves
|
|
128
|
+
*/
|
|
129
|
+
collectAllTestClasses(waves) {
|
|
130
|
+
const testClasses = new Set();
|
|
131
|
+
for (const wave of waves) {
|
|
132
|
+
for (const component of wave.components) {
|
|
133
|
+
if (this.isTestClass(component)) {
|
|
134
|
+
testClasses.add(component);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return Array.from(testClasses);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get code classes (non-test Apex classes)
|
|
142
|
+
*/
|
|
143
|
+
getCodeClasses(wave) {
|
|
144
|
+
return wave.components.filter((c) => c.startsWith('ApexClass:') && !this.isTestClass(c));
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* @ac US-040-AC-4: Ensure trigger tests are included
|
|
148
|
+
*/
|
|
149
|
+
getTriggers(wave) {
|
|
150
|
+
return wave.components.filter((c) => c.startsWith('ApexTrigger:'));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if component is a test class
|
|
154
|
+
*/
|
|
155
|
+
isTestClass(component) {
|
|
156
|
+
return (component.startsWith('ApexClass:') &&
|
|
157
|
+
(component.toLowerCase().includes('test') || component.toLowerCase().endsWith('_test')));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Sync test classes with production classes
|
|
161
|
+
*/
|
|
162
|
+
syncTestClasses(codeClasses, triggers, allTestClasses) {
|
|
163
|
+
const matchedTests = new Set();
|
|
164
|
+
// Match tests to code classes
|
|
165
|
+
for (const codeClass of codeClasses) {
|
|
166
|
+
const className = codeClass.split(':')[1];
|
|
167
|
+
for (const testClass of allTestClasses) {
|
|
168
|
+
const testName = testClass.split(':')[1].toLowerCase();
|
|
169
|
+
const codeName = className.toLowerCase();
|
|
170
|
+
// Match patterns:
|
|
171
|
+
// - AccountService → AccountServiceTest
|
|
172
|
+
// - AccountService → TestAccountService
|
|
173
|
+
// - AccountService → AccountService_Test
|
|
174
|
+
if (testName.includes(codeName) || codeName.includes(testName.replace('test', ''))) {
|
|
175
|
+
matchedTests.add(testClass);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Match tests to triggers
|
|
180
|
+
for (const trigger of triggers) {
|
|
181
|
+
const triggerName = trigger.split(':')[1];
|
|
182
|
+
for (const testClass of allTestClasses) {
|
|
183
|
+
const testName = testClass.split(':')[1].toLowerCase();
|
|
184
|
+
const trgName = triggerName.toLowerCase();
|
|
185
|
+
// Match patterns:
|
|
186
|
+
// - AccountTrigger → AccountTriggerTest
|
|
187
|
+
// - AccountTrigger → TestAccountTrigger
|
|
188
|
+
if (testName.includes(trgName) || testName.includes('trigger')) {
|
|
189
|
+
matchedTests.add(testClass);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// If no tests matched and we have code, include related tests
|
|
194
|
+
if (matchedTests.size === 0 && this.options.includeRelatedTests) {
|
|
195
|
+
// Include a reasonable subset (e.g., first 10 test classes)
|
|
196
|
+
for (let i = 0; i < Math.min(10, allTestClasses.length); i++) {
|
|
197
|
+
matchedTests.add(allTestClasses[i]);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return Array.from(matchedTests);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* @ac US-040-AC-5: Calculate test coverage per wave
|
|
204
|
+
*/
|
|
205
|
+
estimateCoverage(codeClassCount, testClassCount) {
|
|
206
|
+
if (codeClassCount === 0)
|
|
207
|
+
return 100;
|
|
208
|
+
if (testClassCount === 0)
|
|
209
|
+
return 0;
|
|
210
|
+
// Simple heuristic: assume each test class covers ~75% of one class
|
|
211
|
+
const coverage = Math.min(100, (testClassCount / codeClassCount) * 75);
|
|
212
|
+
return Math.round(coverage);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Calculate optimization statistics
|
|
216
|
+
*/
|
|
217
|
+
calculateStats(optimizedWaves, totalAvailableTests) {
|
|
218
|
+
let wavesWithTests = 0;
|
|
219
|
+
let wavesWithoutTests = 0;
|
|
220
|
+
let totalTestsAdded = 0;
|
|
221
|
+
for (const wave of optimizedWaves) {
|
|
222
|
+
if (wave.testClasses.length > 0) {
|
|
223
|
+
wavesWithTests++;
|
|
224
|
+
totalTestsAdded += wave.testClasses.length;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
wavesWithoutTests++;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Estimate time saved (assume 5s per test class skipped)
|
|
231
|
+
const testsSkipped = optimizedWaves.length * totalAvailableTests - totalTestsAdded;
|
|
232
|
+
const timeSaved = testsSkipped * 5;
|
|
233
|
+
return {
|
|
234
|
+
totalWaves: optimizedWaves.length,
|
|
235
|
+
wavesWithTests,
|
|
236
|
+
wavesWithoutTests,
|
|
237
|
+
totalTestsAdded,
|
|
238
|
+
timeSaved,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* @ac US-040-AC-6: Report test optimization savings
|
|
243
|
+
*/
|
|
244
|
+
generateReport(result) {
|
|
245
|
+
const lines = [];
|
|
246
|
+
lines.push('# Test Optimization Report');
|
|
247
|
+
lines.push('');
|
|
248
|
+
lines.push('## Statistics');
|
|
249
|
+
lines.push(`- Total Waves: ${result.stats.totalWaves}`);
|
|
250
|
+
lines.push(`- Waves with Tests: ${result.stats.wavesWithTests}`);
|
|
251
|
+
lines.push(`- Waves without Tests: ${result.stats.wavesWithoutTests}`);
|
|
252
|
+
lines.push(`- Total Test Classes Added: ${result.stats.totalTestsAdded}`);
|
|
253
|
+
lines.push(`- Estimated Time Saved: ${result.stats.timeSaved}s (${Math.round(result.stats.timeSaved / 60)}min)`);
|
|
254
|
+
lines.push('');
|
|
255
|
+
lines.push('## Optimization Decisions');
|
|
256
|
+
lines.push('');
|
|
257
|
+
for (const decision of result.decisions) {
|
|
258
|
+
lines.push(`### Wave ${decision.waveNumber}`);
|
|
259
|
+
lines.push(`- Type: ${decision.type}`);
|
|
260
|
+
lines.push(`- Reason: ${decision.reason}`);
|
|
261
|
+
lines.push(`- Tests Affected: ${decision.testsAffected}`);
|
|
262
|
+
lines.push('');
|
|
263
|
+
}
|
|
264
|
+
lines.push('## Wave Details');
|
|
265
|
+
lines.push('');
|
|
266
|
+
for (const wave of result.optimizedWaves) {
|
|
267
|
+
lines.push(`### Wave ${wave.number}`);
|
|
268
|
+
lines.push(`- Code Classes: ${wave.codeClasses.length}`);
|
|
269
|
+
lines.push(`- Triggers: ${wave.triggers.length}`);
|
|
270
|
+
lines.push(`- Test Classes: ${wave.testClasses.length}`);
|
|
271
|
+
lines.push(`- Needs Tests: ${wave.needsTests ? 'Yes' : 'No'}`);
|
|
272
|
+
lines.push(`- Estimated Coverage: ${wave.estimatedCoverage}%`);
|
|
273
|
+
lines.push('');
|
|
274
|
+
}
|
|
275
|
+
return lines.join('\n');
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Get waves that need test execution
|
|
279
|
+
*/
|
|
280
|
+
getWavesNeedingTests(result) {
|
|
281
|
+
return result.optimizedWaves.filter((w) => w.needsTests);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get total test count across all waves
|
|
285
|
+
*/
|
|
286
|
+
getTotalTestCount(result) {
|
|
287
|
+
return result.optimizedWaves.reduce((sum, wave) => sum + wave.testClasses.length, 0);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=test-optimizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-optimizer.js","sourceRoot":"","sources":["../../src/waves/test-optimizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,MAAM,MAAM,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;AA0E1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,aAAa;IAChB,OAAO,CAA6B;IAE5C,YAAmB,UAA4B,EAAE;QAC/C,IAAI,CAAC,OAAO,GAAG;YACb,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,KAAK;YACrD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,IAAI,EAAE;YACtD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,IAAI,KAAK;SAC1D,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE;YACxC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB;YACjD,mBAAmB,EAAE,IAAI,CAAC,OAAO,CAAC,mBAAmB;SACtD,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACI,aAAa,CAAC,KAAa;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,SAAS,GAA2B,EAAE,CAAC;QAC7C,MAAM,cAAc,GAAoB,EAAE,CAAC;QAE3C,4CAA4C;QAC5C,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAEzD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YAEjE,IAAI,WAAW,GAAa,EAAE,CAAC;YAC/B,IAAI,iBAAiB,GAAG,GAAG,CAAC;YAE5B,IAAI,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;gBACnC,yCAAyC;gBACzC,WAAW,GAAG,cAAc,CAAC;gBAE7B,SAAS,CAAC,IAAI,CAAC;oBACb,UAAU,EAAE,IAAI,CAAC,MAAM;oBACvB,IAAI,EAAE,eAAe;oBACrB,MAAM,EAAE,kCAAkC;oBAC1C,aAAa,EAAE,cAAc,CAAC,MAAM;iBACrC,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,CAAC,UAAU,EAAE,CAAC;gBACvB,8BAA8B;gBAC9B,WAAW,GAAG,EAAE,CAAC;gBAEjB,SAAS,CAAC,IAAI,CAAC;oBACb,UAAU,EAAE,IAAI,CAAC,MAAM;oBACvB,IAAI,EAAE,YAAY;oBAClB,MAAM,EAAE,qCAAqC;oBAC7C,aAAa,EAAE,CAAC;iBACjB,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,sCAAsC;gBACtC,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;gBAC1E,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;gBAElF,SAAS,CAAC,IAAI,CAAC;oBACb,UAAU,EAAE,IAAI,CAAC,MAAM;oBACvB,IAAI,EAAE,YAAY;oBAClB,MAAM,EAAE,WAAW,WAAW,CAAC,MAAM,aAAa,WAAW,CAAC,MAAM,UAAU;oBAC9E,aAAa,EAAE,WAAW,CAAC,MAAM;iBAClC,CAAC,CAAC;YACL,CAAC;YAED,cAAc,CAAC,IAAI,CAAC;gBAClB,GAAG,IAAI;gBACP,WAAW;gBACX,WAAW;gBACX,QAAQ;gBACR,UAAU;gBACV,iBAAiB;aAClB,CAAC,CAAC;QACL,CAAC;QAED,uBAAuB;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;QAEzE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE;YACzC,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,UAAU,EAAE,KAAK,CAAC,eAAe;YACjC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAC;QAEH,OAAO;YACL,aAAa,EAAE,KAAK;YACpB,cAAc;YACd,SAAS;YACT,KAAK;SACN,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,qBAAqB,CAAC,KAAa;QACzC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;QAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACxC,IAAI,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;oBAChC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAU;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3F,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,IAAU;QAC5B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,SAAiB;QACnC,OAAO,CACL,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC;YAClC,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CACxF,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,WAAqB,EAAE,QAAkB,EAAE,cAAwB;QACzF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QAEvC,8BAA8B;QAC9B,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAE1C,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;gBACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBACvD,MAAM,QAAQ,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;gBAEzC,kBAAkB;gBAClB,wCAAwC;gBACxC,wCAAwC;gBACxC,yCAAyC;gBACzC,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;oBACnF,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAE1C,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;gBACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBACvD,MAAM,OAAO,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;gBAE1C,kBAAkB;gBAClB,wCAAwC;gBACxC,wCAAwC;gBACxC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC/D,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAChE,4DAA4D;YAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7D,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,cAAsB,EAAE,cAAsB;QACrE,IAAI,cAAc,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC;QACrC,IAAI,cAAc,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAEnC,oEAAoE;QACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,cAAc,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,cAA+B,EAAE,mBAA2B;QACjF,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,IAAI,eAAe,GAAG,CAAC,CAAC;QAExB,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,cAAc,EAAE,CAAC;gBACjB,eAAe,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,iBAAiB,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;QAED,yDAAyD;QACzD,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,GAAG,mBAAmB,GAAG,eAAe,CAAC;QACnF,MAAM,SAAS,GAAG,YAAY,GAAG,CAAC,CAAC;QAEnC,OAAO;YACL,UAAU,EAAE,cAAc,CAAC,MAAM;YACjC,cAAc;YACd,iBAAiB;YACjB,eAAe;YACf,SAAS;SACV,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,MAA8B;QAClD,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,0BAA0B,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACvE,KAAK,CAAC,IAAI,CAAC,+BAA+B,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC;QAC1E,KAAK,CAAC,IAAI,CAAC,2BAA2B,MAAM,CAAC,KAAK,CAAC,SAAS,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;QACjH,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,WAAW,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,qBAAqB,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;YAC1D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEf,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAClD,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/D,KAAK,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC/D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACI,oBAAoB,CAAC,MAA8B;QACxD,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACI,iBAAiB,CAAC,MAA8B;QACrD,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACvF,CAAC;CACF"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wave Builder
|
|
3
|
+
* Generates deployment waves using topological sort
|
|
4
|
+
*
|
|
5
|
+
* @ac US-038-AC-1: Generate waves from dependency graph
|
|
6
|
+
* @ac US-038-AC-2: Each wave contains independent components
|
|
7
|
+
* @ac US-038-AC-3: Components in wave N don't depend on wave N+1
|
|
8
|
+
* @ac US-038-AC-4: Handle components with no dependencies (wave 1)
|
|
9
|
+
* @ac US-038-AC-5: Handle isolated components
|
|
10
|
+
* @ac US-038-AC-6: Generate wave metadata
|
|
11
|
+
*
|
|
12
|
+
* @issue #38
|
|
13
|
+
*/
|
|
14
|
+
import type { NodeId, DependencyGraph, CircularDependency } from '../types/dependency.js';
|
|
15
|
+
import type { MetadataType } from '../types/metadata.js';
|
|
16
|
+
/**
|
|
17
|
+
* Wave of independent components
|
|
18
|
+
*/
|
|
19
|
+
export type Wave = {
|
|
20
|
+
/** Wave number (1-based) */
|
|
21
|
+
number: number;
|
|
22
|
+
/** Components in this wave */
|
|
23
|
+
components: NodeId[];
|
|
24
|
+
/** Metadata about the wave */
|
|
25
|
+
metadata: WaveMetadata;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Wave metadata
|
|
29
|
+
*/
|
|
30
|
+
export type WaveMetadata = {
|
|
31
|
+
/** Number of components */
|
|
32
|
+
componentCount: number;
|
|
33
|
+
/** Component types in this wave */
|
|
34
|
+
types: MetadataType[];
|
|
35
|
+
/** Maximum dependency depth in this wave */
|
|
36
|
+
maxDepth: number;
|
|
37
|
+
/** Whether this wave has circular dependencies */
|
|
38
|
+
hasCircularDeps: boolean;
|
|
39
|
+
/** Estimated deployment time (seconds) */
|
|
40
|
+
estimatedTime: number;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Wave generation result
|
|
44
|
+
*/
|
|
45
|
+
export type WaveResult = {
|
|
46
|
+
/** Generated waves */
|
|
47
|
+
waves: Wave[];
|
|
48
|
+
/** Total number of components */
|
|
49
|
+
totalComponents: number;
|
|
50
|
+
/** Components that couldn't be placed (circular deps) */
|
|
51
|
+
unplacedComponents: NodeId[];
|
|
52
|
+
/** Circular dependencies detected */
|
|
53
|
+
circularDependencies: CircularDependency[];
|
|
54
|
+
/** Statistics */
|
|
55
|
+
stats: WaveStats;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Wave statistics
|
|
59
|
+
*/
|
|
60
|
+
export type WaveStats = {
|
|
61
|
+
/** Total number of waves */
|
|
62
|
+
totalWaves: number;
|
|
63
|
+
/** Average components per wave */
|
|
64
|
+
avgComponentsPerWave: number;
|
|
65
|
+
/** Largest wave size */
|
|
66
|
+
largestWaveSize: number;
|
|
67
|
+
/** Smallest wave size */
|
|
68
|
+
smallestWaveSize: number;
|
|
69
|
+
/** Total estimated time (seconds) */
|
|
70
|
+
totalEstimatedTime: number;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Wave builder options
|
|
74
|
+
*/
|
|
75
|
+
export type WaveBuilderOptions = {
|
|
76
|
+
/** Maximum components per wave (0 = unlimited) */
|
|
77
|
+
maxComponentsPerWave?: number;
|
|
78
|
+
/** Respect metadata type deployment order */
|
|
79
|
+
respectTypeOrder?: boolean;
|
|
80
|
+
/** Handle circular dependencies */
|
|
81
|
+
handleCircularDeps?: boolean;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Wave Builder
|
|
85
|
+
*
|
|
86
|
+
* Generates deployment waves using topological sort algorithm.
|
|
87
|
+
* Each wave contains components that can be deployed in parallel.
|
|
88
|
+
*
|
|
89
|
+
* Algorithm:
|
|
90
|
+
* 1. Calculate in-degree for all nodes
|
|
91
|
+
* 2. Add nodes with in-degree 0 to first wave
|
|
92
|
+
* 3. Remove those nodes and update in-degrees
|
|
93
|
+
* 4. Repeat until all nodes are placed
|
|
94
|
+
*
|
|
95
|
+
* Performance: O(V + E)
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* const builder = new WaveBuilder({
|
|
99
|
+
* maxComponentsPerWave: 10000,
|
|
100
|
+
* respectTypeOrder: true
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* const result = builder.generateWaves(graph);
|
|
104
|
+
* console.log(`Generated ${result.waves.length} waves`);
|
|
105
|
+
*/
|
|
106
|
+
export declare class WaveBuilder {
|
|
107
|
+
private options;
|
|
108
|
+
constructor(options?: WaveBuilderOptions);
|
|
109
|
+
/**
|
|
110
|
+
* @ac US-038-AC-1: Generate waves from dependency graph
|
|
111
|
+
* @ac US-038-AC-2: Each wave contains independent components
|
|
112
|
+
* @ac US-038-AC-3: Components in wave N don't depend on wave N+1
|
|
113
|
+
*/
|
|
114
|
+
generateWaves(graph: DependencyGraph): WaveResult;
|
|
115
|
+
/**
|
|
116
|
+
* Calculate in-degree for all nodes
|
|
117
|
+
* In-degree = number of dependencies this node has (how many nodes it depends on)
|
|
118
|
+
* Nodes with in-degree 0 have no dependencies and can be deployed first
|
|
119
|
+
*/
|
|
120
|
+
private calculateInDegree;
|
|
121
|
+
private handleCircularWave;
|
|
122
|
+
private collectRemainingNodes;
|
|
123
|
+
/**
|
|
124
|
+
* @ac US-038-AC-6: Generate wave metadata
|
|
125
|
+
*/
|
|
126
|
+
private generateWaveMetadata;
|
|
127
|
+
/**
|
|
128
|
+
* Compare nodes by type deployment order
|
|
129
|
+
*/
|
|
130
|
+
private compareByTypeOrder;
|
|
131
|
+
/**
|
|
132
|
+
* Split array into chunks
|
|
133
|
+
*/
|
|
134
|
+
private chunkArray;
|
|
135
|
+
/**
|
|
136
|
+
* Calculate wave statistics
|
|
137
|
+
*/
|
|
138
|
+
private calculateStats;
|
|
139
|
+
/**
|
|
140
|
+
* Get wave by number
|
|
141
|
+
*/
|
|
142
|
+
getWave(result: WaveResult, waveNumber: number): Wave | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* Get component wave number
|
|
145
|
+
*/
|
|
146
|
+
getComponentWave(result: WaveResult, componentId: NodeId): number | undefined;
|
|
147
|
+
}
|