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.
Files changed (331) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/README.md +195 -0
  3. package/bin/hublaunch +20 -0
  4. package/dist/commands/checkout.d.ts +7 -0
  5. package/dist/commands/checkout.d.ts.map +1 -0
  6. package/dist/commands/checkout.js +164 -0
  7. package/dist/commands/checkout.js.map +1 -0
  8. package/dist/commands/clean.d.ts +7 -0
  9. package/dist/commands/clean.d.ts.map +1 -0
  10. package/dist/commands/clean.js +206 -0
  11. package/dist/commands/clean.js.map +1 -0
  12. package/dist/commands/close.d.ts +7 -0
  13. package/dist/commands/close.d.ts.map +1 -0
  14. package/dist/commands/close.js +109 -0
  15. package/dist/commands/close.js.map +1 -0
  16. package/dist/commands/create.d.ts +7 -0
  17. package/dist/commands/create.d.ts.map +1 -0
  18. package/dist/commands/create.js +367 -0
  19. package/dist/commands/create.js.map +1 -0
  20. package/dist/commands/diff.d.ts +7 -0
  21. package/dist/commands/diff.d.ts.map +1 -0
  22. package/dist/commands/diff.js +98 -0
  23. package/dist/commands/diff.js.map +1 -0
  24. package/dist/commands/execute.d.ts +7 -0
  25. package/dist/commands/execute.d.ts.map +1 -0
  26. package/dist/commands/execute.js +376 -0
  27. package/dist/commands/execute.js.map +1 -0
  28. package/dist/commands/init.d.ts +8 -0
  29. package/dist/commands/init.d.ts.map +1 -0
  30. package/dist/commands/init.js +1243 -0
  31. package/dist/commands/init.js.map +1 -0
  32. package/dist/commands/interactive.d.ts +12 -0
  33. package/dist/commands/interactive.d.ts.map +1 -0
  34. package/dist/commands/interactive.js +1071 -0
  35. package/dist/commands/interactive.js.map +1 -0
  36. package/dist/commands/launch.d.ts +16 -0
  37. package/dist/commands/launch.d.ts.map +1 -0
  38. package/dist/commands/launch.js +684 -0
  39. package/dist/commands/launch.js.map +1 -0
  40. package/dist/commands/login.d.ts +40 -0
  41. package/dist/commands/login.d.ts.map +1 -0
  42. package/dist/commands/login.js +469 -0
  43. package/dist/commands/login.js.map +1 -0
  44. package/dist/commands/logs.d.ts +22 -0
  45. package/dist/commands/logs.d.ts.map +1 -0
  46. package/dist/commands/logs.js +105 -0
  47. package/dist/commands/logs.js.map +1 -0
  48. package/dist/commands/merge.d.ts +7 -0
  49. package/dist/commands/merge.d.ts.map +1 -0
  50. package/dist/commands/merge.js +240 -0
  51. package/dist/commands/merge.js.map +1 -0
  52. package/dist/commands/preview.d.ts +7 -0
  53. package/dist/commands/preview.d.ts.map +1 -0
  54. package/dist/commands/preview.js +160 -0
  55. package/dist/commands/preview.js.map +1 -0
  56. package/dist/commands/project.d.ts +18 -0
  57. package/dist/commands/project.d.ts.map +1 -0
  58. package/dist/commands/project.js +352 -0
  59. package/dist/commands/project.js.map +1 -0
  60. package/dist/commands/respond.d.ts +7 -0
  61. package/dist/commands/respond.d.ts.map +1 -0
  62. package/dist/commands/respond.js +112 -0
  63. package/dist/commands/respond.js.map +1 -0
  64. package/dist/commands/setPriority.d.ts +7 -0
  65. package/dist/commands/setPriority.d.ts.map +1 -0
  66. package/dist/commands/setPriority.js +112 -0
  67. package/dist/commands/setPriority.js.map +1 -0
  68. package/dist/commands/track.d.ts +7 -0
  69. package/dist/commands/track.d.ts.map +1 -0
  70. package/dist/commands/track.js +140 -0
  71. package/dist/commands/track.js.map +1 -0
  72. package/dist/commands/upload.d.ts +21 -0
  73. package/dist/commands/upload.d.ts.map +1 -0
  74. package/dist/commands/upload.js +145 -0
  75. package/dist/commands/upload.js.map +1 -0
  76. package/dist/commands/view.d.ts +7 -0
  77. package/dist/commands/view.d.ts.map +1 -0
  78. package/dist/commands/view.js +168 -0
  79. package/dist/commands/view.js.map +1 -0
  80. package/dist/commands/watch.d.ts +7 -0
  81. package/dist/commands/watch.d.ts.map +1 -0
  82. package/dist/commands/watch.js +438 -0
  83. package/dist/commands/watch.js.map +1 -0
  84. package/dist/commands/worktree.d.ts +7 -0
  85. package/dist/commands/worktree.d.ts.map +1 -0
  86. package/dist/commands/worktree.js +122 -0
  87. package/dist/commands/worktree.js.map +1 -0
  88. package/dist/config/command-names.d.ts +16 -0
  89. package/dist/config/command-names.d.ts.map +1 -0
  90. package/dist/config/command-names.js +17 -0
  91. package/dist/config/command-names.js.map +1 -0
  92. package/dist/config/constants.d.ts +12 -0
  93. package/dist/config/constants.d.ts.map +1 -0
  94. package/dist/config/constants.js +12 -0
  95. package/dist/config/constants.js.map +1 -0
  96. package/dist/config/index.d.ts +47 -0
  97. package/dist/config/index.d.ts.map +1 -0
  98. package/dist/config/index.js +175 -0
  99. package/dist/config/index.js.map +1 -0
  100. package/dist/index.d.ts +3 -0
  101. package/dist/index.d.ts.map +1 -0
  102. package/dist/index.js +148 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/services/api/HulaApiClient.d.ts +170 -0
  105. package/dist/services/api/HulaApiClient.d.ts.map +1 -0
  106. package/dist/services/api/HulaApiClient.js +233 -0
  107. package/dist/services/api/HulaApiClient.js.map +1 -0
  108. package/dist/services/diff/DiffService.d.ts +44 -0
  109. package/dist/services/diff/DiffService.d.ts.map +1 -0
  110. package/dist/services/diff/DiffService.js +126 -0
  111. package/dist/services/diff/DiffService.js.map +1 -0
  112. package/dist/services/editor/EditorService.d.ts +53 -0
  113. package/dist/services/editor/EditorService.d.ts.map +1 -0
  114. package/dist/services/editor/EditorService.js +161 -0
  115. package/dist/services/editor/EditorService.js.map +1 -0
  116. package/dist/services/git/GitService.d.ts +124 -0
  117. package/dist/services/git/GitService.d.ts.map +1 -0
  118. package/dist/services/git/GitService.js +423 -0
  119. package/dist/services/git/GitService.js.map +1 -0
  120. package/dist/services/git/WorktreeService.d.ts +144 -0
  121. package/dist/services/git/WorktreeService.d.ts.map +1 -0
  122. package/dist/services/git/WorktreeService.js +505 -0
  123. package/dist/services/git/WorktreeService.js.map +1 -0
  124. package/dist/services/github/ActionsService.d.ts +66 -0
  125. package/dist/services/github/ActionsService.d.ts.map +1 -0
  126. package/dist/services/github/ActionsService.js +114 -0
  127. package/dist/services/github/ActionsService.js.map +1 -0
  128. package/dist/services/github/AssetUploadService.d.ts +103 -0
  129. package/dist/services/github/AssetUploadService.d.ts.map +1 -0
  130. package/dist/services/github/AssetUploadService.js +299 -0
  131. package/dist/services/github/AssetUploadService.js.map +1 -0
  132. package/dist/services/github/BatchCopilotDetectionService.d.ts +58 -0
  133. package/dist/services/github/BatchCopilotDetectionService.d.ts.map +1 -0
  134. package/dist/services/github/BatchCopilotDetectionService.js +321 -0
  135. package/dist/services/github/BatchCopilotDetectionService.js.map +1 -0
  136. package/dist/services/github/CopilotDetectionService.d.ts +40 -0
  137. package/dist/services/github/CopilotDetectionService.d.ts.map +1 -0
  138. package/dist/services/github/CopilotDetectionService.js +280 -0
  139. package/dist/services/github/CopilotDetectionService.js.map +1 -0
  140. package/dist/services/github/CopilotService.d.ts +27 -0
  141. package/dist/services/github/CopilotService.d.ts.map +1 -0
  142. package/dist/services/github/CopilotService.js +249 -0
  143. package/dist/services/github/CopilotService.js.map +1 -0
  144. package/dist/services/github/DeploymentDetectionService.d.ts +38 -0
  145. package/dist/services/github/DeploymentDetectionService.d.ts.map +1 -0
  146. package/dist/services/github/DeploymentDetectionService.js +104 -0
  147. package/dist/services/github/DeploymentDetectionService.js.map +1 -0
  148. package/dist/services/github/GithubAppService.d.ts +40 -0
  149. package/dist/services/github/GithubAppService.d.ts.map +1 -0
  150. package/dist/services/github/GithubAppService.js +187 -0
  151. package/dist/services/github/GithubAppService.js.map +1 -0
  152. package/dist/services/github/IssueService.d.ts +65 -0
  153. package/dist/services/github/IssueService.d.ts.map +1 -0
  154. package/dist/services/github/IssueService.js +231 -0
  155. package/dist/services/github/IssueService.js.map +1 -0
  156. package/dist/services/github/LabelService.d.ts +36 -0
  157. package/dist/services/github/LabelService.d.ts.map +1 -0
  158. package/dist/services/github/LabelService.js +122 -0
  159. package/dist/services/github/LabelService.js.map +1 -0
  160. package/dist/services/github/PRService.d.ts +77 -0
  161. package/dist/services/github/PRService.d.ts.map +1 -0
  162. package/dist/services/github/PRService.js +287 -0
  163. package/dist/services/github/PRService.js.map +1 -0
  164. package/dist/services/github/ProjectService.d.ts +144 -0
  165. package/dist/services/github/ProjectService.d.ts.map +1 -0
  166. package/dist/services/github/ProjectService.js +804 -0
  167. package/dist/services/github/ProjectService.js.map +1 -0
  168. package/dist/services/hooks/HookExecutor.d.ts +66 -0
  169. package/dist/services/hooks/HookExecutor.d.ts.map +1 -0
  170. package/dist/services/hooks/HookExecutor.js +227 -0
  171. package/dist/services/hooks/HookExecutor.js.map +1 -0
  172. package/dist/services/hooks/index.d.ts +2 -0
  173. package/dist/services/hooks/index.d.ts.map +1 -0
  174. package/dist/services/hooks/index.js +2 -0
  175. package/dist/services/hooks/index.js.map +1 -0
  176. package/dist/services/logs/LogFormatterService.d.ts +17 -0
  177. package/dist/services/logs/LogFormatterService.d.ts.map +1 -0
  178. package/dist/services/logs/LogFormatterService.js +35 -0
  179. package/dist/services/logs/LogFormatterService.js.map +1 -0
  180. package/dist/services/logs/TempFileService.d.ts +27 -0
  181. package/dist/services/logs/TempFileService.d.ts.map +1 -0
  182. package/dist/services/logs/TempFileService.js +90 -0
  183. package/dist/services/logs/TempFileService.js.map +1 -0
  184. package/dist/services/logs/index.d.ts +3 -0
  185. package/dist/services/logs/index.d.ts.map +1 -0
  186. package/dist/services/logs/index.js +4 -0
  187. package/dist/services/logs/index.js.map +1 -0
  188. package/dist/services/plan/PlanService.d.ts +70 -0
  189. package/dist/services/plan/PlanService.d.ts.map +1 -0
  190. package/dist/services/plan/PlanService.js +211 -0
  191. package/dist/services/plan/PlanService.js.map +1 -0
  192. package/dist/services/polling/GitHubDirectPollingAdapter.d.ts +16 -0
  193. package/dist/services/polling/GitHubDirectPollingAdapter.d.ts.map +1 -0
  194. package/dist/services/polling/GitHubDirectPollingAdapter.js +87 -0
  195. package/dist/services/polling/GitHubDirectPollingAdapter.js.map +1 -0
  196. package/dist/services/polling/HulaServerPollingAdapter.d.ts +23 -0
  197. package/dist/services/polling/HulaServerPollingAdapter.d.ts.map +1 -0
  198. package/dist/services/polling/HulaServerPollingAdapter.js +78 -0
  199. package/dist/services/polling/HulaServerPollingAdapter.js.map +1 -0
  200. package/dist/services/polling/IStatusPollingAdapter.d.ts +29 -0
  201. package/dist/services/polling/IStatusPollingAdapter.d.ts.map +1 -0
  202. package/dist/services/polling/IStatusPollingAdapter.js +2 -0
  203. package/dist/services/polling/IStatusPollingAdapter.js.map +1 -0
  204. package/dist/services/polling/StatusPollingAdapterFactory.d.ts +14 -0
  205. package/dist/services/polling/StatusPollingAdapterFactory.d.ts.map +1 -0
  206. package/dist/services/polling/StatusPollingAdapterFactory.js +41 -0
  207. package/dist/services/polling/StatusPollingAdapterFactory.js.map +1 -0
  208. package/dist/services/polling/index.d.ts +5 -0
  209. package/dist/services/polling/index.d.ts.map +1 -0
  210. package/dist/services/polling/index.js +5 -0
  211. package/dist/services/polling/index.js.map +1 -0
  212. package/dist/services/preview/PreviewService.d.ts +86 -0
  213. package/dist/services/preview/PreviewService.d.ts.map +1 -0
  214. package/dist/services/preview/PreviewService.js +439 -0
  215. package/dist/services/preview/PreviewService.js.map +1 -0
  216. package/dist/services/tracking/ProjectTrackingAdapter.d.ts +41 -0
  217. package/dist/services/tracking/ProjectTrackingAdapter.d.ts.map +1 -0
  218. package/dist/services/tracking/ProjectTrackingAdapter.js +230 -0
  219. package/dist/services/tracking/ProjectTrackingAdapter.js.map +1 -0
  220. package/dist/services/tracking/RemoteTrackingAdapter.d.ts +62 -0
  221. package/dist/services/tracking/RemoteTrackingAdapter.d.ts.map +1 -0
  222. package/dist/services/tracking/RemoteTrackingAdapter.js +242 -0
  223. package/dist/services/tracking/RemoteTrackingAdapter.js.map +1 -0
  224. package/dist/services/tracking/TrackingAdapterFactory.d.ts +25 -0
  225. package/dist/services/tracking/TrackingAdapterFactory.d.ts.map +1 -0
  226. package/dist/services/tracking/TrackingAdapterFactory.js +55 -0
  227. package/dist/services/tracking/TrackingAdapterFactory.js.map +1 -0
  228. package/dist/services/tracking/TrackingService.d.ts +104 -0
  229. package/dist/services/tracking/TrackingService.d.ts.map +1 -0
  230. package/dist/services/tracking/TrackingService.js +256 -0
  231. package/dist/services/tracking/TrackingService.js.map +1 -0
  232. package/dist/services/tracking/UntrackedIssuesService.d.ts +20 -0
  233. package/dist/services/tracking/UntrackedIssuesService.d.ts.map +1 -0
  234. package/dist/services/tracking/UntrackedIssuesService.js +148 -0
  235. package/dist/services/tracking/UntrackedIssuesService.js.map +1 -0
  236. package/dist/services/tracking/local-file-migration.d.ts +16 -0
  237. package/dist/services/tracking/local-file-migration.d.ts.map +1 -0
  238. package/dist/services/tracking/local-file-migration.js +86 -0
  239. package/dist/services/tracking/local-file-migration.js.map +1 -0
  240. package/dist/templates/planning-instructions.md +752 -0
  241. package/dist/templates/proceed-instructions.md +453 -0
  242. package/dist/templates/scripts/hula-fix-commit.sh +110 -0
  243. package/dist/templates/scripts/hula-fix-setup.sh +145 -0
  244. package/dist/templates/scripts/hula-launch-run.sh +89 -0
  245. package/dist/templates/scripts/hula-merge-local.sh +138 -0
  246. package/dist/templates/scripts/hula-merge-remote.sh +74 -0
  247. package/dist/templates/scripts/hula-read-config.sh +38 -0
  248. package/dist/templates/scripts/hula-verify-gather.sh +135 -0
  249. package/dist/templates/scripts/hula-verify-post.sh +84 -0
  250. package/dist/templates/skills/hula-confirm/SKILL.md +361 -0
  251. package/dist/templates/skills/hula-create/SKILL.md +211 -0
  252. package/dist/templates/skills/hula-fix/SKILL.md +224 -0
  253. package/dist/templates/skills/hula-launch/SKILL.md +159 -0
  254. package/dist/templates/skills/hula-log/SKILL.md +105 -0
  255. package/dist/templates/skills/hula-merge/SKILL.md +387 -0
  256. package/dist/templates/skills/hula-plan/SKILL.md +148 -0
  257. package/dist/templates/skills/hula-upload/SKILL.md +115 -0
  258. package/dist/templates/skills/hula-verify/SKILL.md +754 -0
  259. package/dist/types/common.schema.d.ts +46 -0
  260. package/dist/types/common.schema.d.ts.map +1 -0
  261. package/dist/types/common.schema.js +60 -0
  262. package/dist/types/common.schema.js.map +1 -0
  263. package/dist/types/config.schema.d.ts +443 -0
  264. package/dist/types/config.schema.d.ts.map +1 -0
  265. package/dist/types/config.schema.js +126 -0
  266. package/dist/types/config.schema.js.map +1 -0
  267. package/dist/types/index.d.ts +6 -0
  268. package/dist/types/index.d.ts.map +1 -0
  269. package/dist/types/index.js +7 -0
  270. package/dist/types/index.js.map +1 -0
  271. package/dist/types/issue.schema.d.ts +136 -0
  272. package/dist/types/issue.schema.d.ts.map +1 -0
  273. package/dist/types/issue.schema.js +49 -0
  274. package/dist/types/issue.schema.js.map +1 -0
  275. package/dist/types/pr.schema.d.ts +118 -0
  276. package/dist/types/pr.schema.d.ts.map +1 -0
  277. package/dist/types/pr.schema.js +40 -0
  278. package/dist/types/pr.schema.js.map +1 -0
  279. package/dist/types/tracking.schema.d.ts +340 -0
  280. package/dist/types/tracking.schema.d.ts.map +1 -0
  281. package/dist/types/tracking.schema.js +56 -0
  282. package/dist/types/tracking.schema.js.map +1 -0
  283. package/dist/utils/browser-launcher.d.ts +60 -0
  284. package/dist/utils/browser-launcher.d.ts.map +1 -0
  285. package/dist/utils/browser-launcher.js +263 -0
  286. package/dist/utils/browser-launcher.js.map +1 -0
  287. package/dist/utils/cache.d.ts +44 -0
  288. package/dist/utils/cache.d.ts.map +1 -0
  289. package/dist/utils/cache.js +94 -0
  290. package/dist/utils/cache.js.map +1 -0
  291. package/dist/utils/config-parser.d.ts +16 -0
  292. package/dist/utils/config-parser.d.ts.map +1 -0
  293. package/dist/utils/config-parser.js +210 -0
  294. package/dist/utils/config-parser.js.map +1 -0
  295. package/dist/utils/editor.d.ts +21 -0
  296. package/dist/utils/editor.d.ts.map +1 -0
  297. package/dist/utils/editor.js +213 -0
  298. package/dist/utils/editor.js.map +1 -0
  299. package/dist/utils/git-utils.d.ts +5 -0
  300. package/dist/utils/git-utils.d.ts.map +1 -0
  301. package/dist/utils/git-utils.js +18 -0
  302. package/dist/utils/git-utils.js.map +1 -0
  303. package/dist/utils/github-cli.d.ts +62 -0
  304. package/dist/utils/github-cli.d.ts.map +1 -0
  305. package/dist/utils/github-cli.js +492 -0
  306. package/dist/utils/github-cli.js.map +1 -0
  307. package/dist/utils/logger.d.ts +45 -0
  308. package/dist/utils/logger.d.ts.map +1 -0
  309. package/dist/utils/logger.js +118 -0
  310. package/dist/utils/logger.js.map +1 -0
  311. package/dist/utils/open-url.d.ts +19 -0
  312. package/dist/utils/open-url.d.ts.map +1 -0
  313. package/dist/utils/open-url.js +37 -0
  314. package/dist/utils/open-url.js.map +1 -0
  315. package/dist/utils/project-resolver.d.ts +13 -0
  316. package/dist/utils/project-resolver.d.ts.map +1 -0
  317. package/dist/utils/project-resolver.js +35 -0
  318. package/dist/utils/project-resolver.js.map +1 -0
  319. package/dist/utils/prompts.d.ts +80 -0
  320. package/dist/utils/prompts.d.ts.map +1 -0
  321. package/dist/utils/prompts.js +326 -0
  322. package/dist/utils/prompts.js.map +1 -0
  323. package/dist/utils/shell.d.ts +54 -0
  324. package/dist/utils/shell.d.ts.map +1 -0
  325. package/dist/utils/shell.js +152 -0
  326. package/dist/utils/shell.js.map +1 -0
  327. package/dist/utils/validators.d.ts +32 -0
  328. package/dist/utils/validators.d.ts.map +1 -0
  329. package/dist/utils/validators.js +64 -0
  330. package/dist/utils/validators.js.map +1 -0
  331. 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":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB;;;;;GAKG;AACH,MAAM,OAAO,qBAAqB;IACxB,MAAM,CAAgB;IACtB,KAAK,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC5C,WAAW,GAAW,CAAC,CAAC;IACf,SAAS,GAAG,KAAK,CAAC,CAAC,aAAa;IACzC,aAAa,GAAkB,IAAI,CAAC;IAE5C,YAAY,MAAqB;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,IAAI,GAAG,GAAqB,EAAE,CAAC;QAC/B,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,GAAG,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YACnE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACjC,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;YACjC,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;gBAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;YAC9C,CAAC;YACD,IAAI,EAAE,CAAC;QACT,CAAC,QAAQ,IAAI,IAAI,UAAU,EAAE;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,uBAAuB,CAAC,OAAuB;QACrD,OAAO;YACL,IAAI,EACF,OAAO,CAAC,WAAW,IAAI,IAAI;gBACzB,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE;gBAC3E,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,YAAY,OAAO,CAAC,EAAE,EAAE;YAC9E,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,MAAM,EAAE,OAAO,CAAC,WAAW,IAAI,SAAS;YACxC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,cAAc,EAAE,OAAO,CAAC,cAIb;YACX,WAAW,EAAE,OAAO,CAAC,WAAgC;YACrD,QAAQ,EAAE,OAAO,CAAC,QAKL;YACb,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK;YACnC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI;YACjC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,SAAS;YACvC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;YACjC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAE,SAAS;YACnB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,SAAS;SACxD,CAAC;IACJ,CAAC;IAEO,aAAa,CAAC,OAAuB;QAC3C,OAAO,OAAO,CAAC,WAAW,IAAI,IAAI;YAChC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE;YAC3E,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,YAAY,OAAO,CAAC,EAAE,EAAE,CAAC;IAC/E,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAkB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACjD,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAChC,CAAC;QAEF,oEAAoE;QACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAE1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI;wBAAE,SAAS;oBAElC,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;wBAC3C,OAAO,CACL,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;4BACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CACjC,CAAC;oBACJ,CAAC,CAAC,CAAC;oBAEH,IAAI,YAAY,EAAE,CAAC;wBACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;oBAC/C,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CACV,mCACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAC;YACJ,CAAC;QACH,CAAC;QAED,eAAe;QACf,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,MAAqB;QAC/B,0DAA0D;QAC1D,MAAM,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAChE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,IAAiB;QACzB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YACtD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAChE,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAEtB,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,yCAAyC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACxE,CAAC;YAED,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC1B,KAAK;gBACL,IAAI;gBACJ,WAAW,EAAE,IAAI,CAAC,MAAM;gBACxB,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI;gBAC5C,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI;gBAC9B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,qFAAqF;gBACrF,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC/D,GAAG,CAAC,IAAI,CAAC,eAAe,KAAK,SAAS,IAAI;oBACxC,eAAe,EAAE,IAAI,CAAC,eAAe;iBACtC,CAAC;aACH,CAAC,CAAC;YAEH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,eAAe,EAAE,CAAC;YAEvB,MAAM,CAAC,KAAK,CAAC,iBAAiB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,yBAAyB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,YAAoB;QAC/B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAE/C,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,YAAY,KAAK,YAAY;gBAC/B,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,YAAY,CACzC,CAAC;YAEF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,QAAQ,YAAY,sBAAsB,CAAC,CAAC;YAC9D,CAAC;YAED,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAE1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAChC,IAAI,CAAC,eAAe,EAAE,CAAC;YAEvB,MAAM,CAAC,KAAK,CAAC,mBAAmB,YAAY,EAAE,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,2BAA2B,YAAY,EAAE,CAAC,CAAC;YACxD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,YAAoB,EACpB,OAA6B;QAE7B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAE/C,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,YAAY,KAAK,YAAY;gBAC/B,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,YAAY,CACzC,CAAC;YAEF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,QAAQ,YAAY,YAAY,CAAC,CAAC;YACpD,CAAC;YAED,qDAAqD;YACrD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YACrE,CAAC;YAED,eAAe;YACf,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5C,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;YAC1D,CAAC;YAED,IAAI,CAAC,eAAe,EAAE,CAAC;YAEvB,MAAM,CAAC,KAAK,CAAC,iBAAiB,YAAY,EAAE,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,YAAoB;QAC5B,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC5C,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,MAAM,CAAC;gBAChB,CAAC;YACH,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI,IAAI,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,uBAAuB,YAAY,EAAE,CAAC,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM;QACV,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAEO,YAAY;QAClB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;IACxD,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IACvB,CAAC;CACF"}
@@ -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"}