@howlil/ez-agents 3.5.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +735 -537
- package/agents/ez-architect-agent.md +267 -0
- package/agents/ez-backend-agent.md +303 -0
- package/agents/ez-chief-strategist.md +271 -0
- package/agents/ez-codebase-mapper.md +770 -770
- package/agents/ez-context-manager.md +319 -0
- package/agents/ez-debugger.md +1255 -1255
- package/agents/ez-design-expert.md +347 -0
- package/agents/ez-devops-agent.md +331 -0
- package/agents/ez-executor.md +487 -487
- package/agents/ez-frontend-agent.md +322 -0
- package/agents/ez-phase-researcher.md +553 -553
- package/agents/ez-planner.md +1307 -1307
- package/agents/ez-product-engineer.md +435 -0
- package/agents/ez-project-researcher.md +629 -629
- package/agents/ez-qa-agent.md +320 -0
- package/agents/ez-release-agent.md +333 -333
- package/agents/ez-requirements-agent.md +377 -377
- package/agents/ez-roadmapper.md +650 -650
- package/agents/ez-technical-writer.md +551 -0
- package/agents/ez-ux-expert.md +393 -0
- package/agents/ez-verifier.md +579 -579
- package/bin/guards/autonomy-guard.cjs +346 -0
- package/bin/guards/context-budget-guard.cjs +278 -0
- package/bin/guards/hallucination-guard.cjs +380 -0
- package/bin/guards/hidden-state-guard.cjs +182 -0
- package/bin/guards/team-overhead-guard.cjs +266 -0
- package/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/bin/lib/archetype-detector.cjs +289 -0
- package/bin/lib/assistant-adapter.cjs +361 -0
- package/bin/lib/audit-exec.cjs +175 -0
- package/bin/lib/auth.cjs +176 -0
- package/bin/lib/backup-service.cjs +422 -0
- package/bin/lib/bdd-validator.cjs +622 -0
- package/bin/lib/business-flow-mapper.cjs +429 -0
- package/bin/lib/circuit-breaker.cjs +276 -0
- package/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/bin/lib/codebase-analyzer.cjs +241 -0
- package/bin/lib/commands.cjs +691 -0
- package/bin/lib/config.cjs +236 -0
- package/bin/lib/constraint-extractor.cjs +526 -0
- package/bin/lib/content-scanner.cjs +238 -0
- package/bin/lib/context-cache.cjs +154 -0
- package/bin/lib/context-compressor.cjs +102 -0
- package/bin/lib/context-deduplicator.cjs +105 -0
- package/bin/lib/context-errors.cjs +78 -0
- package/bin/lib/context-manager.cjs +338 -0
- package/bin/lib/context-metadata-tracker.cjs +140 -0
- package/bin/lib/context-relevance-scorer.cjs +99 -0
- package/bin/lib/core.cjs +507 -0
- package/bin/lib/cost-alerts.cjs +174 -0
- package/bin/lib/cost-tracker.cjs +275 -0
- package/bin/lib/crash-recovery.cjs +220 -0
- package/bin/lib/dependency-graph.cjs +319 -0
- package/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/bin/lib/deploy/deploy-status.cjs +74 -0
- package/bin/lib/discussion-synthesizer.cjs +439 -0
- package/bin/lib/error-cache.cjs +114 -0
- package/bin/lib/error-registry.cjs +177 -0
- package/bin/lib/file-access.cjs +207 -0
- package/bin/lib/file-lock.cjs +236 -0
- package/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/bin/lib/finops/cost-reporter.cjs +132 -0
- package/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/bin/lib/finops/spot-manager.cjs +118 -0
- package/bin/lib/framework-detector.cjs +396 -0
- package/bin/lib/frontmatter.cjs +313 -0
- package/bin/lib/fs-utils.cjs +153 -0
- package/bin/lib/gate-executor.cjs +272 -0
- package/bin/lib/gates/README.md +374 -0
- package/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/bin/lib/gates/gate-03-code.cjs +635 -0
- package/bin/lib/gates/gate-04-security.cjs +829 -0
- package/bin/lib/git-errors.cjs +83 -0
- package/bin/lib/git-utils.cjs +321 -0
- package/bin/lib/git-workflow-engine.cjs +1157 -0
- package/bin/lib/health-check.cjs +227 -0
- package/bin/lib/index.cjs +279 -0
- package/bin/lib/init.cjs +725 -0
- package/bin/lib/lock-logger.cjs +194 -0
- package/bin/lib/lock-state.cjs +263 -0
- package/bin/lib/lockfile-validator.cjs +227 -0
- package/bin/lib/log-rotation.cjs +71 -0
- package/bin/lib/logger.cjs +125 -0
- package/bin/lib/memory-compression.cjs +256 -0
- package/bin/lib/milestone.cjs +247 -0
- package/bin/lib/model-provider.cjs +241 -0
- package/bin/lib/package-manager-detector.cjs +203 -0
- package/bin/lib/package-manager-executor.cjs +385 -0
- package/bin/lib/package-manager-service.cjs +216 -0
- package/bin/lib/perf/api-monitor.cjs +88 -0
- package/bin/lib/perf/db-optimizer.cjs +78 -0
- package/bin/lib/perf/frontend-performance.cjs +56 -0
- package/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/bin/lib/perf/perf-baseline.cjs +102 -0
- package/bin/lib/perf/perf-reporter.cjs +117 -0
- package/bin/lib/perf/regression-detector.cjs +92 -0
- package/bin/lib/phase.cjs +963 -0
- package/bin/lib/planning-write.cjs +123 -0
- package/bin/lib/project-reporter.cjs +565 -0
- package/bin/lib/quality-gate.cjs +332 -0
- package/bin/lib/quality-metrics.cjs +324 -0
- package/bin/lib/recovery-manager.cjs +98 -0
- package/bin/lib/release-validator.cjs +617 -0
- package/bin/lib/retry.cjs +119 -0
- package/bin/lib/roadmap.cjs +309 -0
- package/bin/lib/safe-exec.cjs +173 -0
- package/bin/lib/safe-path.cjs +130 -0
- package/bin/lib/security-errors.cjs +62 -0
- package/bin/lib/session-chain.cjs +304 -0
- package/bin/lib/session-errors.cjs +81 -0
- package/bin/lib/session-export.cjs +251 -0
- package/bin/lib/session-import.cjs +262 -0
- package/bin/lib/session-manager.cjs +280 -0
- package/bin/lib/skill-context.cjs +148 -0
- package/bin/lib/skill-matcher.cjs +236 -0
- package/bin/lib/skill-registry.cjs +360 -0
- package/bin/lib/skill-resolver.cjs +449 -0
- package/bin/lib/skill-triggers.cjs +90 -0
- package/bin/lib/skill-validator.cjs +270 -0
- package/bin/lib/skill-versioning.cjs +355 -0
- package/bin/lib/stack-detector.cjs +399 -0
- package/bin/lib/state.cjs +736 -0
- package/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/bin/lib/temp-file.cjs +239 -0
- package/bin/lib/template.cjs +223 -0
- package/bin/lib/test-file-lock.cjs +112 -0
- package/bin/lib/test-graceful.cjs +93 -0
- package/bin/lib/test-logger.cjs +60 -0
- package/bin/lib/test-safe-exec.cjs +38 -0
- package/bin/lib/test-safe-path.cjs +33 -0
- package/bin/lib/test-temp-file.cjs +125 -0
- package/bin/lib/tier-manager.cjs +428 -0
- package/bin/lib/timeout-exec.cjs +63 -0
- package/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/bin/lib/url-fetch.cjs +170 -0
- package/bin/lib/verify.cjs +863 -0
- package/bin/update.js +217 -214
- package/commands/deploy.cjs +53 -0
- package/commands/ez/add-tests.md +41 -41
- package/commands/ez/audit-milestone.md +36 -36
- package/commands/ez/complete-milestone.md +136 -136
- package/commands/ez/discuss-phase.md +90 -90
- package/commands/ez/execute-phase.md +52 -52
- package/commands/ez/help.md +22 -22
- package/commands/ez/map-codebase.md +71 -71
- package/commands/ez/new-milestone.md +44 -44
- package/commands/ez/new-project.md +51 -42
- package/commands/ez/plan-phase.md +53 -53
- package/commands/ez/progress.md +36 -36
- package/commands/ez/quick.md +45 -45
- package/commands/ez/resume-work.md +40 -40
- package/commands/ez/run-phase.md +580 -0
- package/commands/ez/settings.md +36 -36
- package/commands/ez/update.md +37 -37
- package/commands/ez/verify-work.md +402 -38
- package/commands/health-check.cjs +44 -0
- package/commands/rollback.cjs +47 -0
- package/ez-agents/bin/ez-tools.cjs +599 -2
- package/ez-agents/bin/guards/autonomy-guard.cjs +346 -0
- package/ez-agents/bin/guards/context-budget-guard.cjs +247 -0
- package/ez-agents/bin/guards/hallucination-guard.cjs +271 -0
- package/ez-agents/bin/guards/hidden-state-guard.cjs +182 -0
- package/ez-agents/bin/guards/team-overhead-guard.cjs +266 -0
- package/ez-agents/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/ez-agents/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/ez-agents/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/ez-agents/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/ez-agents/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/ez-agents/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/ez-agents/bin/lib/archetype-detector.cjs +289 -0
- package/ez-agents/bin/lib/audit-exec.cjs +166 -167
- package/ez-agents/bin/lib/auth.cjs +176 -176
- package/ez-agents/bin/lib/backup-service.cjs +422 -0
- package/ez-agents/bin/lib/bdd-validator.cjs +622 -622
- package/ez-agents/bin/lib/business-flow-mapper.cjs +429 -0
- package/ez-agents/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/ez-agents/bin/lib/codebase-analyzer.cjs +241 -0
- package/ez-agents/bin/lib/commands.cjs +685 -685
- package/ez-agents/bin/lib/config.cjs +41 -1
- package/ez-agents/bin/lib/constraint-extractor.cjs +526 -0
- package/ez-agents/bin/lib/content-scanner.cjs +238 -238
- package/ez-agents/bin/lib/context-cache.cjs +154 -154
- package/ez-agents/bin/lib/context-errors.cjs +71 -71
- package/ez-agents/bin/lib/context-manager.cjs +220 -220
- package/ez-agents/bin/lib/core.cjs +507 -512
- package/ez-agents/bin/lib/cost-tracker.cjs +243 -0
- package/ez-agents/bin/lib/crash-recovery.cjs +172 -0
- package/ez-agents/bin/lib/dependency-graph.cjs +319 -0
- package/ez-agents/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/ez-agents/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/ez-agents/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/ez-agents/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/ez-agents/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/ez-agents/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/ez-agents/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/ez-agents/bin/lib/deploy/deploy-status.cjs +74 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -207
- package/ez-agents/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/ez-agents/bin/lib/finops/cost-reporter.cjs +132 -0
- package/ez-agents/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/ez-agents/bin/lib/finops/spot-manager.cjs +118 -0
- package/ez-agents/bin/lib/framework-detector.cjs +396 -0
- package/ez-agents/bin/lib/frontmatter.cjs +3 -1
- package/ez-agents/bin/lib/gates/README.md +374 -0
- package/ez-agents/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/ez-agents/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/ez-agents/bin/lib/gates/gate-03-code.cjs +635 -0
- package/ez-agents/bin/lib/gates/gate-04-security.cjs +829 -0
- package/ez-agents/bin/lib/git-errors.cjs +83 -83
- package/ez-agents/bin/lib/git-utils.cjs +321 -321
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -1157
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +2 -8
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -227
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +22 -47
- package/ez-agents/bin/lib/memory-compression.cjs +256 -256
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -203
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -385
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -216
- package/ez-agents/bin/lib/perf/api-monitor.cjs +88 -0
- package/ez-agents/bin/lib/perf/db-optimizer.cjs +78 -0
- package/ez-agents/bin/lib/perf/frontend-performance.cjs +56 -0
- package/ez-agents/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/ez-agents/bin/lib/perf/perf-baseline.cjs +102 -0
- package/ez-agents/bin/lib/perf/perf-reporter.cjs +117 -0
- package/ez-agents/bin/lib/perf/regression-detector.cjs +92 -0
- package/ez-agents/bin/lib/project-reporter.cjs +502 -0
- package/ez-agents/bin/lib/quality-gate.cjs +332 -0
- package/ez-agents/bin/lib/recovery-manager.cjs +98 -0
- package/ez-agents/bin/lib/release-validator.cjs +617 -614
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -304
- package/ez-agents/bin/lib/session-errors.cjs +81 -81
- package/ez-agents/bin/lib/session-export.cjs +251 -251
- package/ez-agents/bin/lib/session-import.cjs +262 -262
- package/ez-agents/bin/lib/session-manager.cjs +280 -280
- package/ez-agents/bin/lib/skill-context.cjs +148 -0
- package/ez-agents/bin/lib/skill-matcher.cjs +236 -0
- package/ez-agents/bin/lib/skill-registry.cjs +341 -0
- package/ez-agents/bin/lib/skill-resolver.cjs +449 -0
- package/ez-agents/bin/lib/skill-triggers.cjs +90 -0
- package/ez-agents/bin/lib/skill-validator.cjs +270 -0
- package/ez-agents/bin/lib/skill-versioning.cjs +355 -0
- package/ez-agents/bin/lib/stack-detector.cjs +399 -0
- package/ez-agents/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/ez-agents/bin/lib/tier-manager.cjs +428 -428
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -170
- package/ez-agents/bin/lib/verify.cjs +863 -863
- package/ez-agents/references/decimal-phase-calculation.md +65 -65
- package/ez-agents/references/git-integration.md +248 -248
- package/ez-agents/references/git-planning-commit.md +38 -38
- package/ez-agents/references/metrics-schema.md +118 -118
- package/ez-agents/references/model-profile-resolution.md +34 -34
- package/ez-agents/references/model-profiles.md +93 -93
- package/ez-agents/references/phase-argument-parsing.md +61 -61
- package/ez-agents/references/planning-config.md +340 -340
- package/ez-agents/references/tier-strategy.md +103 -103
- package/ez-agents/references/ui-brand.md +160 -160
- package/ez-agents/references/verification-patterns.md +612 -612
- package/ez-agents/templates/DEBUG.md +164 -164
- package/ez-agents/templates/UAT.md +247 -247
- package/ez-agents/templates/agent-output-format.md +404 -0
- package/ez-agents/templates/bdd-feature.md +173 -173
- package/ez-agents/templates/codebase/architecture.md +255 -255
- package/ez-agents/templates/codebase/structure.md +285 -285
- package/ez-agents/templates/copilot-instructions.md +7 -7
- package/ez-agents/templates/debug-subagent-prompt.md +91 -91
- package/ez-agents/templates/discovery.md +146 -146
- package/ez-agents/templates/discussion.md +68 -68
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -205
- package/ez-agents/templates/mode-workflow-templates.md +301 -0
- package/ez-agents/templates/phase-prompt.md +610 -610
- package/ez-agents/templates/planner-subagent-prompt.md +117 -117
- package/ez-agents/templates/project.md +184 -184
- package/ez-agents/templates/release-checklist.md +136 -133
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -201
- package/ez-agents/templates/security-user-setup.md +244 -0
- package/ez-agents/templates/skill-validation-rules.md +476 -0
- package/ez-agents/templates/state.md +180 -176
- package/ez-agents/templates/summary-complex.md +59 -59
- package/ez-agents/tests/gates/gate-01-02.test.cjs +812 -0
- package/ez-agents/tests/gates/gate-03-04.test.cjs +762 -0
- package/ez-agents/tests/gates/gate-05-validator.test.cjs +145 -0
- package/ez-agents/tests/gates/gate-06-docs-validator.test.cjs +244 -0
- package/ez-agents/tests/gates/gate-07-release-validator.test.cjs +219 -0
- package/ez-agents/tests/guards/context-budget-guard.test.cjs +145 -0
- package/ez-agents/tests/guards/edge-case-guards.test.cjs +238 -0
- package/ez-agents/tests/guards/hallucination-guard.test.cjs +124 -0
- package/ez-agents/workflows/audit-milestone.md +1 -1
- package/ez-agents/workflows/autonomous.md +844 -844
- package/ez-agents/workflows/complete-milestone.md +1 -1
- package/ez-agents/workflows/discuss-phase.md +1 -1
- package/ez-agents/workflows/execute-phase.md +124 -3
- package/ez-agents/workflows/help.md +42 -181
- package/ez-agents/workflows/hotfix.md +291 -291
- package/ez-agents/workflows/new-milestone.md +713 -713
- package/ez-agents/workflows/new-project.md +1089 -1107
- package/ez-agents/workflows/plan-phase.md +0 -40
- package/ez-agents/workflows/release.md +253 -253
- package/ez-agents/workflows/resume-session.md +215 -215
- package/ez-agents/workflows/run-phase.md +531 -0
- package/ez-agents/workflows/settings.md +2 -35
- package/hooks/dist/ez-check-update.js +81 -81
- package/hooks/dist/ez-context-monitor.js +148 -141
- package/hooks/dist/ez-statusline.js +115 -115
- package/package.json +78 -71
- package/scripts/fix-qwen-installation.js +144 -144
- package/agents/ez-integration-checker.md +0 -443
- package/agents/ez-nyquist-auditor.md +0 -176
- package/agents/ez-observer-agent.md +0 -260
- package/agents/ez-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- package/agents/ez-scrum-master-agent.md +0 -242
- package/agents/ez-tech-lead-agent.md +0 -267
- package/agents/ez-ui-auditor.md +0 -439
- package/agents/ez-ui-checker.md +0 -300
- package/agents/ez-ui-researcher.md +0 -353
- package/commands/ez/add-phase.md +0 -43
- package/commands/ez/add-todo.md +0 -47
- package/commands/ez/arch-review.md +0 -102
- package/commands/ez/auth.md +0 -87
- package/commands/ez/autonomous.md +0 -41
- package/commands/ez/check-todos.md +0 -45
- package/commands/ez/cleanup.md +0 -18
- package/commands/ez/debug.md +0 -168
- package/commands/ez/export-session.md +0 -79
- package/commands/ez/gather-requirements.md +0 -117
- package/commands/ez/git-workflow.md +0 -72
- package/commands/ez/health.md +0 -22
- package/commands/ez/hotfix.md +0 -120
- package/commands/ez/import-session.md +0 -82
- package/commands/ez/insert-phase.md +0 -32
- package/commands/ez/join-discord.md +0 -18
- package/commands/ez/list-phase-assumptions.md +0 -46
- package/commands/ez/list-sessions.md +0 -96
- package/commands/ez/package-manager.md +0 -316
- package/commands/ez/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/preflight.md +0 -79
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/release.md +0 -153
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/resume.md +0 -107
- package/commands/ez/set-profile.md +0 -34
- package/commands/ez/standup.md +0 -85
- package/commands/ez/stats.md +0 -18
- package/commands/ez/ui-phase.md +0 -34
- package/commands/ez/ui-review.md +0 -32
- package/commands/ez/validate-phase.md +0 -35
- package/ez-agents/bin/lib/metrics-tracker.cjs +0 -406
- package/ez-agents/templates/UI-SPEC.md +0 -100
- package/ez-agents/templates/VALIDATION.md +0 -76
- package/ez-agents/templates/context.md +0 -352
- package/ez-agents/templates/verification-report.md +0 -322
- package/ez-agents/workflows/arch-review.md +0 -54
- package/ez-agents/workflows/export-session.md +0 -255
- package/ez-agents/workflows/gather-requirements.md +0 -206
- package/ez-agents/workflows/import-session.md +0 -303
- package/ez-agents/workflows/research-phase.md +0 -74
- package/ez-agents/workflows/standup.md +0 -64
- package/ez-agents/workflows/ui-phase.md +0 -290
- package/ez-agents/workflows/ui-review.md +0 -157
- package/ez-agents/workflows/validate-phase.md +0 -167
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Graph — Automated dependency analysis using madge
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - build(rootPath, entryPoint): Creates dependency graph using madge for JS/TS files
|
|
6
|
+
* - detectCircular(): Returns array of circular dependency paths
|
|
7
|
+
* - getNodes(), getEdges(), getOrphanFiles(), getLeafFiles(): Graph accessors
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
class DependencyGraph {
|
|
14
|
+
constructor(rootPath, options = {}) {
|
|
15
|
+
this.rootPath = rootPath;
|
|
16
|
+
this.options = {
|
|
17
|
+
entry: options.entry || null,
|
|
18
|
+
detectCircular: options.detectCircular !== false,
|
|
19
|
+
includeNpm: options.includeNpm || false,
|
|
20
|
+
tsConfig: options.tsConfig || 'tsconfig.json',
|
|
21
|
+
fileExtensions: options.fileExtensions || ['.ts', '.tsx', '.js', '.jsx'],
|
|
22
|
+
...options
|
|
23
|
+
};
|
|
24
|
+
this.nodes = [];
|
|
25
|
+
this.edges = {};
|
|
26
|
+
this.circular = [];
|
|
27
|
+
this.orphan = [];
|
|
28
|
+
this.leafs = [];
|
|
29
|
+
this.graph = null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Build dependency graph from root path
|
|
34
|
+
* @param {string} rootPath - Root directory to analyze
|
|
35
|
+
* @param {string} entryPoint - Optional entry point file
|
|
36
|
+
* @returns {Promise<object>} Graph object with nodes, edges, circular, orphan, leafs
|
|
37
|
+
*/
|
|
38
|
+
async build(rootPath = this.rootPath, entryPoint = this.options.entry) {
|
|
39
|
+
try {
|
|
40
|
+
const madge = require('madge');
|
|
41
|
+
|
|
42
|
+
const config = {
|
|
43
|
+
entry: entryPoint || undefined,
|
|
44
|
+
detectCircular: this.options.detectCircular,
|
|
45
|
+
includeNpm: this.options.includeNpm,
|
|
46
|
+
tsConfig: path.join(rootPath, this.options.tsConfig),
|
|
47
|
+
fileExtensions: this.options.fileExtensions,
|
|
48
|
+
extensions: this.options.fileExtensions.map(ext => ext.replace('.', ''))
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Find source files
|
|
52
|
+
const srcDir = path.join(rootPath, 'src');
|
|
53
|
+
const appDir = path.join(rootPath, 'app');
|
|
54
|
+
const libDir = path.join(rootPath, 'lib');
|
|
55
|
+
|
|
56
|
+
let searchPath = rootPath;
|
|
57
|
+
if (fs.existsSync(srcDir)) {
|
|
58
|
+
searchPath = srcDir;
|
|
59
|
+
} else if (fs.existsSync(appDir)) {
|
|
60
|
+
searchPath = appDir;
|
|
61
|
+
} else if (fs.existsSync(libDir)) {
|
|
62
|
+
searchPath = libDir;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Build glob pattern
|
|
66
|
+
const patterns = this.options.fileExtensions
|
|
67
|
+
.flatMap(ext => [
|
|
68
|
+
path.join(searchPath, `**/*${ext}`),
|
|
69
|
+
path.join(rootPath, `bin/**/*${ext}`),
|
|
70
|
+
path.join(rootPath, 'commands/**/*${ext}')
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
// Filter to existing paths
|
|
74
|
+
const existingPatterns = patterns.filter(p => {
|
|
75
|
+
// Simple check - madge will handle the actual globbing
|
|
76
|
+
return true;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Use madge to analyze dependencies
|
|
80
|
+
const depGraph = await madge(existingPatterns.length > 0 ? existingPatterns : searchPath, {
|
|
81
|
+
...config,
|
|
82
|
+
tsConfig: fs.existsSync(config.tsConfig) ? config.tsConfig : undefined
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
this.nodes = depGraph.nodes();
|
|
86
|
+
this.edges = depGraph.dependencies();
|
|
87
|
+
this.circular = this.options.detectCircular ? depGraph.circular() : [];
|
|
88
|
+
this.orphan = depGraph.orphan();
|
|
89
|
+
this.leafs = depGraph.leafs();
|
|
90
|
+
this.graph = depGraph;
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
nodes: this.nodes,
|
|
94
|
+
edges: this.edges,
|
|
95
|
+
circular: this.circular,
|
|
96
|
+
orphan: this.orphan,
|
|
97
|
+
leafs: this.leafs
|
|
98
|
+
};
|
|
99
|
+
} catch (err) {
|
|
100
|
+
// If madge fails, create a basic graph from file system
|
|
101
|
+
console.warn(`Warning: Madge analysis failed (${err.message}), using fallback file-based analysis`);
|
|
102
|
+
return this._buildFallback(rootPath);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Detect circular dependencies
|
|
108
|
+
* @returns {Array} Array of circular dependency paths
|
|
109
|
+
*/
|
|
110
|
+
detectCircular() {
|
|
111
|
+
return this.circular;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get all nodes (files) in the graph
|
|
116
|
+
* @returns {Array} Array of file paths
|
|
117
|
+
*/
|
|
118
|
+
getNodes() {
|
|
119
|
+
return this.nodes;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get all edges (import relationships) in the graph
|
|
124
|
+
* @returns {object} Object mapping file paths to their dependencies
|
|
125
|
+
*/
|
|
126
|
+
getEdges() {
|
|
127
|
+
return this.edges;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get orphan files (files with no imports/exports)
|
|
132
|
+
* @returns {Array} Array of orphan file paths
|
|
133
|
+
*/
|
|
134
|
+
getOrphanFiles() {
|
|
135
|
+
return this.orphan;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get leaf files (files not imported by others)
|
|
140
|
+
* @returns {Array} Array of leaf file paths
|
|
141
|
+
*/
|
|
142
|
+
getLeafFiles() {
|
|
143
|
+
return this.leafs;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get dependency count for a file
|
|
148
|
+
* @param {string} filePath - File path
|
|
149
|
+
* @returns {number} Number of dependencies
|
|
150
|
+
*/
|
|
151
|
+
getDependencyCount(filePath) {
|
|
152
|
+
return this.edges[filePath] ? this.edges[filePath].length : 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Get dependent count (how many files depend on this file)
|
|
157
|
+
* @param {string} filePath - File path
|
|
158
|
+
* @returns {number} Number of files that depend on this file
|
|
159
|
+
*/
|
|
160
|
+
getDependentCount(filePath) {
|
|
161
|
+
let count = 0;
|
|
162
|
+
for (const deps of Object.values(this.edges)) {
|
|
163
|
+
if (deps.includes(filePath)) {
|
|
164
|
+
count++;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return count;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get most depended upon files (hubs)
|
|
172
|
+
* @param {number} limit - Maximum number of results
|
|
173
|
+
* @returns {Array} Array of {file, count} objects
|
|
174
|
+
*/
|
|
175
|
+
getHubFiles(limit = 10) {
|
|
176
|
+
const counts = {};
|
|
177
|
+
for (const deps of Object.values(this.edges)) {
|
|
178
|
+
for (const dep of deps) {
|
|
179
|
+
counts[dep] = (counts[dep] || 0) + 1;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return Object.entries(counts)
|
|
184
|
+
.map(([file, count]) => ({ file, count }))
|
|
185
|
+
.sort((a, b) => b.count - a.count)
|
|
186
|
+
.slice(0, limit);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Get most dependent files (files with many dependencies)
|
|
191
|
+
* @param {number} limit - Maximum number of results
|
|
192
|
+
* @returns {Array} Array of {file, count} objects
|
|
193
|
+
*/
|
|
194
|
+
getMostDependentFiles(limit = 10) {
|
|
195
|
+
return Object.entries(this.edges)
|
|
196
|
+
.map(([file, deps]) => ({ file, count: deps.length }))
|
|
197
|
+
.sort((a, b) => b.count - a.count)
|
|
198
|
+
.slice(0, limit);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Fallback graph builder when madge fails
|
|
203
|
+
* @private
|
|
204
|
+
*/
|
|
205
|
+
_buildFallback(rootPath) {
|
|
206
|
+
const result = {
|
|
207
|
+
nodes: [],
|
|
208
|
+
edges: {},
|
|
209
|
+
circular: [],
|
|
210
|
+
orphan: [],
|
|
211
|
+
leafs: []
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
// Simple file-based analysis
|
|
216
|
+
const files = this._getAllSourceFiles(rootPath);
|
|
217
|
+
result.nodes = files;
|
|
218
|
+
|
|
219
|
+
// Create basic edges from import statements
|
|
220
|
+
for (const file of files) {
|
|
221
|
+
const imports = this._extractImports(file);
|
|
222
|
+
result.edges[file] = imports.filter(imp => files.includes(imp));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Find orphans (no imports and not imported)
|
|
226
|
+
const importedFiles = new Set();
|
|
227
|
+
for (const deps of Object.values(result.edges)) {
|
|
228
|
+
for (const dep of deps) {
|
|
229
|
+
importedFiles.add(dep);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
result.orphan = files.filter(file => {
|
|
234
|
+
const hasImports = result.edges[file] && result.edges[file].length > 0;
|
|
235
|
+
const isImported = importedFiles.has(file);
|
|
236
|
+
return !hasImports && !isImported;
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Find leafs (not imported by others)
|
|
240
|
+
result.leafs = files.filter(file => !importedFiles.has(file));
|
|
241
|
+
|
|
242
|
+
this.nodes = result.nodes;
|
|
243
|
+
this.edges = result.edges;
|
|
244
|
+
this.orphan = result.orphan;
|
|
245
|
+
this.leafs = result.leafs;
|
|
246
|
+
|
|
247
|
+
return result;
|
|
248
|
+
} catch (err) {
|
|
249
|
+
console.warn(`Warning: Fallback graph building failed: ${err.message}`);
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Get all source files in directory
|
|
256
|
+
* @private
|
|
257
|
+
*/
|
|
258
|
+
_getAllSourceFiles(dir, files = []) {
|
|
259
|
+
try {
|
|
260
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
261
|
+
for (const entry of entries) {
|
|
262
|
+
const fullPath = path.join(dir, entry.name);
|
|
263
|
+
if (entry.isDirectory() && !['node_modules', '.git', 'dist', 'build'].includes(entry.name)) {
|
|
264
|
+
this._getAllSourceFiles(fullPath, files);
|
|
265
|
+
} else if (entry.isFile()) {
|
|
266
|
+
const ext = path.extname(entry.name);
|
|
267
|
+
if (this.options.fileExtensions.includes(ext)) {
|
|
268
|
+
files.push(fullPath);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
} catch (err) {
|
|
273
|
+
// Ignore errors
|
|
274
|
+
}
|
|
275
|
+
return files;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Extract imports from a file
|
|
280
|
+
* @private
|
|
281
|
+
*/
|
|
282
|
+
_extractImports(filePath) {
|
|
283
|
+
const imports = [];
|
|
284
|
+
try {
|
|
285
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
286
|
+
const importRegex = /(?:import|require)\s*[\s\S]*?['"]([^'"]+)['"]/g;
|
|
287
|
+
let match;
|
|
288
|
+
|
|
289
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
290
|
+
const importPath = match[1];
|
|
291
|
+
// Only include relative imports
|
|
292
|
+
if (importPath.startsWith('.')) {
|
|
293
|
+
const resolved = path.resolve(path.dirname(filePath), importPath);
|
|
294
|
+
// Try to find the actual file
|
|
295
|
+
for (const ext of this.options.fileExtensions) {
|
|
296
|
+
const withExt = resolved + ext;
|
|
297
|
+
if (fs.existsSync(withExt)) {
|
|
298
|
+
imports.push(withExt);
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// Also check index files
|
|
303
|
+
for (const ext of this.options.fileExtensions) {
|
|
304
|
+
const indexPath = path.join(resolved, `index${ext}`);
|
|
305
|
+
if (fs.existsSync(indexPath)) {
|
|
306
|
+
imports.push(indexPath);
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
} catch (err) {
|
|
313
|
+
// Ignore errors
|
|
314
|
+
}
|
|
315
|
+
return imports;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
module.exports = { DependencyGraph };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy Audit Log — Writes deploy audit logs
|
|
3
|
+
* Logs to temp directory (console-only fallback)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class DeployAuditLog {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
// Use temp directory instead of .planning/logs
|
|
13
|
+
this.logsDir = path.join(process.env.TEMP || process.env.TMPDIR || '/tmp', 'ez-agents-deploy');
|
|
14
|
+
// Ensure temp dir exists
|
|
15
|
+
if (!fs.existsSync(this.logsDir)) {
|
|
16
|
+
fs.mkdirSync(this.logsDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Write deploy audit log
|
|
22
|
+
* @param {Object} deployDetails - Deploy details to log
|
|
23
|
+
* @returns {string} Path to written log
|
|
24
|
+
*/
|
|
25
|
+
writeAuditLog(deployDetails) {
|
|
26
|
+
// Ensure logs directory exists
|
|
27
|
+
if (!fs.existsSync(this.logsDir)) {
|
|
28
|
+
fs.mkdirSync(this.logsDir, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const timestamp = Date.now();
|
|
32
|
+
const filename = `deploy-${timestamp}.json`;
|
|
33
|
+
const logPath = path.join(this.logsDir, filename);
|
|
34
|
+
|
|
35
|
+
const logEntry = {
|
|
36
|
+
timestamp: new Date().toISOString(),
|
|
37
|
+
...deployDetails
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
fs.writeFileSync(logPath, JSON.stringify(logEntry, null, 2), 'utf8');
|
|
41
|
+
return logPath;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Read deploy audit log
|
|
46
|
+
* @param {string} filename - Log filename
|
|
47
|
+
* @returns {Object} Log entry
|
|
48
|
+
*/
|
|
49
|
+
readAuditLog(filename) {
|
|
50
|
+
const logPath = path.join(this.logsDir, filename);
|
|
51
|
+
if (!fs.existsSync(logPath)) return null;
|
|
52
|
+
return JSON.parse(fs.readFileSync(logPath, 'utf8'));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* List all deploy audit logs
|
|
57
|
+
* @returns {Array} Array of log filenames
|
|
58
|
+
*/
|
|
59
|
+
listAuditLogs() {
|
|
60
|
+
if (!fs.existsSync(this.logsDir)) return [];
|
|
61
|
+
return fs.readdirSync(this.logsDir).filter(f => f.startsWith('deploy-') && f.endsWith('.json'));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Write deploy audit log
|
|
67
|
+
* @param {Object} deployDetails - Deploy details
|
|
68
|
+
* @param {string} cwd - Working directory
|
|
69
|
+
* @returns {string} Path to written log
|
|
70
|
+
*/
|
|
71
|
+
function writeAuditLog(deployDetails, cwd) {
|
|
72
|
+
const logger = new DeployAuditLog(cwd);
|
|
73
|
+
return logger.writeAuditLog(deployDetails);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = { DeployAuditLog, writeAuditLog };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy Detector — Detects target deployment environment
|
|
3
|
+
* Checks config files (vercel.json, fly.toml, Procfile) and git remotes
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
class DeployDetector {
|
|
11
|
+
constructor(cwd) {
|
|
12
|
+
this.cwd = cwd || process.cwd();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Detect deployment environment from config files and git remotes
|
|
17
|
+
* @returns {Object} Detection result { platform, confidence, source }
|
|
18
|
+
*/
|
|
19
|
+
detect() {
|
|
20
|
+
// Check for platform config files (high confidence)
|
|
21
|
+
const configChecks = [
|
|
22
|
+
{ file: 'vercel.json', platform: 'vercel', confidence: 'high' },
|
|
23
|
+
{ file: 'fly.toml', platform: 'fly.io', confidence: 'high' },
|
|
24
|
+
{ file: 'Procfile', platform: 'heroku', confidence: 'high' },
|
|
25
|
+
{ file: 'railway.json', platform: 'railway', confidence: 'high' }
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
for (const check of configChecks) {
|
|
29
|
+
if (fs.existsSync(path.join(this.cwd, check.file))) {
|
|
30
|
+
return {
|
|
31
|
+
platform: check.platform,
|
|
32
|
+
confidence: check.confidence,
|
|
33
|
+
source: check.file
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Fallback: check git remotes (medium confidence)
|
|
39
|
+
try {
|
|
40
|
+
const remotes = execSync('git remote -v', { cwd: this.cwd, encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
41
|
+
|
|
42
|
+
if (remotes.includes('vercel.com')) {
|
|
43
|
+
return { platform: 'vercel', confidence: 'medium', source: 'git-remote' };
|
|
44
|
+
}
|
|
45
|
+
if (remotes.includes('fly.dev')) {
|
|
46
|
+
return { platform: 'fly.io', confidence: 'medium', source: 'git-remote' };
|
|
47
|
+
}
|
|
48
|
+
if (remotes.includes('heroku.com')) {
|
|
49
|
+
return { platform: 'heroku', confidence: 'medium', source: 'git-remote' };
|
|
50
|
+
}
|
|
51
|
+
} catch (e) {
|
|
52
|
+
// No git or no remotes
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { platform: 'unknown', confidence: 'none', source: 'none' };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Detect deployment environment
|
|
61
|
+
* @param {string} cwd - Working directory
|
|
62
|
+
* @returns {Object} Detection result
|
|
63
|
+
*/
|
|
64
|
+
function detect(cwd) {
|
|
65
|
+
const detector = new DeployDetector(cwd);
|
|
66
|
+
return detector.detect();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { DeployDetector, detect };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy Env Manager — Multi-environment deploy config
|
|
3
|
+
* Manages dev/staging/prod environment configurations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class DeployEnvManager {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
this.configPath = path.join(this.cwd, '.planning', 'deploy-config.json');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get environment configuration
|
|
17
|
+
* @param {string} env - Environment name (dev, staging, prod)
|
|
18
|
+
* @returns {Object} Environment config
|
|
19
|
+
*/
|
|
20
|
+
getEnvConfig(env) {
|
|
21
|
+
const config = this.loadConfig();
|
|
22
|
+
const defaultConfig = {
|
|
23
|
+
env: 'dev',
|
|
24
|
+
platform: 'vercel',
|
|
25
|
+
url: null,
|
|
26
|
+
requiredVars: []
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return config.environments?.[env] || { ...defaultConfig, env };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Set environment configuration
|
|
34
|
+
* @param {string} env - Environment name
|
|
35
|
+
* @param {Object} config - Configuration to set
|
|
36
|
+
*/
|
|
37
|
+
setEnv(env, config) {
|
|
38
|
+
const current = this.loadConfig();
|
|
39
|
+
if (!current.environments) current.environments = {};
|
|
40
|
+
current.environments[env] = { ...current.environments[env], ...config };
|
|
41
|
+
this.saveConfig(current);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* List all configured environments
|
|
46
|
+
* @returns {Array} Array of environment names
|
|
47
|
+
*/
|
|
48
|
+
listEnvs() {
|
|
49
|
+
const config = this.loadConfig();
|
|
50
|
+
return Object.keys(config.environments || {});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validate environment has required variables
|
|
55
|
+
* @param {string} env - Environment name
|
|
56
|
+
* @returns {Object} Validation result { valid, missing }
|
|
57
|
+
*/
|
|
58
|
+
validateEnv(env) {
|
|
59
|
+
const config = this.getEnvConfig(env);
|
|
60
|
+
const missing = [];
|
|
61
|
+
|
|
62
|
+
for (const envVar of config.requiredVars || []) {
|
|
63
|
+
if (!process.env[envVar]) {
|
|
64
|
+
missing.push(envVar);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
valid: missing.length === 0,
|
|
70
|
+
missing
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Load config from file
|
|
76
|
+
* @returns {Object} Config
|
|
77
|
+
*/
|
|
78
|
+
loadConfig() {
|
|
79
|
+
if (!fs.existsSync(this.configPath)) {
|
|
80
|
+
return { environments: {} };
|
|
81
|
+
}
|
|
82
|
+
return JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Save config to file
|
|
87
|
+
* @param {Object} config - Config to save
|
|
88
|
+
*/
|
|
89
|
+
saveConfig(config) {
|
|
90
|
+
const dir = path.dirname(this.configPath);
|
|
91
|
+
if (!fs.existsSync(dir)) {
|
|
92
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
93
|
+
}
|
|
94
|
+
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get environment configuration
|
|
100
|
+
* @param {string} env - Environment name
|
|
101
|
+
* @param {string} cwd - Working directory
|
|
102
|
+
* @returns {Object} Environment config
|
|
103
|
+
*/
|
|
104
|
+
function getEnvConfig(env, cwd) {
|
|
105
|
+
const manager = new DeployEnvManager(cwd);
|
|
106
|
+
return manager.getEnvConfig(env);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = { DeployEnvManager, getEnvConfig };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy Health Check — Verifies deployment success
|
|
3
|
+
* Checks deployment URL for healthy response
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const https = require('https');
|
|
7
|
+
const http = require('http');
|
|
8
|
+
|
|
9
|
+
class DeployHealthCheck {
|
|
10
|
+
constructor(timeout = 10000) {
|
|
11
|
+
this.timeout = timeout;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check health of deployment URL
|
|
16
|
+
* @param {string} url - Deployment URL to check
|
|
17
|
+
* @param {Array} endpoints - Additional endpoints to check
|
|
18
|
+
* @returns {Object} Health result { healthy, status, message }
|
|
19
|
+
*/
|
|
20
|
+
async checkHealth(url, endpoints = []) {
|
|
21
|
+
const allEndpoints = [url, ...endpoints];
|
|
22
|
+
const results = [];
|
|
23
|
+
|
|
24
|
+
for (const endpoint of allEndpoints) {
|
|
25
|
+
try {
|
|
26
|
+
const result = await this.checkEndpoint(endpoint);
|
|
27
|
+
results.push(result);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
results.push({
|
|
30
|
+
url: endpoint,
|
|
31
|
+
healthy: false,
|
|
32
|
+
status: 'error',
|
|
33
|
+
message: e.message
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const allHealthy = results.every(r => r.healthy);
|
|
39
|
+
return {
|
|
40
|
+
healthy: allHealthy,
|
|
41
|
+
results,
|
|
42
|
+
message: allHealthy ? 'All endpoints healthy' : 'Some endpoints unhealthy'
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check single endpoint
|
|
48
|
+
* @param {string} url - URL to check
|
|
49
|
+
* @returns {Object} Health result
|
|
50
|
+
*/
|
|
51
|
+
async checkEndpoint(url) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const protocol = url.startsWith('https') ? https : http;
|
|
54
|
+
|
|
55
|
+
const req = protocol.get(url, { timeout: this.timeout }, (res) => {
|
|
56
|
+
if (res.statusCode === 200) {
|
|
57
|
+
resolve({ url, healthy: true, status: res.statusCode, message: 'OK' });
|
|
58
|
+
} else if (res.statusCode >= 500) {
|
|
59
|
+
resolve({ url, healthy: false, status: res.statusCode, message: 'Server Error' });
|
|
60
|
+
} else {
|
|
61
|
+
resolve({ url, healthy: true, status: res.statusCode, message: 'OK (non-200)' });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
req.on('error', (e) => {
|
|
66
|
+
resolve({ url, healthy: false, status: 'error', message: e.message });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
req.on('timeout', () => {
|
|
70
|
+
req.destroy();
|
|
71
|
+
resolve({ url, healthy: false, status: 'timeout', message: 'Request timed out' });
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check health of deployment URL
|
|
79
|
+
* @param {string} url - Deployment URL
|
|
80
|
+
* @param {Array} endpoints - Additional endpoints
|
|
81
|
+
* @returns {Object} Health result
|
|
82
|
+
*/
|
|
83
|
+
async function checkHealth(url, endpoints = []) {
|
|
84
|
+
const checker = new DeployHealthCheck();
|
|
85
|
+
return checker.checkHealth(url, endpoints);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { DeployHealthCheck, checkHealth };
|