@eyeauras/youtrack-cli 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -17
- package/dist/src/article-extras-commands.d.ts.map +1 -1
- package/dist/src/article-extras-commands.js +3 -1
- package/dist/src/article-extras-commands.js.map +1 -1
- package/dist/src/articles-commands.d.ts.map +1 -1
- package/dist/src/articles-commands.js +8 -6
- package/dist/src/articles-commands.js.map +1 -1
- package/dist/src/articles.d.ts +9 -0
- package/dist/src/articles.d.ts.map +1 -1
- package/dist/src/articles.js +19 -0
- package/dist/src/articles.js.map +1 -1
- package/dist/src/attachment-download-commands.d.ts +1 -0
- package/dist/src/attachment-download-commands.d.ts.map +1 -1
- package/dist/src/attachment-download-commands.js +11 -6
- package/dist/src/attachment-download-commands.js.map +1 -1
- package/dist/src/attachment-download.d.ts +1 -0
- package/dist/src/attachment-download.d.ts.map +1 -1
- package/dist/src/attachment-download.js +10 -2
- package/dist/src/attachment-download.js.map +1 -1
- package/dist/src/bin.js +0 -0
- package/dist/src/cli-support.d.ts +5 -2
- package/dist/src/cli-support.d.ts.map +1 -1
- package/dist/src/cli-support.js +50 -7
- package/dist/src/cli-support.js.map +1 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +51 -8
- package/dist/src/cli.js.map +1 -1
- package/dist/src/client.d.ts +19 -4
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +61 -27
- package/dist/src/client.js.map +1 -1
- package/dist/src/index.d.ts +5 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/issue-batch.d.ts +28 -0
- package/dist/src/issue-batch.d.ts.map +1 -0
- package/dist/src/issue-batch.js +138 -0
- package/dist/src/issue-batch.js.map +1 -0
- package/dist/src/issue-context-commands.d.ts.map +1 -1
- package/dist/src/issue-context-commands.js +1 -1
- package/dist/src/issue-context-commands.js.map +1 -1
- package/dist/src/issue-fields.d.ts +16 -0
- package/dist/src/issue-fields.d.ts.map +1 -1
- package/dist/src/issue-fields.js +96 -1
- package/dist/src/issue-fields.js.map +1 -1
- package/package.json +3 -2
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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 |
|
|
@@ -38,9 +39,17 @@ onboarding or credential access on CLI, execute and RPC. The static errors are
|
|
|
38
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.
|
|
42
|
-
|
|
43
|
-
|
|
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,7 +63,8 @@ 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
|
|
66
|
+
The ReadOnly download and export commands write only their explicitly requested local file beneath
|
|
67
|
+
profile AppData.
|
|
58
68
|
|
|
59
69
|
JSON responses have no CLI byte ceiling. Invalid/truncated identity transfer lengths, stream failure
|
|
60
70
|
or cancellation fail with `YouTrack response stream failed or was cancelled.` without response content.
|
|
@@ -127,17 +137,37 @@ This documentation does not enable it automatically. The local proof remains Rea
|
|
|
127
137
|
|
|
128
138
|
| Command | Required `--body` JSON object |
|
|
129
139
|
|---|---|
|
|
130
|
-
| `issues create` |
|
|
131
|
-
| `issues update <issueID>` | Nonempty subset of `summary` and `
|
|
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 |
|
|
132
142
|
| `issues comments add <issueID>` | Nonempty `text` only |
|
|
133
143
|
|
|
134
144
|
Missing `--body` and malformed JSON fail before profile onboarding or credential access.
|
|
135
145
|
Description and comment text preserve multiline Markdown. Omitted fields remain unchanged;
|
|
136
146
|
`description: null` clears the description. Unknown fields (including nested project properties)
|
|
137
|
-
are rejected locally.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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.
|
|
141
171
|
|
|
142
172
|
For Windows **CMD**, replace the example project ID before deliberately running a write:
|
|
143
173
|
|
|
@@ -192,7 +222,7 @@ Project fields expose field types and settings without following bundle referenc
|
|
|
192
222
|
preserve polymorphic values, including scalar, null and array values. `issues fields set` accepts
|
|
193
223
|
an explicit `$type` and `value`: single/multi Enum, Build, Version, Owned, Group and User types;
|
|
194
224
|
State, Simple, Date, Period and Text types. References use explicit identity selectors (`id`,
|
|
195
|
-
`name`, and `login` for users);
|
|
225
|
+
`name`, and `login` for users); `fields set` performs no lookup of its own. Single values can use `null`,
|
|
196
226
|
multi values use `[]` to clear. Period values accept nonnegative 32-bit integer `minutes`
|
|
197
227
|
and/or `presentation`; dates use
|
|
198
228
|
integer Unix milliseconds. Text values use `{ "text": "..." }`. StateMachine fields instead
|
|
@@ -286,15 +316,16 @@ add six operations. The hierarchy commands read only the selected relationship a
|
|
|
286
316
|
recursively traverse descendants. A literal JSON null parent remains null; an empty body,
|
|
287
317
|
404 or malformed response is still an error. Article attachment upload requires one explicit
|
|
288
318
|
`--file`, the Update gate, and uses native multipart after checking that the file is regular.
|
|
289
|
-
It supports `--fields` for the response. No implicit file discovery
|
|
290
|
-
|
|
319
|
+
It supports `--fields` for the response. No implicit file discovery is provided, and upload never
|
|
320
|
+
grants permissions.
|
|
291
321
|
|
|
292
322
|
```powershell
|
|
293
323
|
npm run youtrack -- issues attachments download DEMO-1 1-1 --profile youtrack-dev
|
|
294
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
|
|
295
326
|
```
|
|
296
327
|
|
|
297
|
-
Issue attachment
|
|
328
|
+
Issue and article attachment downloads first read the exact attachment's fixed metadata, then request only
|
|
298
329
|
its returned URL. The file request sends neither Authorization nor cookies, follows no redirects,
|
|
299
330
|
and accepts only the configured origin and documented attachment path beneath its context.
|
|
300
331
|
External/CDN URLs fail rather than relaxing this policy. Signatures stay in memory and never
|
|
@@ -315,6 +346,60 @@ current-user-owned AppData; it cannot prevent every malicious same-account repla
|
|
|
315
346
|
last identity check. Errors report whether publication occurred and whether private staging cleanup
|
|
316
347
|
failed, without raw filesystem/service details. The local proof never invokes download or upload.
|
|
317
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
|
+
|
|
318
403
|
## Local proof and offline tests
|
|
319
404
|
|
|
320
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":"
|
|
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
|
|
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,
|
|
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":"
|
|
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 {
|
|
4
|
-
import {
|
|
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
|
-
|
|
11
|
-
projectedBodyUpdate("
|
|
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;
|
|
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"}
|
package/dist/src/articles.d.ts
CHANGED
|
@@ -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"}
|
package/dist/src/articles.js
CHANGED
|
@@ -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"]);
|
package/dist/src/articles.js.map
CHANGED
|
@@ -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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment-download-commands.d.ts","sourceRoot":"","sources":["../../src/attachment-download-commands.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
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",
|
|
@@ -14,5 +11,13 @@ export const attachmentDownloadCommand = readCommand("download <issueID> <attach
|
|
|
14
11
|
description: "Optional maximum transfer size in bytes (positive safe integer)",
|
|
15
12
|
parse: downloadLimit,
|
|
16
13
|
},
|
|
17
|
-
]
|
|
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);
|
|
18
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,
|
|
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,
|
|
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,5 +1,5 @@
|
|
|
1
1
|
import { ProfileFileError, publishProfileFile } from "@eyeauras/cli-factory";
|
|
2
|
-
import {
|
|
2
|
+
import { encodedID, getAttachmentDownloadMetadata, issuePath, youTrackUrl, } from "./client.js";
|
|
3
3
|
class DownloadError extends ProfileFileError {
|
|
4
4
|
}
|
|
5
5
|
export function downloadName(value) {
|
|
@@ -76,10 +76,18 @@ 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
88
|
const maxBytes = options.maxBytes === undefined ? undefined : downloadLimit(options.maxBytes);
|
|
81
89
|
try {
|
|
82
|
-
const metadata = await
|
|
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
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment-download.js","sourceRoot":"","sources":["../../src/attachment-download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"attachment-download.js","sourceRoot":"","sources":["../../src/attachment-download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,SAAS,EACT,6BAA6B,EAC7B,SAAS,EAET,WAAW,GACZ,MAAM,aAAa,CAAC;AAerB,MAAM,aAAc,SAAQ,gBAAgB;CAAG;AAE/C,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,IAAI;QACzC,+CAA+C,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QAClF,kFAAkF,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACnG,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAsB;IAClD,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACxF,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,UAAsB,EAAE,KAAa;IAC1D,MAAM,OAAO,GAAG,IAAI,aAAa,CAC/B,sFAAsF;QACtF,yCAAyC,CAC1C,CAAC;IACF,IAAI,CAAC;QACH,IAAI,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjE,MAAM,OAAO,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC;QACxC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC;QACxF,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,OAAO,CAAC;QAChB,CAAC;QACD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,IAAI,IAAI,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC;YAC1F,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,CAAC;YACtF,MAAM,OAAO,CAAC;QAChB,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI;YACxG,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,QAAQ,YAAY,CAAC,EAAE,CAAC;YAC3D,MAAM,OAAO,CAAC;QAChB,CAAC;QACD,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;aACnD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;aAC7D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG;YACjB,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC;YAC1F,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;SAC3F,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC5C,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC7F,MAAM,OAAO,CAAC;QAChB,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,OAAO,CAAC;IAChB,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,KAAa,EAAE,OAAiB;IAC9C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,QAAgB;IACnD,OAAO,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC;AACxF,CAAC;AAED,SAAS,WAAW,CAAC,KAAoB,EAAE,OAAiB;IAC1D,MAAM,IAAI,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACnD,OAAO,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,gDAAgD,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1G,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,0BAA0B,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAAsB,EACtB,OAAe,EACf,YAAoB,EACpB,gBAAwB,EACxB,OAAO,GAAoB,EAAE;IAE7B,MAAM,IAAI,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,gBAAgB,SAAS,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE,CAAC;IAC7F,OAAO,kBAAkB,CAAC,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;AACvF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,UAAsB,EACtB,SAAiB,EACjB,YAAoB,EACpB,gBAAwB,EACxB,OAAO,GAAoB,EAAE;IAE7B,MAAM,IAAI,GAAG,gBAAgB,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,gBAAgB,SAAS,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE,CAAC;IAC1H,OAAO,kBAAkB,CAAC,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;AACvF,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,UAAsB,EACtB,cAAsB,EACtB,YAAoB,EACpB,gBAAwB,EACxB,OAAwB;IAExB,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9F,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,6BAA6B,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACjF,IAAI,QAAQ,CAAC,EAAE,KAAK,YAAY,EAAE,CAAC;YACjC,MAAM,IAAI,aAAa,CAAC,qEAAqE,CAAC,CAAC;QACjG,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,aAAa;YACxB,YAAY,CAAC,GAAG,EAAE,IAAI,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;QACtF,IAAI,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,gBAAgB,EAAE,OAAO,CAAC,KAAK,gBAAgB,EAAE,CAAC;YAC7F,MAAM,IAAI,aAAa,CACrB,qFAAqF,CACtF,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,GAAG,0BAA0B,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC;YACrC,gBAAgB;YAChB,IAAI;YACJ,QAAQ;YACR,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE;gBAC9D,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,MAAM,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,UAAU,EAAE;gBAC9E,WAAW,EAAE,MAAM;gBACnB,QAAQ,EAAE,OAAO;gBACjB,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;aAC1E,CAAC;YACF,eAAe,CAAC,QAAQ;gBACtB,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC5C,MAAM,IAAI,aAAa,CAAC,6CAA6C,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;gBAC5F,CAAC;gBACD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;gBACtD,MAAM,QAAQ,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAC9D,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;oBAClF,MAAM,IAAI,aAAa,CAAC,oDAAoD,CAAC,CAAC;gBAChF,CAAC;gBACD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;oBAC5E,MAAM,IAAI,aAAa,CAAC,wDAAwD,CAAC,CAAC;gBACpF,CAAC;gBACD,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACzF,CAAC;SACF,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,YAAY,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,aAAa,CACjE,sGAAsG,CACvG,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/src/bin.js
CHANGED
|
File without changes
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type CommandContext, type CommandDefinition, type GatedTargetCommand, type OptionDefinition } from "@eyeauras/cli-factory";
|
|
2
2
|
import { type Connection, type IssueSearchOptions } from "./client.js";
|
|
3
3
|
export declare const bodyOptions: readonly OptionDefinition[];
|
|
4
|
+
export declare const fileOption: (flags: string, description: string, required?: boolean) => OptionDefinition;
|
|
5
|
+
/** Read one caller-selected file as strict UTF-8 (initial BOM removed); call only inside an admitted handler. */
|
|
6
|
+
export declare function readTextFile(path: string): Promise<string>;
|
|
4
7
|
export declare const projectionOptions: readonly OptionDefinition[];
|
|
5
8
|
export declare const pageOptions: readonly OptionDefinition[];
|
|
6
9
|
export declare function connection(context: CommandContext): Promise<Connection>;
|
|
@@ -12,8 +15,8 @@ type BodyOperation<Syntax extends string> = (connection: Connection, ...argument
|
|
|
12
15
|
type ProjectedBodyOperation<Syntax extends string> = (connection: Connection, ...arguments_: [...CommandValues<Syntax>, unknown, IssueSearchOptions]) => unknown;
|
|
13
16
|
export declare function pagedRead<const Syntax extends string>(syntax: Syntax, description: string, operation: ReadOperation<Syntax>): CommandDefinition;
|
|
14
17
|
export declare function projectedRead<const Syntax extends string>(syntax: Syntax, description: string, operation: ReadOperation<Syntax>): CommandDefinition;
|
|
15
|
-
export declare function bodyUpdate<const Syntax extends string>(syntax: Syntax, description: string, operation: BodyOperation<Syntax
|
|
16
|
-
export declare function projectedBodyUpdate<const Syntax extends string>(syntax: Syntax, description: string, operation: ProjectedBodyOperation<Syntax
|
|
18
|
+
export declare function bodyUpdate<const Syntax extends string>(syntax: Syntax, description: string, operation: BodyOperation<Syntax>, textField?: string): CommandDefinition;
|
|
19
|
+
export declare function projectedBodyUpdate<const Syntax extends string>(syntax: Syntax, description: string, operation: ProjectedBodyOperation<Syntax>, textField?: string): CommandDefinition;
|
|
17
20
|
export declare function readOptions(options: Record<string, unknown>): IssueSearchOptions;
|
|
18
21
|
export {};
|
|
19
22
|
//# sourceMappingURL=cli-support.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-support.d.ts","sourceRoot":"","sources":["../../src/cli-support.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli-support.d.ts","sourceRoot":"","sources":["../../src/cli-support.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli-support.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
1
2
|
import { integerParser, jsonParser, targetCommands, } from "@eyeauras/cli-factory";
|
|
2
|
-
import { youTrackUrl } from "./client.js";
|
|
3
|
+
import { requiredText, youTrackUrl } from "./client.js";
|
|
3
4
|
export const bodyOptions = [
|
|
4
5
|
{
|
|
5
6
|
flags: "--body <json>",
|
|
@@ -8,6 +9,46 @@ export const bodyOptions = [
|
|
|
8
9
|
parse: jsonParser("YouTrack body must be valid JSON."),
|
|
9
10
|
},
|
|
10
11
|
];
|
|
12
|
+
export const fileOption = (flags, description, required = false) => ({
|
|
13
|
+
flags, description, required, parse: (value) => requiredText(value, "file path"),
|
|
14
|
+
});
|
|
15
|
+
/** Read one caller-selected file as strict UTF-8 (initial BOM removed); call only inside an admitted handler. */
|
|
16
|
+
export async function readTextFile(path) {
|
|
17
|
+
let bytes;
|
|
18
|
+
try {
|
|
19
|
+
if (!(await stat(path)).isFile())
|
|
20
|
+
throw new Error();
|
|
21
|
+
bytes = await readFile(path);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new Error("YouTrack input file must be a readable regular file.");
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new Error("YouTrack input file must be valid UTF-8.");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Required `--body`, plus an optional `--<field>-file` that supplies one narrative property. */
|
|
34
|
+
function bodyInputOptions(textField) {
|
|
35
|
+
return textField === undefined ? bodyOptions : [
|
|
36
|
+
...bodyOptions,
|
|
37
|
+
fileOption(`--${textField}-file <path>`, `UTF-8 file supplying ${textField}; use --body '{}' when it is the only field`),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
async function bodyInput(options, textField) {
|
|
41
|
+
const file = textField === undefined ? undefined : options[`${textField}File`];
|
|
42
|
+
const body = options.body;
|
|
43
|
+
if (typeof file !== "string")
|
|
44
|
+
return body;
|
|
45
|
+
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
46
|
+
throw new Error("YouTrack body must be a JSON object.");
|
|
47
|
+
if (Object.hasOwn(body, textField)) {
|
|
48
|
+
throw new Error(`YouTrack ${textField} must come from either --body or --${textField}-file.`);
|
|
49
|
+
}
|
|
50
|
+
return { ...body, [textField]: await readTextFile(file) };
|
|
51
|
+
}
|
|
11
52
|
export const projectionOptions = [
|
|
12
53
|
{ flags: "--fields <projection>", description: "Explicit YouTrack fields projection" },
|
|
13
54
|
];
|
|
@@ -52,10 +93,10 @@ function positionalArguments(names, args) {
|
|
|
52
93
|
}
|
|
53
94
|
function operationCommand(leaf, syntax, description, operation, options, operationOptions) {
|
|
54
95
|
const names = positionalNames(syntax);
|
|
55
|
-
return leaf(syntax, description, (connection, input) => Reflect.apply(operation, undefined, [
|
|
96
|
+
return leaf(syntax, description, async (connection, input) => Reflect.apply(operation, undefined, [
|
|
56
97
|
connection,
|
|
57
98
|
...positionalArguments(names, input.args),
|
|
58
|
-
...operationOptions(input.options),
|
|
99
|
+
...await operationOptions(input.options),
|
|
59
100
|
]), options);
|
|
60
101
|
}
|
|
61
102
|
export function pagedRead(syntax, description, operation) {
|
|
@@ -64,11 +105,11 @@ export function pagedRead(syntax, description, operation) {
|
|
|
64
105
|
export function projectedRead(syntax, description, operation) {
|
|
65
106
|
return operationCommand(readCommand, syntax, description, operation, projectionOptions, (options) => [readOptions(options)]);
|
|
66
107
|
}
|
|
67
|
-
export function bodyUpdate(syntax, description, operation) {
|
|
68
|
-
return operationCommand(updateCommand, syntax, description, operation,
|
|
108
|
+
export function bodyUpdate(syntax, description, operation, textField) {
|
|
109
|
+
return operationCommand(updateCommand, syntax, description, operation, bodyInputOptions(textField), async (options) => [await bodyInput(options, textField)]);
|
|
69
110
|
}
|
|
70
|
-
export function projectedBodyUpdate(syntax, description, operation) {
|
|
71
|
-
return operationCommand(updateCommand, syntax, description, operation, [...
|
|
111
|
+
export function projectedBodyUpdate(syntax, description, operation, textField) {
|
|
112
|
+
return operationCommand(updateCommand, syntax, description, operation, [...bodyInputOptions(textField), ...projectionOptions], async (options) => [await bodyInput(options, textField), readOptions(options)]);
|
|
72
113
|
}
|
|
73
114
|
export function readOptions(options) {
|
|
74
115
|
return {
|
|
@@ -76,6 +117,8 @@ export function readOptions(options) {
|
|
|
76
117
|
...(typeof options.top === "number" ? { top: options.top } : {}),
|
|
77
118
|
...(typeof options.skip === "number" ? { skip: options.skip } : {}),
|
|
78
119
|
...(typeof options.query === "string" ? { query: options.query } : {}),
|
|
120
|
+
...(typeof options.maxResults === "number" ? { maxResults: options.maxResults } : {}),
|
|
121
|
+
...(typeof options.maxBytes === "number" ? { maxBytes: options.maxBytes } : {}),
|
|
79
122
|
};
|
|
80
123
|
}
|
|
81
124
|
//# sourceMappingURL=cli-support.js.map
|