prjct-cli 1.22.0 → 1.24.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 +230 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct-core.mjs +1748 -0
- package/dist/bin/prjct.mjs +17 -36672
- package/dist/cli/linear.mjs +14 -0
- package/dist/daemon/entry.mjs +1429 -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,205 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Storage Manager Base Class (PRJ-303: SQLite-backed)
|
|
3
|
-
*
|
|
4
|
-
* Write-through pattern:
|
|
5
|
-
* 1. Write to SQLite kv_store (primary)
|
|
6
|
-
* 2. Regenerate MD in context/
|
|
7
|
-
* 3. Publish event for backend sync
|
|
8
|
-
*
|
|
9
|
-
* Read path: cache → SQLite → default
|
|
10
|
-
*
|
|
11
|
-
* Subclasses implement specific data types (state, queue, ideas, shipped).
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import fs from 'node:fs/promises'
|
|
15
|
-
import path from 'node:path'
|
|
16
|
-
import { eventBus, type SyncEvent } from '../events'
|
|
17
|
-
import pathManager from '../infrastructure/path-manager'
|
|
18
|
-
import { TTLCache } from '../utils/cache'
|
|
19
|
-
import { getTimestamp } from '../utils/date-helper'
|
|
20
|
-
import { prjctDb } from './database'
|
|
21
|
-
|
|
22
|
-
export abstract class StorageManager<T> {
|
|
23
|
-
protected filename: string
|
|
24
|
-
protected cache: TTLCache<T>
|
|
25
|
-
|
|
26
|
-
constructor(filename: string, _schema?: unknown) {
|
|
27
|
-
this.filename = filename
|
|
28
|
-
this.cache = new TTLCache<T>({ ttl: 5000, maxSize: 50 })
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Get the kv_store key for this storage type.
|
|
33
|
-
* Derived from filename: 'state.json' → 'state'
|
|
34
|
-
*/
|
|
35
|
-
protected getStoreKey(): string {
|
|
36
|
-
return this.filename.replace('.json', '')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Get file path for context MD
|
|
41
|
-
* Uses layer-based paths to match MdBaseManager structure
|
|
42
|
-
*/
|
|
43
|
-
protected getContextPath(projectId: string, mdFilename: string): string {
|
|
44
|
-
const layer = this.getLayer()
|
|
45
|
-
return pathManager.getFilePath(projectId, layer, mdFilename)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get the layer for context MD files
|
|
50
|
-
* Override in subclasses: 'core' | 'planning' | 'progress'
|
|
51
|
-
*/
|
|
52
|
-
protected abstract getLayer(): string
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Get default data structure
|
|
56
|
-
*/
|
|
57
|
-
protected abstract getDefault(): T
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Convert data to markdown for Claude
|
|
61
|
-
*/
|
|
62
|
-
protected abstract toMarkdown(data: T): string
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get MD filename for context generation
|
|
66
|
-
*/
|
|
67
|
-
protected abstract getMdFilename(): string
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Get event type for sync
|
|
71
|
-
*/
|
|
72
|
-
protected abstract getEventType(action: 'update' | 'create' | 'delete'): string
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Read data from storage.
|
|
76
|
-
* Path: cache → SQLite kv_store → default
|
|
77
|
-
*/
|
|
78
|
-
async read(projectId: string): Promise<T> {
|
|
79
|
-
// Check cache first (with expiration)
|
|
80
|
-
const cached = this.cache.get(projectId)
|
|
81
|
-
if (cached !== null) {
|
|
82
|
-
return cached
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Try SQLite kv_store (primary store)
|
|
86
|
-
try {
|
|
87
|
-
const data = prjctDb.getDoc<T>(projectId, this.getStoreKey())
|
|
88
|
-
if (data !== null) {
|
|
89
|
-
this.cache.set(projectId, data)
|
|
90
|
-
return data
|
|
91
|
-
}
|
|
92
|
-
} catch {
|
|
93
|
-
// SQLite not available (e.g., DB dir doesn't exist yet)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return this.getDefault()
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Write data to storage + regenerate context + publish event.
|
|
101
|
-
* SQLite primary + MD context regeneration.
|
|
102
|
-
*/
|
|
103
|
-
async write(projectId: string, data: T): Promise<void> {
|
|
104
|
-
const contextPath = this.getContextPath(projectId, this.getMdFilename())
|
|
105
|
-
|
|
106
|
-
// Ensure context directory exists
|
|
107
|
-
await fs.mkdir(path.dirname(contextPath), { recursive: true })
|
|
108
|
-
|
|
109
|
-
// 1. Write to SQLite kv_store (primary)
|
|
110
|
-
prjctDb.setDoc(projectId, this.getStoreKey(), data)
|
|
111
|
-
|
|
112
|
-
// 2. Regenerate MD for Claude
|
|
113
|
-
const md = this.toMarkdown(data)
|
|
114
|
-
await fs.writeFile(contextPath, md, 'utf-8')
|
|
115
|
-
|
|
116
|
-
// 3. Update cache
|
|
117
|
-
this.cache.set(projectId, data)
|
|
118
|
-
|
|
119
|
-
// 4. Publish event for backend sync (NOT included in this call - subclass handles)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Update data with a transform function
|
|
124
|
-
*/
|
|
125
|
-
async update(projectId: string, updater: (current: T) => T): Promise<T> {
|
|
126
|
-
const current = await this.read(projectId)
|
|
127
|
-
const updated = updater(current)
|
|
128
|
-
await this.write(projectId, updated)
|
|
129
|
-
return updated
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Publish sync event to eventBus
|
|
134
|
-
*/
|
|
135
|
-
protected async publishEvent(
|
|
136
|
-
projectId: string,
|
|
137
|
-
eventType: string,
|
|
138
|
-
eventData: unknown
|
|
139
|
-
): Promise<void> {
|
|
140
|
-
const event: SyncEvent = {
|
|
141
|
-
type: eventType,
|
|
142
|
-
path: [this.filename.replace('.json', '')],
|
|
143
|
-
data: eventData,
|
|
144
|
-
timestamp: getTimestamp(),
|
|
145
|
-
projectId,
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
await eventBus.publish(event)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Publish an entity event with automatic type construction
|
|
153
|
-
* Convenience method that builds event type from entity and action
|
|
154
|
-
*
|
|
155
|
-
* @param projectId - Project identifier
|
|
156
|
-
* @param entity - Entity name (e.g., 'task', 'idea', 'queue', 'feature')
|
|
157
|
-
* @param action - Action name (e.g., 'started', 'completed', 'created')
|
|
158
|
-
* @param payload - Event data (timestamp added automatically)
|
|
159
|
-
*/
|
|
160
|
-
protected async publishEntityEvent(
|
|
161
|
-
projectId: string,
|
|
162
|
-
entity: string,
|
|
163
|
-
action: string,
|
|
164
|
-
payload: Record<string, unknown>
|
|
165
|
-
): Promise<void> {
|
|
166
|
-
const eventType = `${entity}.${action}`
|
|
167
|
-
const eventData = {
|
|
168
|
-
...payload,
|
|
169
|
-
timestamp: getTimestamp(),
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
await this.publishEvent(projectId, eventType, eventData)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Check if storage exists for this project.
|
|
177
|
-
*/
|
|
178
|
-
async exists(projectId: string): Promise<boolean> {
|
|
179
|
-
try {
|
|
180
|
-
return prjctDb.hasDoc(projectId, this.getStoreKey())
|
|
181
|
-
} catch {
|
|
182
|
-
return false
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Clear cache for a project
|
|
188
|
-
*/
|
|
189
|
-
clearCache(projectId?: string): void {
|
|
190
|
-
if (projectId) {
|
|
191
|
-
this.cache.delete(projectId)
|
|
192
|
-
} else {
|
|
193
|
-
this.cache.clear()
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Get cache statistics
|
|
199
|
-
*/
|
|
200
|
-
getCacheStats(): { size: number; maxSize: number; ttl: number } {
|
|
201
|
-
return this.cache.stats()
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export default StorageManager
|
package/core/storage/storage.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Granular Storage (Legacy)
|
|
3
|
-
*
|
|
4
|
-
* OpenCode-style per-entity storage
|
|
5
|
-
* For future per-entity storage: data/{entity}s/{id}.json
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import fs from 'node:fs/promises'
|
|
9
|
-
import os from 'node:os'
|
|
10
|
-
import path from 'node:path'
|
|
11
|
-
import { eventBus, inferEventType } from '../events'
|
|
12
|
-
import type { Storage } from '../types'
|
|
13
|
-
import { isNotFoundError } from '../types/fs'
|
|
14
|
-
|
|
15
|
-
class FileStorage implements Storage {
|
|
16
|
-
private projectId: string
|
|
17
|
-
private basePath: string
|
|
18
|
-
|
|
19
|
-
constructor(projectId: string) {
|
|
20
|
-
this.projectId = projectId
|
|
21
|
-
this.basePath = path.join(os.homedir(), '.prjct-cli/projects', projectId, 'data')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Convert path array to file path
|
|
26
|
-
* ["task", "abc123"] → data/tasks/abc123.json
|
|
27
|
-
* ["project"] → data/project.json
|
|
28
|
-
*/
|
|
29
|
-
private pathToFile(pathArray: string[]): string {
|
|
30
|
-
if (pathArray.length === 1) {
|
|
31
|
-
return path.join(this.basePath, `${pathArray[0]}.json`)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Pluralize first segment for directory
|
|
35
|
-
const dir = `${pathArray[0]}s`
|
|
36
|
-
const rest = pathArray.slice(1)
|
|
37
|
-
const filename = `${rest.join('/')}.json`
|
|
38
|
-
|
|
39
|
-
return path.join(this.basePath, dir, filename)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async write<T>(pathArray: string[], data: T): Promise<void> {
|
|
43
|
-
const filePath = this.pathToFile(pathArray)
|
|
44
|
-
|
|
45
|
-
// Ensure directory exists
|
|
46
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true })
|
|
47
|
-
|
|
48
|
-
// Write data
|
|
49
|
-
await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8')
|
|
50
|
-
|
|
51
|
-
// Publish event for sync
|
|
52
|
-
eventBus.publish({
|
|
53
|
-
type: inferEventType(pathArray, 'write'),
|
|
54
|
-
path: pathArray,
|
|
55
|
-
data,
|
|
56
|
-
timestamp: new Date().toISOString(),
|
|
57
|
-
projectId: this.projectId,
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// Update index if it's a collection item
|
|
61
|
-
if (pathArray.length === 2) {
|
|
62
|
-
await this.updateIndex(pathArray[0], pathArray[1], 'add')
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async read<T>(pathArray: string[]): Promise<T | null> {
|
|
67
|
-
const filePath = this.pathToFile(pathArray)
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
const content = await fs.readFile(filePath, 'utf-8')
|
|
71
|
-
return JSON.parse(content) as T
|
|
72
|
-
} catch (error) {
|
|
73
|
-
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
74
|
-
return null
|
|
75
|
-
}
|
|
76
|
-
throw error
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async list(prefix: string[]): Promise<string[][]> {
|
|
81
|
-
const dir = path.join(this.basePath, `${prefix[0]}s`)
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
const files = await fs.readdir(dir)
|
|
85
|
-
return files
|
|
86
|
-
.filter((f) => f.endsWith('.json') && f !== 'index.json')
|
|
87
|
-
.map((f) => [...prefix, f.replace('.json', '')])
|
|
88
|
-
} catch (error) {
|
|
89
|
-
if (isNotFoundError(error)) {
|
|
90
|
-
return []
|
|
91
|
-
}
|
|
92
|
-
throw error
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async delete(pathArray: string[]): Promise<void> {
|
|
97
|
-
const filePath = this.pathToFile(pathArray)
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
await fs.unlink(filePath)
|
|
101
|
-
|
|
102
|
-
// Publish event for sync
|
|
103
|
-
eventBus.publish({
|
|
104
|
-
type: inferEventType(pathArray, 'delete'),
|
|
105
|
-
path: pathArray,
|
|
106
|
-
data: null,
|
|
107
|
-
timestamp: new Date().toISOString(),
|
|
108
|
-
projectId: this.projectId,
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
// Update index if it's a collection item
|
|
112
|
-
if (pathArray.length === 2) {
|
|
113
|
-
await this.updateIndex(pathArray[0], pathArray[1], 'remove')
|
|
114
|
-
}
|
|
115
|
-
} catch (error) {
|
|
116
|
-
// File doesn't exist - ignore
|
|
117
|
-
if (!isNotFoundError(error)) {
|
|
118
|
-
throw error
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async exists(pathArray: string[]): Promise<boolean> {
|
|
124
|
-
const filePath = this.pathToFile(pathArray)
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
await fs.access(filePath)
|
|
128
|
-
return true
|
|
129
|
-
} catch (error) {
|
|
130
|
-
if (isNotFoundError(error)) {
|
|
131
|
-
return false
|
|
132
|
-
}
|
|
133
|
-
throw error
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Update collection index
|
|
139
|
-
*/
|
|
140
|
-
private async updateIndex(
|
|
141
|
-
collection: string,
|
|
142
|
-
id: string,
|
|
143
|
-
action: 'add' | 'remove'
|
|
144
|
-
): Promise<void> {
|
|
145
|
-
const indexPath = path.join(this.basePath, `${collection}s`, 'index.json')
|
|
146
|
-
|
|
147
|
-
let index: { ids: string[]; updatedAt: string } = { ids: [], updatedAt: '' }
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
const content = await fs.readFile(indexPath, 'utf-8')
|
|
151
|
-
index = JSON.parse(content)
|
|
152
|
-
} catch (error) {
|
|
153
|
-
// Index doesn't exist yet or is malformed
|
|
154
|
-
if (!isNotFoundError(error) && !(error instanceof SyntaxError)) {
|
|
155
|
-
throw error
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (action === 'add' && !index.ids.includes(id)) {
|
|
160
|
-
index.ids.push(id)
|
|
161
|
-
} else if (action === 'remove') {
|
|
162
|
-
index.ids = index.ids.filter((i) => i !== id)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
index.updatedAt = new Date().toISOString()
|
|
166
|
-
|
|
167
|
-
await fs.mkdir(path.dirname(indexPath), { recursive: true })
|
|
168
|
-
await fs.writeFile(indexPath, JSON.stringify(index, null, 2), 'utf-8')
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Get storage instance for a project
|
|
174
|
-
*/
|
|
175
|
-
export function getStorage(projectId: string): Storage {
|
|
176
|
-
return new FileStorage(projectId)
|
|
177
|
-
}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Velocity Storage (PRJ-296)
|
|
3
|
-
*
|
|
4
|
-
* Manages velocity metrics with write-through pattern:
|
|
5
|
-
* - storage/velocity.json → source of truth
|
|
6
|
-
* - context/velocity.md → Claude-readable summary
|
|
7
|
-
*
|
|
8
|
-
* Extends StorageManager for consistency with existing storage classes.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { VelocityMetrics } from '../schemas/velocity'
|
|
12
|
-
import { DEFAULT_VELOCITY_METRICS } from '../schemas/velocity'
|
|
13
|
-
import { StorageManager } from './storage-manager'
|
|
14
|
-
|
|
15
|
-
// =============================================================================
|
|
16
|
-
// Types
|
|
17
|
-
// =============================================================================
|
|
18
|
-
|
|
19
|
-
interface VelocityStoreData {
|
|
20
|
-
metrics: VelocityMetrics
|
|
21
|
-
lastUpdated: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// =============================================================================
|
|
25
|
-
// Velocity Storage
|
|
26
|
-
// =============================================================================
|
|
27
|
-
|
|
28
|
-
class VelocityStorage extends StorageManager<VelocityStoreData> {
|
|
29
|
-
constructor() {
|
|
30
|
-
super('velocity.json')
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
protected getDefault(): VelocityStoreData {
|
|
34
|
-
return {
|
|
35
|
-
metrics: DEFAULT_VELOCITY_METRICS,
|
|
36
|
-
lastUpdated: '',
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
protected getMdFilename(): string {
|
|
41
|
-
return 'velocity.md'
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
protected getLayer(): string {
|
|
45
|
-
return 'progress'
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
protected getEventType(action: 'update' | 'create' | 'delete'): string {
|
|
49
|
-
return `velocity.${action}d`
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
protected toMarkdown(data: VelocityStoreData): string {
|
|
53
|
-
const { metrics } = data
|
|
54
|
-
const lines = ['# Velocity', '']
|
|
55
|
-
|
|
56
|
-
if (metrics.sprints.length === 0) {
|
|
57
|
-
lines.push('_No velocity data yet. Complete tasks with estimates to build velocity history._')
|
|
58
|
-
lines.push('')
|
|
59
|
-
return lines.join('\n')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Summary
|
|
63
|
-
lines.push(`**Average**: ${metrics.averageVelocity} pts/sprint`)
|
|
64
|
-
lines.push(`**Trend**: ${formatTrendIcon(metrics.velocityTrend)} ${metrics.velocityTrend}`)
|
|
65
|
-
lines.push(`**Estimation Accuracy**: ${metrics.estimationAccuracy}%`)
|
|
66
|
-
lines.push('')
|
|
67
|
-
|
|
68
|
-
// Sprint table
|
|
69
|
-
lines.push('## Sprint History')
|
|
70
|
-
lines.push('')
|
|
71
|
-
lines.push('| Sprint | Points | Tasks | Accuracy | Variance |')
|
|
72
|
-
lines.push('|--------|--------|-------|----------|----------|')
|
|
73
|
-
|
|
74
|
-
const recentSprints = metrics.sprints.slice(-6)
|
|
75
|
-
for (const sprint of recentSprints) {
|
|
76
|
-
lines.push(
|
|
77
|
-
`| ${sprint.sprintNumber} | ${sprint.pointsCompleted} | ${sprint.tasksCompleted} | ${sprint.estimationAccuracy}% | ${sprint.avgVariance > 0 ? '+' : ''}${sprint.avgVariance}% |`
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
lines.push('')
|
|
81
|
-
|
|
82
|
-
// Patterns
|
|
83
|
-
if (metrics.underEstimated.length > 0 || metrics.overEstimated.length > 0) {
|
|
84
|
-
lines.push('## Estimation Patterns')
|
|
85
|
-
lines.push('')
|
|
86
|
-
|
|
87
|
-
for (const p of metrics.underEstimated) {
|
|
88
|
-
lines.push(
|
|
89
|
-
`- ⚠ **${p.category}**: underestimated by avg ${p.avgVariance}% (${p.taskCount} tasks)`
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
for (const p of metrics.overEstimated) {
|
|
93
|
-
lines.push(
|
|
94
|
-
`- ✓ **${p.category}**: overestimated by avg ${p.avgVariance}% (${p.taskCount} tasks)`
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
lines.push('')
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return lines.join('\n')
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// ===========================================================================
|
|
104
|
-
// Domain Methods
|
|
105
|
-
// ===========================================================================
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Save computed velocity metrics.
|
|
109
|
-
*/
|
|
110
|
-
async saveMetrics(projectId: string, metrics: VelocityMetrics): Promise<void> {
|
|
111
|
-
await this.write(projectId, {
|
|
112
|
-
metrics,
|
|
113
|
-
lastUpdated: metrics.lastUpdated,
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
await this.publishEntityEvent(projectId, 'velocity', 'updated', {
|
|
117
|
-
averageVelocity: metrics.averageVelocity,
|
|
118
|
-
trend: metrics.velocityTrend,
|
|
119
|
-
sprintCount: metrics.sprints.length,
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Get current velocity metrics.
|
|
125
|
-
*/
|
|
126
|
-
async getMetrics(projectId: string): Promise<VelocityMetrics> {
|
|
127
|
-
const data = await this.read(projectId)
|
|
128
|
-
return data.metrics
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// =============================================================================
|
|
133
|
-
// Helpers
|
|
134
|
-
// =============================================================================
|
|
135
|
-
|
|
136
|
-
function formatTrendIcon(trend: string): string {
|
|
137
|
-
switch (trend) {
|
|
138
|
-
case 'improving':
|
|
139
|
-
return '↑'
|
|
140
|
-
case 'declining':
|
|
141
|
-
return '↓'
|
|
142
|
-
default:
|
|
143
|
-
return '→'
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export const velocityStorage = new VelocityStorage()
|
|
148
|
-
export default velocityStorage
|
|
149
|
-
export type { VelocityStoreData }
|
package/core/sync/auth-config.ts
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth Config - Manages API key storage for cloud sync
|
|
3
|
-
*
|
|
4
|
-
* Stores credentials in ~/.prjct-cli/config/auth.json
|
|
5
|
-
* Used by SyncClient to authenticate with prjct API
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import path from 'node:path'
|
|
9
|
-
import pathManager from '../infrastructure/path-manager'
|
|
10
|
-
import type { AuthConfig } from '../types'
|
|
11
|
-
import * as fileHelper from '../utils/file-helper'
|
|
12
|
-
|
|
13
|
-
const DEFAULT_API_URL = 'https://api.prjct.app'
|
|
14
|
-
|
|
15
|
-
const DEFAULT_CONFIG: AuthConfig = {
|
|
16
|
-
apiKey: null,
|
|
17
|
-
apiUrl: DEFAULT_API_URL,
|
|
18
|
-
userId: null,
|
|
19
|
-
email: null,
|
|
20
|
-
lastAuth: null,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
class AuthConfigManager {
|
|
24
|
-
private configPath: string
|
|
25
|
-
private cachedConfig: AuthConfig | null = null
|
|
26
|
-
|
|
27
|
-
constructor() {
|
|
28
|
-
this.configPath = pathManager.getAuthConfigPath()
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Get the auth config file path
|
|
33
|
-
*/
|
|
34
|
-
getConfigPath(): string {
|
|
35
|
-
return this.configPath
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Read auth config from disk
|
|
40
|
-
*/
|
|
41
|
-
async read(): Promise<AuthConfig> {
|
|
42
|
-
if (this.cachedConfig) {
|
|
43
|
-
return this.cachedConfig
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const config = await fileHelper.readJson<AuthConfig>(this.configPath)
|
|
47
|
-
this.cachedConfig = config ?? { ...DEFAULT_CONFIG }
|
|
48
|
-
return this.cachedConfig
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Write auth config to disk
|
|
53
|
-
*/
|
|
54
|
-
async write(config: Partial<AuthConfig>): Promise<void> {
|
|
55
|
-
const current = await this.read()
|
|
56
|
-
const updated: AuthConfig = {
|
|
57
|
-
...current,
|
|
58
|
-
...config,
|
|
59
|
-
lastAuth: new Date().toISOString(),
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
await fileHelper.ensureDir(path.dirname(this.configPath))
|
|
63
|
-
await fileHelper.writeJson(this.configPath, updated)
|
|
64
|
-
this.cachedConfig = updated
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Check if user is authenticated (has valid API key)
|
|
69
|
-
*/
|
|
70
|
-
async hasAuth(): Promise<boolean> {
|
|
71
|
-
const config = await this.read()
|
|
72
|
-
return config.apiKey !== null && config.apiKey.length > 0
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Get the API key if available
|
|
77
|
-
*/
|
|
78
|
-
async getApiKey(): Promise<string | null> {
|
|
79
|
-
const config = await this.read()
|
|
80
|
-
return config.apiKey
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Get the API URL (allows override for dev/staging)
|
|
85
|
-
*/
|
|
86
|
-
async getApiUrl(): Promise<string> {
|
|
87
|
-
const config = await this.read()
|
|
88
|
-
return config.apiUrl || DEFAULT_API_URL
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Save API key and user info after successful auth
|
|
93
|
-
*/
|
|
94
|
-
async saveAuth(apiKey: string, userId: string, email: string): Promise<void> {
|
|
95
|
-
await this.write({
|
|
96
|
-
apiKey,
|
|
97
|
-
userId,
|
|
98
|
-
email,
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Clear all auth data (logout)
|
|
104
|
-
*/
|
|
105
|
-
async clearAuth(): Promise<void> {
|
|
106
|
-
this.cachedConfig = { ...DEFAULT_CONFIG }
|
|
107
|
-
await fileHelper.writeJson(this.configPath, this.cachedConfig)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Get auth status for display
|
|
112
|
-
*/
|
|
113
|
-
async getStatus(): Promise<{
|
|
114
|
-
authenticated: boolean
|
|
115
|
-
email: string | null
|
|
116
|
-
apiKeyPrefix: string | null
|
|
117
|
-
lastAuth: string | null
|
|
118
|
-
}> {
|
|
119
|
-
const config = await this.read()
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
authenticated: config.apiKey !== null,
|
|
123
|
-
email: config.email,
|
|
124
|
-
apiKeyPrefix: config.apiKey ? `${config.apiKey.substring(0, 12)}...` : null,
|
|
125
|
-
lastAuth: config.lastAuth,
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Clear cache (useful for testing)
|
|
131
|
-
*/
|
|
132
|
-
clearCache(): void {
|
|
133
|
-
this.cachedConfig = null
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export const authConfig = new AuthConfigManager()
|
|
138
|
-
export default authConfig
|
package/core/sync/index.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sync Module - Cloud synchronization for prjct-cli
|
|
3
|
-
*
|
|
4
|
-
* Provides:
|
|
5
|
-
* - AuthConfig: API key storage and management
|
|
6
|
-
* - SyncClient: HTTP client for prjct API
|
|
7
|
-
* - SyncManager: Orchestrates push/pull operations
|
|
8
|
-
* - OAuthHandler: Authentication flow management
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
// Re-export types from canonical location
|
|
12
|
-
export type {
|
|
13
|
-
AuthConfig,
|
|
14
|
-
AuthResult,
|
|
15
|
-
PullResult,
|
|
16
|
-
PushResult,
|
|
17
|
-
SyncBatchResult,
|
|
18
|
-
SyncClientError,
|
|
19
|
-
SyncManagerResult as SyncResult,
|
|
20
|
-
SyncPullResult,
|
|
21
|
-
SyncStatus,
|
|
22
|
-
} from '../types'
|
|
23
|
-
// Auth
|
|
24
|
-
export { authConfig } from './auth-config'
|
|
25
|
-
// OAuth
|
|
26
|
-
export { oauthHandler } from './oauth-handler'
|
|
27
|
-
// Client
|
|
28
|
-
export { syncClient } from './sync-client'
|
|
29
|
-
// Manager
|
|
30
|
-
// Default export is the main sync manager
|
|
31
|
-
export { syncManager, syncManager as default } from './sync-manager'
|