prjct-cli 1.22.0 → 1.23.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/CHANGELOG.md +147 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct.mjs +917 -35845
- package/dist/bin/prjct.mjs.map +7 -0
- package/dist/cli/linear.mjs +16 -0
- package/dist/cli/linear.mjs.map +7 -0
- package/dist/templates.json +1 -0
- package/package.json +4 -5
- package/bin/prjct.ts +0 -342
- package/core/__tests__/agentic/analysis-injection.test.ts +0 -377
- package/core/__tests__/agentic/cache-eviction.test.ts +0 -294
- package/core/__tests__/agentic/command-context.test.ts +0 -281
- package/core/__tests__/agentic/command-executor.test.ts +0 -659
- package/core/__tests__/agentic/domain-classifier.test.ts +0 -330
- package/core/__tests__/agentic/injection-validator.test.ts +0 -255
- package/core/__tests__/agentic/memory-system.test.ts +0 -281
- package/core/__tests__/agentic/plan-mode.test.ts +0 -386
- package/core/__tests__/agentic/prompt-assembly.test.ts +0 -298
- package/core/__tests__/agentic/prompt-builder.test.ts +0 -243
- package/core/__tests__/agentic/response-validator.test.ts +0 -263
- package/core/__tests__/agentic/semantic-matching.test.ts +0 -131
- package/core/__tests__/agentic/smart-context.test.ts +0 -372
- package/core/__tests__/agentic/tech-normalizer.test.ts +0 -136
- package/core/__tests__/agentic/token-budget.test.ts +0 -294
- package/core/__tests__/ai-tools/formatters.test.ts +0 -476
- package/core/__tests__/domain/bm25.test.ts +0 -225
- package/core/__tests__/domain/change-propagator.test.ts +0 -100
- package/core/__tests__/domain/fibonacci.test.ts +0 -113
- package/core/__tests__/domain/file-hasher.test.ts +0 -146
- package/core/__tests__/domain/file-ranker.test.ts +0 -169
- package/core/__tests__/domain/git-cochange.test.ts +0 -121
- package/core/__tests__/domain/import-graph.test.ts +0 -156
- package/core/__tests__/domain/velocity.test.ts +0 -623
- package/core/__tests__/infrastructure/performance-tracker.test.ts +0 -328
- package/core/__tests__/schemas/model.test.ts +0 -272
- package/core/__tests__/services/dependency-validator.test.ts +0 -175
- package/core/__tests__/services/hierarchical-agent-resolver.test.ts +0 -359
- package/core/__tests__/services/nested-context-resolver.test.ts +0 -443
- package/core/__tests__/services/project-index.test.ts +0 -355
- package/core/__tests__/services/staleness-checker.test.ts +0 -204
- package/core/__tests__/storage/analysis-storage.test.ts +0 -641
- package/core/__tests__/storage/archive-storage.test.ts +0 -455
- package/core/__tests__/storage/safe-reader.test.ts +0 -262
- package/core/__tests__/storage/sqlite-migration.test.ts +0 -1016
- package/core/__tests__/storage/state-storage-feedback.test.ts +0 -463
- package/core/__tests__/storage/state-storage-history.test.ts +0 -469
- package/core/__tests__/storage/storage-manager.test.ts +0 -383
- package/core/__tests__/storage/subtask-handoff.test.ts +0 -237
- package/core/__tests__/types/fs.test.ts +0 -125
- package/core/__tests__/utils/date-helper.test.ts +0 -449
- package/core/__tests__/utils/output.test.ts +0 -278
- package/core/__tests__/utils/preserve-sections.test.ts +0 -216
- package/core/__tests__/utils/project-commands.test.ts +0 -71
- package/core/__tests__/utils/retry.test.ts +0 -381
- package/core/__tests__/workflow/state-machine.test.ts +0 -216
- package/core/agentic/agent-router.ts +0 -150
- package/core/agentic/anti-hallucination.ts +0 -141
- package/core/agentic/chain-of-thought.ts +0 -234
- package/core/agentic/command-classifier.ts +0 -141
- package/core/agentic/command-context.ts +0 -168
- package/core/agentic/command-executor.ts +0 -471
- package/core/agentic/context-builder.ts +0 -285
- package/core/agentic/domain-classifier.ts +0 -525
- package/core/agentic/environment-block.ts +0 -102
- package/core/agentic/ground-truth.ts +0 -706
- package/core/agentic/index.ts +0 -193
- package/core/agentic/injection-validator.ts +0 -208
- package/core/agentic/loop-detector.ts +0 -451
- package/core/agentic/memory-system.ts +0 -1547
- package/core/agentic/orchestrator-executor.ts +0 -579
- package/core/agentic/plan-mode.ts +0 -525
- package/core/agentic/prompt-builder.ts +0 -1069
- package/core/agentic/response-validator.ts +0 -98
- package/core/agentic/services.ts +0 -167
- package/core/agentic/skill-loader.ts +0 -106
- package/core/agentic/smart-context.ts +0 -393
- package/core/agentic/tech-normalizer.ts +0 -167
- package/core/agentic/template-executor.ts +0 -272
- package/core/agentic/template-loader.ts +0 -109
- package/core/agentic/token-budget.ts +0 -226
- package/core/agentic/tool-registry.ts +0 -146
- package/core/agents/index.ts +0 -28
- package/core/agents/performance.ts +0 -429
- package/core/ai-tools/formatters.ts +0 -341
- package/core/ai-tools/generator.ts +0 -144
- package/core/ai-tools/index.ts +0 -15
- package/core/ai-tools/registry.ts +0 -201
- package/core/bus/bus.ts +0 -314
- package/core/bus/index.ts +0 -8
- package/core/cli/linear.ts +0 -500
- package/core/cli/lint-meta-commentary.ts +0 -177
- package/core/cli/start.ts +0 -386
- package/core/commands/analysis.ts +0 -1274
- package/core/commands/analytics.ts +0 -342
- package/core/commands/base.ts +0 -118
- package/core/commands/cleanup.ts +0 -157
- package/core/commands/command-data.ts +0 -463
- package/core/commands/commands.ts +0 -306
- package/core/commands/context.ts +0 -238
- package/core/commands/design.ts +0 -77
- package/core/commands/index.ts +0 -19
- package/core/commands/maintenance.ts +0 -77
- package/core/commands/performance.ts +0 -114
- package/core/commands/planning.ts +0 -662
- package/core/commands/register.ts +0 -127
- package/core/commands/registry.ts +0 -444
- package/core/commands/setup.ts +0 -280
- package/core/commands/shipping.ts +0 -267
- package/core/commands/snapshots.ts +0 -297
- package/core/commands/uninstall.ts +0 -542
- package/core/commands/velocity.ts +0 -149
- package/core/commands/workflow.ts +0 -505
- package/core/config/command-context.config.json +0 -66
- package/core/constants/index.ts +0 -379
- package/core/context/generator.ts +0 -368
- package/core/context-tools/files-tool.ts +0 -577
- package/core/context-tools/imports-tool.ts +0 -400
- package/core/context-tools/index.ts +0 -434
- package/core/context-tools/recent-tool.ts +0 -301
- package/core/context-tools/signatures-tool.ts +0 -495
- package/core/context-tools/summary-tool.ts +0 -301
- package/core/context-tools/token-counter.ts +0 -273
- package/core/context-tools/types.ts +0 -253
- package/core/domain/agent-generator.ts +0 -186
- package/core/domain/agent-loader.ts +0 -419
- package/core/domain/analyzer.ts +0 -387
- package/core/domain/architecture-generator.ts +0 -108
- package/core/domain/bm25.ts +0 -525
- package/core/domain/change-propagator.ts +0 -162
- package/core/domain/context-estimator.ts +0 -175
- package/core/domain/fibonacci.ts +0 -128
- package/core/domain/file-hasher.ts +0 -296
- package/core/domain/file-ranker.ts +0 -151
- package/core/domain/git-cochange.ts +0 -250
- package/core/domain/import-graph.ts +0 -315
- package/core/domain/snapshot-manager.ts +0 -415
- package/core/domain/task-stack.ts +0 -578
- package/core/domain/velocity.ts +0 -470
- package/core/errors.ts +0 -335
- package/core/events/events.ts +0 -85
- package/core/events/index.ts +0 -8
- package/core/index.ts +0 -481
- package/core/infrastructure/agent-detector.ts +0 -135
- package/core/infrastructure/ai-provider.ts +0 -578
- package/core/infrastructure/author-detector.ts +0 -133
- package/core/infrastructure/capability-installer.ts +0 -76
- package/core/infrastructure/claude-agent.ts +0 -297
- package/core/infrastructure/command-installer.ts +0 -752
- package/core/infrastructure/config-manager.ts +0 -364
- package/core/infrastructure/editors-config.ts +0 -172
- package/core/infrastructure/path-manager.ts +0 -571
- package/core/infrastructure/performance-tracker.ts +0 -326
- package/core/infrastructure/permission-manager.ts +0 -289
- package/core/infrastructure/setup.ts +0 -1061
- package/core/infrastructure/update-checker.ts +0 -246
- package/core/integrations/issue-tracker/enricher.ts +0 -271
- package/core/integrations/issue-tracker/index.ts +0 -8
- package/core/integrations/issue-tracker/manager.ts +0 -286
- package/core/integrations/issue-tracker/types.ts +0 -310
- package/core/integrations/jira/cache.ts +0 -57
- package/core/integrations/jira/client.ts +0 -688
- package/core/integrations/jira/index.ts +0 -23
- package/core/integrations/jira/service.ts +0 -244
- package/core/integrations/linear/cache.ts +0 -68
- package/core/integrations/linear/client.ts +0 -436
- package/core/integrations/linear/index.ts +0 -20
- package/core/integrations/linear/service.ts +0 -260
- package/core/integrations/linear/sync.ts +0 -314
- package/core/outcomes/analyzer.ts +0 -286
- package/core/outcomes/index.ts +0 -34
- package/core/outcomes/recorder.ts +0 -195
- package/core/plugin/builtin/webhook.ts +0 -148
- package/core/plugin/hooks.ts +0 -315
- package/core/plugin/index.ts +0 -50
- package/core/plugin/loader.ts +0 -354
- package/core/plugin/registry.ts +0 -326
- package/core/schemas/agents.ts +0 -27
- package/core/schemas/analysis.ts +0 -530
- package/core/schemas/classification.ts +0 -91
- package/core/schemas/command-context.ts +0 -29
- package/core/schemas/enriched-task.ts +0 -291
- package/core/schemas/ideas.ts +0 -114
- package/core/schemas/index.ts +0 -53
- package/core/schemas/issues.ts +0 -159
- package/core/schemas/llm-output.ts +0 -170
- package/core/schemas/metrics.ts +0 -143
- package/core/schemas/model.ts +0 -153
- package/core/schemas/outcomes.ts +0 -487
- package/core/schemas/performance.ts +0 -128
- package/core/schemas/permissions.ts +0 -180
- package/core/schemas/prd.ts +0 -450
- package/core/schemas/project.ts +0 -57
- package/core/schemas/roadmap.ts +0 -322
- package/core/schemas/schemas.ts +0 -38
- package/core/schemas/shipped.ts +0 -109
- package/core/schemas/state.ts +0 -284
- package/core/schemas/velocity.ts +0 -103
- package/core/server/index.ts +0 -21
- package/core/server/routes-extended.ts +0 -566
- package/core/server/routes.ts +0 -176
- package/core/server/server.ts +0 -149
- package/core/server/sse.ts +0 -192
- package/core/services/agent-generator.ts +0 -385
- package/core/services/agent-service.ts +0 -168
- package/core/services/breakdown-service.ts +0 -124
- package/core/services/context-generator.ts +0 -445
- package/core/services/context-selector.ts +0 -429
- package/core/services/dependency-validator.ts +0 -318
- package/core/services/diff-generator.ts +0 -313
- package/core/services/doctor-service.ts +0 -423
- package/core/services/file-categorizer.ts +0 -448
- package/core/services/file-scorer.ts +0 -270
- package/core/services/git-analyzer.ts +0 -293
- package/core/services/hierarchical-agent-resolver.ts +0 -236
- package/core/services/hooks-service.ts +0 -685
- package/core/services/index.ts +0 -46
- package/core/services/local-state-generator.ts +0 -158
- package/core/services/memory-service.ts +0 -181
- package/core/services/nested-context-resolver.ts +0 -842
- package/core/services/project-index.ts +0 -911
- package/core/services/project-service.ts +0 -155
- package/core/services/session-tracker.ts +0 -287
- package/core/services/skill-installer.ts +0 -447
- package/core/services/skill-lock.ts +0 -132
- package/core/services/skill-service.ts +0 -306
- package/core/services/stack-detector.ts +0 -229
- package/core/services/staleness-checker.ts +0 -327
- package/core/services/sync-service.ts +0 -1515
- package/core/services/sync-verifier.ts +0 -253
- package/core/services/watch-service.ts +0 -312
- package/core/session/compaction.ts +0 -248
- package/core/session/index.ts +0 -35
- package/core/session/log-migration.ts +0 -88
- package/core/session/metrics.ts +0 -323
- package/core/session/session-log-manager.ts +0 -307
- package/core/session/task-session-manager.ts +0 -404
- package/core/session/utils.ts +0 -51
- package/core/storage/analysis-storage.ts +0 -373
- package/core/storage/archive-storage.ts +0 -205
- package/core/storage/database.ts +0 -575
- package/core/storage/ideas-storage.ts +0 -298
- package/core/storage/index-storage.ts +0 -523
- package/core/storage/index.ts +0 -79
- package/core/storage/metrics-storage.ts +0 -321
- package/core/storage/migrate-json.ts +0 -720
- package/core/storage/queue-storage.ts +0 -336
- package/core/storage/safe-reader.ts +0 -105
- package/core/storage/shipped-storage.ts +0 -253
- package/core/storage/state-storage.ts +0 -1035
- package/core/storage/storage-manager.ts +0 -205
- package/core/storage/storage.ts +0 -177
- package/core/storage/velocity-storage.ts +0 -149
- package/core/sync/auth-config.ts +0 -138
- package/core/sync/index.ts +0 -31
- package/core/sync/oauth-handler.ts +0 -143
- package/core/sync/sync-client.ts +0 -251
- package/core/sync/sync-manager.ts +0 -327
- package/core/tsconfig.json +0 -22
- package/core/types/agentic.ts +0 -760
- package/core/types/agents.ts +0 -150
- package/core/types/bus.ts +0 -193
- package/core/types/citations.ts +0 -22
- package/core/types/commands.ts +0 -399
- package/core/types/config.ts +0 -92
- package/core/types/core.ts +0 -96
- package/core/types/diff.ts +0 -41
- package/core/types/domain.ts +0 -71
- package/core/types/errors.ts +0 -111
- package/core/types/events.ts +0 -42
- package/core/types/fs.ts +0 -72
- package/core/types/index.ts +0 -510
- package/core/types/infrastructure.ts +0 -210
- package/core/types/integrations.ts +0 -31
- package/core/types/jira.ts +0 -51
- package/core/types/logger.ts +0 -17
- package/core/types/memory.ts +0 -313
- package/core/types/outcomes.ts +0 -190
- package/core/types/output.ts +0 -47
- package/core/types/plugin.ts +0 -25
- package/core/types/project-sync.ts +0 -129
- package/core/types/provider.ts +0 -163
- package/core/types/server.ts +0 -71
- package/core/types/services.ts +0 -84
- package/core/types/session.ts +0 -135
- package/core/types/stack.ts +0 -19
- package/core/types/storage.ts +0 -318
- package/core/types/sync-verifier.ts +0 -33
- package/core/types/sync.ts +0 -121
- package/core/types/task.ts +0 -72
- package/core/types/template.ts +0 -24
- package/core/types/utils.ts +0 -92
- package/core/types/workflow.ts +0 -23
- package/core/utils/agent-stream.ts +0 -140
- package/core/utils/animations.ts +0 -251
- package/core/utils/branding.ts +0 -88
- package/core/utils/cache.ts +0 -187
- package/core/utils/citations.ts +0 -39
- package/core/utils/collection-filters.ts +0 -209
- package/core/utils/date-helper.ts +0 -176
- package/core/utils/error-messages.ts +0 -38
- package/core/utils/file-helper.ts +0 -277
- package/core/utils/fs-helpers.ts +0 -14
- package/core/utils/help.ts +0 -314
- package/core/utils/jsonl-helper.ts +0 -290
- package/core/utils/keychain.ts +0 -127
- package/core/utils/logger.ts +0 -77
- package/core/utils/markdown-builder.ts +0 -280
- package/core/utils/next-steps.ts +0 -95
- package/core/utils/output.ts +0 -403
- package/core/utils/preserve-sections.ts +0 -218
- package/core/utils/project-commands.ts +0 -126
- package/core/utils/project-credentials.ts +0 -143
- package/core/utils/provider-cache.ts +0 -49
- package/core/utils/retry.ts +0 -318
- package/core/utils/runtime.ts +0 -108
- package/core/utils/session-helper.ts +0 -278
- package/core/utils/subtask-table.ts +0 -227
- package/core/utils/version.ts +0 -128
- package/core/wizard/index.ts +0 -13
- package/core/wizard/onboarding.ts +0 -633
- package/core/workflow/index.ts +0 -7
- package/core/workflow/state-machine.ts +0 -198
- package/core/workflow/workflow-preferences.ts +0 -294
- package/dist/core/infrastructure/command-installer.js +0 -1141
- package/dist/core/infrastructure/editors-config.js +0 -177
- package/dist/core/infrastructure/setup.js +0 -2244
- package/dist/core/utils/version.js +0 -141
- package/templates/agentic/agent-routing.md +0 -45
- package/templates/agentic/agents/uxui.md +0 -63
- package/templates/agentic/checklist-routing.md +0 -98
- package/templates/agentic/orchestrator.md +0 -68
- package/templates/agentic/task-fragmentation.md +0 -89
- package/templates/agents/AGENTS.md +0 -68
- package/templates/analysis/analyze.md +0 -84
- package/templates/analysis/patterns.md +0 -60
- package/templates/antigravity/SKILL.md +0 -39
- package/templates/architect/discovery.md +0 -67
- package/templates/architect/phases.md +0 -59
- package/templates/checklists/architecture.md +0 -28
- package/templates/checklists/code-quality.md +0 -28
- package/templates/checklists/data.md +0 -33
- package/templates/checklists/documentation.md +0 -33
- package/templates/checklists/infrastructure.md +0 -33
- package/templates/checklists/performance.md +0 -33
- package/templates/checklists/security.md +0 -33
- package/templates/checklists/testing.md +0 -33
- package/templates/checklists/ux-ui.md +0 -37
- package/templates/commands/analyze.md +0 -56
- package/templates/commands/auth.md +0 -234
- package/templates/commands/bug.md +0 -163
- package/templates/commands/cleanup.md +0 -19
- package/templates/commands/dash.md +0 -99
- package/templates/commands/design.md +0 -15
- package/templates/commands/done.md +0 -291
- package/templates/commands/enrich.md +0 -174
- package/templates/commands/git.md +0 -295
- package/templates/commands/history.md +0 -389
- package/templates/commands/idea.md +0 -88
- package/templates/commands/impact.md +0 -864
- package/templates/commands/init.md +0 -54
- package/templates/commands/jira.md +0 -278
- package/templates/commands/linear.md +0 -288
- package/templates/commands/merge.md +0 -206
- package/templates/commands/next.md +0 -80
- package/templates/commands/p.md +0 -67
- package/templates/commands/p.toml +0 -37
- package/templates/commands/pause.md +0 -136
- package/templates/commands/plan.md +0 -696
- package/templates/commands/prd.md +0 -356
- package/templates/commands/resume.md +0 -171
- package/templates/commands/review.md +0 -276
- package/templates/commands/serve.md +0 -118
- package/templates/commands/setup.md +0 -91
- package/templates/commands/ship.md +0 -475
- package/templates/commands/skill.md +0 -259
- package/templates/commands/spec.md +0 -218
- package/templates/commands/status.md +0 -207
- package/templates/commands/sync.md +0 -104
- package/templates/commands/task.md +0 -312
- package/templates/commands/test.md +0 -93
- package/templates/commands/update.md +0 -63
- package/templates/commands/verify.md +0 -204
- package/templates/commands/workflow.md +0 -150
- package/templates/config/skill-mappings.json +0 -82
- package/templates/context/dashboard.md +0 -256
- package/templates/context/roadmap.md +0 -221
- package/templates/cursor/commands/bug.md +0 -8
- package/templates/cursor/commands/done.md +0 -4
- package/templates/cursor/commands/pause.md +0 -6
- package/templates/cursor/commands/resume.md +0 -4
- package/templates/cursor/commands/ship.md +0 -8
- package/templates/cursor/commands/sync.md +0 -4
- package/templates/cursor/commands/task.md +0 -8
- package/templates/cursor/p.md +0 -29
- package/templates/cursor/router.mdc +0 -28
- package/templates/design/api.md +0 -95
- package/templates/design/architecture.md +0 -77
- package/templates/design/component.md +0 -89
- package/templates/design/database.md +0 -78
- package/templates/design/flow.md +0 -94
- package/templates/global/ANTIGRAVITY.md +0 -254
- package/templates/global/CLAUDE.md +0 -497
- package/templates/global/CURSOR.mdc +0 -266
- package/templates/global/GEMINI.md +0 -293
- package/templates/global/STORAGE-SPEC.md +0 -391
- package/templates/global/WINDSURF.md +0 -266
- package/templates/global/modules/CLAUDE-commands.md +0 -70
- package/templates/global/modules/CLAUDE-core.md +0 -105
- package/templates/global/modules/CLAUDE-git.md +0 -50
- package/templates/global/modules/CLAUDE-intelligence.md +0 -92
- package/templates/global/modules/CLAUDE-storage.md +0 -50
- package/templates/global/modules/module-config.json +0 -36
- package/templates/mcp-config.json +0 -19
- package/templates/permissions/default.jsonc +0 -60
- package/templates/permissions/permissive.jsonc +0 -49
- package/templates/permissions/strict.jsonc +0 -58
- package/templates/planning-methodology.md +0 -195
- package/templates/skills/code-review.md +0 -47
- package/templates/skills/debug.md +0 -61
- package/templates/skills/refactor.md +0 -47
- package/templates/subagents/agent-base.md +0 -20
- package/templates/subagents/domain/backend.md +0 -109
- package/templates/subagents/domain/database.md +0 -121
- package/templates/subagents/domain/devops.md +0 -152
- package/templates/subagents/domain/frontend.md +0 -103
- package/templates/subagents/domain/testing.md +0 -169
- package/templates/subagents/pm-expert.md +0 -366
- package/templates/subagents/workflow/chief-architect.md +0 -657
- package/templates/subagents/workflow/prjct-planner.md +0 -159
- package/templates/subagents/workflow/prjct-shipper.md +0 -188
- package/templates/subagents/workflow/prjct-workflow.md +0 -98
- package/templates/tools/bash.txt +0 -22
- package/templates/tools/edit.txt +0 -18
- package/templates/tools/glob.txt +0 -19
- package/templates/tools/grep.txt +0 -21
- package/templates/tools/read.txt +0 -14
- package/templates/tools/task.txt +0 -20
- package/templates/tools/webfetch.txt +0 -16
- package/templates/tools/websearch.txt +0 -18
- package/templates/tools/write.txt +0 -17
- package/templates/windsurf/router.md +0 -28
- package/templates/windsurf/workflows/bug.md +0 -8
- package/templates/windsurf/workflows/done.md +0 -4
- package/templates/windsurf/workflows/pause.md +0 -4
- package/templates/windsurf/workflows/resume.md +0 -4
- package/templates/windsurf/workflows/ship.md +0 -8
- package/templates/windsurf/workflows/sync.md +0 -4
- package/templates/windsurf/workflows/task.md +0 -8
|
@@ -1,571 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PathManager - Manages project paths between local and global storage
|
|
3
|
-
*
|
|
4
|
-
* Key responsibilities:
|
|
5
|
-
* - Generate unique project identifiers from project paths
|
|
6
|
-
* - Manage paths between local project and global storage
|
|
7
|
-
* - Ensure directory structures exist
|
|
8
|
-
*
|
|
9
|
-
* @version 0.2.1
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import crypto from 'node:crypto'
|
|
13
|
-
import fs from 'node:fs/promises'
|
|
14
|
-
import os from 'node:os'
|
|
15
|
-
import path from 'node:path'
|
|
16
|
-
import { globSync } from 'glob'
|
|
17
|
-
import type { MonorepoInfo, MonorepoPackage, SessionInfo } from '../types'
|
|
18
|
-
import * as dateHelper from '../utils/date-helper'
|
|
19
|
-
import * as fileHelper from '../utils/file-helper'
|
|
20
|
-
|
|
21
|
-
export type { MonorepoInfo, MonorepoPackage } from '../types'
|
|
22
|
-
|
|
23
|
-
class PathManager {
|
|
24
|
-
globalBaseDir: string
|
|
25
|
-
globalProjectsDir: string
|
|
26
|
-
globalConfigDir: string
|
|
27
|
-
|
|
28
|
-
constructor() {
|
|
29
|
-
// PRJCT_CLI_HOME: Override global storage location (default: ~/.prjct-cli)
|
|
30
|
-
const envOverride = process.env.PRJCT_CLI_HOME?.trim()
|
|
31
|
-
this.globalBaseDir = envOverride
|
|
32
|
-
? path.resolve(envOverride)
|
|
33
|
-
: path.join(os.homedir(), '.prjct-cli')
|
|
34
|
-
this.globalProjectsDir = path.join(this.globalBaseDir, 'projects')
|
|
35
|
-
this.globalConfigDir = path.join(this.globalBaseDir, 'config')
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Override global storage location (primarily for tests and sandboxed environments).
|
|
40
|
-
*
|
|
41
|
-
* When unset, global storage defaults to `~/.prjct-cli/`.
|
|
42
|
-
*
|
|
43
|
-
* @param {string} globalBaseDir - Base directory that will contain `projects/` and `config/`.
|
|
44
|
-
*/
|
|
45
|
-
setGlobalBaseDir(globalBaseDir: string): void {
|
|
46
|
-
this.globalBaseDir = path.resolve(globalBaseDir)
|
|
47
|
-
this.globalProjectsDir = path.join(this.globalBaseDir, 'projects')
|
|
48
|
-
this.globalConfigDir = path.join(this.globalBaseDir, 'config')
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Generate a unique project ID using UUID.
|
|
53
|
-
* Standard UUID format for PostgreSQL consistency.
|
|
54
|
-
*/
|
|
55
|
-
generateProjectId(_projectPath: string): string {
|
|
56
|
-
return crypto.randomUUID()
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Get the base global storage path
|
|
61
|
-
*/
|
|
62
|
-
getGlobalBasePath(): string {
|
|
63
|
-
return this.globalBaseDir
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Get the global storage path for a project
|
|
68
|
-
*/
|
|
69
|
-
getGlobalProjectPath(projectId: string): string {
|
|
70
|
-
return path.join(this.globalProjectsDir, projectId)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Get the local config file path for a project
|
|
75
|
-
*/
|
|
76
|
-
getLocalConfigPath(projectPath: string): string {
|
|
77
|
-
return path.join(projectPath, '.prjct', 'prjct.config.json')
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Get the global config file path for a project
|
|
82
|
-
* This file stores authors and other system data that shouldn't be versioned
|
|
83
|
-
*/
|
|
84
|
-
getGlobalProjectConfigPath(projectId: string): string {
|
|
85
|
-
return path.join(this.getGlobalProjectPath(projectId), 'project.json')
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Get the legacy .prjct directory path
|
|
90
|
-
*/
|
|
91
|
-
getLegacyPrjctPath(projectPath: string): string {
|
|
92
|
-
return path.join(projectPath, '.prjct')
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Check if a project has legacy .prjct directory
|
|
97
|
-
*/
|
|
98
|
-
async hasLegacyStructure(projectPath: string): Promise<boolean> {
|
|
99
|
-
const legacyPath = this.getLegacyPrjctPath(projectPath)
|
|
100
|
-
return await fileHelper.dirExists(legacyPath)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Check if a project has the new config file
|
|
105
|
-
*/
|
|
106
|
-
async hasConfig(projectPath: string): Promise<boolean> {
|
|
107
|
-
const configPath = this.getLocalConfigPath(projectPath)
|
|
108
|
-
return await fileHelper.fileExists(configPath)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Ensure the global directory structure exists
|
|
113
|
-
* Creates all necessary directories in ~/.prjct-cli/
|
|
114
|
-
*/
|
|
115
|
-
async ensureGlobalStructure(): Promise<void> {
|
|
116
|
-
await fileHelper.ensureDir(this.globalBaseDir)
|
|
117
|
-
await fileHelper.ensureDir(this.globalProjectsDir)
|
|
118
|
-
await fileHelper.ensureDir(this.globalConfigDir)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Ensure the project-specific global structure exists
|
|
123
|
-
* Creates the layered directory structure for a project
|
|
124
|
-
*/
|
|
125
|
-
async ensureProjectStructure(projectId: string): Promise<string> {
|
|
126
|
-
await this.ensureGlobalStructure()
|
|
127
|
-
|
|
128
|
-
const projectPath = this.getGlobalProjectPath(projectId)
|
|
129
|
-
|
|
130
|
-
const layers = ['core', 'progress', 'planning', 'analysis', 'memory', 'agents']
|
|
131
|
-
|
|
132
|
-
for (const layer of layers) {
|
|
133
|
-
await fileHelper.ensureDir(path.join(projectPath, layer))
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
await fileHelper.ensureDir(path.join(projectPath, 'planning', 'tasks'))
|
|
137
|
-
await fileHelper.ensureDir(path.join(projectPath, 'sessions'))
|
|
138
|
-
|
|
139
|
-
return projectPath
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Get session directory path for a specific date
|
|
144
|
-
* Creates hierarchical structure: sessions/YYYY/MM/DD/
|
|
145
|
-
*/
|
|
146
|
-
getSessionPath(projectId: string, date: Date = new Date()): string {
|
|
147
|
-
const { year, month, day } = dateHelper.getYearMonthDay(date)
|
|
148
|
-
|
|
149
|
-
return path.join(this.getGlobalProjectPath(projectId), 'sessions', year, month, day)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Get current session directory path (today)
|
|
154
|
-
*/
|
|
155
|
-
getCurrentSessionPath(projectId: string): string {
|
|
156
|
-
return this.getSessionPath(projectId, new Date())
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Ensure session directory exists for a specific date
|
|
161
|
-
*/
|
|
162
|
-
async ensureSessionPath(projectId: string, date: Date = new Date()): Promise<string> {
|
|
163
|
-
const sessionPath = this.getSessionPath(projectId, date)
|
|
164
|
-
await fileHelper.ensureDir(sessionPath)
|
|
165
|
-
return sessionPath
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* List all session dates for a project
|
|
170
|
-
*/
|
|
171
|
-
async listSessions(
|
|
172
|
-
projectId: string,
|
|
173
|
-
year: number | null = null,
|
|
174
|
-
month: number | null = null
|
|
175
|
-
): Promise<SessionInfo[]> {
|
|
176
|
-
const sessionsDir = path.join(this.getGlobalProjectPath(projectId), 'sessions')
|
|
177
|
-
const sessions: SessionInfo[] = []
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
const years = await fs.readdir(sessionsDir, { withFileTypes: true })
|
|
181
|
-
|
|
182
|
-
for (const yearEntry of years) {
|
|
183
|
-
if (!yearEntry.isDirectory()) continue
|
|
184
|
-
if (year && yearEntry.name !== year.toString()) continue
|
|
185
|
-
|
|
186
|
-
const yearPath = path.join(sessionsDir, yearEntry.name)
|
|
187
|
-
const months = await fs.readdir(yearPath, { withFileTypes: true })
|
|
188
|
-
|
|
189
|
-
for (const monthEntry of months) {
|
|
190
|
-
if (!monthEntry.isDirectory()) continue
|
|
191
|
-
if (month && monthEntry.name !== month.toString().padStart(2, '0')) continue
|
|
192
|
-
|
|
193
|
-
const monthPath = path.join(yearPath, monthEntry.name)
|
|
194
|
-
const days = await fs.readdir(monthPath, { withFileTypes: true })
|
|
195
|
-
|
|
196
|
-
for (const dayEntry of days) {
|
|
197
|
-
if (!dayEntry.isDirectory()) continue
|
|
198
|
-
|
|
199
|
-
sessions.push({
|
|
200
|
-
year: yearEntry.name,
|
|
201
|
-
month: monthEntry.name,
|
|
202
|
-
day: dayEntry.name,
|
|
203
|
-
path: path.join(monthPath, dayEntry.name),
|
|
204
|
-
date: new Date(`${yearEntry.name}-${monthEntry.name}-${dayEntry.name}`),
|
|
205
|
-
})
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
sessions.sort((a, b) => b.date.getTime() - a.date.getTime())
|
|
211
|
-
return sessions
|
|
212
|
-
} catch (_error) {
|
|
213
|
-
// Sessions directory might not exist - expected for new projects
|
|
214
|
-
return []
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Get sessions within a date range
|
|
220
|
-
*/
|
|
221
|
-
async getSessionsInRange(
|
|
222
|
-
projectId: string,
|
|
223
|
-
fromDate: Date,
|
|
224
|
-
toDate: Date = new Date()
|
|
225
|
-
): Promise<SessionInfo[]> {
|
|
226
|
-
const allSessions = await this.listSessions(projectId)
|
|
227
|
-
|
|
228
|
-
return allSessions.filter((session) => session.date >= fromDate && session.date <= toDate)
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Get the path for a specific file in the global structure
|
|
233
|
-
*/
|
|
234
|
-
getFilePath(projectId: string, layer: string, filename: string): string {
|
|
235
|
-
return path.join(this.getGlobalProjectPath(projectId), layer, filename)
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Get all project IDs in global storage
|
|
240
|
-
*/
|
|
241
|
-
async listProjects(): Promise<string[]> {
|
|
242
|
-
try {
|
|
243
|
-
await this.ensureGlobalStructure()
|
|
244
|
-
const entries = await fs.readdir(this.globalProjectsDir, { withFileTypes: true })
|
|
245
|
-
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)
|
|
246
|
-
} catch (_error) {
|
|
247
|
-
// Global projects directory might not exist - expected
|
|
248
|
-
return []
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Check if a project exists in global storage
|
|
254
|
-
*/
|
|
255
|
-
async projectExists(projectId: string): Promise<boolean> {
|
|
256
|
-
const projectPath = this.getGlobalProjectPath(projectId)
|
|
257
|
-
return await fileHelper.dirExists(projectPath)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Get the relative path from home directory for display
|
|
262
|
-
*/
|
|
263
|
-
getDisplayPath(absolutePath: string): string {
|
|
264
|
-
const homeDir = os.homedir()
|
|
265
|
-
if (absolutePath.startsWith(homeDir)) {
|
|
266
|
-
return absolutePath.replace(homeDir, '~')
|
|
267
|
-
}
|
|
268
|
-
return absolutePath
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Get the auth config file path for cloud sync
|
|
273
|
-
* Stored in global config directory, not project-specific
|
|
274
|
-
*/
|
|
275
|
-
getAuthConfigPath(): string {
|
|
276
|
-
return path.join(this.globalConfigDir, 'auth.json')
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Get the sync pending events file path for a project
|
|
281
|
-
*/
|
|
282
|
-
getSyncPendingPath(projectId: string): string {
|
|
283
|
-
return path.join(this.getGlobalProjectPath(projectId), 'sync', 'pending.json')
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Get the last sync timestamp file path for a project
|
|
288
|
-
*/
|
|
289
|
-
getLastSyncPath(projectId: string): string {
|
|
290
|
-
return path.join(this.getGlobalProjectPath(projectId), 'sync', 'last-sync.json')
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Get the running status file path (for status signal)
|
|
295
|
-
* Used to indicate when prjct CLI is actively running
|
|
296
|
-
*/
|
|
297
|
-
getRunningStatusPath(): string {
|
|
298
|
-
return path.join(this.globalBaseDir, '.running')
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Get the docs directory path
|
|
303
|
-
* Contains documentation and help files
|
|
304
|
-
*/
|
|
305
|
-
getDocsPath(): string {
|
|
306
|
-
return path.join(this.globalBaseDir, 'docs')
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Get the Claude/Gemini directory path (~/.claude or ~/.gemini)
|
|
311
|
-
* Contains AI CLI configuration
|
|
312
|
-
*/
|
|
313
|
-
async getAgentDir(): Promise<string> {
|
|
314
|
-
const provider = await require('./ai-provider').getActiveProvider()
|
|
315
|
-
return provider.configDir
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Get the agent settings file path (~/.claude/settings.json or ~/.gemini/settings.json)
|
|
320
|
-
*/
|
|
321
|
-
async getAgentSettingsPath(): Promise<string> {
|
|
322
|
-
const provider = await require('./ai-provider').getActiveProvider()
|
|
323
|
-
const aiProvider = require('./ai-provider')
|
|
324
|
-
return aiProvider.getGlobalSettingsPath(provider.name)
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Get the Claude directory path (~/.claude) - Legacy support
|
|
329
|
-
*/
|
|
330
|
-
getClaudeDir(): string {
|
|
331
|
-
return path.join(os.homedir(), '.claude')
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Get the Claude settings file path (~/.claude/settings.json) - Legacy support
|
|
336
|
-
*/
|
|
337
|
-
getClaudeSettingsPath(): string {
|
|
338
|
-
return path.join(this.getClaudeDir(), 'settings.json')
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Get the agents directory path for a project
|
|
343
|
-
* If projectId is null, returns the global agents directory
|
|
344
|
-
*/
|
|
345
|
-
getAgentsPath(projectId: string | null): string {
|
|
346
|
-
if (projectId) {
|
|
347
|
-
return path.join(this.getGlobalProjectPath(projectId), 'agents')
|
|
348
|
-
}
|
|
349
|
-
return path.join(this.globalBaseDir, 'agents')
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Get the storage file path for a project
|
|
354
|
-
* Convenience method for accessing storage layer files
|
|
355
|
-
*/
|
|
356
|
-
getStoragePath(projectId: string, filename: string): string {
|
|
357
|
-
return path.join(this.getGlobalProjectPath(projectId), 'storage', filename)
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Get the context directory path for a project
|
|
362
|
-
* Contains generated markdown context files
|
|
363
|
-
*/
|
|
364
|
-
getContextPath(projectId: string): string {
|
|
365
|
-
return path.join(this.getGlobalProjectPath(projectId), 'context')
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// ===========================================================================
|
|
369
|
-
// Monorepo Detection
|
|
370
|
-
// ===========================================================================
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Detect if a project is a monorepo and get package information
|
|
374
|
-
*/
|
|
375
|
-
async detectMonorepo(projectPath: string): Promise<MonorepoInfo> {
|
|
376
|
-
const result: MonorepoInfo = {
|
|
377
|
-
isMonorepo: false,
|
|
378
|
-
type: null,
|
|
379
|
-
rootPath: projectPath,
|
|
380
|
-
packages: [],
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Check for various monorepo configurations
|
|
384
|
-
const checks = [
|
|
385
|
-
{ file: 'pnpm-workspace.yaml', type: 'pnpm' as const },
|
|
386
|
-
{ file: 'lerna.json', type: 'lerna' as const },
|
|
387
|
-
{ file: 'nx.json', type: 'nx' as const },
|
|
388
|
-
{ file: 'rush.json', type: 'rush' as const },
|
|
389
|
-
{ file: 'turbo.json', type: 'turborepo' as const },
|
|
390
|
-
]
|
|
391
|
-
|
|
392
|
-
for (const check of checks) {
|
|
393
|
-
const filePath = path.join(projectPath, check.file)
|
|
394
|
-
if (await fileHelper.fileExists(filePath)) {
|
|
395
|
-
result.isMonorepo = true
|
|
396
|
-
result.type = check.type
|
|
397
|
-
break
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// Check package.json for workspaces (npm/yarn)
|
|
402
|
-
if (!result.isMonorepo) {
|
|
403
|
-
const packageJsonPath = path.join(projectPath, 'package.json')
|
|
404
|
-
if (await fileHelper.fileExists(packageJsonPath)) {
|
|
405
|
-
try {
|
|
406
|
-
const content = await fs.readFile(packageJsonPath, 'utf-8')
|
|
407
|
-
const pkg = JSON.parse(content)
|
|
408
|
-
if (pkg.workspaces) {
|
|
409
|
-
result.isMonorepo = true
|
|
410
|
-
result.type = 'npm' // Could be yarn too, but npm is more generic
|
|
411
|
-
}
|
|
412
|
-
} catch {
|
|
413
|
-
// Invalid package.json, ignore
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// If it's a monorepo, discover packages
|
|
419
|
-
if (result.isMonorepo) {
|
|
420
|
-
result.packages = await this.discoverMonorepoPackages(projectPath, result.type)
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
return result
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Discover all packages in a monorepo
|
|
428
|
-
*/
|
|
429
|
-
async discoverMonorepoPackages(
|
|
430
|
-
rootPath: string,
|
|
431
|
-
type: MonorepoInfo['type']
|
|
432
|
-
): Promise<MonorepoPackage[]> {
|
|
433
|
-
const packages: MonorepoPackage[] = []
|
|
434
|
-
let patterns: string[] = []
|
|
435
|
-
|
|
436
|
-
try {
|
|
437
|
-
if (type === 'pnpm') {
|
|
438
|
-
// Read pnpm-workspace.yaml
|
|
439
|
-
const yaml = await fs.readFile(path.join(rootPath, 'pnpm-workspace.yaml'), 'utf-8')
|
|
440
|
-
// Simple YAML parsing for packages array
|
|
441
|
-
const match = yaml.match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/)
|
|
442
|
-
if (match) {
|
|
443
|
-
patterns = match[1]
|
|
444
|
-
.split('\n')
|
|
445
|
-
.map((line) => line.replace(/^\s*-\s*['"]?|['"]?\s*$/g, ''))
|
|
446
|
-
.filter(Boolean)
|
|
447
|
-
}
|
|
448
|
-
} else if (type === 'npm' || type === 'lerna') {
|
|
449
|
-
// Read from package.json workspaces or lerna.json
|
|
450
|
-
const packageJsonPath = path.join(rootPath, 'package.json')
|
|
451
|
-
const content = await fs.readFile(packageJsonPath, 'utf-8')
|
|
452
|
-
const pkg = JSON.parse(content)
|
|
453
|
-
if (Array.isArray(pkg.workspaces)) {
|
|
454
|
-
patterns = pkg.workspaces
|
|
455
|
-
} else if (pkg.workspaces?.packages) {
|
|
456
|
-
patterns = pkg.workspaces.packages
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Also check lerna.json
|
|
460
|
-
if (type === 'lerna') {
|
|
461
|
-
const lernaPath = path.join(rootPath, 'lerna.json')
|
|
462
|
-
if (await fileHelper.fileExists(lernaPath)) {
|
|
463
|
-
const lernaContent = await fs.readFile(lernaPath, 'utf-8')
|
|
464
|
-
const lerna = JSON.parse(lernaContent)
|
|
465
|
-
if (lerna.packages) {
|
|
466
|
-
patterns = lerna.packages
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
} else if (type === 'nx') {
|
|
471
|
-
// NX uses apps/* and libs/* by default
|
|
472
|
-
patterns = ['apps/*', 'libs/*', 'packages/*']
|
|
473
|
-
} else if (type === 'turborepo') {
|
|
474
|
-
// Turborepo reads from package.json workspaces
|
|
475
|
-
const packageJsonPath = path.join(rootPath, 'package.json')
|
|
476
|
-
const content = await fs.readFile(packageJsonPath, 'utf-8')
|
|
477
|
-
const pkg = JSON.parse(content)
|
|
478
|
-
if (Array.isArray(pkg.workspaces)) {
|
|
479
|
-
patterns = pkg.workspaces
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// If no patterns found, use common defaults
|
|
484
|
-
if (patterns.length === 0) {
|
|
485
|
-
patterns = ['packages/*', 'apps/*', 'libs/*']
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
// Expand glob patterns to find packages
|
|
489
|
-
for (const pattern of patterns) {
|
|
490
|
-
// Skip negation patterns for now
|
|
491
|
-
if (pattern.startsWith('!')) continue
|
|
492
|
-
|
|
493
|
-
const matches = globSync(pattern, {
|
|
494
|
-
cwd: rootPath,
|
|
495
|
-
absolute: false,
|
|
496
|
-
})
|
|
497
|
-
|
|
498
|
-
for (const match of matches) {
|
|
499
|
-
const packagePath = path.join(rootPath, match)
|
|
500
|
-
const packageJsonPath = path.join(packagePath, 'package.json')
|
|
501
|
-
|
|
502
|
-
// Only include directories with package.json
|
|
503
|
-
if (await fileHelper.fileExists(packageJsonPath)) {
|
|
504
|
-
try {
|
|
505
|
-
const content = await fs.readFile(packageJsonPath, 'utf-8')
|
|
506
|
-
const pkg = JSON.parse(content)
|
|
507
|
-
const prjctMdPath = path.join(packagePath, 'PRJCT.md')
|
|
508
|
-
|
|
509
|
-
packages.push({
|
|
510
|
-
name: pkg.name || path.basename(match),
|
|
511
|
-
path: packagePath,
|
|
512
|
-
relativePath: match,
|
|
513
|
-
hasPrjctMd: await fileHelper.fileExists(prjctMdPath),
|
|
514
|
-
})
|
|
515
|
-
} catch {
|
|
516
|
-
// Invalid package.json, skip
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
} catch {
|
|
522
|
-
// Error reading monorepo config, return empty
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
return packages
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
/**
|
|
529
|
-
* Check if current path is within a monorepo package
|
|
530
|
-
* Returns the package info if found, null otherwise
|
|
531
|
-
*/
|
|
532
|
-
async findContainingPackage(
|
|
533
|
-
currentPath: string,
|
|
534
|
-
monoInfo: MonorepoInfo
|
|
535
|
-
): Promise<MonorepoPackage | null> {
|
|
536
|
-
if (!monoInfo.isMonorepo) return null
|
|
537
|
-
|
|
538
|
-
const normalizedCurrent = path.resolve(currentPath)
|
|
539
|
-
|
|
540
|
-
for (const pkg of monoInfo.packages) {
|
|
541
|
-
const normalizedPkg = path.resolve(pkg.path)
|
|
542
|
-
if (normalizedCurrent.startsWith(normalizedPkg)) {
|
|
543
|
-
return pkg
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
return null
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* Find monorepo root from any subdirectory
|
|
552
|
-
* Walks up the directory tree looking for monorepo markers
|
|
553
|
-
*/
|
|
554
|
-
async findMonorepoRoot(startPath: string): Promise<string | null> {
|
|
555
|
-
let currentPath = path.resolve(startPath)
|
|
556
|
-
const root = path.parse(currentPath).root
|
|
557
|
-
|
|
558
|
-
while (currentPath !== root) {
|
|
559
|
-
const monoInfo = await this.detectMonorepo(currentPath)
|
|
560
|
-
if (monoInfo.isMonorepo) {
|
|
561
|
-
return currentPath
|
|
562
|
-
}
|
|
563
|
-
currentPath = path.dirname(currentPath)
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
return null
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
const pathManager = new PathManager()
|
|
571
|
-
export default pathManager
|