prjct-cli 0.11.5 → 0.12.1
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 +58 -0
- package/README.md +81 -25
- package/bin/dev.js +1 -1
- package/bin/generate-views.js +209 -0
- package/bin/migrate-to-json.js +742 -0
- package/bin/prjct +5 -5
- package/bin/serve.js +226 -50
- package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
- package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
- package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
- package/core/__tests__/utils/{date-helper.test.js → date-helper.test.ts} +19 -30
- package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
- package/core/agentic/agent-router.ts +137 -0
- package/core/agentic/chain-of-thought.ts +228 -0
- package/core/agentic/command-executor/command-executor.ts +384 -0
- package/core/agentic/command-executor/index.ts +16 -0
- package/core/agentic/command-executor/status-signal.ts +38 -0
- package/core/agentic/command-executor/types.ts +79 -0
- package/core/agentic/command-executor.ts +8 -0
- package/core/agentic/{context-builder.js → context-builder.ts} +92 -81
- package/core/agentic/context-filter.ts +365 -0
- package/core/agentic/ground-truth/index.ts +76 -0
- package/core/agentic/ground-truth/types.ts +33 -0
- package/core/agentic/ground-truth/utils.ts +48 -0
- package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
- package/core/agentic/ground-truth/verifiers/done.ts +75 -0
- package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
- package/core/agentic/ground-truth/verifiers/index.ts +37 -0
- package/core/agentic/ground-truth/verifiers/init.ts +52 -0
- package/core/agentic/ground-truth/verifiers/now.ts +57 -0
- package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
- package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
- package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
- package/core/agentic/ground-truth/verifiers.ts +6 -0
- package/core/agentic/ground-truth.ts +8 -0
- package/core/agentic/loop-detector/error-analysis.ts +97 -0
- package/core/agentic/loop-detector/hallucination.ts +71 -0
- package/core/agentic/loop-detector/index.ts +41 -0
- package/core/agentic/loop-detector/loop-detector.ts +222 -0
- package/core/agentic/loop-detector/types.ts +66 -0
- package/core/agentic/loop-detector.ts +8 -0
- package/core/agentic/memory-system/history.ts +53 -0
- package/core/agentic/memory-system/index.ts +192 -0
- package/core/agentic/memory-system/patterns.ts +156 -0
- package/core/agentic/memory-system/semantic-memories.ts +277 -0
- package/core/agentic/memory-system/session.ts +21 -0
- package/core/agentic/memory-system/types.ts +159 -0
- package/core/agentic/memory-system.ts +8 -0
- package/core/agentic/parallel-tools.ts +165 -0
- package/core/agentic/plan-mode/approval.ts +57 -0
- package/core/agentic/plan-mode/constants.ts +44 -0
- package/core/agentic/plan-mode/index.ts +28 -0
- package/core/agentic/plan-mode/plan-mode.ts +406 -0
- package/core/agentic/plan-mode/types.ts +193 -0
- package/core/agentic/plan-mode.ts +8 -0
- package/core/agentic/prompt-builder.ts +566 -0
- package/core/agentic/response-templates.ts +164 -0
- package/core/agentic/semantic-compression.ts +273 -0
- package/core/agentic/services.ts +206 -0
- package/core/agentic/smart-context.ts +476 -0
- package/core/agentic/{template-loader.js → template-loader.ts} +27 -16
- package/core/agentic/think-blocks.ts +202 -0
- package/core/agentic/tool-registry.ts +119 -0
- package/core/agentic/validation-rules.ts +313 -0
- package/core/agents/index.ts +28 -0
- package/core/agents/performance.ts +444 -0
- package/core/agents/types.ts +126 -0
- package/core/bus/{index.js → index.ts} +57 -61
- package/core/command-registry/categories.ts +23 -0
- package/core/command-registry/commands.ts +15 -0
- package/core/command-registry/core-commands.ts +319 -0
- package/core/command-registry/index.ts +158 -0
- package/core/command-registry/optional-commands.ts +119 -0
- package/core/command-registry/setup-commands.ts +53 -0
- package/core/command-registry/types.ts +59 -0
- package/core/command-registry.ts +9 -0
- package/core/commands/analysis.ts +298 -0
- package/core/commands/analytics.ts +288 -0
- package/core/commands/base.ts +273 -0
- package/core/commands/index.ts +211 -0
- package/core/commands/maintenance.ts +226 -0
- package/core/commands/planning.ts +311 -0
- package/core/commands/setup.ts +309 -0
- package/core/commands/shipping.ts +188 -0
- package/core/commands/types.ts +183 -0
- package/core/commands/workflow.ts +226 -0
- package/core/commands.ts +11 -0
- package/core/constants/formats.ts +187 -0
- package/core/constants/index.ts +7 -0
- package/core/{context-sync.js → context-sync.ts} +59 -26
- package/core/data/agents-manager.ts +76 -0
- package/core/data/analysis-manager.ts +83 -0
- package/core/data/base-manager.ts +156 -0
- package/core/data/ideas-manager.ts +81 -0
- package/core/data/index.ts +32 -0
- package/core/data/outcomes-manager.ts +96 -0
- package/core/data/project-manager.ts +75 -0
- package/core/data/roadmap-manager.ts +118 -0
- package/core/data/shipped-manager.ts +65 -0
- package/core/data/state-manager.ts +214 -0
- package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
- package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
- package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
- package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
- package/core/domain/{analyzer.js → analyzer.ts} +91 -85
- package/core/domain/{architect-session.js → architect-session.ts} +49 -34
- package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
- package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
- package/core/domain/{product-standards.js → product-standards.ts} +40 -26
- package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
- package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
- package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
- package/core/domain/task-stack/index.ts +19 -0
- package/core/domain/task-stack/parser.ts +86 -0
- package/core/domain/task-stack/storage.ts +123 -0
- package/core/domain/task-stack/task-stack.ts +340 -0
- package/core/domain/task-stack/types.ts +51 -0
- package/core/domain/task-stack.ts +8 -0
- package/core/{index.js → index.ts} +61 -18
- package/core/infrastructure/{agent-detector.js → agent-detector.ts} +55 -19
- package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
- package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
- package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
- package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
- package/core/infrastructure/command-installer/global-config.ts +106 -0
- package/core/infrastructure/command-installer/index.ts +25 -0
- package/core/infrastructure/command-installer/types.ts +41 -0
- package/core/infrastructure/command-installer.ts +8 -0
- package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
- package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
- package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
- package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
- package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
- package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
- package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
- package/core/infrastructure/legacy-installer-detector.ts +7 -0
- package/core/infrastructure/migrator/file-operations.ts +125 -0
- package/core/infrastructure/migrator/index.ts +288 -0
- package/core/infrastructure/migrator/project-scanner.ts +89 -0
- package/core/infrastructure/migrator/reports.ts +117 -0
- package/core/infrastructure/migrator/types.ts +124 -0
- package/core/infrastructure/migrator/validation.ts +94 -0
- package/core/infrastructure/migrator/version-migration.ts +117 -0
- package/core/infrastructure/migrator.ts +10 -0
- package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
- package/core/infrastructure/session-manager/index.ts +23 -0
- package/core/infrastructure/session-manager/migration.ts +88 -0
- package/core/infrastructure/session-manager/session-manager.ts +307 -0
- package/core/infrastructure/session-manager/types.ts +45 -0
- package/core/infrastructure/session-manager.ts +8 -0
- package/core/infrastructure/{setup.js → setup.ts} +29 -21
- package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
- package/core/outcomes/analyzer.ts +333 -0
- package/core/outcomes/index.ts +34 -0
- package/core/outcomes/recorder.ts +194 -0
- package/core/outcomes/types.ts +145 -0
- package/core/plugin/{hooks.js → hooks.ts} +56 -58
- package/core/plugin/{index.js → index.ts} +19 -8
- package/core/plugin/{loader.js → loader.ts} +87 -69
- package/core/plugin/{registry.js → registry.ts} +49 -45
- package/core/plugins/{webhook.js → webhook.ts} +43 -27
- package/core/schemas/agents.ts +27 -0
- package/core/schemas/analysis.ts +41 -0
- package/core/schemas/ideas.ts +83 -0
- package/core/schemas/index.ts +73 -0
- package/core/schemas/outcomes.ts +22 -0
- package/core/schemas/project.ts +26 -0
- package/core/schemas/roadmap.ts +90 -0
- package/core/schemas/shipped.ts +82 -0
- package/core/schemas/state.ts +107 -0
- package/core/session/index.ts +17 -0
- package/core/session/{metrics.js → metrics.ts} +64 -46
- package/core/session/{index.js → session-manager.ts} +51 -117
- package/core/session/types.ts +29 -0
- package/core/session/utils.ts +57 -0
- package/core/state/index.ts +25 -0
- package/core/state/manager.ts +376 -0
- package/core/state/types.ts +185 -0
- package/core/tsconfig.json +22 -0
- package/core/types/index.ts +506 -0
- package/core/utils/{animations.js → animations.ts} +74 -28
- package/core/utils/{branding.js → branding.ts} +29 -4
- package/core/utils/{date-helper.js → date-helper.ts} +31 -74
- package/core/utils/file-helper.ts +262 -0
- package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
- package/core/utils/{logger.js → logger.ts} +24 -12
- package/core/utils/{output.js → output.ts} +25 -13
- package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
- package/core/utils/{session-helper.js → session-helper.ts} +79 -66
- package/core/utils/{version.js → version.ts} +23 -31
- package/core/view-generator.ts +536 -0
- package/package.json +23 -17
- package/packages/shared/.turbo/turbo-build.log +14 -0
- package/packages/shared/dist/index.d.ts +8 -613
- package/packages/shared/dist/index.d.ts.map +1 -0
- package/packages/shared/dist/index.js +4110 -118
- package/packages/shared/dist/schemas.d.ts +408 -0
- package/packages/shared/dist/schemas.d.ts.map +1 -0
- package/packages/shared/dist/types.d.ts +144 -0
- package/packages/shared/dist/types.d.ts.map +1 -0
- package/packages/shared/dist/unified.d.ts +139 -0
- package/packages/shared/dist/unified.d.ts.map +1 -0
- package/packages/shared/dist/utils.d.ts +60 -0
- package/packages/shared/dist/utils.d.ts.map +1 -0
- package/packages/shared/package.json +4 -4
- package/packages/shared/src/index.ts +1 -0
- package/packages/shared/src/unified.ts +174 -0
- package/packages/web/app/api/claude/sessions/route.ts +1 -1
- package/packages/web/app/api/claude/status/route.ts +1 -1
- package/packages/web/app/api/migrate/route.ts +46 -0
- package/packages/web/app/api/projects/[id]/route.ts +1 -1
- package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
- package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
- package/packages/web/app/api/projects/route.ts +1 -1
- package/packages/web/app/api/settings/route.ts +97 -0
- package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
- package/packages/web/app/globals.css +38 -0
- package/packages/web/app/layout.tsx +10 -2
- package/packages/web/app/page.tsx +9 -224
- package/packages/web/app/project/[id]/page.tsx +191 -63
- package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
- package/packages/web/app/project/[id]/stats/page.tsx +204 -163
- package/packages/web/app/settings/page.tsx +222 -2
- package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
- package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
- package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
- package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
- package/packages/web/components/ActivityTimeline/index.ts +2 -0
- package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
- package/packages/web/components/AgentsCard/index.ts +2 -0
- package/packages/web/components/AppSidebar/AppSidebar.tsx +190 -0
- package/packages/web/components/AppSidebar/index.ts +1 -0
- package/packages/web/components/BackLink/BackLink.tsx +18 -0
- package/packages/web/components/BackLink/BackLink.types.ts +5 -0
- package/packages/web/components/BackLink/index.ts +2 -0
- package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
- package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
- package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
- package/packages/web/components/BentoCard/index.ts +2 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
- package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
- package/packages/web/components/{stats → BentoGrid}/BentoGrid.tsx +4 -8
- package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
- package/packages/web/components/BentoGrid/index.ts +2 -0
- package/packages/web/components/CommandButton/index.ts +1 -0
- package/packages/web/components/ConnectionStatus/index.ts +1 -0
- package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
- package/packages/web/components/DashboardContent/index.ts +1 -0
- package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
- package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
- package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
- package/packages/web/components/DateGroup/index.ts +2 -0
- package/packages/web/components/{stats → EmptyState}/EmptyState.tsx +1 -10
- package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
- package/packages/web/components/EmptyState/index.ts +2 -0
- package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
- package/packages/web/components/EventRow/EventRow.tsx +49 -0
- package/packages/web/components/EventRow/EventRow.types.ts +7 -0
- package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
- package/packages/web/components/EventRow/index.ts +2 -0
- package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
- package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
- package/packages/web/components/ExpandButton/index.ts +2 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
- package/packages/web/components/HealthGradientBackground/index.ts +2 -0
- package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
- package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
- package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
- package/packages/web/components/HeroSection/hooks/index.ts +2 -0
- package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
- package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
- package/packages/web/components/HeroSection/index.ts +2 -0
- package/packages/web/components/{stats → IdeasCard}/IdeasCard.tsx +3 -14
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
- package/packages/web/components/IdeasCard/index.ts +2 -0
- package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
- package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
- package/packages/web/components/InsightMessage/index.ts +2 -0
- package/packages/web/components/Logo/index.ts +1 -0
- package/packages/web/components/MarkdownContent/index.ts +1 -0
- package/packages/web/components/NowCard/NowCard.tsx +93 -0
- package/packages/web/components/NowCard/NowCard.types.ts +15 -0
- package/packages/web/components/NowCard/index.ts +2 -0
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
- package/packages/web/components/{stats → ProgressRing}/ProgressRing.tsx +4 -27
- package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
- package/packages/web/components/ProgressRing/index.ts +2 -0
- package/packages/web/components/ProjectAvatar/index.ts +1 -0
- package/packages/web/components/Providers/index.ts +1 -0
- package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
- package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
- package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
- package/packages/web/components/QueueCard/index.ts +2 -0
- package/packages/web/components/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
- package/packages/web/components/RoadmapCard/index.ts +2 -0
- package/packages/web/components/{stats → ShipsCard}/ShipsCard.tsx +4 -22
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
- package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
- package/packages/web/components/ShipsCard/index.ts +2 -0
- package/packages/web/components/{stats → SparklineChart}/SparklineChart.tsx +1 -7
- package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
- package/packages/web/components/SparklineChart/index.ts +2 -0
- package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
- package/packages/web/components/{stats → StreakCard}/StreakCard.tsx +5 -11
- package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
- package/packages/web/components/StreakCard/index.ts +2 -0
- package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
- package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
- package/packages/web/components/TasksCounter/index.ts +2 -0
- package/packages/web/components/TechStackBadges/index.ts +1 -0
- package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
- package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
- package/packages/web/components/TerminalTabs/index.ts +1 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
- package/packages/web/components/VelocityBadge/index.ts +2 -0
- package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
- package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
- package/packages/web/components/VelocityCard/index.ts +2 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
- package/packages/web/components/WeeklySparkline/index.ts +2 -0
- package/packages/web/components/ui/input.tsx +21 -0
- package/packages/web/context/TerminalTabsContext.tsx +46 -1
- package/packages/web/hooks/useClaudeTerminal.ts +71 -21
- package/packages/web/hooks/useProjectStats.ts +55 -0
- package/packages/web/hooks/useProjects.ts +6 -6
- package/packages/web/lib/actions/projects.ts +15 -0
- package/packages/web/lib/json-loader.ts +630 -0
- package/packages/web/lib/services/index.ts +9 -0
- package/packages/web/lib/services/migration.server.ts +600 -0
- package/packages/web/lib/services/projects.server.ts +52 -0
- package/packages/web/lib/services/stats.server.ts +264 -0
- package/packages/web/lib/unified-loader.ts +396 -0
- package/packages/web/package.json +10 -7
- package/packages/web/server.ts +58 -8
- package/templates/commands/done.md +76 -32
- package/templates/commands/feature.md +121 -47
- package/templates/commands/idea.md +81 -8
- package/templates/commands/now.md +41 -17
- package/templates/commands/ship.md +64 -25
- package/templates/commands/sync.md +28 -3
- package/core/agentic/agent-router.js +0 -140
- package/core/agentic/chain-of-thought.js +0 -578
- package/core/agentic/command-executor.js +0 -417
- package/core/agentic/context-filter.js +0 -354
- package/core/agentic/ground-truth.js +0 -591
- package/core/agentic/loop-detector.js +0 -406
- package/core/agentic/memory-system.js +0 -845
- package/core/agentic/parallel-tools.js +0 -366
- package/core/agentic/plan-mode.js +0 -572
- package/core/agentic/prompt-builder.js +0 -352
- package/core/agentic/response-templates.js +0 -290
- package/core/agentic/semantic-compression.js +0 -517
- package/core/agentic/think-blocks.js +0 -657
- package/core/agentic/tool-registry.js +0 -184
- package/core/agentic/validation-rules.js +0 -380
- package/core/command-registry.js +0 -698
- package/core/commands.js +0 -2237
- package/core/domain/task-stack.js +0 -497
- package/core/infrastructure/legacy-installer-detector.js +0 -546
- package/core/infrastructure/migrator.js +0 -796
- package/core/infrastructure/session-manager.js +0 -390
- package/core/utils/file-helper.js +0 -329
- package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
- package/packages/web/app/api/stats/route.ts +0 -38
- package/packages/web/components/AppSidebar.tsx +0 -113
- package/packages/web/components/stats/ActivityTimeline.tsx +0 -201
- package/packages/web/components/stats/AgentsCard.tsx +0 -56
- package/packages/web/components/stats/BentoCard.tsx +0 -88
- package/packages/web/components/stats/HeroSection.tsx +0 -172
- package/packages/web/components/stats/NowCard.tsx +0 -71
- package/packages/web/components/stats/QueueCard.tsx +0 -58
- package/packages/web/components/stats/VelocityCard.tsx +0 -60
- package/packages/web/components/stats/index.ts +0 -17
- package/packages/web/hooks/useStats.ts +0 -28
- /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
- /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
- /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
- /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
- /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
- /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
- /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
|
@@ -3,12 +3,36 @@
|
|
|
3
3
|
* Single source of truth for all branding across CLI and Claude Code
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import chalk from 'chalk'
|
|
7
7
|
|
|
8
8
|
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
9
9
|
const SPINNER_SPEED = 80
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
interface Branding {
|
|
12
|
+
name: string
|
|
13
|
+
icon: string
|
|
14
|
+
signature: string
|
|
15
|
+
spinner: {
|
|
16
|
+
frames: string[]
|
|
17
|
+
speed: number
|
|
18
|
+
}
|
|
19
|
+
cli: {
|
|
20
|
+
header: () => string
|
|
21
|
+
footer: () => string
|
|
22
|
+
spin: (frame: number, msg?: string) => string
|
|
23
|
+
}
|
|
24
|
+
template: {
|
|
25
|
+
header: string
|
|
26
|
+
footer: string
|
|
27
|
+
}
|
|
28
|
+
commitFooter: string
|
|
29
|
+
urls: {
|
|
30
|
+
website: string
|
|
31
|
+
docs: string
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const branding: Branding = {
|
|
12
36
|
// Core identity
|
|
13
37
|
name: 'prjct',
|
|
14
38
|
icon: '⚡',
|
|
@@ -24,7 +48,8 @@ const branding = {
|
|
|
24
48
|
cli: {
|
|
25
49
|
header: () => chalk.cyan.bold('⚡') + ' ' + chalk.cyan('prjct'),
|
|
26
50
|
footer: () => chalk.dim('⚡ prjct'),
|
|
27
|
-
spin: (frame, msg) =>
|
|
51
|
+
spin: (frame: number, msg?: string) =>
|
|
52
|
+
chalk.cyan('⚡') + ' ' + chalk.cyan('prjct') + ' ' + chalk.cyan(SPINNER_FRAMES[frame % 10]) + ' ' + chalk.dim(msg || '')
|
|
28
53
|
},
|
|
29
54
|
|
|
30
55
|
// Template/Claude (plain text)
|
|
@@ -44,4 +69,4 @@ Designed for [Claude](https://www.anthropic.com/claude)`,
|
|
|
44
69
|
}
|
|
45
70
|
}
|
|
46
71
|
|
|
47
|
-
|
|
72
|
+
export default branding
|
|
@@ -2,20 +2,21 @@
|
|
|
2
2
|
* Date Helper - Centralized date operations and formatting
|
|
3
3
|
*
|
|
4
4
|
* Eliminates duplicated date logic across:
|
|
5
|
-
* - session-manager.
|
|
6
|
-
* - path-manager.
|
|
7
|
-
* - commands.
|
|
8
|
-
*
|
|
9
|
-
* @module date-helper
|
|
5
|
+
* - session-manager.ts (_getDateKey, _getTodayKey)
|
|
6
|
+
* - path-manager.ts (getSessionPath date formatting)
|
|
7
|
+
* - commands.ts (38+ inline date operations)
|
|
10
8
|
*/
|
|
11
9
|
|
|
10
|
+
export interface DateComponents {
|
|
11
|
+
year: string
|
|
12
|
+
month: string
|
|
13
|
+
day: string
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
/**
|
|
13
17
|
* Format a date to YYYY-MM-DD format
|
|
14
|
-
*
|
|
15
|
-
* @param {Date} date - Date to format
|
|
16
|
-
* @returns {string} - Formatted date string (e.g., "2025-10-04")
|
|
17
18
|
*/
|
|
18
|
-
function formatDate(date) {
|
|
19
|
+
export function formatDate(date: Date): string {
|
|
19
20
|
const year = date.getFullYear()
|
|
20
21
|
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
|
21
22
|
const day = date.getDate().toString().padStart(2, '0')
|
|
@@ -24,11 +25,8 @@ function formatDate(date) {
|
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Format a date to YYYY-MM format
|
|
27
|
-
*
|
|
28
|
-
* @param {Date} date - Date to format
|
|
29
|
-
* @returns {string} - Formatted month string (e.g., "2025-10")
|
|
30
28
|
*/
|
|
31
|
-
function formatMonth(date) {
|
|
29
|
+
export function formatMonth(date: Date): string {
|
|
32
30
|
const year = date.getFullYear()
|
|
33
31
|
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
|
34
32
|
return `${year}-${month}`
|
|
@@ -36,32 +34,24 @@ function formatMonth(date) {
|
|
|
36
34
|
|
|
37
35
|
/**
|
|
38
36
|
* Get date key for today (YYYY-MM-DD)
|
|
39
|
-
*
|
|
40
|
-
* @returns {string} - Today's date key
|
|
41
37
|
*/
|
|
42
|
-
function getTodayKey() {
|
|
38
|
+
export function getTodayKey(): string {
|
|
43
39
|
return formatDate(new Date())
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
/**
|
|
47
43
|
* Get date key for any date (YYYY-MM-DD)
|
|
48
44
|
* Alias for formatDate for consistency with session-manager
|
|
49
|
-
*
|
|
50
|
-
* @param {Date} date - Date to format
|
|
51
|
-
* @returns {string} - Date key (e.g., "2025-10-04")
|
|
52
45
|
*/
|
|
53
|
-
function getDateKey(date) {
|
|
46
|
+
export function getDateKey(date: Date): string {
|
|
54
47
|
return formatDate(date)
|
|
55
48
|
}
|
|
56
49
|
|
|
57
50
|
/**
|
|
58
51
|
* Get year, month, day components from a date
|
|
59
52
|
* Useful for path construction
|
|
60
|
-
*
|
|
61
|
-
* @param {Date} date - Date to parse
|
|
62
|
-
* @returns {{year: string, month: string, day: string}} - Date components
|
|
63
53
|
*/
|
|
64
|
-
function getYearMonthDay(date) {
|
|
54
|
+
export function getYearMonthDay(date: Date): DateComponents {
|
|
65
55
|
return {
|
|
66
56
|
year: date.getFullYear().toString(),
|
|
67
57
|
month: (date.getMonth() + 1).toString().padStart(2, '0'),
|
|
@@ -72,30 +62,22 @@ function getYearMonthDay(date) {
|
|
|
72
62
|
/**
|
|
73
63
|
* Parse a date string to Date object
|
|
74
64
|
* Supports: YYYY-MM-DD, YYYY-MM, ISO strings
|
|
75
|
-
*
|
|
76
|
-
* @param {string} dateString - Date string to parse
|
|
77
|
-
* @returns {Date} - Parsed date
|
|
78
65
|
*/
|
|
79
|
-
function parseDate(dateString) {
|
|
66
|
+
export function parseDate(dateString: string): Date {
|
|
80
67
|
return new Date(dateString)
|
|
81
68
|
}
|
|
82
69
|
|
|
83
70
|
/**
|
|
84
71
|
* Get current timestamp in ISO format
|
|
85
|
-
*
|
|
86
|
-
* @returns {string} - ISO timestamp (e.g., "2025-10-04T14:30:00.000Z")
|
|
87
72
|
*/
|
|
88
|
-
function getTimestamp() {
|
|
73
|
+
export function getTimestamp(): string {
|
|
89
74
|
return new Date().toISOString()
|
|
90
75
|
}
|
|
91
76
|
|
|
92
77
|
/**
|
|
93
78
|
* Get date N days ago from today
|
|
94
|
-
*
|
|
95
|
-
* @param {number} days - Number of days to subtract
|
|
96
|
-
* @returns {Date} - Date in the past
|
|
97
79
|
*/
|
|
98
|
-
function getDaysAgo(days) {
|
|
80
|
+
export function getDaysAgo(days: number): Date {
|
|
99
81
|
const date = new Date()
|
|
100
82
|
date.setDate(date.getDate() - days)
|
|
101
83
|
return date
|
|
@@ -103,11 +85,8 @@ function getDaysAgo(days) {
|
|
|
103
85
|
|
|
104
86
|
/**
|
|
105
87
|
* Get date N days from today
|
|
106
|
-
*
|
|
107
|
-
* @param {number} days - Number of days to add
|
|
108
|
-
* @returns {Date} - Date in the future
|
|
109
88
|
*/
|
|
110
|
-
function getDaysFromNow(days) {
|
|
89
|
+
export function getDaysFromNow(days: number): Date {
|
|
111
90
|
const date = new Date()
|
|
112
91
|
date.setDate(date.getDate() + days)
|
|
113
92
|
return date
|
|
@@ -115,13 +94,9 @@ function getDaysFromNow(days) {
|
|
|
115
94
|
|
|
116
95
|
/**
|
|
117
96
|
* Get date range between two dates
|
|
118
|
-
*
|
|
119
|
-
* @param {Date} fromDate - Start date
|
|
120
|
-
* @param {Date} toDate - End date
|
|
121
|
-
* @returns {Array<Date>} - Array of dates in range
|
|
122
97
|
*/
|
|
123
|
-
function getDateRange(fromDate, toDate) {
|
|
124
|
-
const dates = []
|
|
98
|
+
export function getDateRange(fromDate: Date, toDate: Date): Date[] {
|
|
99
|
+
const dates: Date[] = []
|
|
125
100
|
let current = new Date(fromDate)
|
|
126
101
|
|
|
127
102
|
while (current <= toDate) {
|
|
@@ -138,33 +113,23 @@ function getDateRange(fromDate, toDate) {
|
|
|
138
113
|
|
|
139
114
|
/**
|
|
140
115
|
* Check if a date is today
|
|
141
|
-
*
|
|
142
|
-
* @param {Date} date - Date to check
|
|
143
|
-
* @returns {boolean} - True if date is today
|
|
144
116
|
*/
|
|
145
|
-
function isToday(date) {
|
|
117
|
+
export function isToday(date: Date): boolean {
|
|
146
118
|
return formatDate(date) === getTodayKey()
|
|
147
119
|
}
|
|
148
120
|
|
|
149
121
|
/**
|
|
150
122
|
* Check if a date is within the last N days
|
|
151
|
-
*
|
|
152
|
-
* @param {Date} date - Date to check
|
|
153
|
-
* @param {number} days - Number of days
|
|
154
|
-
* @returns {boolean} - True if within range
|
|
155
123
|
*/
|
|
156
|
-
function isWithinLastDays(date, days) {
|
|
124
|
+
export function isWithinLastDays(date: Date, days: number): boolean {
|
|
157
125
|
const threshold = getDaysAgo(days)
|
|
158
126
|
return date >= threshold
|
|
159
127
|
}
|
|
160
128
|
|
|
161
129
|
/**
|
|
162
130
|
* Format duration in human-readable format
|
|
163
|
-
*
|
|
164
|
-
* @param {number} milliseconds - Duration in ms
|
|
165
|
-
* @returns {string} - Formatted duration (e.g., "2h 15m")
|
|
166
131
|
*/
|
|
167
|
-
function formatDuration(milliseconds) {
|
|
132
|
+
export function formatDuration(milliseconds: number): string {
|
|
168
133
|
const seconds = Math.floor(milliseconds / 1000)
|
|
169
134
|
const minutes = Math.floor(seconds / 60)
|
|
170
135
|
const hours = Math.floor(minutes / 60)
|
|
@@ -184,23 +149,16 @@ function formatDuration(milliseconds) {
|
|
|
184
149
|
|
|
185
150
|
/**
|
|
186
151
|
* Calculate duration between two dates
|
|
187
|
-
*
|
|
188
|
-
* @param {Date} startDate - Start date
|
|
189
|
-
* @param {Date} endDate - End date (defaults to now)
|
|
190
|
-
* @returns {string} - Formatted duration
|
|
191
152
|
*/
|
|
192
|
-
function calculateDuration(startDate, endDate = new Date()) {
|
|
193
|
-
const milliseconds = endDate - startDate
|
|
153
|
+
export function calculateDuration(startDate: Date, endDate: Date = new Date()): string {
|
|
154
|
+
const milliseconds = endDate.getTime() - startDate.getTime()
|
|
194
155
|
return formatDuration(milliseconds)
|
|
195
156
|
}
|
|
196
157
|
|
|
197
158
|
/**
|
|
198
159
|
* Get start of day (00:00:00.000)
|
|
199
|
-
*
|
|
200
|
-
* @param {Date} date - Date to process
|
|
201
|
-
* @returns {Date} - Start of day
|
|
202
160
|
*/
|
|
203
|
-
function getStartOfDay(date) {
|
|
161
|
+
export function getStartOfDay(date: Date): Date {
|
|
204
162
|
const result = new Date(date)
|
|
205
163
|
result.setHours(0, 0, 0, 0)
|
|
206
164
|
return result
|
|
@@ -208,17 +166,15 @@ function getStartOfDay(date) {
|
|
|
208
166
|
|
|
209
167
|
/**
|
|
210
168
|
* Get end of day (23:59:59.999)
|
|
211
|
-
*
|
|
212
|
-
* @param {Date} date - Date to process
|
|
213
|
-
* @returns {Date} - End of day
|
|
214
169
|
*/
|
|
215
|
-
function getEndOfDay(date) {
|
|
170
|
+
export function getEndOfDay(date: Date): Date {
|
|
216
171
|
const result = new Date(date)
|
|
217
172
|
result.setHours(23, 59, 59, 999)
|
|
218
173
|
return result
|
|
219
174
|
}
|
|
220
175
|
|
|
221
|
-
|
|
176
|
+
// Default export for CommonJS compatibility
|
|
177
|
+
export default {
|
|
222
178
|
formatDate,
|
|
223
179
|
formatMonth,
|
|
224
180
|
getTodayKey,
|
|
@@ -234,5 +190,6 @@ module.exports = {
|
|
|
234
190
|
formatDuration,
|
|
235
191
|
calculateDuration,
|
|
236
192
|
getStartOfDay,
|
|
237
|
-
getEndOfDay
|
|
193
|
+
getEndOfDay
|
|
238
194
|
}
|
|
195
|
+
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import fs from 'fs/promises'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* File Helper - Centralized file operations with error handling
|
|
6
|
+
*
|
|
7
|
+
* Eliminates duplicated fs operations across:
|
|
8
|
+
* - 101 fs.readFile/writeFile calls in 18 files
|
|
9
|
+
* - Consistent error handling
|
|
10
|
+
* - JSON read/write patterns
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface ListFilesOptions {
|
|
14
|
+
filesOnly?: boolean
|
|
15
|
+
dirsOnly?: boolean
|
|
16
|
+
extension?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface NodeError extends Error {
|
|
20
|
+
code?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Read JSON file and parse
|
|
25
|
+
*/
|
|
26
|
+
export async function readJson<T = unknown>(filePath: string, defaultValue: T | null = null): Promise<T | null> {
|
|
27
|
+
try {
|
|
28
|
+
const content = await fs.readFile(filePath, 'utf-8')
|
|
29
|
+
return JSON.parse(content) as T
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if ((error as NodeError).code === 'ENOENT') {
|
|
32
|
+
return defaultValue
|
|
33
|
+
}
|
|
34
|
+
throw error
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Write object to JSON file (pretty-printed)
|
|
40
|
+
*/
|
|
41
|
+
export async function writeJson(filePath: string, data: unknown, indent = 2): Promise<void> {
|
|
42
|
+
const content = JSON.stringify(data, null, indent)
|
|
43
|
+
await fs.writeFile(filePath, content, 'utf-8')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Read text file
|
|
48
|
+
*/
|
|
49
|
+
export async function readFile(filePath: string, defaultValue = ''): Promise<string> {
|
|
50
|
+
try {
|
|
51
|
+
return await fs.readFile(filePath, 'utf-8')
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if ((error as NodeError).code === 'ENOENT') {
|
|
54
|
+
return defaultValue
|
|
55
|
+
}
|
|
56
|
+
throw error
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Write text file
|
|
62
|
+
*/
|
|
63
|
+
export async function writeFile(filePath: string, content: string): Promise<void> {
|
|
64
|
+
const dir = path.dirname(filePath)
|
|
65
|
+
await fs.mkdir(dir, { recursive: true })
|
|
66
|
+
await fs.writeFile(filePath, content, 'utf-8')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Append to text file
|
|
71
|
+
*/
|
|
72
|
+
export async function appendToFile(filePath: string, content: string): Promise<void> {
|
|
73
|
+
await fs.appendFile(filePath, content, 'utf-8')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Prepend to text file (adds content at beginning)
|
|
78
|
+
*/
|
|
79
|
+
export async function prependToFile(filePath: string, content: string): Promise<void> {
|
|
80
|
+
try {
|
|
81
|
+
const existing = await fs.readFile(filePath, 'utf-8')
|
|
82
|
+
await fs.writeFile(filePath, content + existing, 'utf-8')
|
|
83
|
+
} catch (error) {
|
|
84
|
+
if ((error as NodeError).code === 'ENOENT') {
|
|
85
|
+
await fs.writeFile(filePath, content, 'utf-8')
|
|
86
|
+
} else {
|
|
87
|
+
throw error
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Check if file exists
|
|
94
|
+
*/
|
|
95
|
+
export async function fileExists(filePath: string): Promise<boolean> {
|
|
96
|
+
try {
|
|
97
|
+
await fs.access(filePath)
|
|
98
|
+
return true
|
|
99
|
+
} catch {
|
|
100
|
+
return false
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if directory exists
|
|
106
|
+
*/
|
|
107
|
+
export async function dirExists(dirPath: string): Promise<boolean> {
|
|
108
|
+
try {
|
|
109
|
+
const stats = await fs.stat(dirPath)
|
|
110
|
+
return stats.isDirectory()
|
|
111
|
+
} catch {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Ensure directory exists (create if not)
|
|
118
|
+
*/
|
|
119
|
+
export async function ensureDir(dirPath: string): Promise<void> {
|
|
120
|
+
await fs.mkdir(dirPath, { recursive: true })
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Delete file if it exists
|
|
125
|
+
*/
|
|
126
|
+
export async function deleteFile(filePath: string): Promise<boolean> {
|
|
127
|
+
try {
|
|
128
|
+
await fs.unlink(filePath)
|
|
129
|
+
return true
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if ((error as NodeError).code === 'ENOENT') {
|
|
132
|
+
return false // File didn't exist
|
|
133
|
+
}
|
|
134
|
+
throw error
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Delete directory and all contents
|
|
140
|
+
*/
|
|
141
|
+
export async function deleteDir(dirPath: string): Promise<boolean> {
|
|
142
|
+
try {
|
|
143
|
+
await fs.rm(dirPath, { recursive: true, force: true })
|
|
144
|
+
return true
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if ((error as NodeError).code === 'ENOENT') {
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
throw error
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* List files in directory
|
|
155
|
+
*/
|
|
156
|
+
export async function listFiles(dirPath: string, options: ListFilesOptions = {}): Promise<string[]> {
|
|
157
|
+
try {
|
|
158
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true })
|
|
159
|
+
let files = entries
|
|
160
|
+
|
|
161
|
+
if (options.filesOnly) {
|
|
162
|
+
files = files.filter((entry) => entry.isFile())
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (options.dirsOnly) {
|
|
166
|
+
files = files.filter((entry) => entry.isDirectory())
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (options.extension) {
|
|
170
|
+
files = files.filter((entry) => entry.name.endsWith(options.extension!))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return files.map((entry) => entry.name)
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if ((error as NodeError).code === 'ENOENT') {
|
|
176
|
+
return []
|
|
177
|
+
}
|
|
178
|
+
throw error
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Get file size in bytes
|
|
184
|
+
*/
|
|
185
|
+
export async function getFileSize(filePath: string): Promise<number> {
|
|
186
|
+
const stats = await fs.stat(filePath)
|
|
187
|
+
return stats.size
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get file modification time
|
|
192
|
+
*/
|
|
193
|
+
export async function getFileModifiedTime(filePath: string): Promise<Date> {
|
|
194
|
+
const stats = await fs.stat(filePath)
|
|
195
|
+
return stats.mtime
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Copy file
|
|
200
|
+
*/
|
|
201
|
+
export async function copyFile(sourcePath: string, destPath: string): Promise<void> {
|
|
202
|
+
await fs.copyFile(sourcePath, destPath)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Move/rename file
|
|
207
|
+
*/
|
|
208
|
+
export async function moveFile(oldPath: string, newPath: string): Promise<void> {
|
|
209
|
+
await fs.rename(oldPath, newPath)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Read file and split into lines
|
|
214
|
+
*/
|
|
215
|
+
export async function readLines(filePath: string): Promise<string[]> {
|
|
216
|
+
const content = await readFile(filePath, '')
|
|
217
|
+
return content.split('\n')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Write lines to file
|
|
222
|
+
*/
|
|
223
|
+
export async function writeLines(filePath: string, lines: string[]): Promise<void> {
|
|
224
|
+
const content = lines.join('\n')
|
|
225
|
+
await writeFile(filePath, content)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Get file extension
|
|
230
|
+
*/
|
|
231
|
+
export function getFileExtension(filePath: string): string {
|
|
232
|
+
return path.extname(filePath)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Get filename without extension
|
|
237
|
+
*/
|
|
238
|
+
export function getFileNameWithoutExtension(filePath: string): string {
|
|
239
|
+
return path.basename(filePath, path.extname(filePath))
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Default export for CommonJS compatibility
|
|
243
|
+
export default {
|
|
244
|
+
readJson,
|
|
245
|
+
writeJson,
|
|
246
|
+
readFile,
|
|
247
|
+
writeFile,
|
|
248
|
+
fileExists,
|
|
249
|
+
ensureDir,
|
|
250
|
+
deleteFile,
|
|
251
|
+
deleteDir,
|
|
252
|
+
listFiles,
|
|
253
|
+
getFileSize,
|
|
254
|
+
getFileModifiedTime,
|
|
255
|
+
copyFile,
|
|
256
|
+
moveFile,
|
|
257
|
+
readLines,
|
|
258
|
+
writeLines,
|
|
259
|
+
getFileExtension,
|
|
260
|
+
getFileNameWithoutExtension
|
|
261
|
+
}
|
|
262
|
+
|