hub-launch 1.0.3
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 +144 -0
- package/README.md +195 -0
- package/bin/hublaunch +20 -0
- package/dist/commands/checkout.d.ts +7 -0
- package/dist/commands/checkout.d.ts.map +1 -0
- package/dist/commands/checkout.js +164 -0
- package/dist/commands/checkout.js.map +1 -0
- package/dist/commands/clean.d.ts +7 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +206 -0
- package/dist/commands/clean.js.map +1 -0
- package/dist/commands/close.d.ts +7 -0
- package/dist/commands/close.d.ts.map +1 -0
- package/dist/commands/close.js +109 -0
- package/dist/commands/close.js.map +1 -0
- package/dist/commands/create.d.ts +7 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +367 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/diff.d.ts +7 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +98 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/execute.d.ts +7 -0
- package/dist/commands/execute.d.ts.map +1 -0
- package/dist/commands/execute.js +376 -0
- package/dist/commands/execute.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +1243 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/interactive.d.ts +12 -0
- package/dist/commands/interactive.d.ts.map +1 -0
- package/dist/commands/interactive.js +1071 -0
- package/dist/commands/interactive.js.map +1 -0
- package/dist/commands/launch.d.ts +16 -0
- package/dist/commands/launch.d.ts.map +1 -0
- package/dist/commands/launch.js +684 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/login.d.ts +40 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +469 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logs.d.ts +22 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +105 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/merge.d.ts +7 -0
- package/dist/commands/merge.d.ts.map +1 -0
- package/dist/commands/merge.js +240 -0
- package/dist/commands/merge.js.map +1 -0
- package/dist/commands/preview.d.ts +7 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +160 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/project.d.ts +18 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +352 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/respond.d.ts +7 -0
- package/dist/commands/respond.d.ts.map +1 -0
- package/dist/commands/respond.js +112 -0
- package/dist/commands/respond.js.map +1 -0
- package/dist/commands/setPriority.d.ts +7 -0
- package/dist/commands/setPriority.d.ts.map +1 -0
- package/dist/commands/setPriority.js +112 -0
- package/dist/commands/setPriority.js.map +1 -0
- package/dist/commands/track.d.ts +7 -0
- package/dist/commands/track.d.ts.map +1 -0
- package/dist/commands/track.js +140 -0
- package/dist/commands/track.js.map +1 -0
- package/dist/commands/upload.d.ts +21 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +145 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/view.d.ts +7 -0
- package/dist/commands/view.d.ts.map +1 -0
- package/dist/commands/view.js +168 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/commands/watch.d.ts +7 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +438 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/worktree.d.ts +7 -0
- package/dist/commands/worktree.d.ts.map +1 -0
- package/dist/commands/worktree.js +122 -0
- package/dist/commands/worktree.js.map +1 -0
- package/dist/config/command-names.d.ts +16 -0
- package/dist/config/command-names.d.ts.map +1 -0
- package/dist/config/command-names.js +17 -0
- package/dist/config/command-names.js.map +1 -0
- package/dist/config/constants.d.ts +12 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +12 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/config/index.d.ts +47 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +175 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -0
- package/dist/services/api/HulaApiClient.d.ts +170 -0
- package/dist/services/api/HulaApiClient.d.ts.map +1 -0
- package/dist/services/api/HulaApiClient.js +233 -0
- package/dist/services/api/HulaApiClient.js.map +1 -0
- package/dist/services/diff/DiffService.d.ts +44 -0
- package/dist/services/diff/DiffService.d.ts.map +1 -0
- package/dist/services/diff/DiffService.js +126 -0
- package/dist/services/diff/DiffService.js.map +1 -0
- package/dist/services/editor/EditorService.d.ts +53 -0
- package/dist/services/editor/EditorService.d.ts.map +1 -0
- package/dist/services/editor/EditorService.js +161 -0
- package/dist/services/editor/EditorService.js.map +1 -0
- package/dist/services/git/GitService.d.ts +124 -0
- package/dist/services/git/GitService.d.ts.map +1 -0
- package/dist/services/git/GitService.js +423 -0
- package/dist/services/git/GitService.js.map +1 -0
- package/dist/services/git/WorktreeService.d.ts +144 -0
- package/dist/services/git/WorktreeService.d.ts.map +1 -0
- package/dist/services/git/WorktreeService.js +505 -0
- package/dist/services/git/WorktreeService.js.map +1 -0
- package/dist/services/github/ActionsService.d.ts +66 -0
- package/dist/services/github/ActionsService.d.ts.map +1 -0
- package/dist/services/github/ActionsService.js +114 -0
- package/dist/services/github/ActionsService.js.map +1 -0
- package/dist/services/github/AssetUploadService.d.ts +103 -0
- package/dist/services/github/AssetUploadService.d.ts.map +1 -0
- package/dist/services/github/AssetUploadService.js +299 -0
- package/dist/services/github/AssetUploadService.js.map +1 -0
- package/dist/services/github/BatchCopilotDetectionService.d.ts +58 -0
- package/dist/services/github/BatchCopilotDetectionService.d.ts.map +1 -0
- package/dist/services/github/BatchCopilotDetectionService.js +321 -0
- package/dist/services/github/BatchCopilotDetectionService.js.map +1 -0
- package/dist/services/github/CopilotDetectionService.d.ts +40 -0
- package/dist/services/github/CopilotDetectionService.d.ts.map +1 -0
- package/dist/services/github/CopilotDetectionService.js +280 -0
- package/dist/services/github/CopilotDetectionService.js.map +1 -0
- package/dist/services/github/CopilotService.d.ts +27 -0
- package/dist/services/github/CopilotService.d.ts.map +1 -0
- package/dist/services/github/CopilotService.js +249 -0
- package/dist/services/github/CopilotService.js.map +1 -0
- package/dist/services/github/DeploymentDetectionService.d.ts +38 -0
- package/dist/services/github/DeploymentDetectionService.d.ts.map +1 -0
- package/dist/services/github/DeploymentDetectionService.js +104 -0
- package/dist/services/github/DeploymentDetectionService.js.map +1 -0
- package/dist/services/github/GithubAppService.d.ts +40 -0
- package/dist/services/github/GithubAppService.d.ts.map +1 -0
- package/dist/services/github/GithubAppService.js +187 -0
- package/dist/services/github/GithubAppService.js.map +1 -0
- package/dist/services/github/IssueService.d.ts +65 -0
- package/dist/services/github/IssueService.d.ts.map +1 -0
- package/dist/services/github/IssueService.js +231 -0
- package/dist/services/github/IssueService.js.map +1 -0
- package/dist/services/github/LabelService.d.ts +36 -0
- package/dist/services/github/LabelService.d.ts.map +1 -0
- package/dist/services/github/LabelService.js +122 -0
- package/dist/services/github/LabelService.js.map +1 -0
- package/dist/services/github/PRService.d.ts +77 -0
- package/dist/services/github/PRService.d.ts.map +1 -0
- package/dist/services/github/PRService.js +287 -0
- package/dist/services/github/PRService.js.map +1 -0
- package/dist/services/github/ProjectService.d.ts +144 -0
- package/dist/services/github/ProjectService.d.ts.map +1 -0
- package/dist/services/github/ProjectService.js +804 -0
- package/dist/services/github/ProjectService.js.map +1 -0
- package/dist/services/hooks/HookExecutor.d.ts +66 -0
- package/dist/services/hooks/HookExecutor.d.ts.map +1 -0
- package/dist/services/hooks/HookExecutor.js +227 -0
- package/dist/services/hooks/HookExecutor.js.map +1 -0
- package/dist/services/hooks/index.d.ts +2 -0
- package/dist/services/hooks/index.d.ts.map +1 -0
- package/dist/services/hooks/index.js +2 -0
- package/dist/services/hooks/index.js.map +1 -0
- package/dist/services/logs/LogFormatterService.d.ts +17 -0
- package/dist/services/logs/LogFormatterService.d.ts.map +1 -0
- package/dist/services/logs/LogFormatterService.js +35 -0
- package/dist/services/logs/LogFormatterService.js.map +1 -0
- package/dist/services/logs/TempFileService.d.ts +27 -0
- package/dist/services/logs/TempFileService.d.ts.map +1 -0
- package/dist/services/logs/TempFileService.js +90 -0
- package/dist/services/logs/TempFileService.js.map +1 -0
- package/dist/services/logs/index.d.ts +3 -0
- package/dist/services/logs/index.d.ts.map +1 -0
- package/dist/services/logs/index.js +4 -0
- package/dist/services/logs/index.js.map +1 -0
- package/dist/services/plan/PlanService.d.ts +70 -0
- package/dist/services/plan/PlanService.d.ts.map +1 -0
- package/dist/services/plan/PlanService.js +211 -0
- package/dist/services/plan/PlanService.js.map +1 -0
- package/dist/services/polling/GitHubDirectPollingAdapter.d.ts +16 -0
- package/dist/services/polling/GitHubDirectPollingAdapter.d.ts.map +1 -0
- package/dist/services/polling/GitHubDirectPollingAdapter.js +87 -0
- package/dist/services/polling/GitHubDirectPollingAdapter.js.map +1 -0
- package/dist/services/polling/HulaServerPollingAdapter.d.ts +23 -0
- package/dist/services/polling/HulaServerPollingAdapter.d.ts.map +1 -0
- package/dist/services/polling/HulaServerPollingAdapter.js +78 -0
- package/dist/services/polling/HulaServerPollingAdapter.js.map +1 -0
- package/dist/services/polling/IStatusPollingAdapter.d.ts +29 -0
- package/dist/services/polling/IStatusPollingAdapter.d.ts.map +1 -0
- package/dist/services/polling/IStatusPollingAdapter.js +2 -0
- package/dist/services/polling/IStatusPollingAdapter.js.map +1 -0
- package/dist/services/polling/StatusPollingAdapterFactory.d.ts +14 -0
- package/dist/services/polling/StatusPollingAdapterFactory.d.ts.map +1 -0
- package/dist/services/polling/StatusPollingAdapterFactory.js +41 -0
- package/dist/services/polling/StatusPollingAdapterFactory.js.map +1 -0
- package/dist/services/polling/index.d.ts +5 -0
- package/dist/services/polling/index.d.ts.map +1 -0
- package/dist/services/polling/index.js +5 -0
- package/dist/services/polling/index.js.map +1 -0
- package/dist/services/preview/PreviewService.d.ts +86 -0
- package/dist/services/preview/PreviewService.d.ts.map +1 -0
- package/dist/services/preview/PreviewService.js +439 -0
- package/dist/services/preview/PreviewService.js.map +1 -0
- package/dist/services/tracking/ProjectTrackingAdapter.d.ts +41 -0
- package/dist/services/tracking/ProjectTrackingAdapter.d.ts.map +1 -0
- package/dist/services/tracking/ProjectTrackingAdapter.js +230 -0
- package/dist/services/tracking/ProjectTrackingAdapter.js.map +1 -0
- package/dist/services/tracking/RemoteTrackingAdapter.d.ts +62 -0
- package/dist/services/tracking/RemoteTrackingAdapter.d.ts.map +1 -0
- package/dist/services/tracking/RemoteTrackingAdapter.js +242 -0
- package/dist/services/tracking/RemoteTrackingAdapter.js.map +1 -0
- package/dist/services/tracking/TrackingAdapterFactory.d.ts +25 -0
- package/dist/services/tracking/TrackingAdapterFactory.d.ts.map +1 -0
- package/dist/services/tracking/TrackingAdapterFactory.js +55 -0
- package/dist/services/tracking/TrackingAdapterFactory.js.map +1 -0
- package/dist/services/tracking/TrackingService.d.ts +104 -0
- package/dist/services/tracking/TrackingService.d.ts.map +1 -0
- package/dist/services/tracking/TrackingService.js +256 -0
- package/dist/services/tracking/TrackingService.js.map +1 -0
- package/dist/services/tracking/UntrackedIssuesService.d.ts +20 -0
- package/dist/services/tracking/UntrackedIssuesService.d.ts.map +1 -0
- package/dist/services/tracking/UntrackedIssuesService.js +148 -0
- package/dist/services/tracking/UntrackedIssuesService.js.map +1 -0
- package/dist/services/tracking/local-file-migration.d.ts +16 -0
- package/dist/services/tracking/local-file-migration.d.ts.map +1 -0
- package/dist/services/tracking/local-file-migration.js +86 -0
- package/dist/services/tracking/local-file-migration.js.map +1 -0
- package/dist/templates/planning-instructions.md +752 -0
- package/dist/templates/proceed-instructions.md +453 -0
- package/dist/templates/scripts/hula-fix-commit.sh +110 -0
- package/dist/templates/scripts/hula-fix-setup.sh +145 -0
- package/dist/templates/scripts/hula-launch-run.sh +89 -0
- package/dist/templates/scripts/hula-merge-local.sh +138 -0
- package/dist/templates/scripts/hula-merge-remote.sh +74 -0
- package/dist/templates/scripts/hula-read-config.sh +38 -0
- package/dist/templates/scripts/hula-verify-gather.sh +135 -0
- package/dist/templates/scripts/hula-verify-post.sh +84 -0
- package/dist/templates/skills/hula-confirm/SKILL.md +361 -0
- package/dist/templates/skills/hula-create/SKILL.md +211 -0
- package/dist/templates/skills/hula-fix/SKILL.md +224 -0
- package/dist/templates/skills/hula-launch/SKILL.md +159 -0
- package/dist/templates/skills/hula-log/SKILL.md +105 -0
- package/dist/templates/skills/hula-merge/SKILL.md +387 -0
- package/dist/templates/skills/hula-plan/SKILL.md +148 -0
- package/dist/templates/skills/hula-upload/SKILL.md +115 -0
- package/dist/templates/skills/hula-verify/SKILL.md +754 -0
- package/dist/types/common.schema.d.ts +46 -0
- package/dist/types/common.schema.d.ts.map +1 -0
- package/dist/types/common.schema.js +60 -0
- package/dist/types/common.schema.js.map +1 -0
- package/dist/types/config.schema.d.ts +443 -0
- package/dist/types/config.schema.d.ts.map +1 -0
- package/dist/types/config.schema.js +126 -0
- package/dist/types/config.schema.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/issue.schema.d.ts +136 -0
- package/dist/types/issue.schema.d.ts.map +1 -0
- package/dist/types/issue.schema.js +49 -0
- package/dist/types/issue.schema.js.map +1 -0
- package/dist/types/pr.schema.d.ts +118 -0
- package/dist/types/pr.schema.d.ts.map +1 -0
- package/dist/types/pr.schema.js +40 -0
- package/dist/types/pr.schema.js.map +1 -0
- package/dist/types/tracking.schema.d.ts +340 -0
- package/dist/types/tracking.schema.d.ts.map +1 -0
- package/dist/types/tracking.schema.js +56 -0
- package/dist/types/tracking.schema.js.map +1 -0
- package/dist/utils/browser-launcher.d.ts +60 -0
- package/dist/utils/browser-launcher.d.ts.map +1 -0
- package/dist/utils/browser-launcher.js +263 -0
- package/dist/utils/browser-launcher.js.map +1 -0
- package/dist/utils/cache.d.ts +44 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +94 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/config-parser.d.ts +16 -0
- package/dist/utils/config-parser.d.ts.map +1 -0
- package/dist/utils/config-parser.js +210 -0
- package/dist/utils/config-parser.js.map +1 -0
- package/dist/utils/editor.d.ts +21 -0
- package/dist/utils/editor.d.ts.map +1 -0
- package/dist/utils/editor.js +213 -0
- package/dist/utils/editor.js.map +1 -0
- package/dist/utils/git-utils.d.ts +5 -0
- package/dist/utils/git-utils.d.ts.map +1 -0
- package/dist/utils/git-utils.js +18 -0
- package/dist/utils/git-utils.js.map +1 -0
- package/dist/utils/github-cli.d.ts +62 -0
- package/dist/utils/github-cli.d.ts.map +1 -0
- package/dist/utils/github-cli.js +492 -0
- package/dist/utils/github-cli.js.map +1 -0
- package/dist/utils/logger.d.ts +45 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +118 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/open-url.d.ts +19 -0
- package/dist/utils/open-url.d.ts.map +1 -0
- package/dist/utils/open-url.js +37 -0
- package/dist/utils/open-url.js.map +1 -0
- package/dist/utils/project-resolver.d.ts +13 -0
- package/dist/utils/project-resolver.d.ts.map +1 -0
- package/dist/utils/project-resolver.js +35 -0
- package/dist/utils/project-resolver.js.map +1 -0
- package/dist/utils/prompts.d.ts +80 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +326 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/shell.d.ts +54 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +152 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/validators.d.ts +32 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +64 -0
- package/dist/utils/validators.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { type TrackedPlan, type Priority, type IssueStatus } from '../../types/index.js';
|
|
2
|
+
type TrackedIssue = TrackedPlan;
|
|
3
|
+
/**
|
|
4
|
+
* Interface for tracking data adapter
|
|
5
|
+
* Dependency Inversion Principle
|
|
6
|
+
*/
|
|
7
|
+
export interface ITrackingAdapter {
|
|
8
|
+
read(): Promise<TrackedIssue[]>;
|
|
9
|
+
write(issues: TrackedIssue[]): Promise<void>;
|
|
10
|
+
add?(issue: TrackedIssue): Promise<void>;
|
|
11
|
+
remove?(trackingName: string): Promise<void>;
|
|
12
|
+
updatePriority?(trackingName: string, priority: string): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Service for managing tracked issues
|
|
16
|
+
* Single Responsibility: Issue tracking operations
|
|
17
|
+
*/
|
|
18
|
+
export declare class TrackingService {
|
|
19
|
+
private adapter;
|
|
20
|
+
constructor(adapter: ITrackingAdapter);
|
|
21
|
+
/**
|
|
22
|
+
* Returns the authenticated user id from the underlying adapter, if it
|
|
23
|
+
* supports the concept (currently only RemoteTrackingAdapter). Returns
|
|
24
|
+
* null when unsupported (e.g. local file adapter) or when the adapter
|
|
25
|
+
* has not yet observed the id.
|
|
26
|
+
*/
|
|
27
|
+
getCurrentUserId(): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Get all tracked issues
|
|
30
|
+
*/
|
|
31
|
+
getAll(): Promise<TrackedIssue[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Get a specific tracked issue by number
|
|
34
|
+
*/
|
|
35
|
+
getByNumber(issueNumber: number): Promise<TrackedIssue | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Check if an issue is tracked
|
|
38
|
+
*/
|
|
39
|
+
exists(issueNumber: number): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Add a new issue to tracking
|
|
42
|
+
*/
|
|
43
|
+
add(issue: TrackedIssue): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Remove an issue from tracking by number.
|
|
46
|
+
* WARNING: Matches the first issue with this number regardless of repo.
|
|
47
|
+
* Prefer removeByName() for cross-repo safety.
|
|
48
|
+
*/
|
|
49
|
+
remove(issueNumber: number): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Remove an issue from tracking by name (owner/repo#number).
|
|
52
|
+
* Safe for cross-repo scenarios where multiple repos may share the same issue number.
|
|
53
|
+
*/
|
|
54
|
+
removeByName(issueName: string): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Update a tracked issue
|
|
57
|
+
*/
|
|
58
|
+
update(issueNumber: number, updates: Partial<TrackedIssue>): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Update issue status
|
|
61
|
+
*/
|
|
62
|
+
updateStatus(issueNumber: number, status: IssueStatus): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Update issue priority
|
|
65
|
+
*/
|
|
66
|
+
updatePriority(issueNumber: number, priority: Priority): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Update deployment status
|
|
69
|
+
*/
|
|
70
|
+
updateDeploymentStatus(issueNumber: number, status: 'pending' | 'success' | 'failed', timestamp?: string): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Mark that Copilot was notified about deployment failure
|
|
73
|
+
*/
|
|
74
|
+
markDeploymentNotified(issueNumber: number, timestamp: string): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Get issues by status
|
|
77
|
+
*/
|
|
78
|
+
getByStatus(status: IssueStatus): Promise<TrackedIssue[]>;
|
|
79
|
+
/**
|
|
80
|
+
* Get issues by priority
|
|
81
|
+
*/
|
|
82
|
+
getByPriority(priority: Priority): Promise<TrackedIssue[]>;
|
|
83
|
+
/**
|
|
84
|
+
* Sort issues by criteria
|
|
85
|
+
*/
|
|
86
|
+
sortIssues(issues: TrackedIssue[], sortBy: 'created' | 'updated' | 'number' | 'priority', direction?: 'asc' | 'desc'): TrackedIssue[];
|
|
87
|
+
/**
|
|
88
|
+
* Clean up closed issues from GitHub
|
|
89
|
+
* Since we only track 4 active statuses, this checks GitHub for closed issues
|
|
90
|
+
*/
|
|
91
|
+
cleanClosed(): Promise<number>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* File-based tracking adapter
|
|
95
|
+
* Open/Closed Principle: Can extend with new adapters
|
|
96
|
+
*/
|
|
97
|
+
export declare class TrackingFileAdapter implements ITrackingAdapter {
|
|
98
|
+
private filePath;
|
|
99
|
+
constructor(filePath: string);
|
|
100
|
+
read(): Promise<TrackedIssue[]>;
|
|
101
|
+
write(issues: TrackedIssue[]): Promise<void>;
|
|
102
|
+
}
|
|
103
|
+
export {};
|
|
104
|
+
//# sourceMappingURL=TrackingService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrackingService.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/TrackingService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
import { logger } from '../../utils/logger.js';
|
|
5
|
+
import { TrackedPlansSchema, PROJECT_FIELD_OPTIONS, } from '../../types/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Service for managing tracked issues
|
|
8
|
+
* Single Responsibility: Issue tracking operations
|
|
9
|
+
*/
|
|
10
|
+
export class TrackingService {
|
|
11
|
+
adapter;
|
|
12
|
+
constructor(adapter) {
|
|
13
|
+
this.adapter = adapter;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Returns the authenticated user id from the underlying adapter, if it
|
|
17
|
+
* supports the concept (currently only RemoteTrackingAdapter). Returns
|
|
18
|
+
* null when unsupported (e.g. local file adapter) or when the adapter
|
|
19
|
+
* has not yet observed the id.
|
|
20
|
+
*/
|
|
21
|
+
getCurrentUserId() {
|
|
22
|
+
const adapter = this.adapter;
|
|
23
|
+
return adapter.getCurrentUserId?.() ?? null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get all tracked issues
|
|
27
|
+
*/
|
|
28
|
+
async getAll() {
|
|
29
|
+
return this.adapter.read();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get a specific tracked issue by number
|
|
33
|
+
*/
|
|
34
|
+
async getByNumber(issueNumber) {
|
|
35
|
+
const issues = await this.getAll();
|
|
36
|
+
return issues.find((i) => i.number === issueNumber) ?? null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if an issue is tracked
|
|
40
|
+
*/
|
|
41
|
+
async exists(issueNumber) {
|
|
42
|
+
const issue = await this.getByNumber(issueNumber);
|
|
43
|
+
return issue !== null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Add a new issue to tracking
|
|
47
|
+
*/
|
|
48
|
+
async add(issue) {
|
|
49
|
+
const issues = await this.getAll();
|
|
50
|
+
// Check if already tracked
|
|
51
|
+
const existing = issues.find((i) => i.number === issue.number);
|
|
52
|
+
if (existing) {
|
|
53
|
+
logger.warning(`Issue #${issue.number} is already tracked`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Use adapter's add method if available (for remote tracking)
|
|
57
|
+
// Otherwise fall back to write method (for local file tracking)
|
|
58
|
+
if (typeof this.adapter.add === 'function') {
|
|
59
|
+
await this.adapter.add(issue);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
issues.push(issue);
|
|
63
|
+
await this.adapter.write(issues);
|
|
64
|
+
}
|
|
65
|
+
logger.success(`Added issue #${issue.number} to tracking`);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Remove an issue from tracking by number.
|
|
69
|
+
* WARNING: Matches the first issue with this number regardless of repo.
|
|
70
|
+
* Prefer removeByName() for cross-repo safety.
|
|
71
|
+
*/
|
|
72
|
+
async remove(issueNumber) {
|
|
73
|
+
const issues = await this.getAll();
|
|
74
|
+
const issueToRemove = issues.find((i) => i.number === issueNumber);
|
|
75
|
+
if (!issueToRemove) {
|
|
76
|
+
logger.warning(`Issue #${issueNumber} is not tracked`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Use adapter's remove method if available (for remote tracking)
|
|
80
|
+
// Otherwise fall back to write method (for local file tracking)
|
|
81
|
+
if (typeof this.adapter.remove === 'function') {
|
|
82
|
+
await this.adapter.remove(issueToRemove.name);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const filtered = issues.filter((i) => i.number !== issueNumber);
|
|
86
|
+
await this.adapter.write(filtered);
|
|
87
|
+
}
|
|
88
|
+
logger.success(`Removed issue #${issueNumber} from tracking`);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Remove an issue from tracking by name (owner/repo#number).
|
|
92
|
+
* Safe for cross-repo scenarios where multiple repos may share the same issue number.
|
|
93
|
+
*/
|
|
94
|
+
async removeByName(issueName) {
|
|
95
|
+
if (typeof this.adapter.remove === 'function') {
|
|
96
|
+
// Let the adapter handle lookup + removal in a single pass
|
|
97
|
+
// (avoids a redundant getAll() → listIssues() call)
|
|
98
|
+
await this.adapter.remove(issueName);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const issues = await this.getAll();
|
|
102
|
+
const filtered = issues.filter((i) => i.name !== issueName);
|
|
103
|
+
if (filtered.length === issues.length) {
|
|
104
|
+
logger.warning(`Issue ${issueName} is not tracked`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
await this.adapter.write(filtered);
|
|
108
|
+
}
|
|
109
|
+
logger.success(`Removed issue ${issueName} from tracking`);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Update a tracked issue
|
|
113
|
+
*/
|
|
114
|
+
async update(issueNumber, updates) {
|
|
115
|
+
const issues = await this.getAll();
|
|
116
|
+
const index = issues.findIndex((i) => i.number === issueNumber);
|
|
117
|
+
if (index === -1) {
|
|
118
|
+
logger.error(`Issue #${issueNumber} is not tracked`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const existingIssue = issues[index];
|
|
122
|
+
if (!existingIssue)
|
|
123
|
+
return;
|
|
124
|
+
issues[index] = {
|
|
125
|
+
...existingIssue,
|
|
126
|
+
...updates,
|
|
127
|
+
updatedAt: new Date().toISOString(),
|
|
128
|
+
};
|
|
129
|
+
await this.adapter.write(issues);
|
|
130
|
+
logger.debug(`Updated issue #${issueNumber}`);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Update issue status
|
|
134
|
+
*/
|
|
135
|
+
async updateStatus(issueNumber, status) {
|
|
136
|
+
await this.update(issueNumber, { trackingStatus: status });
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Update issue priority
|
|
140
|
+
*/
|
|
141
|
+
async updatePriority(issueNumber, priority) {
|
|
142
|
+
await this.update(issueNumber, { priority });
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Update deployment status
|
|
146
|
+
*/
|
|
147
|
+
async updateDeploymentStatus(issueNumber, status, timestamp) {
|
|
148
|
+
const updates = { deploymentStatus: status };
|
|
149
|
+
// Clear deploymentNotifiedAt when deployment succeeds (so future failures trigger notification)
|
|
150
|
+
if (status === 'success') {
|
|
151
|
+
updates.deploymentNotifiedAt = undefined;
|
|
152
|
+
}
|
|
153
|
+
await this.update(issueNumber, updates);
|
|
154
|
+
logger.debug(`Updated deployment status for #${issueNumber} to ${status}${timestamp ? ` at ${timestamp}` : ''}`);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Mark that Copilot was notified about deployment failure
|
|
158
|
+
*/
|
|
159
|
+
async markDeploymentNotified(issueNumber, timestamp) {
|
|
160
|
+
await this.update(issueNumber, { deploymentNotifiedAt: timestamp });
|
|
161
|
+
logger.debug(`Marked deployment notification sent for #${issueNumber} at ${timestamp}`);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get issues by status
|
|
165
|
+
*/
|
|
166
|
+
async getByStatus(status) {
|
|
167
|
+
const issues = await this.getAll();
|
|
168
|
+
return issues.filter((i) => i.trackingStatus === status);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get issues by priority
|
|
172
|
+
*/
|
|
173
|
+
async getByPriority(priority) {
|
|
174
|
+
const issues = await this.getAll();
|
|
175
|
+
return issues.filter((i) => i.priority === priority);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Sort issues by criteria
|
|
179
|
+
*/
|
|
180
|
+
sortIssues(issues, sortBy, direction = 'desc') {
|
|
181
|
+
const sorted = [...issues].sort((a, b) => {
|
|
182
|
+
let comparison = 0;
|
|
183
|
+
switch (sortBy) {
|
|
184
|
+
case 'created':
|
|
185
|
+
comparison =
|
|
186
|
+
new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
|
187
|
+
break;
|
|
188
|
+
case 'updated':
|
|
189
|
+
comparison =
|
|
190
|
+
new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
|
|
191
|
+
break;
|
|
192
|
+
case 'number':
|
|
193
|
+
comparison = (a.number ?? 0) - (b.number ?? 0);
|
|
194
|
+
break;
|
|
195
|
+
case 'priority':
|
|
196
|
+
const priorityOrder = PROJECT_FIELD_OPTIONS.PRIORITY;
|
|
197
|
+
comparison =
|
|
198
|
+
priorityOrder.indexOf(a.priority) -
|
|
199
|
+
priorityOrder.indexOf(b.priority);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
return direction === 'desc' ? -comparison : comparison;
|
|
203
|
+
});
|
|
204
|
+
return sorted;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Clean up closed issues from GitHub
|
|
208
|
+
* Since we only track 4 active statuses, this checks GitHub for closed issues
|
|
209
|
+
*/
|
|
210
|
+
async cleanClosed() {
|
|
211
|
+
// This method is kept for backwards compatibility with clean command
|
|
212
|
+
// It now checks GitHub issue state instead of tracking status
|
|
213
|
+
// The actual implementation is in the clean command which checks GitHub API
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* File-based tracking adapter
|
|
219
|
+
* Open/Closed Principle: Can extend with new adapters
|
|
220
|
+
*/
|
|
221
|
+
export class TrackingFileAdapter {
|
|
222
|
+
filePath;
|
|
223
|
+
constructor(filePath) {
|
|
224
|
+
this.filePath = filePath;
|
|
225
|
+
}
|
|
226
|
+
async read() {
|
|
227
|
+
if (!existsSync(this.filePath)) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
const content = await readFile(this.filePath, 'utf-8');
|
|
232
|
+
const data = JSON.parse(content);
|
|
233
|
+
const validated = TrackedPlansSchema.parse(data);
|
|
234
|
+
return validated.plans;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
logger.warning(`Error reading tracking file: ${String(error)}`);
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async write(issues) {
|
|
242
|
+
const data = {
|
|
243
|
+
version: '3.0',
|
|
244
|
+
lastUpdated: new Date().toISOString(),
|
|
245
|
+
plans: issues,
|
|
246
|
+
};
|
|
247
|
+
const validated = TrackedPlansSchema.parse(data);
|
|
248
|
+
// Ensure directory exists
|
|
249
|
+
const dir = dirname(this.filePath);
|
|
250
|
+
if (!existsSync(dir)) {
|
|
251
|
+
await mkdir(dir, { recursive: true });
|
|
252
|
+
}
|
|
253
|
+
await writeFile(this.filePath, JSON.stringify(validated, null, 2), 'utf-8');
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=TrackingService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrackingService.js","sourceRoot":"","sources":["../../../src/services/tracking/TrackingService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Config } from '../../types/index.js';
|
|
2
|
+
import type { TrackingService } from './TrackingService.js';
|
|
3
|
+
/**
|
|
4
|
+
* Service for managing untracked assigned issues
|
|
5
|
+
* Helps users track issues they're assigned to but didn't create
|
|
6
|
+
*/
|
|
7
|
+
export declare class UntrackedIssuesService {
|
|
8
|
+
/**
|
|
9
|
+
* Find issues assigned to user but not created by them and not tracked
|
|
10
|
+
*/
|
|
11
|
+
findUntrackedAssignedIssues(trackingService: TrackingService): Promise<Array<{
|
|
12
|
+
number: number;
|
|
13
|
+
title: string;
|
|
14
|
+
}>>;
|
|
15
|
+
/**
|
|
16
|
+
* Prompt user to add untracked assigned issues to tracking
|
|
17
|
+
*/
|
|
18
|
+
promptToAddUntrackedAssignedIssues(config: Config, trackingService: TrackingService): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=UntrackedIssuesService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UntrackedIssuesService.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/UntrackedIssuesService.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAA+B,MAAM,sBAAsB,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;GAGG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACG,2BAA2B,CAC/B,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA8FpD;;OAEG;IACG,kCAAkC,CACtC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,IAAI,CAAC;CAqGjB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
import { IssueService } from '../github/IssueService.js';
|
|
3
|
+
import { getRepoInfo, ghGraphQL } from '../../utils/github-cli.js';
|
|
4
|
+
import { confirm, input, selectPriority } from '../../utils/prompts.js';
|
|
5
|
+
import { STATUS } from '../../types/common.schema.js';
|
|
6
|
+
/**
|
|
7
|
+
* Service for managing untracked assigned issues
|
|
8
|
+
* Helps users track issues they're assigned to but didn't create
|
|
9
|
+
*/
|
|
10
|
+
export class UntrackedIssuesService {
|
|
11
|
+
/**
|
|
12
|
+
* Find issues assigned to user but not created by them and not tracked
|
|
13
|
+
*/
|
|
14
|
+
async findUntrackedAssignedIssues(trackingService) {
|
|
15
|
+
try {
|
|
16
|
+
const repo = await getRepoInfo();
|
|
17
|
+
const trackedIssues = await trackingService.getAll();
|
|
18
|
+
const trackedNumbers = new Set(trackedIssues.map((i) => i.number));
|
|
19
|
+
// GraphQL query to fetch open issues assigned to the current user
|
|
20
|
+
// First get viewer login, then use search to find issues assigned to them
|
|
21
|
+
const viewerQuery = `
|
|
22
|
+
query {
|
|
23
|
+
viewer {
|
|
24
|
+
login
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
const viewerResponse = await ghGraphQL(viewerQuery, {});
|
|
29
|
+
const username = viewerResponse.data.viewer.login;
|
|
30
|
+
// Now search for issues assigned to this user
|
|
31
|
+
const query = `
|
|
32
|
+
query($owner: String!, $name: String!, $assignee: String!) {
|
|
33
|
+
repository(owner: $owner, name: $name) {
|
|
34
|
+
issues(first: 100, states: OPEN, filterBy: {assignee: $assignee}, orderBy: {field: UPDATED_AT, direction: DESC}) {
|
|
35
|
+
nodes {
|
|
36
|
+
number
|
|
37
|
+
title
|
|
38
|
+
author {
|
|
39
|
+
login
|
|
40
|
+
}
|
|
41
|
+
assignees(first: 10) {
|
|
42
|
+
nodes {
|
|
43
|
+
login
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
const response = await ghGraphQL(query, {
|
|
52
|
+
owner: repo.owner,
|
|
53
|
+
name: repo.name,
|
|
54
|
+
assignee: username,
|
|
55
|
+
});
|
|
56
|
+
const untrackedAssigned = [];
|
|
57
|
+
for (const issue of response.data.repository.issues.nodes) {
|
|
58
|
+
// Skip if already tracked
|
|
59
|
+
if (trackedNumbers.has(issue.number))
|
|
60
|
+
continue;
|
|
61
|
+
// Check if assigned to user
|
|
62
|
+
const isAssigned = issue.assignees.nodes.some((assignee) => assignee.login === username);
|
|
63
|
+
// Include all assigned issues (regardless of author)
|
|
64
|
+
if (isAssigned) {
|
|
65
|
+
untrackedAssigned.push({
|
|
66
|
+
number: issue.number,
|
|
67
|
+
title: issue.title,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return untrackedAssigned;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logger.debug(`Error finding untracked assigned issues: ${error instanceof Error ? error.message : String(error)}`);
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Prompt user to add untracked assigned issues to tracking
|
|
80
|
+
*/
|
|
81
|
+
async promptToAddUntrackedAssignedIssues(config, trackingService) {
|
|
82
|
+
const untrackedAssigned = await this.findUntrackedAssignedIssues(trackingService);
|
|
83
|
+
if (untrackedAssigned.length === 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
logger.blank();
|
|
87
|
+
logger.warning(`Found ${untrackedAssigned.length} issue(s) assigned to you that are not being tracked:`);
|
|
88
|
+
logger.blank();
|
|
89
|
+
const repo = await getRepoInfo();
|
|
90
|
+
untrackedAssigned.forEach((issue, index) => {
|
|
91
|
+
logger.info(` ${index + 1}) Issue ${repo.owner}/${repo.name}#${issue.number}: ${issue.title}`);
|
|
92
|
+
});
|
|
93
|
+
logger.blank();
|
|
94
|
+
const shouldAdd = await confirm('Would you like to add these to tracking?', false);
|
|
95
|
+
if (!shouldAdd) {
|
|
96
|
+
logger.info("Skipped adding assigned issues. You can add them later using 'hublaunch track'.");
|
|
97
|
+
logger.blank();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Add each issue to tracking
|
|
101
|
+
const issueService = new IssueService();
|
|
102
|
+
let addedCount = 0;
|
|
103
|
+
for (const untrackedIssue of untrackedAssigned) {
|
|
104
|
+
try {
|
|
105
|
+
logger.blank();
|
|
106
|
+
logger.info(`Issue #${untrackedIssue.number}: ${untrackedIssue.title}`);
|
|
107
|
+
const issueName = await input("Enter a short name to reference this issue (e.g., 'feature-x' or 'bug-fix-y'):");
|
|
108
|
+
if (!issueName || issueName.trim() === '') {
|
|
109
|
+
logger.warning('Skipped - issue name cannot be empty');
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
// Select priority
|
|
113
|
+
const priorityLevels = config.priorityLevels ?? [
|
|
114
|
+
{ name: 'Critical', emoji: '🔴', color: 'red' },
|
|
115
|
+
{ name: 'High', emoji: '🟠', color: 'orange' },
|
|
116
|
+
{ name: 'Medium', emoji: '🟡', color: 'yellow' },
|
|
117
|
+
{ name: 'Low', emoji: '🟢', color: 'green' },
|
|
118
|
+
{ name: 'Minimal', emoji: '⚪', color: 'gray' },
|
|
119
|
+
];
|
|
120
|
+
const priority = await selectPriority('Select priority for this issue:', priorityLevels);
|
|
121
|
+
// Get full issue details
|
|
122
|
+
const issue = await issueService.get(untrackedIssue.number);
|
|
123
|
+
const trackedIssue = {
|
|
124
|
+
name: issueName,
|
|
125
|
+
number: issue.number,
|
|
126
|
+
planPath: '',
|
|
127
|
+
trackingStatus: STATUS.UNASSIGNED,
|
|
128
|
+
priority: priority,
|
|
129
|
+
createdAt: issue.createdAt,
|
|
130
|
+
updatedAt: issue.updatedAt,
|
|
131
|
+
assignees: issue.assignees,
|
|
132
|
+
};
|
|
133
|
+
await trackingService.add(trackedIssue);
|
|
134
|
+
addedCount++;
|
|
135
|
+
logger.success(`Added issue #${issue.number} to tracking`);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
logger.warning(`Could not add issue #${untrackedIssue.number}: ${error instanceof Error ? error.message : String(error)}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
logger.blank();
|
|
142
|
+
if (addedCount > 0) {
|
|
143
|
+
logger.success(`✓ Added ${addedCount} issue(s) to tracking`);
|
|
144
|
+
}
|
|
145
|
+
logger.blank();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=UntrackedIssuesService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UntrackedIssuesService.js","sourceRoot":"","sources":["../../../src/services/tracking/UntrackedIssuesService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idempotent. Renames `<dir>/trackedIssues.json` to
|
|
3
|
+
* `<dir>/trackedPlans.json` if the new file does not already exist, then
|
|
4
|
+
* rewrites the JSON payload to the new schema (renames
|
|
5
|
+
* `repoOwner`/`repoName` fields, drops `job*` fields, sets `version: '3.0'`).
|
|
6
|
+
*
|
|
7
|
+
* Safe to call once per process. No-op when neither file is present, or
|
|
8
|
+
* when the user configured a custom (non-default) `trackingFile` name.
|
|
9
|
+
*/
|
|
10
|
+
export declare function migrateLocalTrackingFile(configuredFilePath: string): Promise<void>;
|
|
11
|
+
export declare function transformLegacyTrackingJson(input: unknown): {
|
|
12
|
+
version: string;
|
|
13
|
+
lastUpdated: string;
|
|
14
|
+
plans: Array<Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=local-file-migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-file-migration.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/local-file-migration.ts"],"names":[],"mappings":"AAQA;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC,CAgDf;AASD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC,CAiCA"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile, rename, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { logger } from '../../utils/logger.js';
|
|
5
|
+
const LEGACY_DEFAULT = 'trackedIssues.json';
|
|
6
|
+
const NEW_DEFAULT = 'trackedPlans.json';
|
|
7
|
+
/**
|
|
8
|
+
* Idempotent. Renames `<dir>/trackedIssues.json` to
|
|
9
|
+
* `<dir>/trackedPlans.json` if the new file does not already exist, then
|
|
10
|
+
* rewrites the JSON payload to the new schema (renames
|
|
11
|
+
* `repoOwner`/`repoName` fields, drops `job*` fields, sets `version: '3.0'`).
|
|
12
|
+
*
|
|
13
|
+
* Safe to call once per process. No-op when neither file is present, or
|
|
14
|
+
* when the user configured a custom (non-default) `trackingFile` name.
|
|
15
|
+
*/
|
|
16
|
+
export async function migrateLocalTrackingFile(configuredFilePath) {
|
|
17
|
+
const dir = dirname(configuredFilePath);
|
|
18
|
+
const legacyPath = join(dir, LEGACY_DEFAULT);
|
|
19
|
+
const newPath = join(dir, NEW_DEFAULT);
|
|
20
|
+
// Honor a non-default configured path: only migrate if user is on
|
|
21
|
+
// the new default name AND the legacy default file is present.
|
|
22
|
+
if (!configuredFilePath.endsWith(NEW_DEFAULT) || !existsSync(legacyPath)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (existsSync(newPath)) {
|
|
26
|
+
logger.warning(`Both trackedIssues.json and trackedPlans.json exist in ${dir}. ` +
|
|
27
|
+
`Using trackedPlans.json; please remove the legacy file manually.`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Rename
|
|
31
|
+
await rename(legacyPath, newPath);
|
|
32
|
+
// Transform JSON
|
|
33
|
+
let raw;
|
|
34
|
+
try {
|
|
35
|
+
raw = await readFile(newPath, 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
logger.warning(`Renamed ${LEGACY_DEFAULT} → ${NEW_DEFAULT} but could not read content.`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
logger.warning(`${NEW_DEFAULT} after rename is not valid JSON; leaving untouched.`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const migrated = transformLegacyTrackingJson(parsed);
|
|
50
|
+
await writeFile(newPath, JSON.stringify(migrated, null, 2) + '\n', 'utf-8');
|
|
51
|
+
logger.info(`Migrated local tracking file: ${LEGACY_DEFAULT} → ${NEW_DEFAULT}`);
|
|
52
|
+
}
|
|
53
|
+
export function transformLegacyTrackingJson(input) {
|
|
54
|
+
const doc = (input ?? {});
|
|
55
|
+
const items = doc.plans ?? doc.issues ?? [];
|
|
56
|
+
const plans = items.map((row) => {
|
|
57
|
+
const out = { ...row };
|
|
58
|
+
if ('repoOwner' in out) {
|
|
59
|
+
out.projectOwner = out.repoOwner;
|
|
60
|
+
delete out.repoOwner;
|
|
61
|
+
}
|
|
62
|
+
if ('repoName' in out) {
|
|
63
|
+
out.projectName = out.repoName;
|
|
64
|
+
delete out.repoName;
|
|
65
|
+
}
|
|
66
|
+
for (const k of [
|
|
67
|
+
'jobStatus',
|
|
68
|
+
'jobPid',
|
|
69
|
+
'jobStartedAt',
|
|
70
|
+
'jobCompletedAt',
|
|
71
|
+
'jobExitCode',
|
|
72
|
+
'jobOutputPath',
|
|
73
|
+
'jobLogPath',
|
|
74
|
+
'jobStartedBy',
|
|
75
|
+
]) {
|
|
76
|
+
delete out[k];
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
version: '3.0',
|
|
82
|
+
lastUpdated: doc.lastUpdated ?? new Date().toISOString(),
|
|
83
|
+
plans,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=local-file-migration.js.map
|