jirallm 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/README.md +87 -9
  2. package/dist/cli/commands/assign.d.ts +9 -0
  3. package/dist/cli/commands/assign.d.ts.map +1 -0
  4. package/dist/cli/commands/assign.js +37 -0
  5. package/dist/cli/commands/assign.js.map +1 -0
  6. package/dist/cli/commands/assign.test.d.ts +2 -0
  7. package/dist/cli/commands/assign.test.d.ts.map +1 -0
  8. package/dist/cli/commands/assign.test.js +69 -0
  9. package/dist/cli/commands/assign.test.js.map +1 -0
  10. package/dist/cli/commands/attach.d.ts +16 -0
  11. package/dist/cli/commands/attach.d.ts.map +1 -0
  12. package/dist/cli/commands/attach.js +52 -0
  13. package/dist/cli/commands/attach.js.map +1 -0
  14. package/dist/cli/commands/attach.test.d.ts +2 -0
  15. package/dist/cli/commands/attach.test.d.ts.map +1 -0
  16. package/dist/cli/commands/attach.test.js +92 -0
  17. package/dist/cli/commands/attach.test.js.map +1 -0
  18. package/dist/cli/commands/board.d.ts +10 -0
  19. package/dist/cli/commands/board.d.ts.map +1 -0
  20. package/dist/cli/commands/board.js +54 -0
  21. package/dist/cli/commands/board.js.map +1 -0
  22. package/dist/cli/commands/boards.d.ts +11 -0
  23. package/dist/cli/commands/boards.d.ts.map +1 -0
  24. package/dist/cli/commands/boards.js +27 -0
  25. package/dist/cli/commands/boards.js.map +1 -0
  26. package/dist/cli/commands/boards.test.d.ts +2 -0
  27. package/dist/cli/commands/boards.test.d.ts.map +1 -0
  28. package/dist/cli/commands/boards.test.js +80 -0
  29. package/dist/cli/commands/boards.test.js.map +1 -0
  30. package/dist/cli/commands/comment.d.ts +15 -0
  31. package/dist/cli/commands/comment.d.ts.map +1 -0
  32. package/dist/cli/commands/comment.js +61 -0
  33. package/dist/cli/commands/comment.js.map +1 -0
  34. package/dist/cli/commands/create.d.ts +16 -0
  35. package/dist/cli/commands/create.d.ts.map +1 -0
  36. package/dist/cli/commands/create.js +44 -0
  37. package/dist/cli/commands/create.js.map +1 -0
  38. package/dist/cli/commands/create.test.d.ts +2 -0
  39. package/dist/cli/commands/create.test.d.ts.map +1 -0
  40. package/dist/cli/commands/create.test.js +98 -0
  41. package/dist/cli/commands/create.test.js.map +1 -0
  42. package/dist/cli/commands/doctor.js +8 -8
  43. package/dist/cli/commands/doctor.js.map +1 -1
  44. package/dist/cli/commands/edit.d.ts +15 -0
  45. package/dist/cli/commands/edit.d.ts.map +1 -0
  46. package/dist/cli/commands/edit.js +47 -0
  47. package/dist/cli/commands/edit.js.map +1 -0
  48. package/dist/cli/commands/edit.test.d.ts +2 -0
  49. package/dist/cli/commands/edit.test.d.ts.map +1 -0
  50. package/dist/cli/commands/edit.test.js +77 -0
  51. package/dist/cli/commands/edit.test.js.map +1 -0
  52. package/dist/cli/commands/fetch.d.ts +7 -0
  53. package/dist/cli/commands/fetch.d.ts.map +1 -0
  54. package/dist/cli/commands/fetch.js +32 -0
  55. package/dist/cli/commands/fetch.js.map +1 -0
  56. package/dist/cli/commands/fetch.test.d.ts +2 -0
  57. package/dist/cli/commands/fetch.test.d.ts.map +1 -0
  58. package/dist/cli/commands/fetch.test.js +93 -0
  59. package/dist/cli/commands/fetch.test.js.map +1 -0
  60. package/dist/cli/commands/init.js +3 -3
  61. package/dist/cli/commands/init.js.map +1 -1
  62. package/dist/cli/commands/issuetypes.d.ts +7 -0
  63. package/dist/cli/commands/issuetypes.d.ts.map +1 -0
  64. package/dist/cli/commands/issuetypes.js +23 -0
  65. package/dist/cli/commands/issuetypes.js.map +1 -0
  66. package/dist/cli/commands/issuetypes.test.d.ts +2 -0
  67. package/dist/cli/commands/issuetypes.test.d.ts.map +1 -0
  68. package/dist/cli/commands/issuetypes.test.js +62 -0
  69. package/dist/cli/commands/issuetypes.test.js.map +1 -0
  70. package/dist/cli/commands/link.d.ts +18 -0
  71. package/dist/cli/commands/link.d.ts.map +1 -0
  72. package/dist/cli/commands/link.js +51 -0
  73. package/dist/cli/commands/link.js.map +1 -0
  74. package/dist/cli/commands/link.test.d.ts +2 -0
  75. package/dist/cli/commands/link.test.d.ts.map +1 -0
  76. package/dist/cli/commands/link.test.js +96 -0
  77. package/dist/cli/commands/link.test.js.map +1 -0
  78. package/dist/cli/commands/linktypes.d.ts +6 -0
  79. package/dist/cli/commands/linktypes.d.ts.map +1 -0
  80. package/dist/cli/commands/linktypes.js +21 -0
  81. package/dist/cli/commands/linktypes.js.map +1 -0
  82. package/dist/cli/commands/linktypes.test.d.ts +2 -0
  83. package/dist/cli/commands/linktypes.test.d.ts.map +1 -0
  84. package/dist/cli/commands/linktypes.test.js +55 -0
  85. package/dist/cli/commands/linktypes.test.js.map +1 -0
  86. package/dist/cli/commands/me.d.ts +6 -0
  87. package/dist/cli/commands/me.d.ts.map +1 -0
  88. package/dist/cli/commands/me.js +17 -0
  89. package/dist/cli/commands/me.js.map +1 -0
  90. package/dist/cli/commands/me.test.d.ts +2 -0
  91. package/dist/cli/commands/me.test.d.ts.map +1 -0
  92. package/dist/cli/commands/me.test.js +58 -0
  93. package/dist/cli/commands/me.test.js.map +1 -0
  94. package/dist/cli/commands/projects.d.ts +9 -0
  95. package/dist/cli/commands/projects.d.ts.map +1 -0
  96. package/dist/cli/commands/projects.js +25 -0
  97. package/dist/cli/commands/projects.js.map +1 -0
  98. package/dist/cli/commands/projects.test.d.ts +2 -0
  99. package/dist/cli/commands/projects.test.d.ts.map +1 -0
  100. package/dist/cli/commands/projects.test.js +73 -0
  101. package/dist/cli/commands/projects.test.js.map +1 -0
  102. package/dist/cli/commands/search.d.ts +11 -0
  103. package/dist/cli/commands/search.d.ts.map +1 -0
  104. package/dist/cli/commands/search.js +41 -0
  105. package/dist/cli/commands/search.js.map +1 -0
  106. package/dist/cli/commands/search.test.d.ts +2 -0
  107. package/dist/cli/commands/search.test.d.ts.map +1 -0
  108. package/dist/cli/commands/search.test.js +106 -0
  109. package/dist/cli/commands/search.test.js.map +1 -0
  110. package/dist/cli/commands/setup.d.ts.map +1 -1
  111. package/dist/cli/commands/setup.js +5 -13
  112. package/dist/cli/commands/setup.js.map +1 -1
  113. package/dist/cli/commands/sprints.d.ts +10 -0
  114. package/dist/cli/commands/sprints.d.ts.map +1 -0
  115. package/dist/cli/commands/sprints.js +28 -0
  116. package/dist/cli/commands/sprints.js.map +1 -0
  117. package/dist/cli/commands/sprints.test.d.ts +2 -0
  118. package/dist/cli/commands/sprints.test.d.ts.map +1 -0
  119. package/dist/cli/commands/sprints.test.js +68 -0
  120. package/dist/cli/commands/sprints.test.js.map +1 -0
  121. package/dist/cli/commands/transition.d.ts +8 -0
  122. package/dist/cli/commands/transition.d.ts.map +1 -0
  123. package/dist/cli/commands/transition.js +46 -0
  124. package/dist/cli/commands/transition.js.map +1 -0
  125. package/dist/cli/commands/upgrade.d.ts +16 -0
  126. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  127. package/dist/cli/commands/upgrade.js +83 -0
  128. package/dist/cli/commands/upgrade.js.map +1 -0
  129. package/dist/cli/commands/upgrade.test.d.ts +2 -0
  130. package/dist/cli/commands/upgrade.test.d.ts.map +1 -0
  131. package/dist/cli/commands/upgrade.test.js +146 -0
  132. package/dist/cli/commands/upgrade.test.js.map +1 -0
  133. package/dist/cli/commands/watchers.d.ts +10 -0
  134. package/dist/cli/commands/watchers.d.ts.map +1 -0
  135. package/dist/cli/commands/watchers.js +43 -0
  136. package/dist/cli/commands/watchers.js.map +1 -0
  137. package/dist/cli/commands/watchers.test.d.ts +2 -0
  138. package/dist/cli/commands/watchers.test.d.ts.map +1 -0
  139. package/dist/cli/commands/watchers.test.js +90 -0
  140. package/dist/cli/commands/watchers.test.js.map +1 -0
  141. package/dist/cli/commands/worklog.d.ts +8 -0
  142. package/dist/cli/commands/worklog.d.ts.map +1 -0
  143. package/dist/cli/commands/worklog.js +100 -0
  144. package/dist/cli/commands/worklog.js.map +1 -0
  145. package/dist/cli/commands/worklog.test.d.ts +2 -0
  146. package/dist/cli/commands/worklog.test.d.ts.map +1 -0
  147. package/dist/cli/commands/worklog.test.js +195 -0
  148. package/dist/cli/commands/worklog.test.js.map +1 -0
  149. package/dist/cli/index.js +648 -6
  150. package/dist/cli/index.js.map +1 -1
  151. package/dist/cli/issueKey.d.ts.map +1 -1
  152. package/dist/cli/issueKey.js +6 -2
  153. package/dist/cli/issueKey.js.map +1 -1
  154. package/dist/cli/issueKey.test.js +36 -1
  155. package/dist/cli/issueKey.test.js.map +1 -1
  156. package/dist/cli/jsonOutput.d.ts +6 -0
  157. package/dist/cli/jsonOutput.d.ts.map +1 -0
  158. package/dist/cli/jsonOutput.js +7 -0
  159. package/dist/cli/jsonOutput.js.map +1 -0
  160. package/dist/cli/jsonOutput.test.d.ts +2 -0
  161. package/dist/cli/jsonOutput.test.d.ts.map +1 -0
  162. package/dist/cli/jsonOutput.test.js +44 -0
  163. package/dist/cli/jsonOutput.test.js.map +1 -0
  164. package/dist/cli/resolveOrg.d.ts +2 -0
  165. package/dist/cli/resolveOrg.d.ts.map +1 -0
  166. package/dist/cli/resolveOrg.js +15 -0
  167. package/dist/cli/resolveOrg.js.map +1 -0
  168. package/dist/index.d.ts +3 -1
  169. package/dist/index.d.ts.map +1 -1
  170. package/dist/index.js +2 -0
  171. package/dist/index.js.map +1 -1
  172. package/dist/lib/chunkMarkdown.d.ts +6 -0
  173. package/dist/lib/chunkMarkdown.d.ts.map +1 -0
  174. package/dist/lib/chunkMarkdown.js +73 -0
  175. package/dist/lib/chunkMarkdown.js.map +1 -0
  176. package/dist/lib/chunkMarkdown.test.d.ts +2 -0
  177. package/dist/lib/chunkMarkdown.test.d.ts.map +1 -0
  178. package/dist/lib/chunkMarkdown.test.js +171 -0
  179. package/dist/lib/chunkMarkdown.test.js.map +1 -0
  180. package/dist/lib/config.d.ts +6 -0
  181. package/dist/lib/config.d.ts.map +1 -1
  182. package/dist/lib/config.js +25 -0
  183. package/dist/lib/config.js.map +1 -1
  184. package/dist/lib/config.test.js +73 -6
  185. package/dist/lib/config.test.js.map +1 -1
  186. package/dist/lib/configSchema.d.ts +44 -0
  187. package/dist/lib/configSchema.d.ts.map +1 -1
  188. package/dist/lib/configSchema.js +20 -0
  189. package/dist/lib/configSchema.js.map +1 -1
  190. package/dist/lib/credentials.d.ts.map +1 -1
  191. package/dist/lib/credentials.js +32 -31
  192. package/dist/lib/credentials.js.map +1 -1
  193. package/dist/lib/credentials.test.js +18 -11
  194. package/dist/lib/credentials.test.js.map +1 -1
  195. package/dist/lib/exportFields.d.ts +30 -0
  196. package/dist/lib/exportFields.d.ts.map +1 -0
  197. package/dist/lib/exportFields.js +169 -0
  198. package/dist/lib/exportFields.js.map +1 -0
  199. package/dist/lib/exportFields.test.d.ts +2 -0
  200. package/dist/lib/exportFields.test.d.ts.map +1 -0
  201. package/dist/lib/exportFields.test.js +145 -0
  202. package/dist/lib/exportFields.test.js.map +1 -0
  203. package/dist/lib/exporter.d.ts +25 -3
  204. package/dist/lib/exporter.d.ts.map +1 -1
  205. package/dist/lib/exporter.js +195 -18
  206. package/dist/lib/exporter.js.map +1 -1
  207. package/dist/lib/exporter.test.d.ts +2 -0
  208. package/dist/lib/exporter.test.d.ts.map +1 -0
  209. package/dist/lib/exporter.test.js +227 -0
  210. package/dist/lib/exporter.test.js.map +1 -0
  211. package/dist/lib/jiraClient.d.ts +248 -1
  212. package/dist/lib/jiraClient.d.ts.map +1 -1
  213. package/dist/lib/jiraClient.discovery.test.d.ts +2 -0
  214. package/dist/lib/jiraClient.discovery.test.d.ts.map +1 -0
  215. package/dist/lib/jiraClient.discovery.test.js +209 -0
  216. package/dist/lib/jiraClient.discovery.test.js.map +1 -0
  217. package/dist/lib/jiraClient.js +624 -17
  218. package/dist/lib/jiraClient.js.map +1 -1
  219. package/dist/lib/jiraClient.test.d.ts +2 -0
  220. package/dist/lib/jiraClient.test.d.ts.map +1 -0
  221. package/dist/lib/jiraClient.test.js +383 -0
  222. package/dist/lib/jiraClient.test.js.map +1 -0
  223. package/dist/lib/jiraClient.write.test.d.ts +2 -0
  224. package/dist/lib/jiraClient.write.test.d.ts.map +1 -0
  225. package/dist/lib/jiraClient.write.test.js +268 -0
  226. package/dist/lib/jiraClient.write.test.js.map +1 -0
  227. package/dist/lib/markdownToWiki.d.ts +2 -0
  228. package/dist/lib/markdownToWiki.d.ts.map +1 -0
  229. package/dist/lib/markdownToWiki.js +110 -0
  230. package/dist/lib/markdownToWiki.js.map +1 -0
  231. package/dist/lib/markdownToWiki.test.d.ts +2 -0
  232. package/dist/lib/markdownToWiki.test.d.ts.map +1 -0
  233. package/dist/lib/markdownToWiki.test.js +122 -0
  234. package/dist/lib/markdownToWiki.test.js.map +1 -0
  235. package/dist/lib/platform.d.ts +2 -0
  236. package/dist/lib/platform.d.ts.map +1 -1
  237. package/dist/lib/platform.js +8 -0
  238. package/dist/lib/platform.js.map +1 -1
  239. package/dist/lib/runCommand.d.ts +1 -0
  240. package/dist/lib/runCommand.d.ts.map +1 -1
  241. package/dist/lib/runCommand.js +8 -1
  242. package/dist/lib/runCommand.js.map +1 -1
  243. package/dist/lib/worklog.d.ts +36 -0
  244. package/dist/lib/worklog.d.ts.map +1 -0
  245. package/dist/lib/worklog.js +188 -0
  246. package/dist/lib/worklog.js.map +1 -0
  247. package/dist/lib/worklog.test.d.ts +2 -0
  248. package/dist/lib/worklog.test.d.ts.map +1 -0
  249. package/dist/lib/worklog.test.js +118 -0
  250. package/dist/lib/worklog.test.js.map +1 -0
  251. package/package.json +42 -12
  252. package/dist/cli/commands/profiles.d.ts +0 -2
  253. package/dist/cli/commands/profiles.d.ts.map +0 -1
  254. package/dist/cli/commands/profiles.js +0 -20
  255. package/dist/cli/commands/profiles.js.map +0 -1
package/README.md CHANGED
@@ -9,13 +9,13 @@ Export Jira Cloud issues as LLM-ready context bundles — markdown, attachments,
9
9
 
10
10
  ## Why it exists
11
11
 
12
- Pasting Jira tickets into an LLM is painful: descriptions are ADF (Atlassian Document Format), comments live in a separate API, attachments are URLs behind auth, and video recordings are useless to a text model. `jirallm` turns a Jira issue (or a JQL query) into a self-contained folder of clean markdown plus extracted media — ready to drop into Claude, ChatGPT, Cursor, or any RAG pipeline.
12
+ Pasting Jira tickets into an LLM is painful: descriptions are ADF (Atlassian Document Format), comments live in a separate API, attachments are URLs behind auth, and video recordings are useless to a text model. `jirallm` turns a Jira issue into a self-contained folder of clean markdown plus extracted media — ready to drop into Claude, ChatGPT, Cursor, or any RAG pipeline.
13
13
 
14
14
  It exists because every team that uses Jira + LLMs ends up writing the same brittle scraping script. This is the version you wish you had.
15
15
 
16
16
  ## Features
17
17
 
18
- - Export a single issue or a JQL result set into a structured folder
18
+ - Export one or more issues by key into a structured folder
19
19
  - Renders Jira ADF descriptions and comments to clean Markdown
20
20
  - Downloads all attachments with original filenames (auth handled)
21
21
  - Extracts frames from attached videos via `ffmpeg` and deduplicates near-identical frames using `pixelmatch`
@@ -41,6 +41,15 @@ pnpm add -g jirallm
41
41
  pnpm add jirallm
42
42
  ```
43
43
 
44
+ ### Updating
45
+
46
+ `jirallm` checks for new versions once a day in the background and prints a notice on the next invocation. To upgrade:
47
+
48
+ ```bash
49
+ jirallm upgrade # auto-detects npm / pnpm / yarn / Homebrew
50
+ jirallm upgrade --check # just report whether an update is available
51
+ ```
52
+
44
53
  ## Configuration
45
54
 
46
55
  The recommended way to configure `jirallm` is the interactive wizard:
@@ -83,8 +92,8 @@ user_email = "user@acme.example"
83
92
  [orgs.acme.projects.PROJ]
84
93
  output_dir = "~/jira/acme/proj"
85
94
 
86
- [orgs.acme.projects.CORE]
87
- output_dir = "~/jira/acme/core"
95
+ [orgs.acme.projects.DOCS]
96
+ output_dir = "~/jira/acme/docs"
88
97
 
89
98
  [orgs.acme.projects.LIB]
90
99
  ```
@@ -167,11 +176,11 @@ jira-export/
167
176
  import { JiraExporter, loadProfile } from 'jirallm';
168
177
 
169
178
  // Resolve an org/project (config file + keychain), with the same precedence as the CLI
170
- const { config, apiToken, org, project } = await loadProfile({ org: 'acme', project: 'CORE' });
179
+ const { config, apiToken, org, project } = await loadProfile({ org: 'acme', project: 'DOCS' });
171
180
 
172
181
  const exporter = new JiraExporter(config, apiToken);
173
182
 
174
- const result = await exporter.exportIssues(['CIT-123'], {
183
+ const result = await exporter.exportIssues(['DOCS-123'], {
175
184
  outputDir: project.outputDir ?? './jira-export',
176
185
  includeSubtasks: org.includeSubtasks ?? false,
177
186
  videoFrames: { enabled: true, fps: 5, maxFrames: 10 },
@@ -191,11 +200,80 @@ jirallm PROJ-123 PROJ-124 --output-dir ./triage-bundle
191
200
  cat ./triage-bundle/PROJ-123/index.md | pbcopy
192
201
  ```
193
202
 
203
+ ## For agents (CLI commands)
204
+
205
+ Every read command supports `--json` (and automatically switches to JSON when stdout is not a TTY), so they're safe to pipe into `jq` or feed back into an agent. Every write command supports `--dry-run`.
206
+
207
+ Discovery & search:
208
+
209
+ ```bash
210
+ jirallm me --org acme --json
211
+ jirallm projects --org acme --json
212
+ jirallm boards --org acme --project PROJ --json
213
+ jirallm sprints 123 --org acme --state active --json
214
+ jirallm issuetypes --org acme --project PROJ --json
215
+ jirallm linktypes --org acme --json
216
+ jirallm search 'assignee = currentUser() AND statusCategory != Done' --org acme --limit 25 --json
217
+ jirallm fetch PROJ-123 --json
218
+ jirallm transition PROJ-123 --list --json
219
+ ```
220
+
221
+ Mutations (all accept `--dry-run`):
222
+
223
+ ```bash
224
+ jirallm comment PROJ-123 --file ./summary.md
225
+ jirallm transition PROJ-123 --to "In Review"
226
+ jirallm worklog -f ./worklogs.json
227
+ jirallm create --org acme --project PROJ --type Task --summary "Spike" --description-file ./spike.md
228
+ jirallm edit PROJ-123 --labels a,b --priority High
229
+ jirallm assign PROJ-123 me
230
+ jirallm link PROJ-1 "blocks" PROJ-2 --comment "blocked by infra work"
231
+ jirallm link:rm 10042 --org acme
232
+ jirallm attach PROJ-123 ./screenshot.png ./recording.mp4
233
+ jirallm attach:rm 99021 --org acme
234
+ jirallm watchers PROJ-123 --add me
235
+ ```
236
+
237
+ ## Library usage
238
+
239
+ The package re-exports `JiraClient` plus all the domain types so you can drive Jira directly from your own TypeScript:
240
+
241
+ ```ts
242
+ import { JiraClient, loadProfile } from 'jirallm';
243
+
244
+ const { config, apiToken } = await loadProfile({ org: 'acme' });
245
+ const client = new JiraClient(config, apiToken);
246
+
247
+ // Search (single page; pass nextPageToken for the next one)
248
+ const page = await client.searchIssues('project = PROJ AND statusCategory != Done', {
249
+ fields: ['summary', 'status'],
250
+ limit: 50,
251
+ });
252
+
253
+ // Create + comment
254
+ const created = await client.createIssue({
255
+ projectKey: 'PROJ',
256
+ issueType: 'Task',
257
+ summary: 'Investigate flaky test',
258
+ descriptionMarkdown: '**Repro**\n\n1. step\n2. step',
259
+ });
260
+ await client.addComment(created.key, 'Auto-filed from triage script.');
261
+ ```
262
+
263
+ See `examples/` for runnable scripts:
264
+
265
+ - `examples/search-my-issues.ts` — paginated JQL
266
+ - `examples/create-bug.ts` — create + comment
267
+ - `examples/board-snapshot.ts` — boards → sprints → issues
268
+
194
269
  ## Platform support
195
270
 
196
- - macOSfully supported
197
- - Linux — fully supported
198
- - Windowsshould work; `ffmpeg` must be on `PATH`
271
+ Native binaries (via [`@napi-rs/keyring`](https://www.npmjs.com/package/@napi-rs/keyring)) ship prebuilt no compile step on install.
272
+
273
+ - **macOS** (arm64, x64) fully supported. Tokens stored in macOS Keychain.
274
+ - **Linux** (x64, arm64, arm, riscv64; glibc and musl) — fully supported. Tokens stored via Secret Service (`libsecret`); requires a running keyring daemon (e.g. `gnome-keyring` or KWallet). Headless servers without a keyring backend will fail the keychain step in `jirallm doctor`.
275
+ - **Windows** (x64, arm64, ia32) — fully supported. Tokens stored in Windows Credential Manager. `ffmpeg` must be on `PATH` for video frame extraction.
276
+ - **FreeBSD** (x64) — keychain works; other features untested.
199
277
 
200
278
  ## Contributing
201
279
 
@@ -0,0 +1,9 @@
1
+ export type AssignOptions = {
2
+ issueKey: string;
3
+ assignee: string;
4
+ org?: string;
5
+ dryRun?: boolean;
6
+ json?: boolean;
7
+ };
8
+ export declare function runAssign(opts: AssignOptions): Promise<void>;
9
+ //# sourceMappingURL=assign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/assign.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BlE"}
@@ -0,0 +1,37 @@
1
+ import { loadProfile } from '../../lib/config.js';
2
+ import { JiraClient } from '../../lib/jiraClient.js';
3
+ import { parseIssueKey } from '../issueKey.js';
4
+ import { resolveOrg } from '../resolveOrg.js';
5
+ import { printJson, shouldOutputJson } from '../jsonOutput.js';
6
+ export async function runAssign(opts) {
7
+ const parsed = parseIssueKey(opts.issueKey);
8
+ const org = resolveOrg(parsed.org, opts.org, parsed.projectKey);
9
+ const profile = await loadProfile({ org, project: parsed.projectKey });
10
+ const client = new JiraClient(profile.config, profile.apiToken);
11
+ let accountId;
12
+ if (opts.assignee === 'none' || opts.assignee === '-') {
13
+ accountId = null;
14
+ }
15
+ else if (opts.assignee === 'me') {
16
+ const me = await client.getCurrentUser();
17
+ accountId = me.accountId;
18
+ }
19
+ else {
20
+ accountId = opts.assignee;
21
+ }
22
+ if (opts.dryRun) {
23
+ const payload = { dryRun: true, issueKey: parsed.key, accountId };
24
+ if (shouldOutputJson(opts))
25
+ printJson(payload);
26
+ else
27
+ console.log(`Dry run — would assign ${parsed.key} to ${accountId ?? 'none'}`);
28
+ return;
29
+ }
30
+ await client.assignIssue(parsed.key, accountId);
31
+ if (shouldOutputJson(opts)) {
32
+ printJson({ issueKey: parsed.key, accountId });
33
+ return;
34
+ }
35
+ console.log(`✓ ${parsed.key} assigned to ${accountId ?? 'nobody'}`);
36
+ }
37
+ //# sourceMappingURL=assign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.js","sourceRoot":"","sources":["../../../src/cli/commands/assign.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAU/D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEhE,IAAI,SAAwB,CAAC;IAC7B,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;QACtD,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAClC,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;QACzC,SAAS,GAAG,EAAE,CAAC,SAAS,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC;QAClE,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,OAAO,CAAC,CAAC;;YAC1C,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,CAAC,CAAC;QACnF,OAAO;IACT,CAAC;IAED,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAEhD,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,gBAAgB,SAAS,IAAI,QAAQ,EAAE,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=assign.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/assign.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ vi.mock('../../lib/config.js', () => ({
3
+ loadProfile: vi.fn(async () => ({
4
+ config: { baseUrl: 'https://x', userEmail: 'u@x', projectKey: 'PROJ' },
5
+ apiToken: 'tok',
6
+ })),
7
+ findOrgsByProjectKey: vi.fn(() => ['solo']),
8
+ }));
9
+ const assignIssueMock = vi.fn();
10
+ const getCurrentUserMock = vi.fn();
11
+ vi.mock('../../lib/jiraClient.js', () => ({
12
+ JiraClient: class {
13
+ assignIssue = assignIssueMock;
14
+ getCurrentUser = getCurrentUserMock;
15
+ },
16
+ }));
17
+ import { runAssign } from './assign.js';
18
+ let logs;
19
+ let writes;
20
+ const originalIsTTY = process.stdout.isTTY;
21
+ beforeEach(() => {
22
+ logs = [];
23
+ writes = [];
24
+ vi.spyOn(console, 'log').mockImplementation((...a) => { logs.push(a.map(String).join(' ')); });
25
+ vi.spyOn(process.stdout, 'write').mockImplementation((c) => { writes.push(String(c)); return true; });
26
+ assignIssueMock.mockReset();
27
+ getCurrentUserMock.mockReset();
28
+ });
29
+ afterEach(() => {
30
+ vi.restoreAllMocks();
31
+ Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true });
32
+ });
33
+ describe('runAssign', () => {
34
+ it('resolves "me" to current user accountId', async () => {
35
+ getCurrentUserMock.mockResolvedValue({ accountId: 'acc-me', displayName: 'Me' });
36
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
37
+ await runAssign({ issueKey: 'PROJ-1', assignee: 'me' });
38
+ expect(assignIssueMock).toHaveBeenCalledWith('PROJ-1', 'acc-me');
39
+ });
40
+ it('resolves "none" to null (unassign)', async () => {
41
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
42
+ await runAssign({ issueKey: 'PROJ-1', assignee: 'none' });
43
+ expect(assignIssueMock).toHaveBeenCalledWith('PROJ-1', null);
44
+ expect(getCurrentUserMock).not.toHaveBeenCalled();
45
+ });
46
+ it('treats "-" as unassign sugar', async () => {
47
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
48
+ await runAssign({ issueKey: 'PROJ-1', assignee: '-' });
49
+ expect(assignIssueMock).toHaveBeenCalledWith('PROJ-1', null);
50
+ });
51
+ it('passes through a literal accountId', async () => {
52
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
53
+ await runAssign({ issueKey: 'PROJ-1', assignee: 'acc-42' });
54
+ expect(assignIssueMock).toHaveBeenCalledWith('PROJ-1', 'acc-42');
55
+ });
56
+ it('does NOT call assignIssue on --dry-run', async () => {
57
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
58
+ await runAssign({ issueKey: 'PROJ-1', assignee: 'acc-1', dryRun: true, json: true });
59
+ expect(assignIssueMock).not.toHaveBeenCalled();
60
+ const parsed = JSON.parse(writes.join(''));
61
+ expect(parsed).toEqual({ dryRun: true, issueKey: 'PROJ-1', accountId: 'acc-1' });
62
+ });
63
+ it('emits {issueKey, accountId} JSON on success', async () => {
64
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
65
+ await runAssign({ issueKey: 'PROJ-1', assignee: 'acc-1', json: true });
66
+ expect(JSON.parse(writes.join(''))).toEqual({ issueKey: 'PROJ-1', accountId: 'acc-1' });
67
+ });
68
+ });
69
+ //# sourceMappingURL=assign.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign.test.js","sourceRoot":"","sources":["../../../src/cli/commands/assign.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type AttachOptions = {
2
+ issueKey: string;
3
+ files: string[];
4
+ org?: string;
5
+ dryRun?: boolean;
6
+ json?: boolean;
7
+ };
8
+ export declare function runAttach(opts: AttachOptions): Promise<void>;
9
+ export type AttachRemoveOptions = {
10
+ attachmentId: string;
11
+ org: string;
12
+ dryRun?: boolean;
13
+ json?: boolean;
14
+ };
15
+ export declare function runAttachRemove(opts: AttachRemoveOptions): Promise<void>;
16
+ //# sourceMappingURL=attach.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/attach.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAe9E"}
@@ -0,0 +1,52 @@
1
+ import { loadProfile } from '../../lib/config.js';
2
+ import { JiraClient } from '../../lib/jiraClient.js';
3
+ import { parseIssueKey } from '../issueKey.js';
4
+ import { resolveOrg } from '../resolveOrg.js';
5
+ import { printJson, shouldOutputJson } from '../jsonOutput.js';
6
+ export async function runAttach(opts) {
7
+ const parsed = parseIssueKey(opts.issueKey);
8
+ const org = resolveOrg(parsed.org, opts.org, parsed.projectKey);
9
+ const profile = await loadProfile({ org, project: parsed.projectKey });
10
+ if (opts.dryRun) {
11
+ const payload = { dryRun: true, issueKey: parsed.key, files: opts.files };
12
+ if (shouldOutputJson(opts))
13
+ printJson(payload);
14
+ else
15
+ console.log(`Dry run — would attach ${opts.files.length} file(s) to ${parsed.key}:\n ${opts.files.join('\n ')}`);
16
+ return;
17
+ }
18
+ const client = new JiraClient(profile.config, profile.apiToken);
19
+ const uploaded = [];
20
+ for (const file of opts.files) {
21
+ const result = await client.uploadAttachment(parsed.key, file);
22
+ for (const a of result)
23
+ uploaded.push(a);
24
+ }
25
+ if (shouldOutputJson(opts)) {
26
+ printJson({ issueKey: parsed.key, attachments: uploaded });
27
+ return;
28
+ }
29
+ console.log(`✓ Uploaded ${uploaded.length} attachment(s) to ${parsed.key}:`);
30
+ for (const a of uploaded) {
31
+ console.log(` [${a.id}] ${a.filename} (${a.size}b)`);
32
+ }
33
+ }
34
+ export async function runAttachRemove(opts) {
35
+ if (opts.dryRun) {
36
+ const payload = { dryRun: true, attachmentId: opts.attachmentId };
37
+ if (shouldOutputJson(opts))
38
+ printJson(payload);
39
+ else
40
+ console.log(`Dry run — would delete attachment ${opts.attachmentId}`);
41
+ return;
42
+ }
43
+ const profile = await loadProfile({ org: opts.org });
44
+ const client = new JiraClient(profile.config, profile.apiToken);
45
+ await client.deleteAttachment(opts.attachmentId);
46
+ if (shouldOutputJson(opts)) {
47
+ printJson({ attachmentId: opts.attachmentId, removed: true });
48
+ return;
49
+ }
50
+ console.log(`✓ Removed attachment ${opts.attachmentId}`);
51
+ }
52
+ //# sourceMappingURL=attach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.js","sourceRoot":"","sources":["../../../src/cli/commands/attach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAU/D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAEvE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC1E,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,OAAO,CAAC,CAAC;;YAC1C,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,CAAC,KAAK,CAAC,MAAM,eAAe,MAAM,CAAC,GAAG,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxH,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,QAAQ,GAA0D,EAAE,CAAC;IAC3E,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/D,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,CAAC,MAAM,qBAAqB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;IAC7E,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAyB;IAC7D,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClE,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,OAAO,CAAC,CAAC;;YAC1C,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAC3E,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=attach.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/attach.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ vi.mock('../../lib/config.js', () => ({
3
+ loadProfile: vi.fn(async () => ({
4
+ config: { baseUrl: 'https://x', userEmail: 'u@x', projectKey: 'PROJ' },
5
+ apiToken: 'tok',
6
+ })),
7
+ findOrgsByProjectKey: vi.fn(() => ['solo']),
8
+ }));
9
+ const uploadAttachmentMock = vi.fn();
10
+ const deleteAttachmentMock = vi.fn();
11
+ vi.mock('../../lib/jiraClient.js', () => ({
12
+ JiraClient: class {
13
+ uploadAttachment = uploadAttachmentMock;
14
+ deleteAttachment = deleteAttachmentMock;
15
+ },
16
+ }));
17
+ import { runAttach, runAttachRemove } from './attach.js';
18
+ let logs;
19
+ let writes;
20
+ const originalIsTTY = process.stdout.isTTY;
21
+ beforeEach(() => {
22
+ logs = [];
23
+ writes = [];
24
+ vi.spyOn(console, 'log').mockImplementation((...a) => { logs.push(a.map(String).join(' ')); });
25
+ vi.spyOn(process.stdout, 'write').mockImplementation((c) => { writes.push(String(c)); return true; });
26
+ uploadAttachmentMock.mockReset();
27
+ deleteAttachmentMock.mockReset();
28
+ });
29
+ afterEach(() => {
30
+ vi.restoreAllMocks();
31
+ Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true });
32
+ });
33
+ describe('runAttach', () => {
34
+ it('uploads each file sequentially and aggregates results', async () => {
35
+ uploadAttachmentMock
36
+ .mockResolvedValueOnce([{ id: 'a1', filename: 'a.png', size: 10 }])
37
+ .mockResolvedValueOnce([{ id: 'b1', filename: 'b.txt', size: 5 }]);
38
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
39
+ await runAttach({
40
+ issueKey: 'PROJ-1',
41
+ files: ['./a.png', './b.txt'],
42
+ json: true,
43
+ });
44
+ expect(uploadAttachmentMock).toHaveBeenCalledTimes(2);
45
+ expect(uploadAttachmentMock).toHaveBeenNthCalledWith(1, 'PROJ-1', './a.png');
46
+ expect(uploadAttachmentMock).toHaveBeenNthCalledWith(2, 'PROJ-1', './b.txt');
47
+ const parsed = JSON.parse(writes.join(''));
48
+ expect(parsed.issueKey).toBe('PROJ-1');
49
+ expect(parsed.attachments).toHaveLength(2);
50
+ });
51
+ it('does NOT call uploadAttachment on --dry-run', async () => {
52
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
53
+ await runAttach({
54
+ issueKey: 'PROJ-1',
55
+ files: ['./a.png'],
56
+ dryRun: true,
57
+ json: true,
58
+ });
59
+ expect(uploadAttachmentMock).not.toHaveBeenCalled();
60
+ const parsed = JSON.parse(writes.join(''));
61
+ expect(parsed).toEqual({ dryRun: true, issueKey: 'PROJ-1', files: ['./a.png'] });
62
+ });
63
+ it('prints per-attachment summary on TTY', async () => {
64
+ uploadAttachmentMock.mockResolvedValueOnce([
65
+ { id: 'a1', filename: 'a.png', size: 10 },
66
+ ]);
67
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
68
+ await runAttach({ issueKey: 'PROJ-1', files: ['./a.png'] });
69
+ const out = logs.join('\n');
70
+ expect(out).toContain('Uploaded 1 attachment(s)');
71
+ expect(out).toContain('[a1] a.png (10b)');
72
+ });
73
+ });
74
+ describe('runAttachRemove', () => {
75
+ it('calls deleteAttachment with the id', async () => {
76
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
77
+ await runAttachRemove({ attachmentId: 'att-9', org: 'acme' });
78
+ expect(deleteAttachmentMock).toHaveBeenCalledWith('att-9');
79
+ });
80
+ it('does NOT call deleteAttachment on --dry-run', async () => {
81
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
82
+ await runAttachRemove({ attachmentId: 'att-9', org: 'acme', dryRun: true, json: true });
83
+ expect(deleteAttachmentMock).not.toHaveBeenCalled();
84
+ expect(JSON.parse(writes.join(''))).toEqual({ dryRun: true, attachmentId: 'att-9' });
85
+ });
86
+ it('emits {attachmentId, removed:true} when --json after success', async () => {
87
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
88
+ await runAttachRemove({ attachmentId: 'att-9', org: 'acme', json: true });
89
+ expect(JSON.parse(writes.join(''))).toEqual({ attachmentId: 'att-9', removed: true });
90
+ });
91
+ });
92
+ //# sourceMappingURL=attach.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach.test.js","sourceRoot":"","sources":["../../../src/cli/commands/attach.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export type BoardIssuesOptions = {
2
+ board: string;
3
+ column: string;
4
+ org: string;
5
+ project?: string;
6
+ assignee?: string;
7
+ json?: boolean;
8
+ };
9
+ export declare function runBoardIssues(opts: BoardIssuesOptions): Promise<void>;
10
+ //# sourceMappingURL=board.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/board.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAUF,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8D5E"}
@@ -0,0 +1,54 @@
1
+ import { loadProfile } from '../../lib/config.js';
2
+ import { JiraClient } from '../../lib/jiraClient.js';
3
+ export async function runBoardIssues(opts) {
4
+ const profile = await loadProfile({ org: opts.org, project: opts.project });
5
+ const client = new JiraClient(profile.config, profile.apiToken);
6
+ const statusIds = await client.getBoardColumnStatusIds(opts.board, opts.column);
7
+ if (statusIds.length === 0) {
8
+ if (opts.json) {
9
+ process.stdout.write('[]\n');
10
+ }
11
+ else {
12
+ console.error(`Column "${opts.column}" has no mapped statuses.`);
13
+ }
14
+ return;
15
+ }
16
+ const clauses = [
17
+ `project = ${profile.project.key}`,
18
+ `status in (${statusIds.map((id) => `"${id}"`).join(', ')})`,
19
+ ];
20
+ if (opts.assignee) {
21
+ if (opts.assignee === 'me' || opts.assignee === 'currentUser') {
22
+ clauses.push('assignee = currentUser()');
23
+ }
24
+ else {
25
+ clauses.push(`assignee = "${opts.assignee}"`);
26
+ }
27
+ }
28
+ const jql = clauses.join(' AND ') + ' ORDER BY rank ASC';
29
+ const issues = await client.searchByJql(jql);
30
+ const rows = issues.map((issue) => {
31
+ const fields = issue.fields;
32
+ return {
33
+ key: issue.key,
34
+ summary: fields.summary ?? '',
35
+ status: fields.status?.name ?? 'Unknown',
36
+ assignee: fields.assignee?.displayName,
37
+ issueType: fields.issuetype?.name,
38
+ };
39
+ });
40
+ if (opts.json) {
41
+ process.stdout.write(JSON.stringify({ board: opts.board, column: opts.column, issues: rows }, null, 2) + '\n');
42
+ return;
43
+ }
44
+ if (rows.length === 0) {
45
+ console.log(`No issues in "${opts.column}" on board "${opts.board}".`);
46
+ return;
47
+ }
48
+ console.log(`Board "${opts.board}" / column "${opts.column}" — ${rows.length} issue(s):`);
49
+ for (const row of rows) {
50
+ const assignee = row.assignee ? ` [${row.assignee}]` : '';
51
+ console.log(` ${row.key} ${row.summary}${assignee}`);
52
+ }
53
+ }
54
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../../src/cli/commands/board.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export type BoardsOptions = {
2
+ org: string;
3
+ project?: string;
4
+ type?: 'scrum' | 'kanban' | 'simple';
5
+ name?: string;
6
+ limit?: string;
7
+ startAt?: string;
8
+ json?: boolean;
9
+ };
10
+ export declare function runBoards(opts: BoardsOptions): Promise<void>;
11
+ //# sourceMappingURL=boards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boards.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/boards.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBlE"}
@@ -0,0 +1,27 @@
1
+ import { loadProfile } from '../../lib/config.js';
2
+ import { JiraClient } from '../../lib/jiraClient.js';
3
+ import { printJson, shouldOutputJson } from '../jsonOutput.js';
4
+ export async function runBoards(opts) {
5
+ const profile = await loadProfile({ org: opts.org, project: opts.project });
6
+ const client = new JiraClient(profile.config, profile.apiToken);
7
+ const page = await client.listBoards({
8
+ projectKey: opts.project ?? profile.project.key,
9
+ type: opts.type,
10
+ name: opts.name,
11
+ limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
12
+ startAt: opts.startAt ? parseInt(opts.startAt, 10) : undefined,
13
+ });
14
+ if (shouldOutputJson(opts)) {
15
+ printJson(page);
16
+ return;
17
+ }
18
+ if (page.values.length === 0) {
19
+ console.log('No boards found.');
20
+ return;
21
+ }
22
+ console.log(`${page.values.length} board(s):`);
23
+ for (const b of page.values) {
24
+ console.log(` [${b.id}] ${b.name} (${b.type})`);
25
+ }
26
+ }
27
+ //# sourceMappingURL=boards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boards.js","sourceRoot":"","sources":["../../../src/cli/commands/boards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAY/D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEhE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;QACnC,UAAU,EAAE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG;QAC/C,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QACxD,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;KAC/D,CAAC,CAAC;IAEH,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,YAAY,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=boards.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boards.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/boards.test.ts"],"names":[],"mappings":""}