@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,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tech Debt Analyzer — Automated tech debt hotspot identification
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - detectDebtMarkers(rootPath): Finds TODO/FIXME/HACK/XXX/BUG/DEPRECATED comments with severity scores
|
|
6
|
+
* - analyzeDependencyRisk(rootPath): npm audit parsing for vulnerabilities
|
|
7
|
+
* - aggregateFindings(debtMarkers, complexityIssues, largeFiles, duplicates): Combines all findings with severity scores
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const { execSync } = require('child_process');
|
|
13
|
+
|
|
14
|
+
class TechDebtAnalyzer {
|
|
15
|
+
constructor(rootPath) {
|
|
16
|
+
this.rootPath = rootPath;
|
|
17
|
+
this.patterns = [
|
|
18
|
+
{ marker: 'TODO', severity: 'Low', weight: 1 },
|
|
19
|
+
{ marker: 'FIXME', severity: 'Medium', weight: 2 },
|
|
20
|
+
{ marker: 'HACK', severity: 'Medium', weight: 2 },
|
|
21
|
+
{ marker: 'XXX', severity: 'High', weight: 3 },
|
|
22
|
+
{ marker: 'BUG', severity: 'High', weight: 3 },
|
|
23
|
+
{ marker: 'DEPRECATED', severity: 'Critical', weight: 4 },
|
|
24
|
+
{ marker: 'OPTIMIZE', severity: 'Low', weight: 1 },
|
|
25
|
+
{ marker: 'REFACTOR', severity: 'Medium', weight: 2 }
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Detect debt markers in codebase
|
|
31
|
+
* @param {string} rootPath - Root directory to analyze
|
|
32
|
+
* @returns {Array} Array of debt marker objects with file, line, marker, severity, weight, content
|
|
33
|
+
*/
|
|
34
|
+
detectDebtMarkers(rootPath = this.rootPath) {
|
|
35
|
+
const results = [];
|
|
36
|
+
const srcDirs = ['src', 'app', 'lib', 'commands', 'bin', 'agents', 'hooks'];
|
|
37
|
+
|
|
38
|
+
// Try grep first (Unix-like systems), fallback to pure JS for Windows
|
|
39
|
+
for (const pattern of this.patterns) {
|
|
40
|
+
for (const srcDir of srcDirs) {
|
|
41
|
+
const searchPath = path.join(rootPath, srcDir);
|
|
42
|
+
if (!fs.existsSync(searchPath)) continue;
|
|
43
|
+
|
|
44
|
+
// Try grep on Unix-like systems
|
|
45
|
+
try {
|
|
46
|
+
const output = execSync(
|
|
47
|
+
`grep -rn "${pattern.marker}" "${searchPath}" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.cjs" --include="*.mjs" 2>nul`,
|
|
48
|
+
{ cwd: rootPath, encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const lines = output.trim().split('\n');
|
|
52
|
+
for (const line of lines) {
|
|
53
|
+
if (!line.trim()) continue;
|
|
54
|
+
|
|
55
|
+
const parts = line.split(':');
|
|
56
|
+
if (parts.length < 3) continue;
|
|
57
|
+
|
|
58
|
+
const filePath = parts[0];
|
|
59
|
+
const lineNum = parseInt(parts[1], 10);
|
|
60
|
+
const content = parts.slice(2).join(':').trim();
|
|
61
|
+
|
|
62
|
+
results.push({
|
|
63
|
+
file: filePath,
|
|
64
|
+
line: lineNum,
|
|
65
|
+
marker: pattern.marker,
|
|
66
|
+
severity: pattern.severity,
|
|
67
|
+
weight: pattern.weight,
|
|
68
|
+
content: content.substring(0, 200),
|
|
69
|
+
age: null
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
} catch (err) {
|
|
73
|
+
// grep not available or no matches, use fallback
|
|
74
|
+
if (err.code === 'ENOENT' || err.status === 1) {
|
|
75
|
+
// Use pure JavaScript fallback
|
|
76
|
+
const fallbackResults = this._detectDebtMarkersJS(searchPath, pattern);
|
|
77
|
+
results.push(...fallbackResults);
|
|
78
|
+
}
|
|
79
|
+
// Other errors are ignored (grep returns non-zero if no matches)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Sort by severity (Critical first)
|
|
85
|
+
results.sort((a, b) => b.weight - a.weight || a.file.localeCompare(b.file));
|
|
86
|
+
|
|
87
|
+
return results;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Pure JavaScript fallback for debt marker detection (Windows compatibility)
|
|
92
|
+
* @private
|
|
93
|
+
*/
|
|
94
|
+
_detectDebtMarkersJS(dir, pattern) {
|
|
95
|
+
const results = [];
|
|
96
|
+
const fileExtensions = ['.ts', '.tsx', '.js', '.cjs', '.mjs'];
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
100
|
+
for (const entry of entries) {
|
|
101
|
+
const fullPath = path.join(dir, entry.name);
|
|
102
|
+
|
|
103
|
+
if (entry.isDirectory()) {
|
|
104
|
+
// Recurse into subdirectory
|
|
105
|
+
results.push(...this._detectDebtMarkersJS(fullPath, pattern));
|
|
106
|
+
} else if (entry.isFile() && fileExtensions.includes(path.extname(entry.name))) {
|
|
107
|
+
try {
|
|
108
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
109
|
+
const lines = content.split('\n');
|
|
110
|
+
|
|
111
|
+
for (let i = 0; i < lines.length; i++) {
|
|
112
|
+
const line = lines[i];
|
|
113
|
+
if (line.includes(pattern.marker)) {
|
|
114
|
+
results.push({
|
|
115
|
+
file: fullPath,
|
|
116
|
+
line: i + 1,
|
|
117
|
+
marker: pattern.marker,
|
|
118
|
+
severity: pattern.severity,
|
|
119
|
+
weight: pattern.weight,
|
|
120
|
+
content: line.trim().substring(0, 200),
|
|
121
|
+
age: null
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch (err) {
|
|
126
|
+
// Ignore read errors
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} catch (err) {
|
|
131
|
+
// Ignore directory read errors
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Analyze dependency risk from npm audit
|
|
139
|
+
* @param {string} rootPath - Root directory to analyze
|
|
140
|
+
* @returns {Array} Array of vulnerability objects with type, package, severity, message, score
|
|
141
|
+
*/
|
|
142
|
+
analyzeDependencyRisk(rootPath = this.rootPath) {
|
|
143
|
+
const risks = [];
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const auditOutput = execSync('npm audit --json', {
|
|
147
|
+
cwd: rootPath,
|
|
148
|
+
encoding: 'utf8',
|
|
149
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const audit = JSON.parse(auditOutput);
|
|
153
|
+
const vulnerabilities = audit.vulnerabilities || {};
|
|
154
|
+
|
|
155
|
+
for (const [pkgName, vuln] of Object.entries(vulnerabilities)) {
|
|
156
|
+
const severity = vuln.severity || 'medium';
|
|
157
|
+
const score = severity === 'critical' ? 4 : severity === 'high' ? 3 : severity === 'medium' ? 2 : 1;
|
|
158
|
+
|
|
159
|
+
risks.push({
|
|
160
|
+
type: 'security',
|
|
161
|
+
package: pkgName,
|
|
162
|
+
severity: severity.charAt(0).toUpperCase() + severity.slice(1),
|
|
163
|
+
message: `${pkgName}@${vuln.vulnerable_versions || 'unknown'} has ${severity} vulnerability`,
|
|
164
|
+
score,
|
|
165
|
+
via: vuln.via || [],
|
|
166
|
+
recommendation: vuln.recommendation || 'Update to latest version'
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
} catch (err) {
|
|
170
|
+
// npm audit may fail or return no vulnerabilities
|
|
171
|
+
if (err.status !== 1) {
|
|
172
|
+
console.warn(`Warning: npm audit failed: ${err.message}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Sort by severity
|
|
177
|
+
risks.sort((a, b) => b.score - a.score);
|
|
178
|
+
|
|
179
|
+
return risks;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Aggregate all findings into a single report
|
|
184
|
+
* @param {Array} debtMarkers - Debt markers from detectDebtMarkers
|
|
185
|
+
* @param {Array} complexityIssues - Complexity issues from CodeComplexityAnalyzer
|
|
186
|
+
* @param {Array} largeFiles - Large files from CodeComplexityAnalyzer
|
|
187
|
+
* @param {Array} duplicates - Duplicate code from CodeComplexityAnalyzer
|
|
188
|
+
* @param {Array} dependencyRisks - Dependency risks from analyzeDependencyRisk
|
|
189
|
+
* @returns {Array} Aggregated findings sorted by score
|
|
190
|
+
*/
|
|
191
|
+
aggregateFindings(debtMarkers = [], complexityIssues = [], largeFiles = [], duplicates = [], dependencyRisks = []) {
|
|
192
|
+
const allFindings = [];
|
|
193
|
+
|
|
194
|
+
// Add debt markers
|
|
195
|
+
for (const marker of debtMarkers) {
|
|
196
|
+
allFindings.push({
|
|
197
|
+
...marker,
|
|
198
|
+
type: 'debt_marker',
|
|
199
|
+
score: marker.weight,
|
|
200
|
+
description: `${marker.marker}: ${marker.content}`
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Add complexity issues
|
|
205
|
+
for (const issue of complexityIssues) {
|
|
206
|
+
allFindings.push({
|
|
207
|
+
...issue,
|
|
208
|
+
type: 'complexity',
|
|
209
|
+
description: issue.message
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Add large files
|
|
214
|
+
for (const file of largeFiles) {
|
|
215
|
+
allFindings.push({
|
|
216
|
+
...file,
|
|
217
|
+
type: 'large_file',
|
|
218
|
+
description: `Large file: ${file.lines} lines, ${file.sizeKB}KB`
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Add duplicates
|
|
223
|
+
for (const dup of duplicates) {
|
|
224
|
+
allFindings.push({
|
|
225
|
+
...dup,
|
|
226
|
+
type: 'duplicate',
|
|
227
|
+
description: `Duplicate code in ${dup.fileCount} files`
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Add dependency risks
|
|
232
|
+
for (const risk of dependencyRisks) {
|
|
233
|
+
allFindings.push({
|
|
234
|
+
...risk,
|
|
235
|
+
type: 'dependency',
|
|
236
|
+
description: risk.message
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Sort by score descending
|
|
241
|
+
allFindings.sort((a, b) => b.score - a.score || a.file?.localeCompare(b.file) || 0);
|
|
242
|
+
|
|
243
|
+
return allFindings;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Get summary of tech debt
|
|
248
|
+
* @param {Array} findings - Aggregated findings
|
|
249
|
+
* @returns {object} Summary object
|
|
250
|
+
*/
|
|
251
|
+
getSummary(findings = []) {
|
|
252
|
+
const summary = {
|
|
253
|
+
total: findings.length,
|
|
254
|
+
byType: {},
|
|
255
|
+
bySeverity: {
|
|
256
|
+
Critical: 0,
|
|
257
|
+
High: 0,
|
|
258
|
+
Medium: 0,
|
|
259
|
+
Low: 0
|
|
260
|
+
},
|
|
261
|
+
topIssues: []
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
for (const finding of findings) {
|
|
265
|
+
// Count by type
|
|
266
|
+
summary.byType[finding.type] = (summary.byType[finding.type] || 0) + 1;
|
|
267
|
+
|
|
268
|
+
// Count by severity
|
|
269
|
+
const severity = finding.severity || 'Medium';
|
|
270
|
+
if (summary.bySeverity[severity] !== undefined) {
|
|
271
|
+
summary.bySeverity[severity]++;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Get top 10 issues
|
|
276
|
+
summary.topIssues = findings.slice(0, 10);
|
|
277
|
+
|
|
278
|
+
return summary;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Get tech debt by file
|
|
283
|
+
* @param {Array} findings - Aggregated findings
|
|
284
|
+
* @returns {object} Object mapping file paths to their issues
|
|
285
|
+
*/
|
|
286
|
+
getByFile(findings = []) {
|
|
287
|
+
const byFile = {};
|
|
288
|
+
|
|
289
|
+
for (const finding of findings) {
|
|
290
|
+
if (!finding.file) continue;
|
|
291
|
+
|
|
292
|
+
if (!byFile[finding.file]) {
|
|
293
|
+
byFile[finding.file] = {
|
|
294
|
+
file: finding.file,
|
|
295
|
+
issues: [],
|
|
296
|
+
totalScore: 0
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
byFile[finding.file].issues.push(finding);
|
|
301
|
+
byFile[finding.file].totalScore += finding.score || 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Sort by total score
|
|
305
|
+
return Object.values(byFile).sort((a, b) => b.totalScore - a.totalScore);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
module.exports = { TechDebtAnalyzer };
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EZ Temp File — Secure temporary file handler
|
|
5
|
+
*
|
|
6
|
+
* Creates secure temp files with fs.mkdtemp(), automatic cleanup on exit,
|
|
7
|
+
* and path validation to prevent traversal attacks.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const { createTempFile, cleanupAll } = require('./temp-file.cjs');
|
|
11
|
+
* const tempFile = await createTempFile('prefix-');
|
|
12
|
+
* // ... use temp file ...
|
|
13
|
+
* // Automatically cleaned up on process exit
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const os = require('os');
|
|
19
|
+
const crypto = require('crypto');
|
|
20
|
+
const Logger = require('./logger.cjs');
|
|
21
|
+
const logger = new Logger();
|
|
22
|
+
|
|
23
|
+
// Track all created temp resources for cleanup
|
|
24
|
+
const tempResources = new Set();
|
|
25
|
+
let cleanupRegistered = false;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Generate a secure random suffix for temp names
|
|
29
|
+
* @returns {string} - Random hex string
|
|
30
|
+
*/
|
|
31
|
+
function generateSecureSuffix() {
|
|
32
|
+
return crypto.randomBytes(8).toString('hex');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Validate that a path is safe (no traversal attacks)
|
|
37
|
+
* @param {string} basePath - Base directory
|
|
38
|
+
* @param {string} targetPath - Target path to validate
|
|
39
|
+
* @returns {boolean} - True if safe
|
|
40
|
+
*/
|
|
41
|
+
function isPathSafe(basePath, targetPath) {
|
|
42
|
+
const resolvedBase = path.resolve(basePath);
|
|
43
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
44
|
+
|
|
45
|
+
// Ensure target starts with base (is inside base)
|
|
46
|
+
const normalizedBase = resolvedBase + path.sep;
|
|
47
|
+
return resolvedTarget === resolvedBase ||
|
|
48
|
+
resolvedTarget.startsWith(normalizedBase);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a secure temporary directory
|
|
53
|
+
* @param {string} prefix - Prefix for temp directory name
|
|
54
|
+
* @param {string} customBase - Custom base directory (default: os.tmpdir())
|
|
55
|
+
* @returns {Promise<string>} - Path to created temp directory
|
|
56
|
+
*/
|
|
57
|
+
async function createTempDir(prefix = 'ez-', customBase = null) {
|
|
58
|
+
const baseDir = customBase || os.tmpdir();
|
|
59
|
+
const tempPath = await fs.promises.mkdtemp(path.join(baseDir, prefix));
|
|
60
|
+
|
|
61
|
+
logger.debug(`Created temp directory: ${tempPath}`);
|
|
62
|
+
tempResources.add({ type: 'dir', path: tempPath });
|
|
63
|
+
|
|
64
|
+
registerCleanup();
|
|
65
|
+
|
|
66
|
+
return tempPath;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Create a secure temporary file
|
|
71
|
+
* @param {string} prefix - Prefix for temp file name
|
|
72
|
+
* @param {string} customBase - Custom base directory (default: os.tmpdir())
|
|
73
|
+
* @param {string} content - Optional initial content
|
|
74
|
+
* @returns {Promise<string>} - Path to created temp file
|
|
75
|
+
*/
|
|
76
|
+
async function createTempFile(prefix = 'ez-', customBase = null, content = '') {
|
|
77
|
+
const baseDir = customBase || os.tmpdir();
|
|
78
|
+
const fileName = `${prefix}${generateSecureSuffix()}`;
|
|
79
|
+
const tempPath = path.join(baseDir, fileName);
|
|
80
|
+
|
|
81
|
+
await fs.promises.writeFile(tempPath, content, 'utf-8');
|
|
82
|
+
|
|
83
|
+
logger.debug(`Created temp file: ${tempPath}`);
|
|
84
|
+
tempResources.add({ type: 'file', path: tempPath });
|
|
85
|
+
|
|
86
|
+
registerCleanup();
|
|
87
|
+
|
|
88
|
+
return tempPath;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Write content to a temp file safely
|
|
93
|
+
* @param {string} tempPath - Path to temp file
|
|
94
|
+
* @param {string} content - Content to write
|
|
95
|
+
* @param {Object} options - Write options
|
|
96
|
+
*/
|
|
97
|
+
async function writeToTemp(tempPath, content, options = {}) {
|
|
98
|
+
const { validateBase = os.tmpdir() } = options;
|
|
99
|
+
|
|
100
|
+
if (!isPathSafe(validateBase, tempPath)) {
|
|
101
|
+
throw new Error(`Path traversal detected: ${tempPath}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await fs.promises.writeFile(tempPath, content, 'utf-8');
|
|
105
|
+
logger.debug(`Written to temp file: ${tempPath}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Read content from a temp file safely
|
|
110
|
+
* @param {string} tempPath - Path to temp file
|
|
111
|
+
* @param {Object} options - Read options
|
|
112
|
+
* @returns {Promise<string>} - File content
|
|
113
|
+
*/
|
|
114
|
+
async function readFromTemp(tempPath, options = {}) {
|
|
115
|
+
const { validateBase = os.tmpdir() } = options;
|
|
116
|
+
|
|
117
|
+
if (!isPathSafe(validateBase, tempPath)) {
|
|
118
|
+
throw new Error(`Path traversal detected: ${tempPath}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const content = await fs.promises.readFile(tempPath, 'utf-8');
|
|
122
|
+
logger.debug(`Read from temp file: ${tempPath}`);
|
|
123
|
+
|
|
124
|
+
return content;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Clean up a specific temp resource
|
|
129
|
+
* @param {string} tempPath - Path to temp file or directory
|
|
130
|
+
*/
|
|
131
|
+
async function cleanupTemp(tempPath) {
|
|
132
|
+
const resolvedPath = path.resolve(tempPath);
|
|
133
|
+
|
|
134
|
+
for (const resource of tempResources) {
|
|
135
|
+
if (path.resolve(resource.path) === resolvedPath) {
|
|
136
|
+
try {
|
|
137
|
+
if (resource.type === 'dir') {
|
|
138
|
+
await fs.promises.rm(resolvedPath, { recursive: true, force: true });
|
|
139
|
+
logger.debug(`Cleaned up temp directory: ${resolvedPath}`);
|
|
140
|
+
} else {
|
|
141
|
+
await fs.promises.unlink(resolvedPath);
|
|
142
|
+
logger.debug(`Cleaned up temp file: ${resolvedPath}`);
|
|
143
|
+
}
|
|
144
|
+
tempResources.delete(resource);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
logger.warn(`Failed to cleanup temp: ${resolvedPath}`, {
|
|
147
|
+
error: err.message
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Clean up all tracked temp resources
|
|
157
|
+
*/
|
|
158
|
+
async function cleanupAll() {
|
|
159
|
+
logger.info(`Cleaning up ${tempResources.size} temp resources...`);
|
|
160
|
+
|
|
161
|
+
const cleanupPromises = [];
|
|
162
|
+
for (const resource of tempResources) {
|
|
163
|
+
cleanupPromises.push(
|
|
164
|
+
cleanupTemp(resource.path).catch(err => {
|
|
165
|
+
logger.warn(`Cleanup failed for ${resource.path}: ${err.message}`);
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
await Promise.all(cleanupPromises);
|
|
171
|
+
logger.info('Temp cleanup complete');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Register cleanup handlers (called automatically)
|
|
176
|
+
*/
|
|
177
|
+
function registerCleanup() {
|
|
178
|
+
if (cleanupRegistered) return;
|
|
179
|
+
cleanupRegistered = true;
|
|
180
|
+
|
|
181
|
+
const cleanupHandler = async () => {
|
|
182
|
+
if (tempResources.size > 0) {
|
|
183
|
+
await cleanupAll();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// Register for various exit scenarios
|
|
188
|
+
process.on('exit', () => {
|
|
189
|
+
// Synchronous cleanup for exit event
|
|
190
|
+
if (tempResources.size > 0) {
|
|
191
|
+
logger.debug('Synchronous temp cleanup on exit');
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
process.on('SIGINT', async () => {
|
|
196
|
+
await cleanupHandler();
|
|
197
|
+
process.exit(130);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
process.on('SIGTERM', async () => {
|
|
201
|
+
await cleanupHandler();
|
|
202
|
+
process.exit(143);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
process.on('beforeExit', async () => {
|
|
206
|
+
await cleanupHandler();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Handle uncaught errors
|
|
210
|
+
process.on('uncaughtException', async (err) => {
|
|
211
|
+
logger.error('Uncaught exception, cleaning up temps...', {
|
|
212
|
+
error: err.message
|
|
213
|
+
});
|
|
214
|
+
await cleanupHandler();
|
|
215
|
+
process.exit(1);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
logger.debug('Temp cleanup handlers registered');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get list of tracked temp resources
|
|
223
|
+
* @returns {Array} - Array of {type, path} objects
|
|
224
|
+
*/
|
|
225
|
+
function getTrackedTemps() {
|
|
226
|
+
return Array.from(tempResources);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
module.exports = {
|
|
230
|
+
createTempDir,
|
|
231
|
+
createTempFile,
|
|
232
|
+
writeToTemp,
|
|
233
|
+
readFromTemp,
|
|
234
|
+
cleanupTemp,
|
|
235
|
+
cleanupAll,
|
|
236
|
+
getTrackedTemps,
|
|
237
|
+
isPathSafe,
|
|
238
|
+
generateSecureSuffix
|
|
239
|
+
};
|