@eyeauras/youtrack-cli 0.1.0 → 0.3.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 (51) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +113 -30
  3. package/dist/src/article-extras-commands.d.ts.map +1 -1
  4. package/dist/src/article-extras-commands.js +3 -1
  5. package/dist/src/article-extras-commands.js.map +1 -1
  6. package/dist/src/articles-commands.d.ts.map +1 -1
  7. package/dist/src/articles-commands.js +8 -6
  8. package/dist/src/articles-commands.js.map +1 -1
  9. package/dist/src/articles.d.ts +9 -0
  10. package/dist/src/articles.d.ts.map +1 -1
  11. package/dist/src/articles.js +19 -0
  12. package/dist/src/articles.js.map +1 -1
  13. package/dist/src/attachment-download-commands.d.ts +1 -0
  14. package/dist/src/attachment-download-commands.d.ts.map +1 -1
  15. package/dist/src/attachment-download-commands.js +12 -8
  16. package/dist/src/attachment-download-commands.js.map +1 -1
  17. package/dist/src/attachment-download.d.ts +1 -0
  18. package/dist/src/attachment-download.d.ts.map +1 -1
  19. package/dist/src/attachment-download.js +19 -11
  20. package/dist/src/attachment-download.js.map +1 -1
  21. package/dist/src/cli-support.d.ts +5 -2
  22. package/dist/src/cli-support.d.ts.map +1 -1
  23. package/dist/src/cli-support.js +53 -10
  24. package/dist/src/cli-support.js.map +1 -1
  25. package/dist/src/cli.d.ts.map +1 -1
  26. package/dist/src/cli.js +51 -8
  27. package/dist/src/cli.js.map +1 -1
  28. package/dist/src/client.d.ts +19 -4
  29. package/dist/src/client.d.ts.map +1 -1
  30. package/dist/src/client.js +66 -33
  31. package/dist/src/client.js.map +1 -1
  32. package/dist/src/index.d.ts +5 -4
  33. package/dist/src/index.d.ts.map +1 -1
  34. package/dist/src/index.js +5 -4
  35. package/dist/src/index.js.map +1 -1
  36. package/dist/src/issue-batch.d.ts +28 -0
  37. package/dist/src/issue-batch.d.ts.map +1 -0
  38. package/dist/src/issue-batch.js +138 -0
  39. package/dist/src/issue-batch.js.map +1 -0
  40. package/dist/src/issue-context-commands.d.ts.map +1 -1
  41. package/dist/src/issue-context-commands.js +1 -1
  42. package/dist/src/issue-context-commands.js.map +1 -1
  43. package/dist/src/issue-fields.d.ts +16 -0
  44. package/dist/src/issue-fields.d.ts.map +1 -1
  45. package/dist/src/issue-fields.js +96 -1
  46. package/dist/src/issue-fields.js.map +1 -1
  47. package/dist/src/issue-query-commands.js +2 -2
  48. package/dist/src/issue-query-commands.js.map +1 -1
  49. package/dist/src/issue-query.js +2 -2
  50. package/dist/src/issue-query.js.map +1 -1
  51. package/package.json +3 -2
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 AI CLI Factory contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AI CLI Factory contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -16,9 +16,10 @@ Licensed under MIT. See the [release guide](https://github.com/iXab3r/EyeAuras.C
16
16
 
17
17
  YouTrack uses the same `@eyeauras/cli-factory` workspace as TeamCity. The CLI
18
18
  provides standard profiles/auth/permissions and 118 REST operations: 98 ReadOnly and 20 Update.
19
- A separate ReadOnly command downloads one selected issue attachment; it is not REST operation 119.
20
- There are 117 service leaves: 116 for REST operations plus download. Two `--direct` selectors
21
- each select a second REST endpoint without adding another leaf.
19
+ Five workflow leaves reuse those operations instead of adding REST operations: issue and article
20
+ attachment download, article export, and `issues batch validate/apply`. There are 121 service
21
+ leaves: 116 for REST operations plus these five. Two `--direct` selectors each select a second
22
+ REST endpoint without adding another leaf.
22
23
  The foundational read projections are:
23
24
 
24
25
  | Command | Default fields |
@@ -31,16 +32,24 @@ The foundational read projections are:
31
32
 
32
33
  REST reads support explicit `--fields <projection>`. Projection results retain the server's
33
34
  field names, `$type` and nullable values; authentication always validates fixed `id,login`.
34
- Offset collections use `--top 50 --skip 0` by default; top is 1–100 and skip a nonnegative integer.
35
+ Offset collections use `--top 50 --skip 0` by default; top is a positive safe integer and skip a nonnegative safe integer.
35
36
  Paging accepts unsigned decimal digits, including leading zeros; signs (including `-0`), whitespace,
36
37
  fractions, exponents and unsafe integers reject. Invalid syntax, range and overflow now fail before
37
38
  onboarding or credential access on CLI, execute and RPC. The static errors are
38
- `YouTrack top must be a decimal integer between 1 and 100.` and
39
+ `YouTrack top must be a positive safe decimal integer.` and
39
40
  `YouTrack skip must be a nonnegative safe decimal integer.`; they never include the supplied input.
40
41
  Directly callable service methods retain their own range validation.
41
- Each collection command makes one request, and rejects an oversized server page. No `--all`
42
- or implicit nested follow-up requests are provided. Issue IDs are encoded as opaque path
43
- segments, including readable IDs such as `DEMO-1`.
42
+ Each collection command makes one request, and rejects an oversized server page. Multi-page reads
43
+ happen only for the explicit `issues list --all` described below and for field `name` selectors in
44
+ issue writes (their field list is read completely; cancellable); no other nested follow-up requests
45
+ are made. Issue IDs are encoded as opaque path segments, including readable IDs such as `DEMO-1`.
46
+
47
+ `issues list --all --max-results <n>` reads every page (`--top` is the page size, `--skip` the start)
48
+ with the same query and projection. Success means the selection is complete: the result is the
49
+ same JSON array in server order, with repeated `id`s removed. More than `n` issues, responses over
50
+ the optional `--max-bytes <n>` (total decoded bytes; also valid without `--all`) or any failed page
51
+ fail the whole command without partial output or retries. `--all` and `--max-results` require each
52
+ other. Offset paging is not a snapshot: concurrent changes can still omit issues.
44
53
 
45
54
  ```powershell
46
55
  npm run youtrack -- project list --top 3 --profile youtrack-dev
@@ -54,16 +63,14 @@ Empty collections are `[]`. Signed/credential-bearing URLs and the active bearer
54
63
  scrubbed recursively, including explicitly projected nested fields. Unsigned URLs remain
55
64
  unchanged. Failures expose HTTP status and safe Retry-After information, never raw server
56
65
  errors or authentication material. Remote mutations require the Update gate, described below.
57
- The ReadOnly download command writes only its explicitly requested local file beneath profile AppData.
66
+ The ReadOnly download and export commands write only their explicitly requested local file beneath
67
+ profile AppData.
58
68
 
59
- JSON responses now have an 8 MiB limit on actual decoded bytes, including responses without a
60
- Content-Length header. This allows room for the existing bounded pages and text-rich projections;
61
- it does not guarantee every requested projection will fit. Narrow `--fields` or reduce `--top` if
62
- needed. Invalid/truncated identity transfer lengths, overflow, stream failure or cancellation fail
63
- with `YouTrack response stream failed, exceeded 8 MiB, or was cancelled.` without response content.
64
- Compressed wire length is syntax-checked but not compared with decoded size. Existing HTTP status,
65
- Retry-After, empty/null mutation and UTF-8 BOM behavior are unchanged. Attachment-download limits
66
- remain separate; no request is retried automatically.
69
+ JSON responses have no CLI byte ceiling. Invalid/truncated identity transfer lengths, stream failure
70
+ or cancellation fail with `YouTrack response stream failed or was cancelled.` without response content.
71
+ Compressed wire length is syntax-checked but not compared with decoded size. HTTP status,
72
+ Retry-After, empty/null mutation and UTF-8 BOM behavior are unchanged. No request is retried
73
+ automatically. Runtime memory and service limits still apply.
67
74
 
68
75
  ## Sign in locally
69
76
 
@@ -130,17 +137,37 @@ This documentation does not enable it automatically. The local proof remains Rea
130
137
 
131
138
  | Command | Required `--body` JSON object |
132
139
  |---|---|
133
- | `issues create` | Nonempty `project.id` and `summary`; optional string or null `description` |
134
- | `issues update <issueID>` | Nonempty subset of `summary` and `description`; summary must be nonempty |
140
+ | `issues create` | `project` as exactly one of `{id}`/`{shortName}`, nonempty `summary`; optional string or null `description`, optional `customFields` |
141
+ | `issues update <issueID>` | Nonempty subset of `summary`, `description` and `customFields`; summary must be nonempty |
135
142
  | `issues comments add <issueID>` | Nonempty `text` only |
136
143
 
137
144
  Missing `--body` and malformed JSON fail before profile onboarding or credential access.
138
145
  Description and comment text preserve multiline Markdown. Omitted fields remain unchanged;
139
146
  `description: null` clears the description. Unknown fields (including nested project properties)
140
- are rejected locally. The `issues create` and `issues update` bodies do not accept custom fields,
141
- state/assignee, visibility or notification controls. Use the separate `issues fields set` command
142
- for supported custom-field changes described below. A project may require custom fields without
143
- defaults; creation then fails safely with the server's status rather than guessing missing values.
147
+ are rejected locally. Visibility, notification controls and state-machine events are not accepted.
148
+
149
+ `customFields` is a nonempty array sent in the same single POST, so a project's required fields
150
+ can be set at creation. Each entry has an explicit `$type`, exactly one of `id` or `name`, and a
151
+ `value` validated like `issues fields set` below (`null`/`[]` clear on update). A field may appear
152
+ once. `StateMachineIssueCustomField` is rejected: a new issue starts in its workflow's initial
153
+ state, and transitions stay on `issues fields set` events or `commands apply`. Selectors resolve
154
+ exactly before the write: `project.shortName` by one project read (case-insensitive match
155
+ required), field `name` (case-sensitive) against all fields of the project (create) or issue
156
+ (update). Zero or several matches fail before the POST; `id` entries need no lookup. Value
157
+ selectors (`id`, `name`, `login` for users) are resolved by YouTrack inside the request; `$type`
158
+ is never inferred and nothing is cached.
159
+
160
+ ```powershell
161
+ npm run youtrack -- issues create --profile youtrack-dev --body '{"project":{"shortName":"DEMO"},"summary":"Example","customFields":[{"$type":"SingleEnumIssueCustomField","name":"Priority","value":{"name":"Major"}}]}'
162
+ ```
163
+
164
+ Every narrative write also accepts a UTF-8 file for its text field: `--description-file` (issue
165
+ create/update), `--content-file` (article create/update) and `--text-file` (issue/article comment
166
+ add/update). `--body` stays required (use `{}` when the file supplies the only field) and must not
167
+ also contain that field. Files are read only after Update admission, as strict UTF-8 with an
168
+ initial BOM removed and otherwise unchanged (line endings included); invalid encoding, directories
169
+ and unreadable paths fail before any request. Clearing still uses `--body` with `null`. There is no
170
+ local size ceiling, and stdin is not used because JSON-RPC owns it.
144
171
 
145
172
  For Windows **CMD**, replace the example project ID before deliberately running a write:
146
173
 
@@ -182,7 +209,7 @@ for exact arguments and permission categories; no endpoint, header or arbitrary
182
209
  `commands assist`, `search assist` and `issues count` use POST on the wire but remain ReadOnly:
183
210
  they compute suggestions or counts without applying changes. Assist is not a dry run or a guarantee
184
211
  that a later command will succeed. Required `--query` is preserved exactly; optional `--caret` is
185
- between zero and its length. `commands apply` requires 1–20 comma-separated explicit issue IDs via
212
+ between zero and its length. `commands apply` requires comma-separated distinct explicit issue IDs via
186
213
  `--issues`, never an implicit search expansion. It has no run-as or silent mode. Count returns the
187
214
  server's `count`, including `-1` (pending) or `null`; the CLI never polls automatically.
188
215
 
@@ -195,7 +222,7 @@ Project fields expose field types and settings without following bundle referenc
195
222
  preserve polymorphic values, including scalar, null and array values. `issues fields set` accepts
196
223
  an explicit `$type` and `value`: single/multi Enum, Build, Version, Owned, Group and User types;
197
224
  State, Simple, Date, Period and Text types. References use explicit identity selectors (`id`,
198
- `name`, and `login` for users); the CLI performs no name lookup. Single values can use `null`,
225
+ `name`, and `login` for users); `fields set` performs no lookup of its own. Single values can use `null`,
199
226
  multi values use `[]` to clear. Period values accept nonnegative 32-bit integer `minutes`
200
227
  and/or `presentation`; dates use
201
228
  integer Unix milliseconds. Text values use `{ "text": "..." }`. StateMachine fields instead
@@ -289,15 +316,16 @@ add six operations. The hierarchy commands read only the selected relationship a
289
316
  recursively traverse descendants. A literal JSON null parent remains null; an empty body,
290
317
  404 or malformed response is still an error. Article attachment upload requires one explicit
291
318
  `--file`, the Update gate, and uses native multipart after checking that the file is regular.
292
- It supports `--fields` for the response. No implicit file discovery or article binary download
293
- is provided, and upload never grants permissions.
319
+ It supports `--fields` for the response. No implicit file discovery is provided, and upload never
320
+ grants permissions.
294
321
 
295
322
  ```powershell
296
323
  npm run youtrack -- issues attachments download DEMO-1 1-1 --profile youtrack-dev
297
324
  npm run youtrack -- issues attachments download DEMO-1 1-1 --name report.txt --max-bytes 1048576 --profile youtrack-dev
325
+ npm run youtrack -- article attachment download KB-A-1 7-1 --profile youtrack-dev
298
326
  ```
299
327
 
300
- Issue attachment download first reads the exact attachment's fixed metadata, then requests only
328
+ Issue and article attachment downloads first read the exact attachment's fixed metadata, then request only
301
329
  its returned URL. The file request sends neither Authorization nor cookies, follows no redirects,
302
330
  and accepts only the configured origin and documented attachment path beneath its context.
303
331
  External/CDN URLs fail rather than relaxing this policy. Signatures stay in memory and never
@@ -305,8 +333,9 @@ appear in metadata output, errors or the download result.
305
333
 
306
334
  Files go beneath the selected profile's `AppDataDirectory/downloads`. `--name` must be a safe
307
335
  single basename; the default prefixes the sanitized attachment name with its ID. Existing
308
- filenames are never overwritten. The default limit is 25 MiB; `--max-bytes` accepts 1–104857600
309
- and is enforced while streaming as well as against Content-Length. Core stages bytes in a fresh
336
+ filenames are never overwritten. Downloads have no default byte ceiling. Optional `--max-bytes`
337
+ accepts a positive safe integer and enforces the caller-selected bound while streaming and against
338
+ Content-Length. Filename lengths are left to the filesystem. Core stages bytes in a fresh
310
339
  private directory under this profile's `temp`, then hard-links only the complete identity-checked
311
340
  file into `downloads`. Partial files are removed when their identities remain trusted. Output
312
341
  contains only sanitized ID/name, local path, byte count and content type.
@@ -317,6 +346,60 @@ current-user-owned AppData; it cannot prevent every malicious same-account repla
317
346
  last identity check. Errors report whether publication occurred and whether private staging cleanup
318
347
  failed, without raw filesystem/service details. The local proof never invokes download or upload.
319
348
 
349
+ `article export <article> [--name <basename>]` (ReadOnly) saves the article content, with signed
350
+ URLs scrubbed like console output, as `downloads/<idReadable>.md` through the same no-overwrite
351
+ publication. Edit it and send it back with `article update <article> --body '{}' --content-file <path>`.
352
+ The result's `redacted: true` means the file contains `[redacted]` placeholders where console-output
353
+ scrubbing removed text (signed or credential-bearing URLs, undecodable URL-like text or the token);
354
+ sending it back unchanged would replace that text in YouTrack, so restore it first or edit that
355
+ article elsewhere.
356
+ The local `downloads list`, `downloads delete <name>` and `downloads clean` built-ins (ungated, no
357
+ network) show or remove saved files: only regular files directly in the selected profile's
358
+ `downloads` directory, never links, subdirectories, staging or other profiles.
359
+
360
+ ## Issue batches
361
+
362
+ `issues batch validate --file <manifest>` (ReadOnly; sends no requests and never uses the token,
363
+ but like every service command runs against a configured profile) and `issues batch apply --file
364
+ <manifest>` (Update, checked before the file is read) accept a `.json` array of rows or a UTF-8 `.csv`
365
+ with a header row. A row is `action` (`create`/`update`), `issue` (update only, an exact ID, never a
366
+ search) and the same body fields as `issues create/update`. CSV columns are `action`, `issue`,
367
+ `project.id`, `project.shortName`, `summary`, `description` and `customFields` (a JSON array cell);
368
+ an empty cell omits the field, so clearing needs JSON. CSV syntax errors and unknown or repeated
369
+ columns fail as a whole; unknown keys and invalid rows fail with the row number. Either way nothing
370
+ is written. Name selectors are resolved per row during apply.
371
+
372
+ Apply runs rows in order, one request per write plus exact selector reads, without retries,
373
+ rollback or compensation; a batch is not atomic. It stops at the first unsuccessful row unless
374
+ `--continue-on-error` is given. Each row reports `completed` (with the write result), `failed`
375
+ (rejected before the write or with HTTP 4xx: not applied), `uncertain` (connectivity, 5xx or an
376
+ invalid response: it may have been applied) or `unattempted`; the overall `status` is `completed`
377
+ or `incomplete`, with counts. The command itself succeeds (exit code 0) once rows ran, so callers
378
+ must check `status`. `--failed-rows <name>.json` saves the `failed` and `unattempted` rows
379
+ as a manifest under `downloads` for deliberate resubmission; `uncertain` rows are left out and must
380
+ be checked in YouTrack first. A save failure is reported in `failedRows.error` without hiding row results.
381
+
382
+ ## Compared with `yt` 0.22.2
383
+
384
+ The everyday issue and article workflows have explicit, typed commands:
385
+ - issue creation and updates with custom fields in one request;
386
+ - exact human-readable selectors;
387
+ - budgeted `issues list --all`;
388
+ - JSON/CSV batches;
389
+ - attachment downloads, article export and text-file inputs.
390
+
391
+ Deliberate differences:
392
+ - field types are never guessed and selectors never take the first match;
393
+ - field-value names are validated by YouTrack rather than pre-resolved;
394
+ - a failed batch never deletes created issues to compensate.
395
+
396
+ Not provided:
397
+ - project, user, group and role administration;
398
+ - deletion wrappers;
399
+ - burndown and velocity reports;
400
+ - interactive tables, themes, tutorials and aliases;
401
+ - stdin input (JSON-RPC owns stdin).
402
+
320
403
  ## Local proof and offline tests
321
404
 
322
405
  After configuring a profile, explicitly run:
@@ -1 +1 @@
1
- {"version":3,"file":"article-extras-commands.d.ts","sourceRoot":"","sources":["../../src/article-extras-commands.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,qBAAqB,qDAgDjC,CAAC"}
1
+ {"version":3,"file":"article-extras-commands.d.ts","sourceRoot":"","sources":["../../src/article-extras-commands.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,qBAAqB,qDAiDjC,CAAC"}
@@ -1,9 +1,11 @@
1
1
  import { command } from "@eyeauras/cli-factory";
2
2
  import { requiredText } from "./client.js";
3
+ import { articleAttachmentDownloadCommand } from "./attachment-download-commands.js";
3
4
  import { pagedRead, projectedRead, updateCommand, projectionOptions, readOptions } from "./cli-support.js";
4
5
  import { getArticleAttachment, getChildArticle, getParentArticle, listArticleAttachments, listChildArticles, uploadArticleAttachment, } from "./article-extras.js";
5
6
  export const articlesExtraChildren = [
6
- command("attachment", "Inspect article attachment metadata and upload one file", [
7
+ command("attachment", "Inspect, upload or download one selected article attachment", [
8
+ articleAttachmentDownloadCommand,
7
9
  pagedRead("list <article>", "List one page of attachment metadata without downloading files", listArticleAttachments),
8
10
  projectedRead("get <article> <attachment>", "Read attachment metadata without downloading its contents", getArticleAttachment),
9
11
  updateCommand("upload <article>", "Upload one selected regular file to an existing article", async (connection, { args, options }, context) => uploadArticleAttachment(connection, args.article, String(options.file), readOptions(options)), [
@@ -1 +1 @@
1
- {"version":3,"file":"article-extras-commands.js","sourceRoot":"","sources":["../../src/article-extras-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3G,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,OAAO,CAAC,YAAY,EAAE,yDAAyD,EAAE;QAC/E,SAAS,CACP,gBAAgB,EAChB,gEAAgE,EAChE,sBAAsB,CACvB;QACD,aAAa,CACX,4BAA4B,EAC5B,2DAA2D,EAC3D,oBAAoB,CACrB;QACD,aAAa,CACX,kBAAkB,EAClB,yDAAyD,EACzD,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAC/C,uBAAuB,CACrB,UAAU,EACV,IAAI,CAAC,OAAO,EACZ,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EACpB,WAAW,CAAC,OAAO,CAAC,CACrB,EACH;YACI,GAAG,iBAAiB;YACpB;gBACE,KAAK,EAAE,eAAe;gBACtB,WAAW,EAAE,4DAA4D;gBACzE,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC;aACnD;SACF,CACJ;KACF,CAAC;IACF,OAAO,CAAC,OAAO,EAAE,8DAA8D,EAAE;QAC/E,SAAS,CAAC,gBAAgB,EAAE,2CAA2C,EAAE,iBAAiB,CAAC;QAC3F,aAAa,CACX,uBAAuB,EACvB,gDAAgD,EAChD,eAAe,CAChB;KACF,CAAC;IACF,OAAO,CAAC,QAAQ,EAAE,6BAA6B,EAAE;QAC/C,aAAa,CACX,eAAe,EACf,gEAAgE,EAChE,gBAAgB,CACjB;KACF,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"article-extras-commands.js","sourceRoot":"","sources":["../../src/article-extras-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gCAAgC,EAAE,MAAM,mCAAmC,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3G,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,OAAO,CAAC,YAAY,EAAE,6DAA6D,EAAE;QACnF,gCAAgC;QAChC,SAAS,CACP,gBAAgB,EAChB,gEAAgE,EAChE,sBAAsB,CACvB;QACD,aAAa,CACX,4BAA4B,EAC5B,2DAA2D,EAC3D,oBAAoB,CACrB;QACD,aAAa,CACX,kBAAkB,EAClB,yDAAyD,EACzD,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAC/C,uBAAuB,CACrB,UAAU,EACV,IAAI,CAAC,OAAO,EACZ,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EACpB,WAAW,CAAC,OAAO,CAAC,CACrB,EACH;YACI,GAAG,iBAAiB;YACpB;gBACE,KAAK,EAAE,eAAe;gBACtB,WAAW,EAAE,4DAA4D;gBACzE,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC;aACnD;SACF,CACJ;KACF,CAAC;IACF,OAAO,CAAC,OAAO,EAAE,8DAA8D,EAAE;QAC/E,SAAS,CAAC,gBAAgB,EAAE,2CAA2C,EAAE,iBAAiB,CAAC;QAC3F,aAAa,CACX,uBAAuB,EACvB,gDAAgD,EAChD,eAAe,CAChB;KACF,CAAC;IACF,OAAO,CAAC,QAAQ,EAAE,6BAA6B,EAAE;QAC/C,aAAa,CACX,eAAe,EACf,gEAAgE,EAChE,gBAAgB,CACjB;KACF,CAAC;CACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"articles-commands.d.ts","sourceRoot":"","sources":["../../src/articles-commands.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,oBAAoB,qDA8BhC,CAAC;AAEF,eAAO,MAAM,uBAAuB,qDAInC,CAAC"}
1
+ {"version":3,"file":"articles-commands.d.ts","sourceRoot":"","sources":["../../src/articles-commands.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,oBAAoB,qDA6ChC,CAAC;AAEF,eAAO,MAAM,uBAAuB,qDAInC,CAAC"}
@@ -1,19 +1,21 @@
1
1
  import { command } from "@eyeauras/cli-factory";
2
2
  import { articlesExtraChildren } from "./article-extras-commands.js";
3
- import { pagedRead, projectedBodyUpdate, projectedRead } from "./cli-support.js";
4
- import { addArticleComment, createArticle, getArticle, getArticleComment, listArticleComments, listArticles, listProjectArticles, updateArticle, updateArticleComment, } from "./articles.js";
3
+ import { downloadName } from "./attachment-download.js";
4
+ import { pagedRead, projectedBodyUpdate, projectedRead, readCommand } from "./cli-support.js";
5
+ import { addArticleComment, createArticle, exportArticle, getArticle, getArticleComment, listArticleComments, listArticles, listProjectArticles, updateArticle, updateArticleComment, } from "./articles.js";
5
6
  export const articlesRootCommands = [
6
7
  command("article", "Read and write knowledge-base articles", [
7
8
  ...articlesExtraChildren,
8
9
  pagedRead("list", "List one page of accessible articles", listArticles),
9
10
  projectedRead("get <article>", "Read article content and parent identity", getArticle),
10
- projectedBodyUpdate("create", "Create an article with project.id, summary and optional content", createArticle),
11
- projectedBodyUpdate("update <article>", "Update summary/content; null content clears it and omitted fields stay unchanged", updateArticle),
11
+ readCommand("export <article>", "Save article content under this profile's downloads directory without overwriting files", async (connection, { args, options }, context) => exportArticle(connection, args.article, context.appArguments.AppDataDirectory, typeof options.name === "string" ? options.name : undefined), [{ flags: "--name <basename>", description: "Optional safe filename (default: <idReadable>.md)", parse: downloadName }]),
12
+ projectedBodyUpdate("create", "Create an article with project.id, summary and optional content", createArticle, "content"),
13
+ projectedBodyUpdate("update <article>", "Update summary/content; null content clears it and omitted fields stay unchanged", updateArticle, "content"),
12
14
  command("comment", "Read and write article comments", [
13
15
  pagedRead("list <article>", "List one page of comments", listArticleComments),
14
16
  projectedRead("get <article> <comment>", "Read an article comment", getArticleComment),
15
- projectedBodyUpdate("add <article>", "Add an article comment with nonempty text", addArticleComment),
16
- projectedBodyUpdate("update <article> <comment>", "Replace an article comment's text", updateArticleComment),
17
+ projectedBodyUpdate("add <article>", "Add an article comment with nonempty text", addArticleComment, "text"),
18
+ projectedBodyUpdate("update <article> <comment>", "Replace an article comment's text", updateArticleComment, "text"),
17
19
  ]),
18
20
  ]),
19
21
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"articles-commands.js","sourceRoot":"","sources":["../../src/articles-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,OAAO,CAAC,SAAS,EAAE,wCAAwC,EAAE;QAC3D,GAAG,qBAAqB;QACxB,SAAS,CAAC,MAAM,EAAE,sCAAsC,EAAE,YAAY,CAAC;QACvE,aAAa,CAAC,eAAe,EAAE,0CAA0C,EAAE,UAAU,CAAC;QACtF,mBAAmB,CACjB,QAAQ,EACR,iEAAiE,EACjE,aAAa,CACd;QACD,mBAAmB,CACjB,kBAAkB,EAClB,kFAAkF,EAClF,aAAa,CACd;QACD,OAAO,CAAC,SAAS,EAAE,iCAAiC,EAAE;YACpD,SAAS,CAAC,gBAAgB,EAAE,2BAA2B,EAAE,mBAAmB,CAAC;YAC7E,aAAa,CAAC,yBAAyB,EAAE,yBAAyB,EAAE,iBAAiB,CAAC;YACtF,mBAAmB,CACjB,eAAe,EACf,2CAA2C,EAC3C,iBAAiB,CAClB;YACD,mBAAmB,CACjB,4BAA4B,EAC5B,mCAAmC,EACnC,oBAAoB,CACrB;SACF,CAAC;KACH,CAAC;CACH,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO,CAAC,SAAS,EAAE,yCAAyC,EAAE;QAC5D,SAAS,CAAC,gBAAgB,EAAE,wCAAwC,EAAE,mBAAmB,CAAC;KAC3F,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"articles-commands.js","sourceRoot":"","sources":["../../src/articles-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,OAAO,CAAC,SAAS,EAAE,wCAAwC,EAAE;QAC3D,GAAG,qBAAqB;QACxB,SAAS,CAAC,MAAM,EAAE,sCAAsC,EAAE,YAAY,CAAC;QACvE,aAAa,CAAC,eAAe,EAAE,0CAA0C,EAAE,UAAU,CAAC;QACtF,WAAW,CACT,kBAAkB,EAClB,yFAAyF,EACzF,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,aAAa,CAC7D,UAAU,EACV,IAAI,CAAC,OAAO,EACZ,OAAO,CAAC,YAAY,CAAC,gBAAgB,EACrC,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAC5D,EACD,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,mDAAmD,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CACxH;QACD,mBAAmB,CACjB,QAAQ,EACR,iEAAiE,EACjE,aAAa,EACb,SAAS,CACV;QACD,mBAAmB,CACjB,kBAAkB,EAClB,kFAAkF,EAClF,aAAa,EACb,SAAS,CACV;QACD,OAAO,CAAC,SAAS,EAAE,iCAAiC,EAAE;YACpD,SAAS,CAAC,gBAAgB,EAAE,2BAA2B,EAAE,mBAAmB,CAAC;YAC7E,aAAa,CAAC,yBAAyB,EAAE,yBAAyB,EAAE,iBAAiB,CAAC;YACtF,mBAAmB,CACjB,eAAe,EACf,2CAA2C,EAC3C,iBAAiB,EACjB,MAAM,CACP;YACD,mBAAmB,CACjB,4BAA4B,EAC5B,mCAAmC,EACnC,oBAAoB,EACpB,MAAM,CACP;SACF,CAAC;KACH,CAAC;CACH,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO,CAAC,SAAS,EAAE,yCAAyC,EAAE;QAC5D,SAAS,CAAC,gBAAgB,EAAE,wCAAwC,EAAE,mBAAmB,CAAC;KAC3F,CAAC;CACH,CAAC"}
@@ -1,6 +1,15 @@
1
+ import { type PublishedProfileFile } from "@eyeauras/cli-factory";
1
2
  import { type Connection, type ProjectionOptions, type YouTrackObject } from "./client.js";
2
3
  export declare const listArticles: (connection: Connection, options?: import("./client.js").PageOptions | undefined) => Promise<YouTrackObject[]>;
3
4
  export declare const getArticle: (connection: Connection, articleID: string, options?: ProjectionOptions | undefined) => Promise<YouTrackObject>;
5
+ /**
6
+ * Save the scrubbed article content as a profile-owned file for a fetch/edit/update workflow.
7
+ * `redacted` warns that URL placeholders would replace the originals if the file were sent back.
8
+ */
9
+ export declare function exportArticle(connection: Connection, articleID: string, appDataDirectory: string, name?: string): Promise<{
10
+ id: string;
11
+ redacted: boolean;
12
+ } & PublishedProfileFile>;
4
13
  export declare function createArticle(connection: Connection, input: unknown, options?: ProjectionOptions): Promise<YouTrackObject | null>;
5
14
  export declare function updateArticle(connection: Connection, articleID: string, input: unknown, options?: ProjectionOptions): Promise<YouTrackObject | null>;
6
15
  export declare const listArticleComments: (connection: Connection, articleID: string, options?: import("./client.js").PageOptions | undefined) => Promise<YouTrackObject[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"articles.d.ts","sourceRoot":"","sources":["../../src/articles.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAWrB,eAAO,MAAM,YAAY,gHAAsD,CAAC;AAChF,eAAO,MAAM,UAAU,iHAAiD,CAAC;AAEzE,wBAAsB,aAAa,CACjC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAahC;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAchC;AAED,eAAO,MAAM,mBAAmB,mIAG/B,CAAC;AACF,eAAO,MAAM,iBAAiB,oIAI7B,CAAC;AAEF,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQhC;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQhC;AAED,eAAO,MAAM,mBAAmB,mIAG/B,CAAC"}
1
+ {"version":3,"file":"articles.d.ts","sourceRoot":"","sources":["../../src/articles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EASL,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAWrB,eAAO,MAAM,YAAY,gHAAsD,CAAC;AAChF,eAAO,MAAM,UAAU,iHAAiD,CAAC;AAEzE;;;GAGG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,EACxB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,oBAAoB,CAAC,CAanE;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAahC;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAchC;AAED,eAAO,MAAM,mBAAmB,mIAG/B,CAAC;AACF,eAAO,MAAM,iBAAiB,oIAI7B,CAAC;AAEF,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQhC;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQhC;AAED,eAAO,MAAM,mBAAmB,mIAG/B,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { saveProfileFile } from "@eyeauras/cli-factory";
1
2
  import { encodedID, fields, mutate, mutationBody, narrative, nullableText, readCollectionAt, readObjectAt, } from "./client.js";
2
3
  const articleListFields = "id,idReadable,summary,project(id,shortName),updated";
3
4
  const articleDetailFields = `${articleListFields},content,parentArticle(id,idReadable),created`;
@@ -8,6 +9,24 @@ function articlePath(articleID) {
8
9
  }
9
10
  export const listArticles = readCollectionAt("api/articles", articleListFields);
10
11
  export const getArticle = readObjectAt(articlePath, articleDetailFields);
12
+ /**
13
+ * Save the scrubbed article content as a profile-owned file for a fetch/edit/update workflow.
14
+ * `redacted` warns that URL placeholders would replace the originals if the file were sent back.
15
+ */
16
+ export async function exportArticle(connection, articleID, appDataDirectory, name) {
17
+ const article = await getArticle(connection, articleID, { fields: "id,idReadable,content" });
18
+ const id = typeof article.idReadable === "string" ? article.idReadable : article.id;
19
+ if (typeof id !== "string" || !id || (article.content !== null && typeof article.content !== "string")) {
20
+ throw new Error("YouTrack returned an invalid article for export.");
21
+ }
22
+ const saved = await saveProfileFile({
23
+ appDataDirectory,
24
+ name: name ?? `${id.replace(/[^a-zA-Z0-9._-]/g, "_")}.md`,
25
+ content: article.content ?? "",
26
+ signal: connection.signal,
27
+ });
28
+ return { id, ...saved, redacted: article.content?.includes("[redacted]") ?? false };
29
+ }
11
30
  export async function createArticle(connection, input, options = {}) {
12
31
  const body = mutationBody(input, ["project", "summary", "content"]);
13
32
  const project = mutationBody(body.project, ["id"]);
@@ -1 +1 @@
1
- {"version":3,"file":"articles.js","sourceRoot":"","sources":["../../src/articles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"articles.js","sourceRoot":"","sources":["../../src/articles.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,3 @@
1
1
  export declare const attachmentDownloadCommand: import("@eyeauras/cli-factory").CommandDefinition;
2
+ export declare const articleAttachmentDownloadCommand: import("@eyeauras/cli-factory").CommandDefinition;
2
3
  //# sourceMappingURL=attachment-download-commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-download-commands.d.ts","sourceRoot":"","sources":["../../src/attachment-download-commands.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,yBAAyB,mDA0BrC,CAAC"}
1
+ {"version":3,"file":"attachment-download-commands.d.ts","sourceRoot":"","sources":["../../src/attachment-download-commands.ts"],"names":[],"mappings":"AA8BA,eAAO,MAAM,yBAAyB,mDAWrC,CAAC;AAEF,eAAO,MAAM,gCAAgC,mDAW5C,CAAC"}
@@ -1,9 +1,6 @@
1
1
  import { readCommand } from "./cli-support.js";
2
- import { downloadIssueAttachment, downloadLimit, downloadName } from "./attachment-download.js";
3
- export const attachmentDownloadCommand = readCommand("download <issueID> <attachmentID>", "Download one attachment into this profile's downloads directory without overwriting files", async (connection, { args, options }, context) => downloadIssueAttachment(connection, args.issueID, args.attachmentID, context.appArguments.AppDataDirectory, {
4
- ...(typeof options.name === "string" ? { name: options.name } : {}),
5
- ...(typeof options.maxBytes === "number" ? { maxBytes: options.maxBytes } : {}),
6
- }), [
2
+ import { downloadArticleAttachment, downloadIssueAttachment, downloadLimit, downloadName, } from "./attachment-download.js";
3
+ const downloadOptions = [
7
4
  {
8
5
  flags: "--name <basename>",
9
6
  description: "Optional safe filename; an existing name is never overwritten",
@@ -11,9 +8,16 @@ export const attachmentDownloadCommand = readCommand("download <issueID> <attach
11
8
  },
12
9
  {
13
10
  flags: "--max-bytes <n>",
14
- description: "Maximum transfer size in bytes (1-104857600)",
15
- defaultValue: 25 * 1024 * 1024,
11
+ description: "Optional maximum transfer size in bytes (positive safe integer)",
16
12
  parse: downloadLimit,
17
13
  },
18
- ]);
14
+ ];
15
+ function downloadInput(options) {
16
+ return {
17
+ ...(typeof options.name === "string" ? { name: options.name } : {}),
18
+ ...(typeof options.maxBytes === "number" ? { maxBytes: options.maxBytes } : {}),
19
+ };
20
+ }
21
+ export const attachmentDownloadCommand = readCommand("download <issueID> <attachmentID>", "Download one attachment into this profile's downloads directory without overwriting files", async (connection, { args, options }, context) => downloadIssueAttachment(connection, args.issueID, args.attachmentID, context.appArguments.AppDataDirectory, downloadInput(options)), downloadOptions);
22
+ export const articleAttachmentDownloadCommand = readCommand("download <article> <attachment>", "Download one article attachment into this profile's downloads directory without overwriting files", async (connection, { args, options }, context) => downloadArticleAttachment(connection, args.article, args.attachment, context.appArguments.AppDataDirectory, downloadInput(options)), downloadOptions);
19
23
  //# sourceMappingURL=attachment-download-commands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-download-commands.js","sourceRoot":"","sources":["../../src/attachment-download-commands.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEhG,MAAM,CAAC,MAAM,yBAAyB,GAAG,WAAW,CAClD,mCAAmC,EACnC,2FAA2F,EAC3F,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,uBAAuB,CACvE,UAAU,EACV,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,YAAY,EACjB,OAAO,CAAC,YAAY,CAAC,gBAAgB,EACrC;IACE,GAAG,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,GAAG,CAAC,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CAChF,CACF,EACD;IACI;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,+DAA+D;QAC5E,KAAK,EAAE,YAAY;KACpB;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,8CAA8C;QAC3D,YAAY,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;QAC9B,KAAK,EAAE,aAAa;KACrB;CACF,CACJ,CAAC"}
1
+ {"version":3,"file":"attachment-download-commands.js","sourceRoot":"","sources":["../../src/attachment-download-commands.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,aAAa,EACb,YAAY,GAEb,MAAM,0BAA0B,CAAC;AAElC,MAAM,eAAe,GAAG;IACtB;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,+DAA+D;QAC5E,KAAK,EAAE,YAAY;KACpB;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,iEAAiE;QAC9E,KAAK,EAAE,aAAa;KACrB;CACF,CAAC;AAEF,SAAS,aAAa,CAAC,OAAgC;IACrD,OAAO;QACL,GAAG,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,WAAW,CAClD,mCAAmC,EACnC,2FAA2F,EAC3F,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,uBAAuB,CACvE,UAAU,EACV,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,YAAY,EACjB,OAAO,CAAC,YAAY,CAAC,gBAAgB,EACrC,aAAa,CAAC,OAAO,CAAC,CACvB,EACD,eAAe,CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAAG,WAAW,CACzD,iCAAiC,EACjC,mGAAmG,EACnG,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,yBAAyB,CACzE,UAAU,EACV,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,UAAU,EACf,OAAO,CAAC,YAAY,CAAC,gBAAgB,EACrC,aAAa,CAAC,OAAO,CAAC,CACvB,EACD,eAAe,CAChB,CAAC"}
@@ -13,4 +13,5 @@ export interface AttachmentDownloadResult {
13
13
  export declare function downloadName(value: string): string;
14
14
  export declare function downloadLimit(value: number | string): number;
15
15
  export declare function downloadIssueAttachment(connection: Connection, issueID: string, attachmentID: string, appDataDirectory: string, options?: DownloadOptions): Promise<AttachmentDownloadResult>;
16
+ export declare function downloadArticleAttachment(connection: Connection, articleID: string, attachmentID: string, appDataDirectory: string, options?: DownloadOptions): Promise<AttachmentDownloadResult>;
16
17
  //# sourceMappingURL=attachment-download.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-download.d.ts","sourceRoot":"","sources":["../../src/attachment-download.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAM5D;AAiED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,wBAAwB,CAAC,CAmDnC"}
1
+ {"version":3,"file":"attachment-download.d.ts","sourceRoot":"","sources":["../../src/attachment-download.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,UAAU,EAEhB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAM5D;AAiED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,wBAAwB,CAAC,CAGnC;AAED,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,wBAAwB,CAAC,CAGnC"}
@@ -1,9 +1,9 @@
1
1
  import { ProfileFileError, publishProfileFile } from "@eyeauras/cli-factory";
2
- import { getIssueAttachmentDownloadMetadata, youTrackUrl, } from "./client.js";
2
+ import { encodedID, getAttachmentDownloadMetadata, issuePath, youTrackUrl, } from "./client.js";
3
3
  class DownloadError extends ProfileFileError {
4
4
  }
5
5
  export function downloadName(value) {
6
- if (!value || Buffer.byteLength(value, "utf8") > 180 || value === "." || value === ".." ||
6
+ if (!value || value === "." || value === ".." ||
7
7
  /[<>:"/\\|?*\u0000-\u001f\u007f-\u009f\p{Cf}]/u.test(value) || /[. ]$/.test(value) ||
8
8
  /^(?:con|prn|aux|nul|conin\$|conout\$|clock\$|com[1-9¹²³]|lpt[1-9¹²³])(?:[ .]|$)/i.test(value)) {
9
9
  throw new Error("YouTrack download name must be one safe basename, without reserved paths or characters.");
@@ -12,8 +12,8 @@ export function downloadName(value) {
12
12
  }
13
13
  export function downloadLimit(value) {
14
14
  const number = typeof value === "string" && /^\d+$/.test(value) ? Number(value) : value;
15
- if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 1 || number > 104857600) {
16
- throw new Error("YouTrack max-bytes must be an integer between 1 and 104857600.");
15
+ if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 1) {
16
+ throw new Error("YouTrack max-bytes must be a positive safe integer.");
17
17
  }
18
18
  return number;
19
19
  }
@@ -67,8 +67,8 @@ function redact(value, secrets) {
67
67
  }
68
68
  return value;
69
69
  }
70
- function filenamePart(value, fallback, length) {
71
- return value.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, length).replace(/^\.+|[. ]+$/g, "") || fallback;
70
+ function filenamePart(value, fallback) {
71
+ return value.replace(/[^a-zA-Z0-9._-]/g, "_").replace(/^\.+|[. ]+$/g, "") || fallback;
72
72
  }
73
73
  function contentType(value, secrets) {
74
74
  const type = value?.split(";", 1)[0]?.trim() ?? "";
@@ -76,17 +76,25 @@ function contentType(value, secrets) {
76
76
  ? type : "application/octet-stream";
77
77
  }
78
78
  export async function downloadIssueAttachment(connection, issueID, attachmentID, appDataDirectory, options = {}) {
79
+ const path = `${issuePath(issueID)}/attachments/${encodedID(attachmentID, "attachment ID")}`;
80
+ return downloadAttachment(connection, path, attachmentID, appDataDirectory, options);
81
+ }
82
+ export async function downloadArticleAttachment(connection, articleID, attachmentID, appDataDirectory, options = {}) {
83
+ const path = `api/articles/${encodedID(articleID, "article ID")}/attachments/${encodedID(attachmentID, "attachment ID")}`;
84
+ return downloadAttachment(connection, path, attachmentID, appDataDirectory, options);
85
+ }
86
+ async function downloadAttachment(connection, attachmentPath, attachmentID, appDataDirectory, options) {
79
87
  const requestedName = options.name === undefined ? undefined : downloadName(options.name);
80
- const maxBytes = downloadLimit(options.maxBytes ?? 25 * 1024 * 1024);
88
+ const maxBytes = options.maxBytes === undefined ? undefined : downloadLimit(options.maxBytes);
81
89
  try {
82
- const metadata = await getIssueAttachmentDownloadMetadata(connection, issueID, attachmentID);
90
+ const metadata = await getAttachmentDownloadMetadata(connection, attachmentPath);
83
91
  if (metadata.id !== attachmentID) {
84
92
  throw new DownloadError("YouTrack returned a different attachment identity for the download.");
85
93
  }
86
94
  const { url, secrets } = attachmentUrl(connection, metadata.url);
87
- const id = filenamePart(redact(metadata.id, secrets), "attachment", 64);
95
+ const id = filenamePart(redact(metadata.id, secrets), "attachment");
88
96
  const name = requestedName ??
89
- downloadName(`${id}-${filenamePart(redact(metadata.name, secrets), "attachment", 96)}`);
97
+ downloadName(`${id}-${filenamePart(redact(metadata.name, secrets), "attachment")}`);
90
98
  if (redact(name, secrets) !== name || redact(appDataDirectory, secrets) !== appDataDirectory) {
91
99
  throw new DownloadError("YouTrack download destination must not contain reflected credentials or signatures.");
92
100
  }
@@ -112,7 +120,7 @@ export async function downloadIssueAttachment(connection, issueID, attachmentID,
112
120
  if (length !== null && (!/^\d+$/.test(length) || !Number.isSafeInteger(declared))) {
113
121
  throw new DownloadError("YouTrack attachment has an invalid Content-Length.");
114
122
  }
115
- if (declared !== undefined && declared > maxBytes) {
123
+ if (maxBytes !== undefined && declared !== undefined && declared > maxBytes) {
116
124
  throw new DownloadError("YouTrack attachment exceeds the configured byte limit.");
117
125
  }
118
126
  type = contentType(response.headers.get("content-type") ?? metadata.mimeType, secrets);
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-download.js","sourceRoot":"","sources":["../../src/attachment-download.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attachment-download.js","sourceRoot":"","sources":["../../src/attachment-download.ts"],"names":[],"mappings":"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"}