prjct-cli 0.13.3 → 0.15.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 +106 -0
- package/bin/prjct +10 -13
- package/core/agentic/memory-system/semantic-memories.ts +2 -1
- package/core/agentic/plan-mode/plan-mode.ts +2 -1
- package/core/agentic/prompt-builder.ts +22 -43
- package/core/agentic/services.ts +5 -5
- package/core/agentic/smart-context.ts +7 -2
- package/core/command-registry/core-commands.ts +54 -29
- package/core/command-registry/optional-commands.ts +64 -0
- package/core/command-registry/setup-commands.ts +18 -3
- package/core/commands/analysis.ts +21 -68
- package/core/commands/analytics.ts +247 -213
- package/core/commands/base.ts +1 -1
- package/core/commands/index.ts +41 -36
- package/core/commands/maintenance.ts +300 -31
- package/core/commands/planning.ts +233 -22
- package/core/commands/setup.ts +3 -8
- package/core/commands/shipping.ts +14 -18
- package/core/commands/types.ts +8 -6
- package/core/commands/workflow.ts +105 -100
- package/core/context/generator.ts +317 -0
- package/core/context-sync.ts +7 -350
- package/core/data/index.ts +13 -32
- package/core/data/md-ideas-manager.ts +155 -0
- package/core/data/md-queue-manager.ts +4 -3
- package/core/data/md-shipped-manager.ts +90 -0
- package/core/data/md-state-manager.ts +11 -7
- package/core/domain/agent-generator.ts +23 -63
- package/core/events/index.ts +143 -0
- package/core/index.ts +17 -14
- package/core/infrastructure/capability-installer.ts +13 -149
- package/core/infrastructure/migrator/project-scanner.ts +2 -1
- package/core/infrastructure/path-manager.ts +4 -6
- package/core/infrastructure/setup.ts +3 -0
- package/core/infrastructure/uuid-migration.ts +750 -0
- package/core/outcomes/recorder.ts +2 -1
- package/core/plugin/loader.ts +4 -7
- package/core/plugin/registry.ts +3 -3
- package/core/schemas/index.ts +23 -25
- package/core/schemas/state.ts +1 -0
- package/core/serializers/ideas-serializer.ts +187 -0
- package/core/serializers/index.ts +16 -0
- package/core/serializers/shipped-serializer.ts +108 -0
- package/core/session/utils.ts +3 -9
- package/core/storage/ideas-storage.ts +273 -0
- package/core/storage/index.ts +204 -0
- package/core/storage/queue-storage.ts +297 -0
- package/core/storage/shipped-storage.ts +223 -0
- package/core/storage/state-storage.ts +235 -0
- package/core/storage/storage-manager.ts +175 -0
- package/package.json +1 -1
- package/packages/web/app/api/projects/[id]/momentum/route.ts +257 -0
- package/packages/web/app/api/sessions/current/route.ts +132 -0
- package/packages/web/app/api/sessions/history/route.ts +96 -14
- package/packages/web/app/globals.css +5 -0
- package/packages/web/app/layout.tsx +2 -0
- package/packages/web/app/project/[id]/code/layout.tsx +18 -0
- package/packages/web/app/project/[id]/code/page.tsx +408 -0
- package/packages/web/app/project/[id]/page.tsx +359 -389
- package/packages/web/app/project/[id]/reports/page.tsx +59 -0
- package/packages/web/app/project/[id]/reports/print/page.tsx +58 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -1
- package/packages/web/components/AgentsCard/AgentsCard.tsx +64 -34
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +1 -0
- package/packages/web/components/AppSidebar/AppSidebar.tsx +135 -11
- package/packages/web/components/BentoCard/BentoCard.constants.ts +3 -3
- package/packages/web/components/BentoCard/BentoCard.tsx +2 -1
- package/packages/web/components/BentoGrid/BentoGrid.tsx +2 -2
- package/packages/web/components/BlockersCard/BlockersCard.tsx +65 -57
- package/packages/web/components/BlockersCard/BlockersCard.types.ts +1 -0
- package/packages/web/components/CommandBar/CommandBar.tsx +67 -0
- package/packages/web/components/CommandBar/index.ts +1 -0
- package/packages/web/components/DashboardContent/DashboardContent.tsx +35 -5
- package/packages/web/components/DateGroup/DateGroup.tsx +1 -1
- package/packages/web/components/EmptyState/EmptyState.tsx +39 -21
- package/packages/web/components/EmptyState/EmptyState.types.ts +1 -0
- package/packages/web/components/EventRow/EventRow.tsx +4 -4
- package/packages/web/components/EventRow/EventRow.utils.ts +3 -3
- package/packages/web/components/HeroSection/HeroSection.tsx +52 -15
- package/packages/web/components/HeroSection/HeroSection.types.ts +4 -4
- package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -3
- package/packages/web/components/IdeasCard/IdeasCard.tsx +94 -27
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +1 -0
- package/packages/web/components/MasonryGrid/MasonryGrid.tsx +18 -0
- package/packages/web/components/MasonryGrid/index.ts +1 -0
- package/packages/web/components/MomentumWidget/MomentumWidget.tsx +119 -0
- package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +16 -0
- package/packages/web/components/MomentumWidget/index.ts +2 -0
- package/packages/web/components/NowCard/NowCard.tsx +81 -56
- package/packages/web/components/NowCard/NowCard.types.ts +1 -0
- package/packages/web/components/PageHeader/PageHeader.tsx +24 -0
- package/packages/web/components/PageHeader/index.ts +1 -0
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +2 -2
- package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +2 -2
- package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +37 -0
- package/packages/web/components/ProjectColorDot/index.ts +1 -0
- package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +104 -0
- package/packages/web/components/ProjectSelectorModal/index.ts +1 -0
- package/packages/web/components/Providers/Providers.tsx +4 -1
- package/packages/web/components/QueueCard/QueueCard.tsx +78 -25
- package/packages/web/components/QueueCard/QueueCard.types.ts +1 -0
- package/packages/web/components/QueueCard/QueueCard.utils.ts +3 -3
- package/packages/web/components/RecoverCard/RecoverCard.tsx +72 -0
- package/packages/web/components/RecoverCard/RecoverCard.types.ts +16 -0
- package/packages/web/components/RecoverCard/index.ts +2 -0
- package/packages/web/components/RoadmapCard/RoadmapCard.tsx +101 -33
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +1 -0
- package/packages/web/components/ShipsCard/ShipsCard.tsx +71 -28
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +2 -0
- package/packages/web/components/SparklineChart/SparklineChart.tsx +20 -18
- package/packages/web/components/StatsMasonry/StatsMasonry.tsx +95 -0
- package/packages/web/components/StatsMasonry/index.ts +1 -0
- package/packages/web/components/StreakCard/StreakCard.tsx +37 -35
- package/packages/web/components/TasksCounter/TasksCounter.tsx +1 -1
- package/packages/web/components/TechStackBadges/TechStackBadges.tsx +12 -4
- package/packages/web/components/TerminalDock/DockToggleTab.tsx +29 -0
- package/packages/web/components/TerminalDock/TerminalDock.tsx +386 -0
- package/packages/web/components/TerminalDock/TerminalDockTab.tsx +130 -0
- package/packages/web/components/TerminalDock/TerminalTabBar.tsx +142 -0
- package/packages/web/components/TerminalDock/index.ts +2 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +8 -3
- package/packages/web/components/VelocityCard/VelocityCard.tsx +49 -47
- package/packages/web/components/WeeklyReports/PrintableReport.tsx +259 -0
- package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +187 -0
- package/packages/web/components/WeeklyReports/WeekCalendar.tsx +288 -0
- package/packages/web/components/WeeklyReports/WeeklyReports.tsx +149 -0
- package/packages/web/components/WeeklyReports/index.ts +4 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +16 -4
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +1 -0
- package/packages/web/components/charts/SessionsChart.tsx +6 -3
- package/packages/web/components/ui/dialog.tsx +143 -0
- package/packages/web/components/ui/drawer.tsx +135 -0
- package/packages/web/components/ui/select.tsx +187 -0
- package/packages/web/context/GlobalTerminalContext.tsx +538 -0
- package/packages/web/lib/commands.ts +81 -0
- package/packages/web/lib/generate-week-report.ts +285 -0
- package/packages/web/lib/parse-prjct-files.ts +56 -55
- package/packages/web/lib/project-colors.ts +58 -0
- package/packages/web/lib/projects.ts +58 -5
- package/packages/web/lib/services/projects.server.ts +11 -1
- package/packages/web/next-env.d.ts +1 -1
- package/packages/web/package.json +5 -1
- package/templates/commands/analyze.md +39 -3
- package/templates/commands/ask.md +58 -3
- package/templates/commands/bug.md +117 -26
- package/templates/commands/dash.md +95 -158
- package/templates/commands/done.md +130 -148
- package/templates/commands/feature.md +125 -103
- package/templates/commands/git.md +18 -3
- package/templates/commands/idea.md +121 -38
- package/templates/commands/init.md +124 -20
- package/templates/commands/migrate-all.md +63 -28
- package/templates/commands/migrate.md +140 -0
- package/templates/commands/next.md +115 -5
- package/templates/commands/now.md +146 -82
- package/templates/commands/pause.md +89 -74
- package/templates/commands/redo.md +6 -4
- package/templates/commands/resume.md +141 -59
- package/templates/commands/ship.md +103 -231
- package/templates/commands/spec.md +98 -8
- package/templates/commands/suggest.md +22 -2
- package/templates/commands/sync.md +192 -203
- package/templates/commands/undo.md +6 -4
- package/core/data/agents-manager.ts +0 -76
- package/core/data/analysis-manager.ts +0 -83
- package/core/data/base-manager.ts +0 -156
- package/core/data/ideas-manager.ts +0 -81
- package/core/data/outcomes-manager.ts +0 -96
- package/core/data/project-manager.ts +0 -75
- package/core/data/roadmap-manager.ts +0 -118
- package/core/data/shipped-manager.ts +0 -65
- package/core/data/state-manager.ts +0 -214
- package/core/state/index.ts +0 -25
- package/core/state/manager.ts +0 -376
- package/core/state/types.ts +0 -185
- package/core/utils/project-capabilities.ts +0 -156
- package/core/view-generator.ts +0 -536
- package/packages/web/app/project/[id]/stats/loading.tsx +0 -43
- package/packages/web/app/project/[id]/stats/page.tsx +0 -253
- package/templates/agent-assignment.md +0 -72
- package/templates/analysis/project-analysis.md +0 -78
- package/templates/checklists/accessibility.md +0 -33
- package/templates/commands/build.md +0 -17
- package/templates/commands/decision.md +0 -226
- package/templates/commands/fix.md +0 -79
- package/templates/commands/help.md +0 -61
- package/templates/commands/progress.md +0 -14
- package/templates/commands/recap.md +0 -14
- package/templates/commands/roadmap.md +0 -52
- package/templates/commands/status.md +0 -17
- package/templates/commands/task.md +0 -63
- package/templates/commands/work.md +0 -44
- package/templates/commands/workflow.md +0 -12
package/core/state/types.ts
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* State Types
|
|
3
|
-
*
|
|
4
|
-
* Unified project state that replaces scattered files.
|
|
5
|
-
* This is the single source of truth for project status.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Priority levels for tasks.
|
|
10
|
-
*/
|
|
11
|
-
export type Priority = 'low' | 'medium' | 'high' | 'critical'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Task status values.
|
|
15
|
-
*/
|
|
16
|
-
export type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'blocked' | 'paused'
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Feature status values.
|
|
20
|
-
*/
|
|
21
|
-
export type FeatureStatus = 'planned' | 'in_progress' | 'completed' | 'shipped'
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* A task in the queue.
|
|
25
|
-
*/
|
|
26
|
-
export interface QueuedTask {
|
|
27
|
-
/** Unique task ID */
|
|
28
|
-
id: string
|
|
29
|
-
/** Task description */
|
|
30
|
-
description: string
|
|
31
|
-
/** Priority level */
|
|
32
|
-
priority: Priority
|
|
33
|
-
/** Related feature (if any) */
|
|
34
|
-
featureId?: string
|
|
35
|
-
/** Estimated duration (e.g., "2h", "30m") */
|
|
36
|
-
estimatedDuration?: string
|
|
37
|
-
/** Tags for categorization */
|
|
38
|
-
tags?: string[]
|
|
39
|
-
/** When task was added */
|
|
40
|
-
createdAt: string
|
|
41
|
-
/** Blocking reason if blocked */
|
|
42
|
-
blockedReason?: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The currently active task.
|
|
47
|
-
*/
|
|
48
|
-
export interface CurrentTask {
|
|
49
|
-
/** Unique task ID */
|
|
50
|
-
id: string
|
|
51
|
-
/** Task description */
|
|
52
|
-
description: string
|
|
53
|
-
/** When task started */
|
|
54
|
-
startedAt: string
|
|
55
|
-
/** Assigned agent */
|
|
56
|
-
agent?: string
|
|
57
|
-
/** Agent confidence (0-1) */
|
|
58
|
-
agentConfidence?: number
|
|
59
|
-
/** Estimated duration */
|
|
60
|
-
estimatedDuration?: string
|
|
61
|
-
/** Related feature */
|
|
62
|
-
featureId?: string
|
|
63
|
-
/** Paused state info */
|
|
64
|
-
pausedAt?: string
|
|
65
|
-
/** Reason for pause */
|
|
66
|
-
pauseReason?: string
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Active feature being worked on.
|
|
71
|
-
*/
|
|
72
|
-
export interface ActiveFeature {
|
|
73
|
-
/** Feature ID */
|
|
74
|
-
id: string
|
|
75
|
-
/** Feature name */
|
|
76
|
-
name: string
|
|
77
|
-
/** Current status */
|
|
78
|
-
status: FeatureStatus
|
|
79
|
-
/** Tasks completed for this feature */
|
|
80
|
-
tasksCompleted: number
|
|
81
|
-
/** Tasks remaining */
|
|
82
|
-
tasksRemaining: number
|
|
83
|
-
/** Total estimated effort */
|
|
84
|
-
estimatedEffort?: string
|
|
85
|
-
/** Actual effort so far */
|
|
86
|
-
actualEffort?: string
|
|
87
|
-
/** When feature was started */
|
|
88
|
-
startedAt: string
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Performance statistics.
|
|
93
|
-
*/
|
|
94
|
-
export interface PerformanceStats {
|
|
95
|
-
/** Tasks completed today */
|
|
96
|
-
tasksToday: number
|
|
97
|
-
/** Tasks completed this week */
|
|
98
|
-
tasksThisWeek: number
|
|
99
|
-
/** Average task duration */
|
|
100
|
-
avgDuration: string
|
|
101
|
-
/** Tasks per day velocity */
|
|
102
|
-
velocity: string
|
|
103
|
-
/** Estimate accuracy percentage (0-100) */
|
|
104
|
-
estimateAccuracy: number
|
|
105
|
-
/** Streak of consecutive productive days */
|
|
106
|
-
streak: number
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Recent activity entry.
|
|
111
|
-
*/
|
|
112
|
-
export interface RecentActivity {
|
|
113
|
-
/** Activity type */
|
|
114
|
-
type: 'task_completed' | 'feature_shipped' | 'idea_captured' | 'session_started'
|
|
115
|
-
/** Description */
|
|
116
|
-
description: string
|
|
117
|
-
/** When it happened */
|
|
118
|
-
timestamp: string
|
|
119
|
-
/** Duration if applicable */
|
|
120
|
-
duration?: string
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Unified project state.
|
|
125
|
-
* This replaces reading from now.md, next.md, roadmap.md, etc.
|
|
126
|
-
*/
|
|
127
|
-
export interface ProjectState {
|
|
128
|
-
/** Project ID */
|
|
129
|
-
projectId: string
|
|
130
|
-
|
|
131
|
-
/** Currently active task (null if none) */
|
|
132
|
-
currentTask: CurrentTask | null
|
|
133
|
-
|
|
134
|
-
/** Task queue (priority ordered) */
|
|
135
|
-
queue: QueuedTask[]
|
|
136
|
-
|
|
137
|
-
/** Active feature being worked on */
|
|
138
|
-
activeFeature: ActiveFeature | null
|
|
139
|
-
|
|
140
|
-
/** Performance statistics */
|
|
141
|
-
stats: PerformanceStats
|
|
142
|
-
|
|
143
|
-
/** Recent activity (last 10 items) */
|
|
144
|
-
recentActivity: RecentActivity[]
|
|
145
|
-
|
|
146
|
-
/** When state was last synced */
|
|
147
|
-
lastSync: string
|
|
148
|
-
|
|
149
|
-
/** State version for migrations */
|
|
150
|
-
version: number
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Default empty state.
|
|
155
|
-
*/
|
|
156
|
-
export const DEFAULT_STATE: ProjectState = {
|
|
157
|
-
projectId: '',
|
|
158
|
-
currentTask: null,
|
|
159
|
-
queue: [],
|
|
160
|
-
activeFeature: null,
|
|
161
|
-
stats: {
|
|
162
|
-
tasksToday: 0,
|
|
163
|
-
tasksThisWeek: 0,
|
|
164
|
-
avgDuration: '0h',
|
|
165
|
-
velocity: '0',
|
|
166
|
-
estimateAccuracy: 0,
|
|
167
|
-
streak: 0,
|
|
168
|
-
},
|
|
169
|
-
recentActivity: [],
|
|
170
|
-
lastSync: new Date().toISOString(),
|
|
171
|
-
version: 1,
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* State update operations.
|
|
176
|
-
*/
|
|
177
|
-
export type StateUpdate =
|
|
178
|
-
| { type: 'SET_CURRENT_TASK'; task: CurrentTask | null }
|
|
179
|
-
| { type: 'ADD_TO_QUEUE'; task: QueuedTask }
|
|
180
|
-
| { type: 'REMOVE_FROM_QUEUE'; taskId: string }
|
|
181
|
-
| { type: 'UPDATE_QUEUE_TASK'; taskId: string; updates: Partial<QueuedTask> }
|
|
182
|
-
| { type: 'SET_ACTIVE_FEATURE'; feature: ActiveFeature | null }
|
|
183
|
-
| { type: 'UPDATE_STATS'; stats: Partial<PerformanceStats> }
|
|
184
|
-
| { type: 'ADD_ACTIVITY'; activity: RecentActivity }
|
|
185
|
-
| { type: 'SYNC' }
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project Capabilities Detector
|
|
3
|
-
* Detects ONLY what exists - no assumptions, no hallucinations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import fs from 'fs/promises'
|
|
7
|
-
import path from 'path'
|
|
8
|
-
|
|
9
|
-
interface Capabilities {
|
|
10
|
-
design: boolean
|
|
11
|
-
test: boolean
|
|
12
|
-
docs: boolean
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface PackageJson {
|
|
16
|
-
dependencies?: Record<string, string>
|
|
17
|
-
devDependencies?: Record<string, string>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class ProjectCapabilities {
|
|
21
|
-
/**
|
|
22
|
-
* Detect project capabilities
|
|
23
|
-
*/
|
|
24
|
-
async detect(projectPath = process.cwd()): Promise<Capabilities> {
|
|
25
|
-
return {
|
|
26
|
-
design: await this.hasDesign(projectPath),
|
|
27
|
-
test: await this.hasTest(projectPath),
|
|
28
|
-
docs: await this.hasDocs(projectPath),
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Check if project has design system
|
|
34
|
-
*/
|
|
35
|
-
async hasDesign(projectPath: string): Promise<boolean> {
|
|
36
|
-
return (
|
|
37
|
-
(await this.hasFolder(projectPath, 'design')) ||
|
|
38
|
-
(await this.hasFolder(projectPath, 'designs')) ||
|
|
39
|
-
(await this.hasFolder(projectPath, '.storybook')) ||
|
|
40
|
-
(await this.hasDep(projectPath, '@storybook/react')) ||
|
|
41
|
-
(await this.hasDep(projectPath, '@storybook/vue')) ||
|
|
42
|
-
(await this.hasFiles(projectPath, '**/*.figma'))
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Check if project has test framework
|
|
48
|
-
*/
|
|
49
|
-
async hasTest(projectPath: string): Promise<boolean> {
|
|
50
|
-
return (
|
|
51
|
-
(await this.hasDep(projectPath, 'jest')) ||
|
|
52
|
-
(await this.hasDep(projectPath, 'vitest')) ||
|
|
53
|
-
(await this.hasDep(projectPath, 'mocha')) ||
|
|
54
|
-
(await this.hasDep(projectPath, '@jest/core')) ||
|
|
55
|
-
(await this.hasFiles(projectPath, '**/*.{test,spec}.{js,ts,jsx,tsx}')) ||
|
|
56
|
-
(await this.hasFile(projectPath, 'jest.config.js')) ||
|
|
57
|
-
(await this.hasFile(projectPath, 'vitest.config.js'))
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Check if project has documentation system
|
|
63
|
-
*/
|
|
64
|
-
async hasDocs(projectPath: string): Promise<boolean> {
|
|
65
|
-
return (
|
|
66
|
-
(await this.hasFolder(projectPath, 'docs')) ||
|
|
67
|
-
(await this.hasFolder(projectPath, 'documentation')) ||
|
|
68
|
-
(await this.hasFile(projectPath, 'README.md')) ||
|
|
69
|
-
(await this.hasDep(projectPath, 'typedoc')) ||
|
|
70
|
-
(await this.hasDep(projectPath, 'jsdoc'))
|
|
71
|
-
)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Check if folder exists
|
|
76
|
-
*/
|
|
77
|
-
async hasFolder(projectPath: string, folderName: string): Promise<boolean> {
|
|
78
|
-
try {
|
|
79
|
-
const folderPath = path.join(projectPath, folderName)
|
|
80
|
-
const stat = await fs.stat(folderPath)
|
|
81
|
-
return stat.isDirectory()
|
|
82
|
-
} catch {
|
|
83
|
-
return false
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Check if file exists
|
|
89
|
-
*/
|
|
90
|
-
async hasFile(projectPath: string, fileName: string): Promise<boolean> {
|
|
91
|
-
try {
|
|
92
|
-
const filePath = path.join(projectPath, fileName)
|
|
93
|
-
await fs.access(filePath)
|
|
94
|
-
return true
|
|
95
|
-
} catch {
|
|
96
|
-
return false
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Check if files matching pattern exist
|
|
102
|
-
*/
|
|
103
|
-
async hasFiles(projectPath: string, pattern: string): Promise<boolean> {
|
|
104
|
-
try {
|
|
105
|
-
// Convert glob pattern to regex
|
|
106
|
-
const regex = this.globToRegex(pattern)
|
|
107
|
-
const files = await fs.readdir(projectPath, { recursive: true })
|
|
108
|
-
|
|
109
|
-
// Filter by pattern and ignore node_modules, dist, build
|
|
110
|
-
return files.some((file) => {
|
|
111
|
-
const fileName = typeof file === 'string' ? file : file.toString()
|
|
112
|
-
const skip =
|
|
113
|
-
fileName.includes('node_modules/') ||
|
|
114
|
-
fileName.includes('dist/') ||
|
|
115
|
-
fileName.includes('build/')
|
|
116
|
-
return !skip && regex.test(fileName)
|
|
117
|
-
})
|
|
118
|
-
} catch {
|
|
119
|
-
return false
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Convert simple glob pattern to regex
|
|
125
|
-
*/
|
|
126
|
-
globToRegex(pattern: string): RegExp {
|
|
127
|
-
// Convert **/*.{test,spec}.{js,ts,jsx,tsx} to regex
|
|
128
|
-
const escaped = pattern
|
|
129
|
-
.replace(/\./g, '\\.')
|
|
130
|
-
.replace(/\*\*/g, '.*')
|
|
131
|
-
.replace(/\*/g, '[^/]*')
|
|
132
|
-
.replace(/\{([^}]+)\}/g, (_, group: string) => `(${group.split(',').join('|')})`)
|
|
133
|
-
return new RegExp(escaped)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Check if dependency exists in package.json
|
|
138
|
-
*/
|
|
139
|
-
async hasDep(projectPath: string, depName: string): Promise<boolean> {
|
|
140
|
-
try {
|
|
141
|
-
const pkgPath = path.join(projectPath, 'package.json')
|
|
142
|
-
const content = await fs.readFile(pkgPath, 'utf8')
|
|
143
|
-
const pkg: PackageJson = JSON.parse(content)
|
|
144
|
-
|
|
145
|
-
return !!(
|
|
146
|
-
(pkg.dependencies && pkg.dependencies[depName]) ||
|
|
147
|
-
(pkg.devDependencies && pkg.devDependencies[depName])
|
|
148
|
-
)
|
|
149
|
-
} catch {
|
|
150
|
-
return false
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const projectCapabilities = new ProjectCapabilities()
|
|
156
|
-
export default projectCapabilities
|