@howlil/ez-agents 3.4.2 → 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 -462
- 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 -0
- package/agents/ez-requirements-agent.md +377 -0
- 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/install.js +3221 -3272
- 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 -41
- 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 -45
- package/commands/ez/progress.md +36 -24
- 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 +1692 -716
- 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 -0
- 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 -0
- package/ez-agents/bin/lib/context-cache.cjs +154 -0
- package/ez-agents/bin/lib/context-errors.cjs +71 -0
- package/ez-agents/bin/lib/context-manager.cjs +220 -0
- 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/discussion-synthesizer.cjs +458 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -0
- 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 -0
- package/ez-agents/bin/lib/git-utils.cjs +118 -0
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +40 -2
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +99 -154
- package/ez-agents/bin/lib/memory-compression.cjs +256 -0
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
- 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 -0
- package/ez-agents/bin/lib/safe-exec.cjs +128 -214
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -0
- package/ez-agents/bin/lib/session-errors.cjs +81 -0
- package/ez-agents/bin/lib/session-export.cjs +251 -0
- package/ez-agents/bin/lib/session-import.cjs +262 -0
- package/ez-agents/bin/lib/session-manager.cjs +280 -0
- 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 -0
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -0
- 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 -0
- 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 -200
- package/ez-agents/references/tier-strategy.md +103 -0
- 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 -0
- 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 -0
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -0
- 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 -0
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -0
- 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 +131 -30
- 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 +169 -3
- package/ez-agents/workflows/help.md +86 -133
- package/ez-agents/workflows/hotfix.md +291 -0
- package/ez-agents/workflows/new-milestone.md +340 -11
- package/ez-agents/workflows/new-project.md +294 -318
- package/ez-agents/workflows/plan-phase.md +22 -40
- package/ez-agents/workflows/progress.md +15 -25
- package/ez-agents/workflows/release.md +253 -0
- package/ez-agents/workflows/resume-session.md +215 -0
- 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 -64
- 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-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- 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/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/health.md +0 -22
- 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/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/set-profile.md +0 -34
- 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/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/research-phase.md +0 -74
- 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,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Package Manager Service — Unified package manager operations
|
|
5
|
+
*
|
|
6
|
+
* High-level service that integrates detection, execution, and validation:
|
|
7
|
+
* - Automatic package manager detection with priority-based strategy
|
|
8
|
+
* - Lockfile validation before operations
|
|
9
|
+
* - Unified interface for install, add, remove operations
|
|
10
|
+
* - Configuration-driven defaults from .planning/config.json
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const PackageManagerService = require('./package-manager-service.cjs');
|
|
14
|
+
* const service = new PackageManagerService(cwd);
|
|
15
|
+
* await service.initialize();
|
|
16
|
+
* await service.install({ frozenLockfile: true });
|
|
17
|
+
* await service.add(['lodash'], { dev: true });
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
const Logger = require('./logger.cjs');
|
|
23
|
+
const PackageManagerDetector = require('./package-manager-detector.cjs');
|
|
24
|
+
const PackageManagerExecutor = require('./package-manager-executor.cjs');
|
|
25
|
+
const LockfileValidator = require('./lockfile-validator.cjs');
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Package Manager Service class
|
|
29
|
+
* Provides unified interface for package manager operations
|
|
30
|
+
*/
|
|
31
|
+
class PackageManagerService {
|
|
32
|
+
/**
|
|
33
|
+
* Create a PackageManagerService instance
|
|
34
|
+
* @param {string} cwd - Working directory (default: process.cwd())
|
|
35
|
+
*/
|
|
36
|
+
constructor(cwd = process.cwd()) {
|
|
37
|
+
this.cwd = cwd;
|
|
38
|
+
this.logger = new Logger();
|
|
39
|
+
this.detector = new PackageManagerDetector(cwd);
|
|
40
|
+
this.validator = new LockfileValidator(cwd);
|
|
41
|
+
this.executor = null;
|
|
42
|
+
this.currentManager = null;
|
|
43
|
+
this.detectionSource = null;
|
|
44
|
+
this.initialized = false;
|
|
45
|
+
this.config = this._loadConfig();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Initialize the package manager service
|
|
50
|
+
* @param {Object} options - Initialization options
|
|
51
|
+
* @param {string} [options.forceManager] - Force specific package manager
|
|
52
|
+
* @returns {Promise<void>}
|
|
53
|
+
*/
|
|
54
|
+
async initialize(options = {}) {
|
|
55
|
+
const { forceManager } = options;
|
|
56
|
+
|
|
57
|
+
this.logger.info('Initializing package manager service', {
|
|
58
|
+
cwd: this.cwd,
|
|
59
|
+
forceManager
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Detect package manager
|
|
63
|
+
let detection;
|
|
64
|
+
if (forceManager) {
|
|
65
|
+
detection = {
|
|
66
|
+
manager: forceManager,
|
|
67
|
+
source: 'override',
|
|
68
|
+
confidence: 'high'
|
|
69
|
+
};
|
|
70
|
+
this.logger.info('Using forced package manager', { manager: forceManager });
|
|
71
|
+
} else {
|
|
72
|
+
detection = this.detector.detect();
|
|
73
|
+
this.logger.info('Package manager detected', {
|
|
74
|
+
manager: detection.manager,
|
|
75
|
+
source: detection.source,
|
|
76
|
+
confidence: detection.confidence
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Validate detection
|
|
81
|
+
if (!detection.manager) {
|
|
82
|
+
throw new Error('No package manager detected or available');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Create executor
|
|
86
|
+
this.executor = new PackageManagerExecutor(detection.manager, this.cwd);
|
|
87
|
+
this.currentManager = detection.manager;
|
|
88
|
+
this.detectionSource = detection.source;
|
|
89
|
+
|
|
90
|
+
// Validate lockfile if present
|
|
91
|
+
const lockfileValidation = this.validator.validate(detection.manager);
|
|
92
|
+
if (!lockfileValidation.valid) {
|
|
93
|
+
this.logger.warn('Lockfile validation failed', {
|
|
94
|
+
manager: detection.manager,
|
|
95
|
+
reason: lockfileValidation.reason,
|
|
96
|
+
message: lockfileValidation.message
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
this.logger.debug('Lockfile validated', {
|
|
100
|
+
manager: detection.manager,
|
|
101
|
+
lockfileVersion: lockfileValidation.lockfileVersion,
|
|
102
|
+
packageCount: lockfileValidation.packageCount || lockfileValidation.entryCount
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.initialized = true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Ensure service is initialized
|
|
111
|
+
* @private
|
|
112
|
+
* @returns {Promise<void>}
|
|
113
|
+
*/
|
|
114
|
+
async _ensureInitialized() {
|
|
115
|
+
if (!this.initialized) {
|
|
116
|
+
await this.initialize();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Install dependencies
|
|
122
|
+
* @param {Object} options - Install options
|
|
123
|
+
* @param {boolean} [options.production] - Production install (exclude devDependencies)
|
|
124
|
+
* @param {boolean} [options.frozenLockfile] - Use frozen lockfile (CI/CD safe)
|
|
125
|
+
* @param {boolean} [options.preferOffline] - Prefer offline cache
|
|
126
|
+
* @returns {Promise<string>} Command output
|
|
127
|
+
*/
|
|
128
|
+
async install(options = {}) {
|
|
129
|
+
await this._ensureInitialized();
|
|
130
|
+
|
|
131
|
+
this.logger.info('Installing dependencies', {
|
|
132
|
+
manager: this.currentManager,
|
|
133
|
+
options
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return await this.executor.install(options);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Add package(s) to project
|
|
141
|
+
* @param {string|string[]} packages - Package name(s) to add
|
|
142
|
+
* @param {Object} options - Add options
|
|
143
|
+
* @param {boolean} [options.dev] - Add as devDependency
|
|
144
|
+
* @param {boolean} [options.peer] - Add as peerDependency
|
|
145
|
+
* @param {boolean} [options.optional] - Add as optionalDependency
|
|
146
|
+
* @param {boolean} [options.global] - Install globally
|
|
147
|
+
* @returns {Promise<string>} Command output
|
|
148
|
+
*/
|
|
149
|
+
async add(packages, options = {}) {
|
|
150
|
+
await this._ensureInitialized();
|
|
151
|
+
|
|
152
|
+
const packageArray = Array.isArray(packages) ? packages : [packages];
|
|
153
|
+
|
|
154
|
+
this.logger.info('Adding packages', {
|
|
155
|
+
manager: this.currentManager,
|
|
156
|
+
packages: packageArray,
|
|
157
|
+
options
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return await this.executor.add(packageArray, options);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Remove package(s) from project
|
|
165
|
+
* @param {string|string[]} packages - Package name(s) to remove
|
|
166
|
+
* @param {Object} options - Remove options
|
|
167
|
+
* @param {boolean} [options.global] - Remove from global install
|
|
168
|
+
* @returns {Promise<string>} Command output
|
|
169
|
+
*/
|
|
170
|
+
async remove(packages, options = {}) {
|
|
171
|
+
await this._ensureInitialized();
|
|
172
|
+
|
|
173
|
+
const packageArray = Array.isArray(packages) ? packages : [packages];
|
|
174
|
+
|
|
175
|
+
this.logger.info('Removing packages', {
|
|
176
|
+
manager: this.currentManager,
|
|
177
|
+
packages: packageArray,
|
|
178
|
+
options
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
return await this.executor.remove(packageArray, options);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get current package manager information
|
|
186
|
+
* @returns {Object} Package manager info
|
|
187
|
+
*/
|
|
188
|
+
getInfo() {
|
|
189
|
+
return {
|
|
190
|
+
manager: this.currentManager,
|
|
191
|
+
source: this.detectionSource,
|
|
192
|
+
cwd: this.cwd,
|
|
193
|
+
lockfile: this.detector.getLockfilePath(this.currentManager)
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Load configuration from .planning/config.json
|
|
199
|
+
* @private
|
|
200
|
+
* @returns {Object} Configuration object
|
|
201
|
+
*/
|
|
202
|
+
_loadConfig() {
|
|
203
|
+
const configPath = path.join(this.cwd, '.planning', 'config.json');
|
|
204
|
+
try {
|
|
205
|
+
if (fs.existsSync(configPath)) {
|
|
206
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
207
|
+
return JSON.parse(content);
|
|
208
|
+
}
|
|
209
|
+
} catch (err) {
|
|
210
|
+
this.logger.warn('Failed to load config', { path: configPath, error: err.message });
|
|
211
|
+
}
|
|
212
|
+
return {};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = PackageManagerService;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Monitor — Endpoint latency tracking with baseline storage
|
|
3
|
+
* Tracks p50, p95, p99 percentiles
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class ApiMonitor {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
this.latenciesPath = path.join(this.cwd, '.planning', 'perf', 'api-latencies.json');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Track endpoint latency
|
|
17
|
+
* @param {string} baseUrl - Base URL of API
|
|
18
|
+
* @param {Array} endpoints - Array of endpoint paths to track
|
|
19
|
+
* @returns {Array} Latency results
|
|
20
|
+
*/
|
|
21
|
+
async trackEndpoint(baseUrl, endpoints) {
|
|
22
|
+
const results = [];
|
|
23
|
+
|
|
24
|
+
for (const endpoint of endpoints) {
|
|
25
|
+
const start = Date.now();
|
|
26
|
+
try {
|
|
27
|
+
// Placeholder - would make actual HTTP request in real implementation
|
|
28
|
+
const latency = Date.now() - start;
|
|
29
|
+
results.push({
|
|
30
|
+
endpoint: endpoint.path || endpoint,
|
|
31
|
+
method: endpoint.method || 'GET',
|
|
32
|
+
latency,
|
|
33
|
+
status: 200,
|
|
34
|
+
timestamp: new Date().toISOString()
|
|
35
|
+
});
|
|
36
|
+
} catch (e) {
|
|
37
|
+
results.push({
|
|
38
|
+
endpoint: endpoint.path || endpoint,
|
|
39
|
+
method: endpoint.method || 'GET',
|
|
40
|
+
latency: -1,
|
|
41
|
+
error: e.message,
|
|
42
|
+
timestamp: new Date().toISOString()
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Calculate percentiles from latency array
|
|
52
|
+
* @param {Array} latencies - Array of latency values
|
|
53
|
+
* @returns {Object} Percentile values
|
|
54
|
+
*/
|
|
55
|
+
calculatePercentiles(latencies) {
|
|
56
|
+
const sorted = latencies.filter(l => l > 0).sort((a, b) => a - b);
|
|
57
|
+
if (sorted.length === 0) return { p50: 0, p95: 0, p99: 0 };
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
p50: sorted[Math.floor(sorted.length * 0.50)],
|
|
61
|
+
p95: sorted[Math.floor(sorted.length * 0.95)],
|
|
62
|
+
p99: sorted[Math.floor(sorted.length * 0.99)]
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Track endpoint latency
|
|
69
|
+
* @param {string} baseUrl - Base URL of API
|
|
70
|
+
* @param {Array} endpoints - Array of endpoint paths to track
|
|
71
|
+
* @returns {Array} Latency results
|
|
72
|
+
*/
|
|
73
|
+
async function trackEndpoint(baseUrl, endpoints) {
|
|
74
|
+
const monitor = new ApiMonitor();
|
|
75
|
+
return monitor.trackEndpoint(baseUrl, endpoints);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Calculate percentiles from latency array
|
|
80
|
+
* @param {Array} latencies - Array of latency values
|
|
81
|
+
* @returns {Object} Percentile values
|
|
82
|
+
*/
|
|
83
|
+
function calculatePercentiles(latencies) {
|
|
84
|
+
const monitor = new ApiMonitor();
|
|
85
|
+
return monitor.calculatePercentiles(latencies);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { ApiMonitor, trackEndpoint, calculatePercentiles };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DB Optimizer — Query analysis and index recommendations
|
|
3
|
+
* Analyzes slow queries, suggests indexes, detects N+1 patterns
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
class DbOptimizer {
|
|
9
|
+
constructor(dbUrl) {
|
|
10
|
+
this.dbUrl = dbUrl;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Analyze queries and provide optimization recommendations
|
|
15
|
+
* @param {string} dbUrl - Database connection URL
|
|
16
|
+
* @param {Array} queries - Array of queries to analyze
|
|
17
|
+
* @returns {Array} Analysis results with suggestions
|
|
18
|
+
*/
|
|
19
|
+
async analyzeQueries(dbUrl, queries) {
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
for (const query of queries) {
|
|
23
|
+
const explain = await this.explainQuery(dbUrl, query);
|
|
24
|
+
const suggestions = [];
|
|
25
|
+
|
|
26
|
+
// Detect sequential scans
|
|
27
|
+
if (explain.scanType === 'Seq Scan' || explain.scanType === 'Sequential Scan') {
|
|
28
|
+
suggestions.push({
|
|
29
|
+
type: 'index',
|
|
30
|
+
reason: 'Sequential scan detected',
|
|
31
|
+
recommendation: `CREATE INDEX ON ${explain.table} (${explain.filterColumn || 'column'})`
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Detect N+1 patterns
|
|
36
|
+
if (explain.nestedLoops > 5) {
|
|
37
|
+
suggestions.push({
|
|
38
|
+
type: 'n-plus-one',
|
|
39
|
+
reason: 'N+1 query pattern detected',
|
|
40
|
+
recommendation: 'Use JOIN or batch loading'
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
results.push({ query, explain, suggestions });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get EXPLAIN plan for a query
|
|
52
|
+
* @param {string} dbUrl - Database connection URL
|
|
53
|
+
* @param {string} query - Query to explain
|
|
54
|
+
* @returns {Object} Explain plan
|
|
55
|
+
*/
|
|
56
|
+
async explainQuery(dbUrl, query) {
|
|
57
|
+
// Placeholder - would execute EXPLAIN QUERY in real implementation
|
|
58
|
+
return {
|
|
59
|
+
scanType: 'Unknown',
|
|
60
|
+
table: 'unknown',
|
|
61
|
+
filterColumn: null,
|
|
62
|
+
nestedLoops: 0
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Analyze queries and provide optimization recommendations
|
|
69
|
+
* @param {string} dbUrl - Database connection URL
|
|
70
|
+
* @param {Array} queries - Array of queries to analyze
|
|
71
|
+
* @returns {Array} Analysis results with suggestions
|
|
72
|
+
*/
|
|
73
|
+
async function analyzeQueries(dbUrl, queries) {
|
|
74
|
+
const optimizer = new DbOptimizer(dbUrl);
|
|
75
|
+
return optimizer.analyzeQueries(dbUrl, queries);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = { DbOptimizer, analyzeQueries };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontend Performance — Lighthouse integration for bundle/render analysis
|
|
3
|
+
* Measures Core Web Vitals: FCP, LCP, CLS, TTI
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class FrontendPerformance {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.lighthouse = null;
|
|
9
|
+
this.chromeLauncher = null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Run Lighthouse analysis on a URL
|
|
14
|
+
* @param {string} url - URL to analyze
|
|
15
|
+
* @returns {Object} Lighthouse results
|
|
16
|
+
*/
|
|
17
|
+
async runLighthouse(url) {
|
|
18
|
+
// Placeholder - would run actual Lighthouse in real implementation
|
|
19
|
+
// Requires: npm install lighthouse chrome-launcher
|
|
20
|
+
return {
|
|
21
|
+
performance: 0,
|
|
22
|
+
metrics: {
|
|
23
|
+
fcp: 0,
|
|
24
|
+
lcp: 0,
|
|
25
|
+
cls: 0,
|
|
26
|
+
tti: 0
|
|
27
|
+
},
|
|
28
|
+
opportunities: []
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Analyze bundle size
|
|
34
|
+
* @param {string} buildPath - Path to build directory
|
|
35
|
+
* @returns {Object} Bundle analysis
|
|
36
|
+
*/
|
|
37
|
+
async analyzeBundle(buildPath) {
|
|
38
|
+
// Placeholder - would use webpack-bundle-analyzer in real implementation
|
|
39
|
+
return {
|
|
40
|
+
totalSize: 0,
|
|
41
|
+
chunks: []
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Run Lighthouse analysis on a URL
|
|
48
|
+
* @param {string} url - URL to analyze
|
|
49
|
+
* @returns {Object} Lighthouse results
|
|
50
|
+
*/
|
|
51
|
+
async function runLighthouse(url) {
|
|
52
|
+
const perf = new FrontendPerformance();
|
|
53
|
+
return perf.runLighthouse(url);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = { FrontendPerformance, runLighthouse };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perf Analyzer — Core performance analysis coordinator
|
|
3
|
+
* Orchestrates all analyzers and aggregates results
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class PerfAnalyzer {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Run all performance analyzers and aggregate results
|
|
16
|
+
* @param {Object} options - Analysis options
|
|
17
|
+
* @returns {Object} Aggregated performance results
|
|
18
|
+
*/
|
|
19
|
+
async analyze(options = {}) {
|
|
20
|
+
const results = {
|
|
21
|
+
timestamp: new Date().toISOString(),
|
|
22
|
+
db: null,
|
|
23
|
+
frontend: null,
|
|
24
|
+
api: null,
|
|
25
|
+
errors: []
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// Run DB analysis if DB URL provided
|
|
30
|
+
if (options.dbUrl) {
|
|
31
|
+
const { analyzeQueries } = require('./db-optimizer.cjs');
|
|
32
|
+
results.db = await analyzeQueries(options.dbUrl, options.queries || []);
|
|
33
|
+
}
|
|
34
|
+
} catch (e) {
|
|
35
|
+
results.errors.push(`DB analysis failed: ${e.message}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
// Run frontend analysis if URL provided
|
|
40
|
+
if (options.url) {
|
|
41
|
+
const { runLighthouse } = require('./frontend-performance.cjs');
|
|
42
|
+
results.frontend = await runLighthouse(options.url);
|
|
43
|
+
}
|
|
44
|
+
} catch (e) {
|
|
45
|
+
results.errors.push(`Frontend analysis failed: ${e.message}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// Run API analysis if API URL provided
|
|
50
|
+
if (options.apiUrl) {
|
|
51
|
+
const { trackEndpoint } = require('./api-monitor.cjs');
|
|
52
|
+
results.api = await trackEndpoint(options.apiUrl, options.endpoints || []);
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
results.errors.push(`API analysis failed: ${e.message}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return results;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Aggregate results from multiple analyzers
|
|
63
|
+
* @param {Array} results - Array of analysis results
|
|
64
|
+
* @returns {Object} Aggregated results
|
|
65
|
+
*/
|
|
66
|
+
aggregate(results) {
|
|
67
|
+
return results.reduce((acc, r) => {
|
|
68
|
+
if (r.db) acc.db.push(r.db);
|
|
69
|
+
if (r.frontend) acc.frontend.push(r.frontend);
|
|
70
|
+
if (r.api) acc.api.push(r.api);
|
|
71
|
+
acc.errors.push(...(r.errors || []));
|
|
72
|
+
return acc;
|
|
73
|
+
}, { db: [], frontend: [], api: [], errors: [] });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = { PerfAnalyzer, analyze: PerfAnalyzer.prototype.analyze };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perf Baseline — Save and load performance baselines
|
|
3
|
+
* Stores baselines in .planning/perf-baselines/
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class PerfBaseline {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
this.baselinesDir = path.join(this.cwd, '.planning', 'perf-baselines');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Save baseline metrics
|
|
17
|
+
* @param {Object} metrics - Metrics to save
|
|
18
|
+
* @param {string} name - Baseline name
|
|
19
|
+
* @returns {string} Path to saved baseline
|
|
20
|
+
*/
|
|
21
|
+
saveBaseline(metrics, name = 'default') {
|
|
22
|
+
// Ensure directory exists
|
|
23
|
+
if (!fs.existsSync(this.baselinesDir)) {
|
|
24
|
+
fs.mkdirSync(this.baselinesDir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const baselinePath = path.join(this.baselinesDir, `${name}.json`);
|
|
28
|
+
const baseline = {
|
|
29
|
+
...metrics,
|
|
30
|
+
metadata: {
|
|
31
|
+
name,
|
|
32
|
+
createdAt: new Date().toISOString(),
|
|
33
|
+
updatedAt: new Date().toISOString()
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
fs.writeFileSync(baselinePath, JSON.stringify(baseline, null, 2), 'utf8');
|
|
38
|
+
return baselinePath;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Load baseline metrics
|
|
43
|
+
* @param {string} name - Baseline name
|
|
44
|
+
* @returns {Object|null} Baseline metrics or null
|
|
45
|
+
*/
|
|
46
|
+
loadBaseline(name = 'default') {
|
|
47
|
+
const baselinePath = path.join(this.baselinesDir, `${name}.json`);
|
|
48
|
+
|
|
49
|
+
if (!fs.existsSync(baselinePath)) return null;
|
|
50
|
+
|
|
51
|
+
return JSON.parse(fs.readFileSync(baselinePath, 'utf8'));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* List all available baselines
|
|
56
|
+
* @returns {Array} Array of baseline names
|
|
57
|
+
*/
|
|
58
|
+
listBaselines() {
|
|
59
|
+
if (!fs.existsSync(this.baselinesDir)) return [];
|
|
60
|
+
|
|
61
|
+
return fs.readdirSync(this.baselinesDir)
|
|
62
|
+
.filter(f => f.endsWith('.json'))
|
|
63
|
+
.map(f => f.replace('.json', ''));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Delete a baseline
|
|
68
|
+
* @param {string} name - Baseline name
|
|
69
|
+
* @returns {boolean} Success
|
|
70
|
+
*/
|
|
71
|
+
deleteBaseline(name) {
|
|
72
|
+
const baselinePath = path.join(this.baselinesDir, `${name}.json`);
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(baselinePath)) return false;
|
|
75
|
+
|
|
76
|
+
fs.unlinkSync(baselinePath);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Save baseline metrics
|
|
83
|
+
* @param {Object} metrics - Metrics to save
|
|
84
|
+
* @param {string} name - Baseline name
|
|
85
|
+
* @returns {string} Path to saved baseline
|
|
86
|
+
*/
|
|
87
|
+
function saveBaseline(metrics, name = 'default') {
|
|
88
|
+
const baseline = new PerfBaseline();
|
|
89
|
+
return baseline.saveBaseline(metrics, name);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Load baseline metrics
|
|
94
|
+
* @param {string} name - Baseline name
|
|
95
|
+
* @returns {Object|null} Baseline metrics or null
|
|
96
|
+
*/
|
|
97
|
+
function loadBaseline(name = 'default') {
|
|
98
|
+
const baseline = new PerfBaseline();
|
|
99
|
+
return baseline.loadBaseline(name);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = { PerfBaseline, saveBaseline, loadBaseline };
|