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,230 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
6
|
+
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
|
7
|
+
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
8
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { dirname } from 'path';
|
|
11
|
+
import { ProjectService } from '../github/ProjectService.js';
|
|
12
|
+
import { getRepoInfo } from '../../utils/github-cli.js';
|
|
13
|
+
import { logger } from '../../utils/logger.js';
|
|
14
|
+
/**
|
|
15
|
+
* GitHub Projects V2 adapter for tracking issues
|
|
16
|
+
* Reads/writes tracking data from GitHub Projects instead of local file
|
|
17
|
+
* Deployment status is detected from PR comments when fetching issues
|
|
18
|
+
* Notification timestamps are cached locally (minimal persistence)
|
|
19
|
+
*
|
|
20
|
+
* @note This adapter is in development and has type safety disabled temporarily
|
|
21
|
+
*/
|
|
22
|
+
export class ProjectTrackingAdapter {
|
|
23
|
+
projectService;
|
|
24
|
+
projectNumber;
|
|
25
|
+
projectId;
|
|
26
|
+
owner;
|
|
27
|
+
notificationCachePath = '.hublaunch/notificationCache.json';
|
|
28
|
+
constructor(projectNumber, projectId, owner) {
|
|
29
|
+
this.projectService = new ProjectService();
|
|
30
|
+
this.projectNumber = projectNumber;
|
|
31
|
+
this.projectId = projectId;
|
|
32
|
+
this.owner = owner;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get owner from repo or use configured owner
|
|
36
|
+
*/
|
|
37
|
+
async getOwner() {
|
|
38
|
+
if (this.owner) {
|
|
39
|
+
return this.owner;
|
|
40
|
+
}
|
|
41
|
+
const repo = await getRepoInfo();
|
|
42
|
+
return repo.owner;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Load notification timestamps from cache
|
|
46
|
+
*/
|
|
47
|
+
async loadNotificationCache() {
|
|
48
|
+
if (!existsSync(this.notificationCachePath)) {
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const content = await readFile(this.notificationCachePath, 'utf-8');
|
|
53
|
+
return JSON.parse(content);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
logger.debug(`Failed to load notification cache: ${String(error)}`);
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Save notification timestamps to cache
|
|
62
|
+
*/
|
|
63
|
+
async saveNotificationCache(issues) {
|
|
64
|
+
try {
|
|
65
|
+
const cache = {};
|
|
66
|
+
for (const issue of issues) {
|
|
67
|
+
if (issue.deploymentNotifiedAt && issue.number !== undefined) {
|
|
68
|
+
cache[issue.number] = issue.deploymentNotifiedAt;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const dir = dirname(this.notificationCachePath);
|
|
72
|
+
if (!existsSync(dir)) {
|
|
73
|
+
await mkdir(dir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
await writeFile(this.notificationCachePath, JSON.stringify(cache, null, 2), 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
logger.debug(`Failed to save notification cache: ${String(error)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Read all tracked issues from GitHub Projects
|
|
83
|
+
* Deployment status is detected from PR comments by ProjectService
|
|
84
|
+
*/
|
|
85
|
+
async read() {
|
|
86
|
+
try {
|
|
87
|
+
const owner = await this.getOwner();
|
|
88
|
+
const projectIssues = await this.projectService.getProjectIssues(owner, this.projectNumber);
|
|
89
|
+
// Load notification timestamps from cache
|
|
90
|
+
const notificationCache = await this.loadNotificationCache();
|
|
91
|
+
// Convert project issues to TrackedIssue format
|
|
92
|
+
// Filter issues where either owner is tracking OR assignee is following
|
|
93
|
+
const trackedIssues = projectIssues
|
|
94
|
+
.filter((issue) => issue.ownerIsTracking || issue.assigneeIsFollowing)
|
|
95
|
+
.map((issue) => ({
|
|
96
|
+
number: issue.number,
|
|
97
|
+
name: issue.trackingName,
|
|
98
|
+
priority: issue.priority,
|
|
99
|
+
trackingStatus: issue.status,
|
|
100
|
+
createdAt: new Date().toISOString(),
|
|
101
|
+
updatedAt: new Date().toISOString(),
|
|
102
|
+
projectItemId: issue.itemId, // Store project item ID for updates
|
|
103
|
+
githubState: issue.githubState, // Store GitHub issue state
|
|
104
|
+
prNumber: issue.prNumber, // Store PR number if available
|
|
105
|
+
prUrl: issue.prUrl, // Store PR URL if available
|
|
106
|
+
deploymentStatus: issue.deploymentStatus, // From PR comments
|
|
107
|
+
deploymentNotifiedAt: notificationCache[issue.number], // From cache
|
|
108
|
+
}));
|
|
109
|
+
return trackedIssues;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
113
|
+
const errorLower = errorMessage.toLowerCase();
|
|
114
|
+
// Check if it's a connection/auth error
|
|
115
|
+
const isConnectionError = errorLower.includes('enotfound') ||
|
|
116
|
+
errorLower.includes('etimedout') ||
|
|
117
|
+
errorLower.includes('econnrefused') ||
|
|
118
|
+
errorLower.includes('api.github.com') ||
|
|
119
|
+
errorLower.includes('network');
|
|
120
|
+
const isAuthError = errorLower.includes('authentication') ||
|
|
121
|
+
errorLower.includes('unauthorized') ||
|
|
122
|
+
errorLower.includes('http 401');
|
|
123
|
+
// Only log connection/auth errors as debug to avoid spam during background polling
|
|
124
|
+
if (isConnectionError || isAuthError) {
|
|
125
|
+
logger.debug(`Failed to read from GitHub Projects: ${errorMessage}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
logger.error('Failed to read from GitHub Projects');
|
|
129
|
+
logger.debug(errorMessage);
|
|
130
|
+
}
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Write tracked issues to GitHub Projects
|
|
136
|
+
* This syncs all local changes to the project
|
|
137
|
+
*/
|
|
138
|
+
async write(issues) {
|
|
139
|
+
try {
|
|
140
|
+
const owner = await this.getOwner();
|
|
141
|
+
// Get current project state
|
|
142
|
+
const projectIssues = await this.projectService.getProjectIssues(owner, this.projectNumber);
|
|
143
|
+
// Update each issue in the project
|
|
144
|
+
for (const issue of issues) {
|
|
145
|
+
// Skip issues without a number (e.g., standalone jobs)
|
|
146
|
+
if (issue.number === undefined) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const projectIssue = projectIssues.find((pi) => pi.number === issue.number);
|
|
150
|
+
if (!projectIssue) {
|
|
151
|
+
// Issue not in project yet, add it
|
|
152
|
+
logger.debug(`Adding issue #${issue.number} to project...`);
|
|
153
|
+
try {
|
|
154
|
+
const itemId = await this.projectService.addIssueToProject(issue.number, this.projectNumber, owner);
|
|
155
|
+
// Set tracking name
|
|
156
|
+
const trackingField = await this.projectService.findFieldByName(owner, this.projectNumber, 'Tracking Name');
|
|
157
|
+
if (trackingField) {
|
|
158
|
+
await this.projectService.updateTextField(this.projectId, itemId, trackingField.id, issue.name);
|
|
159
|
+
}
|
|
160
|
+
// Set tracking field (OwnerIsTracking or AssigneeIsFollowing)
|
|
161
|
+
await this.projectService.setIssueTracking(itemId, true, this.projectId, owner, this.projectNumber);
|
|
162
|
+
// Set status
|
|
163
|
+
await this.projectService.updateIssueStatus(itemId, issue.trackingStatus, this.projectId, owner, this.projectNumber);
|
|
164
|
+
// Set priority
|
|
165
|
+
await this.projectService.updateIssuePriority(itemId, issue.priority, this.projectId, owner, this.projectNumber);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
logger.debug(`Failed to add issue #${issue.number} to project: ${error}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
// Issue exists, update if changed
|
|
173
|
+
const itemId = issue.projectItemId || projectIssue.itemId;
|
|
174
|
+
// Ensure tracking field is set (OwnerIsTracking or AssigneeIsFollowing)
|
|
175
|
+
if (!projectIssue.ownerIsTracking &&
|
|
176
|
+
!projectIssue.assigneeIsFollowing) {
|
|
177
|
+
logger.debug(`Setting tracking field for existing issue #${issue.number}...`);
|
|
178
|
+
await this.projectService.setIssueTracking(itemId, true, this.projectId, owner, this.projectNumber);
|
|
179
|
+
}
|
|
180
|
+
if (projectIssue.trackingName !== issue.name) {
|
|
181
|
+
logger.debug(`Updating tracking name for issue #${issue.number}...`);
|
|
182
|
+
const trackingField = await this.projectService.findFieldByName(owner, this.projectNumber, 'Tracking Name');
|
|
183
|
+
if (trackingField) {
|
|
184
|
+
await this.projectService.updateTextField(this.projectId, itemId, trackingField.id, issue.name);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (projectIssue.status !== issue.trackingStatus) {
|
|
188
|
+
logger.debug(`Updating status for issue #${issue.number}: ${projectIssue.status} → ${issue.trackingStatus}`);
|
|
189
|
+
await this.projectService.updateIssueStatus(itemId, issue.trackingStatus, this.projectId, owner, this.projectNumber);
|
|
190
|
+
}
|
|
191
|
+
if (projectIssue.priority !== issue.priority) {
|
|
192
|
+
logger.debug(`Updating priority for issue #${issue.number}: ${projectIssue.priority} → ${issue.priority}`);
|
|
193
|
+
await this.projectService.updateIssuePriority(itemId, issue.priority, this.projectId, owner, this.projectNumber);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Note: We don't remove issues from the project when untracking
|
|
198
|
+
// Instead, the OwnerIsTracking/AssigneeIsFollowing fields control visibility
|
|
199
|
+
// Issues remain in the project for historical tracking
|
|
200
|
+
// Save notification timestamps to cache (not stored in GitHub Projects)
|
|
201
|
+
await this.saveNotificationCache(issues);
|
|
202
|
+
logger.debug('Successfully synced to GitHub Projects');
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
206
|
+
const errorLower = errorMessage.toLowerCase();
|
|
207
|
+
// Check if it's a connection/auth error
|
|
208
|
+
const isConnectionError = errorLower.includes('enotfound') ||
|
|
209
|
+
errorLower.includes('etimedout') ||
|
|
210
|
+
errorLower.includes('econnrefused') ||
|
|
211
|
+
errorLower.includes('econnreset') ||
|
|
212
|
+
errorLower.includes('api.github.com') ||
|
|
213
|
+
errorLower.includes('network');
|
|
214
|
+
const isAuthError = errorLower.includes('authentication') ||
|
|
215
|
+
errorLower.includes('unauthorized') ||
|
|
216
|
+
errorLower.includes('http 401');
|
|
217
|
+
// Only log connection/auth errors as debug to avoid spam during background polling
|
|
218
|
+
// These are transient errors that will be handled by the polling service
|
|
219
|
+
if (isConnectionError || isAuthError) {
|
|
220
|
+
logger.debug(`Failed to write to GitHub Projects: ${errorMessage}`);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
logger.error('Failed to write to GitHub Projects');
|
|
224
|
+
logger.debug(errorMessage);
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=ProjectTrackingAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectTrackingAdapter.js","sourceRoot":"","sources":["../../../src/services/tracking/ProjectTrackingAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ITrackingAdapter } from './TrackingService.js';
|
|
2
|
+
import { TrackedPlan } from '../../types/index.js';
|
|
3
|
+
import { HulaApiClient } from '../api/HulaApiClient.js';
|
|
4
|
+
/**
|
|
5
|
+
* Remote tracking adapter that uses hula-project API for plan tracking.
|
|
6
|
+
* Replaces local GitHub Projects integration with server-side tracking.
|
|
7
|
+
*
|
|
8
|
+
* Implements caching to reduce API calls during interactive mode.
|
|
9
|
+
*/
|
|
10
|
+
export declare class RemoteTrackingAdapter implements ITrackingAdapter {
|
|
11
|
+
private client;
|
|
12
|
+
private cache;
|
|
13
|
+
private lastFetched;
|
|
14
|
+
private readonly CACHE_TTL;
|
|
15
|
+
private currentUserId;
|
|
16
|
+
constructor(client: HulaApiClient);
|
|
17
|
+
/**
|
|
18
|
+
* Returns the authenticated user id captured from the most recent
|
|
19
|
+
* server response, or null if it has not yet been observed (older
|
|
20
|
+
* server, or no list call has been made yet).
|
|
21
|
+
*/
|
|
22
|
+
getCurrentUserId(): string | null;
|
|
23
|
+
private fetchAllPlans;
|
|
24
|
+
private mapApiPlanToTrackedPlan;
|
|
25
|
+
private canonicalName;
|
|
26
|
+
/**
|
|
27
|
+
* Read all tracked plans from the server (implements ITrackingAdapter)
|
|
28
|
+
*/
|
|
29
|
+
read(): Promise<TrackedPlan[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Write tracked plans (implements ITrackingAdapter)
|
|
32
|
+
* No-op for remote adapter - server handles persistence via API calls
|
|
33
|
+
*/
|
|
34
|
+
write(_plans: TrackedPlan[]): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Add a new tracked plan
|
|
37
|
+
*/
|
|
38
|
+
add(plan: TrackedPlan): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Remove a tracked plan
|
|
41
|
+
*/
|
|
42
|
+
remove(trackingName: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Update a tracked plan
|
|
45
|
+
*/
|
|
46
|
+
update(trackingName: string, updates: Partial<TrackedPlan>): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Get a specific tracked plan
|
|
49
|
+
*/
|
|
50
|
+
get(trackingName: string): Promise<TrackedPlan | null>;
|
|
51
|
+
/**
|
|
52
|
+
* Get all tracked plans
|
|
53
|
+
*/
|
|
54
|
+
getAll(): Promise<TrackedPlan[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Force refresh cache (useful after mutations)
|
|
57
|
+
*/
|
|
58
|
+
refresh(): Promise<void>;
|
|
59
|
+
private isCacheValid;
|
|
60
|
+
private invalidateCache;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=RemoteTrackingAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RemoteTrackingAdapter.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/RemoteTrackingAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAkB,MAAM,yBAAyB,CAAC;AAOxE;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,aAAa,CAAuB;gBAEhC,MAAM,EAAE,aAAa;IAIjC;;;;OAIG;IACH,gBAAgB,IAAI,MAAM,GAAG,IAAI;YAInB,aAAa;IAgB3B,OAAO,CAAC,uBAAuB;IAiC/B,OAAO,CAAC,aAAa;IAMrB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IA+CpC;;;OAGG;IACG,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjD;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA0C3C;;OAEG;IACG,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BjD;;OAEG;IACG,MAAM,CACV,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;IAkChB;;OAEG;IACG,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAiB5D;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAItC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;CAGxB"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
import { readdir } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
/**
|
|
7
|
+
* Remote tracking adapter that uses hula-project API for plan tracking.
|
|
8
|
+
* Replaces local GitHub Projects integration with server-side tracking.
|
|
9
|
+
*
|
|
10
|
+
* Implements caching to reduce API calls during interactive mode.
|
|
11
|
+
*/
|
|
12
|
+
export class RemoteTrackingAdapter {
|
|
13
|
+
client;
|
|
14
|
+
cache = new Map();
|
|
15
|
+
lastFetched = 0;
|
|
16
|
+
CACHE_TTL = 10000; // 10 seconds
|
|
17
|
+
currentUserId = null;
|
|
18
|
+
constructor(client) {
|
|
19
|
+
this.client = client;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns the authenticated user id captured from the most recent
|
|
23
|
+
* server response, or null if it has not yet been observed (older
|
|
24
|
+
* server, or no list call has been made yet).
|
|
25
|
+
*/
|
|
26
|
+
getCurrentUserId() {
|
|
27
|
+
return this.currentUserId;
|
|
28
|
+
}
|
|
29
|
+
async fetchAllPlans() {
|
|
30
|
+
let all = [];
|
|
31
|
+
let page = 1;
|
|
32
|
+
let totalPages = 1;
|
|
33
|
+
do {
|
|
34
|
+
const response = await this.client.listPlans({ page, limit: 100 });
|
|
35
|
+
all = all.concat(response.plans);
|
|
36
|
+
totalPages = response.totalPages;
|
|
37
|
+
if (response.currentUserId) {
|
|
38
|
+
this.currentUserId = response.currentUserId;
|
|
39
|
+
}
|
|
40
|
+
page++;
|
|
41
|
+
} while (page <= totalPages);
|
|
42
|
+
return all;
|
|
43
|
+
}
|
|
44
|
+
mapApiPlanToTrackedPlan(apiPlan) {
|
|
45
|
+
return {
|
|
46
|
+
name: apiPlan.issueNumber != null
|
|
47
|
+
? `${apiPlan.project.owner}/${apiPlan.project.name}#${apiPlan.issueNumber}`
|
|
48
|
+
: `${apiPlan.project.owner}/${apiPlan.project.name}#unknown-${apiPlan.id}`,
|
|
49
|
+
trackingName: apiPlan.trackingName,
|
|
50
|
+
number: apiPlan.issueNumber ?? undefined,
|
|
51
|
+
title: apiPlan.title,
|
|
52
|
+
trackingStatus: apiPlan.trackingStatus,
|
|
53
|
+
githubState: apiPlan.githubState,
|
|
54
|
+
priority: apiPlan.priority,
|
|
55
|
+
projectOwner: apiPlan.project.owner,
|
|
56
|
+
projectName: apiPlan.project.name,
|
|
57
|
+
createdById: apiPlan.createdById,
|
|
58
|
+
prNumber: apiPlan.prNumber || undefined,
|
|
59
|
+
prUrl: apiPlan.prUrl || undefined,
|
|
60
|
+
createdAt: apiPlan.createdAt,
|
|
61
|
+
updatedAt: apiPlan.updatedAt,
|
|
62
|
+
planPath: undefined,
|
|
63
|
+
deploymentStatus: apiPlan.deploymentStatus ?? undefined,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
canonicalName(apiPlan) {
|
|
67
|
+
return apiPlan.issueNumber != null
|
|
68
|
+
? `${apiPlan.project.owner}/${apiPlan.project.name}#${apiPlan.issueNumber}`
|
|
69
|
+
: `${apiPlan.project.owner}/${apiPlan.project.name}#unknown-${apiPlan.id}`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Read all tracked plans from the server (implements ITrackingAdapter)
|
|
73
|
+
*/
|
|
74
|
+
async read() {
|
|
75
|
+
if (this.isCacheValid()) {
|
|
76
|
+
return Array.from(this.cache.values());
|
|
77
|
+
}
|
|
78
|
+
const allApiPlans = await this.fetchAllPlans();
|
|
79
|
+
const plans = allApiPlans.map((p) => this.mapApiPlanToTrackedPlan(p));
|
|
80
|
+
// Populate planPath for each plan by searching local plan directory
|
|
81
|
+
const plansDir = join(os.homedir(), '.hublaunch', 'plans');
|
|
82
|
+
if (existsSync(plansDir)) {
|
|
83
|
+
try {
|
|
84
|
+
const planFiles = await readdir(plansDir);
|
|
85
|
+
for (const plan of plans) {
|
|
86
|
+
if (plan.number == null)
|
|
87
|
+
continue;
|
|
88
|
+
const matchingFile = planFiles.find((file) => {
|
|
89
|
+
return (file.includes(`-${plan.number}-`) ||
|
|
90
|
+
file.includes(`#${plan.number}`));
|
|
91
|
+
});
|
|
92
|
+
if (matchingFile) {
|
|
93
|
+
plan.planPath = join(plansDir, matchingFile);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
logger.debug(`Could not read plans directory: ${error instanceof Error ? error.message : String(error)}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Update cache
|
|
102
|
+
this.cache.clear();
|
|
103
|
+
plans.forEach((plan) => this.cache.set(plan.name, plan));
|
|
104
|
+
this.lastFetched = Date.now();
|
|
105
|
+
return plans;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Write tracked plans (implements ITrackingAdapter)
|
|
109
|
+
* No-op for remote adapter - server handles persistence via API calls
|
|
110
|
+
*/
|
|
111
|
+
async write(_plans) {
|
|
112
|
+
// No-op: server handles persistence through API endpoints
|
|
113
|
+
logger.debug('RemoteTrackingAdapter: write() called (no-op)');
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Add a new tracked plan
|
|
117
|
+
*/
|
|
118
|
+
async add(plan) {
|
|
119
|
+
try {
|
|
120
|
+
const match = plan.name.match(/^(.+?)\/(.+?)#(\d+)$/);
|
|
121
|
+
if (!match) {
|
|
122
|
+
throw new Error(`Invalid tracking name format: ${plan.name}`);
|
|
123
|
+
}
|
|
124
|
+
const owner = match[1];
|
|
125
|
+
const repo = match[2];
|
|
126
|
+
if (!owner || !repo) {
|
|
127
|
+
throw new Error(`Could not extract owner/repo from: ${plan.name}`);
|
|
128
|
+
}
|
|
129
|
+
if (plan.number === undefined) {
|
|
130
|
+
throw new Error(`Plan number is required for tracking: ${plan.name}`);
|
|
131
|
+
}
|
|
132
|
+
await this.client.trackPlan({
|
|
133
|
+
owner,
|
|
134
|
+
repo,
|
|
135
|
+
issueNumber: plan.number,
|
|
136
|
+
trackingName: plan.trackingName || plan.name,
|
|
137
|
+
title: plan.title || plan.name,
|
|
138
|
+
priority: plan.priority,
|
|
139
|
+
// Forward new fields if present (presence of planPath triggers create-new on server)
|
|
140
|
+
...(plan.planPath !== undefined && { planPath: plan.planPath }),
|
|
141
|
+
...(plan.copilotAssigned !== undefined && {
|
|
142
|
+
copilotAssigned: plan.copilotAssigned,
|
|
143
|
+
}),
|
|
144
|
+
});
|
|
145
|
+
this.cache.set(plan.name, plan);
|
|
146
|
+
this.invalidateCache();
|
|
147
|
+
logger.debug(`Tracked plan: ${plan.name}`);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
logger.error(`Failed to track plan: ${plan.name}`);
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Remove a tracked plan
|
|
156
|
+
*/
|
|
157
|
+
async remove(trackingName) {
|
|
158
|
+
try {
|
|
159
|
+
const allApiPlans = await this.fetchAllPlans();
|
|
160
|
+
const apiPlan = allApiPlans.find((p) => p.trackingName === trackingName ||
|
|
161
|
+
this.canonicalName(p) === trackingName);
|
|
162
|
+
if (!apiPlan) {
|
|
163
|
+
throw new Error(`Plan ${trackingName} not found on server`);
|
|
164
|
+
}
|
|
165
|
+
await this.client.untrackPlan(apiPlan.id);
|
|
166
|
+
this.cache.delete(trackingName);
|
|
167
|
+
this.invalidateCache();
|
|
168
|
+
logger.debug(`Untracked plan: ${trackingName}`);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
logger.debug(`Failed to untrack plan: ${trackingName}`);
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Update a tracked plan
|
|
177
|
+
*/
|
|
178
|
+
async update(trackingName, updates) {
|
|
179
|
+
try {
|
|
180
|
+
const allApiPlans = await this.fetchAllPlans();
|
|
181
|
+
const apiPlan = allApiPlans.find((p) => p.trackingName === trackingName ||
|
|
182
|
+
this.canonicalName(p) === trackingName);
|
|
183
|
+
if (!apiPlan) {
|
|
184
|
+
throw new Error(`Plan ${trackingName} not found`);
|
|
185
|
+
}
|
|
186
|
+
// Only priority updates are supported in current API
|
|
187
|
+
if (updates.priority) {
|
|
188
|
+
await this.client.updatePlanPriority(apiPlan.id, updates.priority);
|
|
189
|
+
}
|
|
190
|
+
// Update cache
|
|
191
|
+
const cached = this.cache.get(trackingName);
|
|
192
|
+
if (cached) {
|
|
193
|
+
this.cache.set(trackingName, { ...cached, ...updates });
|
|
194
|
+
}
|
|
195
|
+
this.invalidateCache();
|
|
196
|
+
logger.debug(`Updated plan: ${trackingName}`);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
logger.error(`Failed to update plan: ${trackingName}`);
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get a specific tracked plan
|
|
205
|
+
*/
|
|
206
|
+
async get(trackingName) {
|
|
207
|
+
try {
|
|
208
|
+
if (this.isCacheValid()) {
|
|
209
|
+
const cached = this.cache.get(trackingName);
|
|
210
|
+
if (cached) {
|
|
211
|
+
return cached;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const all = await this.read();
|
|
215
|
+
return all.find((plan) => plan.name === trackingName) || null;
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
logger.error(`Failed to get plan: ${trackingName}`);
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get all tracked plans
|
|
224
|
+
*/
|
|
225
|
+
async getAll() {
|
|
226
|
+
return this.read();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Force refresh cache (useful after mutations)
|
|
230
|
+
*/
|
|
231
|
+
async refresh() {
|
|
232
|
+
this.invalidateCache();
|
|
233
|
+
await this.read();
|
|
234
|
+
}
|
|
235
|
+
isCacheValid() {
|
|
236
|
+
return Date.now() - this.lastFetched < this.CACHE_TTL;
|
|
237
|
+
}
|
|
238
|
+
invalidateCache() {
|
|
239
|
+
this.lastFetched = 0;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=RemoteTrackingAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RemoteTrackingAdapter.js","sourceRoot":"","sources":["../../../src/services/tracking/RemoteTrackingAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ITrackingAdapter } from './TrackingService.js';
|
|
2
|
+
import { type Config } from '../../types/config.schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Factory for creating the appropriate tracking adapter based on configuration
|
|
5
|
+
*
|
|
6
|
+
* Strategy:
|
|
7
|
+
* - If hulaApiKey is configured → Use RemoteTrackingAdapter (hula-project server)
|
|
8
|
+
* - Else if projectNumber and projectId are configured AND projectAutoSync is true → Use ProjectTrackingAdapter (deprecated)
|
|
9
|
+
* - Otherwise → Use TrackingFileAdapter (local JSON storage)
|
|
10
|
+
*/
|
|
11
|
+
export declare class TrackingAdapterFactory {
|
|
12
|
+
/**
|
|
13
|
+
* Create the appropriate tracking adapter based on config
|
|
14
|
+
*/
|
|
15
|
+
static create(config: Config): ITrackingAdapter;
|
|
16
|
+
/**
|
|
17
|
+
* Check if GitHub Projects integration is available (configured but not necessarily auto-sync)
|
|
18
|
+
*/
|
|
19
|
+
static isProjectsAvailable(config: Config): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Check if auto-sync is enabled
|
|
22
|
+
*/
|
|
23
|
+
static isAutoSyncEnabled(config: Config): boolean;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=TrackingAdapterFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrackingAdapterFactory.d.ts","sourceRoot":"","sources":["../../../src/services/tracking/TrackingAdapterFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAG3D;;;;;;;GAOG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB;IA4B/C;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAInD;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAKlD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { TrackingFileAdapter, } from './TrackingService.js';
|
|
2
|
+
import { ProjectTrackingAdapter } from './ProjectTrackingAdapter.js';
|
|
3
|
+
import { RemoteTrackingAdapter } from './RemoteTrackingAdapter.js';
|
|
4
|
+
import { HulaApiClient } from '../api/HulaApiClient.js';
|
|
5
|
+
import { logger } from '../../utils/logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Factory for creating the appropriate tracking adapter based on configuration
|
|
8
|
+
*
|
|
9
|
+
* Strategy:
|
|
10
|
+
* - If hulaApiKey is configured → Use RemoteTrackingAdapter (hula-project server)
|
|
11
|
+
* - Else if projectNumber and projectId are configured AND projectAutoSync is true → Use ProjectTrackingAdapter (deprecated)
|
|
12
|
+
* - Otherwise → Use TrackingFileAdapter (local JSON storage)
|
|
13
|
+
*/
|
|
14
|
+
export class TrackingAdapterFactory {
|
|
15
|
+
/**
|
|
16
|
+
* Create the appropriate tracking adapter based on config
|
|
17
|
+
*/
|
|
18
|
+
static create(config) {
|
|
19
|
+
// Priority 1: Remote tracking via hula-project API
|
|
20
|
+
if (config.hulaApiKey && config.hulaProjectUrl) {
|
|
21
|
+
logger.debug('Using Remote tracking adapter (hula-project API)');
|
|
22
|
+
const client = new HulaApiClient({
|
|
23
|
+
baseUrl: config.hulaProjectUrl,
|
|
24
|
+
apiKey: config.hulaApiKey,
|
|
25
|
+
});
|
|
26
|
+
return new RemoteTrackingAdapter(client);
|
|
27
|
+
}
|
|
28
|
+
// Show migration message if using deprecated GitHub Projects
|
|
29
|
+
if (config.projectNumber && config.projectId) {
|
|
30
|
+
logger.warning('GitHub Projects integration is deprecated!');
|
|
31
|
+
logger.warning("Run 'hula login' to migrate to hula-project.");
|
|
32
|
+
}
|
|
33
|
+
// Priority 2: GitHub Projects (deprecated, but still supported)
|
|
34
|
+
if (config.projectNumber && config.projectId && config.projectAutoSync) {
|
|
35
|
+
logger.debug('Using GitHub Projects adapter (deprecated)');
|
|
36
|
+
return new ProjectTrackingAdapter(config.projectNumber, config.projectId);
|
|
37
|
+
}
|
|
38
|
+
// Default: file-based tracking
|
|
39
|
+
logger.debug(`Using file-based tracking adapter: ${config.trackingFile}`);
|
|
40
|
+
return new TrackingFileAdapter(config.trackingFile);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if GitHub Projects integration is available (configured but not necessarily auto-sync)
|
|
44
|
+
*/
|
|
45
|
+
static isProjectsAvailable(config) {
|
|
46
|
+
return Boolean(config.projectNumber && config.projectId);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if auto-sync is enabled
|
|
50
|
+
*/
|
|
51
|
+
static isAutoSyncEnabled(config) {
|
|
52
|
+
return Boolean(config.projectNumber && config.projectId && config.projectAutoSync);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=TrackingAdapterFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrackingAdapterFactory.js","sourceRoot":"","sources":["../../../src/services/tracking/TrackingAdapterFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,OAAO,sBAAsB;IACjC;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,MAAc;QAC1B,mDAAmD;QACnD,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;YACjE,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC;gBAC/B,OAAO,EAAE,MAAM,CAAC,cAAc;gBAC9B,MAAM,EAAE,MAAM,CAAC,UAAU;aAC1B,CAAC,CAAC;YACH,OAAO,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;QAED,6DAA6D;QAC7D,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YAC7C,MAAM,CAAC,OAAO,CAAC,4CAA4C,CAAC,CAAC;YAC7D,MAAM,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC;QACjE,CAAC;QAED,gEAAgE;QAChE,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YACvE,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAC3D,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5E,CAAC;QAED,+BAA+B;QAC/B,MAAM,CAAC,KAAK,CAAC,sCAAsC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1E,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,MAAc;QACvC,OAAO,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,MAAc;QACrC,OAAO,OAAO,CACZ,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,eAAe,CACnE,CAAC;IACJ,CAAC;CACF"}
|