@eyeauras/youtrack-cli 0.8.0 → 0.9.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 (142) hide show
  1. package/README.md +153 -88
  2. package/dist/src/access-catalog-commands.d.ts +2 -0
  3. package/dist/src/access-catalog-commands.d.ts.map +1 -0
  4. package/dist/src/access-catalog-commands.js +24 -0
  5. package/dist/src/access-catalog-commands.js.map +1 -0
  6. package/dist/src/access-catalog.d.ts +12 -0
  7. package/dist/src/access-catalog.d.ts.map +1 -0
  8. package/dist/src/access-catalog.js +44 -0
  9. package/dist/src/access-catalog.js.map +1 -0
  10. package/dist/src/agile-commands.d.ts.map +1 -1
  11. package/dist/src/agile-commands.js +14 -5
  12. package/dist/src/agile-commands.js.map +1 -1
  13. package/dist/src/agile.d.ts +11 -2
  14. package/dist/src/agile.d.ts.map +1 -1
  15. package/dist/src/agile.js +29 -2
  16. package/dist/src/agile.js.map +1 -1
  17. package/dist/src/article-extras-commands.d.ts +1 -0
  18. package/dist/src/article-extras-commands.d.ts.map +1 -1
  19. package/dist/src/article-extras-commands.js +23 -6
  20. package/dist/src/article-extras-commands.js.map +1 -1
  21. package/dist/src/article-extras.d.ts +15 -2
  22. package/dist/src/article-extras.d.ts.map +1 -1
  23. package/dist/src/article-extras.js +49 -2
  24. package/dist/src/article-extras.js.map +1 -1
  25. package/dist/src/articles-commands.d.ts.map +1 -1
  26. package/dist/src/articles-commands.js +11 -8
  27. package/dist/src/articles-commands.js.map +1 -1
  28. package/dist/src/articles.d.ts +7 -5
  29. package/dist/src/articles.d.ts.map +1 -1
  30. package/dist/src/articles.js +13 -7
  31. package/dist/src/articles.js.map +1 -1
  32. package/dist/src/backup-commands.d.ts +2 -0
  33. package/dist/src/backup-commands.d.ts.map +1 -0
  34. package/dist/src/backup-commands.js +16 -0
  35. package/dist/src/backup-commands.js.map +1 -0
  36. package/dist/src/backup.d.ts +7 -0
  37. package/dist/src/backup.d.ts.map +1 -0
  38. package/dist/src/backup.js +30 -0
  39. package/dist/src/backup.js.map +1 -0
  40. package/dist/src/bundle-values-commands.d.ts.map +1 -1
  41. package/dist/src/bundle-values-commands.js +27 -9
  42. package/dist/src/bundle-values-commands.js.map +1 -1
  43. package/dist/src/bundle-values.d.ts +31 -12
  44. package/dist/src/bundle-values.d.ts.map +1 -1
  45. package/dist/src/bundle-values.js +61 -1
  46. package/dist/src/bundle-values.js.map +1 -1
  47. package/dist/src/cli-support.d.ts +3 -1
  48. package/dist/src/cli-support.d.ts.map +1 -1
  49. package/dist/src/cli-support.js +15 -6
  50. package/dist/src/cli-support.js.map +1 -1
  51. package/dist/src/cli.d.ts.map +1 -1
  52. package/dist/src/cli.js +18 -8
  53. package/dist/src/cli.js.map +1 -1
  54. package/dist/src/client.d.ts +14 -1
  55. package/dist/src/client.d.ts.map +1 -1
  56. package/dist/src/client.js +111 -33
  57. package/dist/src/client.js.map +1 -1
  58. package/dist/src/credential-alias.d.ts +7 -0
  59. package/dist/src/credential-alias.d.ts.map +1 -0
  60. package/dist/src/credential-alias.js +21 -0
  61. package/dist/src/credential-alias.js.map +1 -0
  62. package/dist/src/field-catalog-commands.d.ts.map +1 -1
  63. package/dist/src/field-catalog-commands.js +30 -8
  64. package/dist/src/field-catalog-commands.js.map +1 -1
  65. package/dist/src/field-catalog.d.ts +30 -11
  66. package/dist/src/field-catalog.d.ts.map +1 -1
  67. package/dist/src/field-catalog.js +56 -1
  68. package/dist/src/field-catalog.js.map +1 -1
  69. package/dist/src/group-directory-commands.d.ts.map +1 -1
  70. package/dist/src/group-directory-commands.js +18 -9
  71. package/dist/src/group-directory-commands.js.map +1 -1
  72. package/dist/src/group-directory.d.ts +13 -4
  73. package/dist/src/group-directory.d.ts.map +1 -1
  74. package/dist/src/group-directory.js +41 -2
  75. package/dist/src/group-directory.js.map +1 -1
  76. package/dist/src/index.d.ts +16 -12
  77. package/dist/src/index.d.ts.map +1 -1
  78. package/dist/src/index.js +16 -12
  79. package/dist/src/index.js.map +1 -1
  80. package/dist/src/issue-context-commands.d.ts.map +1 -1
  81. package/dist/src/issue-context-commands.js +22 -4
  82. package/dist/src/issue-context-commands.js.map +1 -1
  83. package/dist/src/issue-context.d.ts +9 -0
  84. package/dist/src/issue-context.d.ts.map +1 -1
  85. package/dist/src/issue-context.js +29 -1
  86. package/dist/src/issue-context.js.map +1 -1
  87. package/dist/src/issue-fields-commands.d.ts.map +1 -1
  88. package/dist/src/issue-fields-commands.js +25 -4
  89. package/dist/src/issue-fields-commands.js.map +1 -1
  90. package/dist/src/issue-fields.d.ts +27 -7
  91. package/dist/src/issue-fields.d.ts.map +1 -1
  92. package/dist/src/issue-fields.js +64 -2
  93. package/dist/src/issue-fields.js.map +1 -1
  94. package/dist/src/issue-query-commands.d.ts.map +1 -1
  95. package/dist/src/issue-query-commands.js +28 -6
  96. package/dist/src/issue-query-commands.js.map +1 -1
  97. package/dist/src/issue-query.d.ts +12 -1
  98. package/dist/src/issue-query.d.ts.map +1 -1
  99. package/dist/src/issue-query.js +24 -4
  100. package/dist/src/issue-query.js.map +1 -1
  101. package/dist/src/issue-relations-commands.d.ts.map +1 -1
  102. package/dist/src/issue-relations-commands.js +17 -5
  103. package/dist/src/issue-relations-commands.js.map +1 -1
  104. package/dist/src/issue-relations.d.ts +15 -5
  105. package/dist/src/issue-relations.d.ts.map +1 -1
  106. package/dist/src/issue-relations.js +35 -1
  107. package/dist/src/issue-relations.js.map +1 -1
  108. package/dist/src/organization-commands.d.ts +2 -0
  109. package/dist/src/organization-commands.d.ts.map +1 -0
  110. package/dist/src/organization-commands.js +14 -0
  111. package/dist/src/organization-commands.js.map +1 -0
  112. package/dist/src/organizations.d.ts +7 -0
  113. package/dist/src/organizations.d.ts.map +1 -0
  114. package/dist/src/organizations.js +16 -0
  115. package/dist/src/organizations.js.map +1 -0
  116. package/dist/src/presentation.d.ts +34 -1
  117. package/dist/src/presentation.d.ts.map +1 -1
  118. package/dist/src/presentation.js +224 -0
  119. package/dist/src/presentation.js.map +1 -1
  120. package/dist/src/server-settings-commands.d.ts +2 -0
  121. package/dist/src/server-settings-commands.d.ts.map +1 -0
  122. package/dist/src/server-settings-commands.js +95 -0
  123. package/dist/src/server-settings-commands.js.map +1 -0
  124. package/dist/src/server-settings.d.ts +18 -0
  125. package/dist/src/server-settings.d.ts.map +1 -0
  126. package/dist/src/server-settings.js +101 -0
  127. package/dist/src/server-settings.js.map +1 -0
  128. package/dist/src/time-settings-commands.d.ts.map +1 -1
  129. package/dist/src/time-settings-commands.js +15 -8
  130. package/dist/src/time-settings-commands.js.map +1 -1
  131. package/dist/src/time-settings.d.ts +15 -7
  132. package/dist/src/time-settings.d.ts.map +1 -1
  133. package/dist/src/time-settings.js +35 -1
  134. package/dist/src/time-settings.js.map +1 -1
  135. package/dist/src/user-directory-commands.d.ts.map +1 -1
  136. package/dist/src/user-directory-commands.js +80 -7
  137. package/dist/src/user-directory-commands.js.map +1 -1
  138. package/dist/src/user-directory.d.ts +26 -8
  139. package/dist/src/user-directory.d.ts.map +1 -1
  140. package/dist/src/user-directory.js +80 -1
  141. package/dist/src/user-directory.js.map +1 -1
  142. package/package.json +3 -2
package/README.md CHANGED
@@ -22,12 +22,12 @@ for each profile and reimport auxiliary secrets. Existing profiles and permissio
22
22
 
23
23
  Licensed under MIT. See the [release guide](docs/release.md).
24
24
 
25
- YouTrack consumes the exact published `@eyeauras/cli-factory` version declared in package.json. The CLI
26
- provides standard profiles/auth/permissions and 128 REST operations: 103 ReadOnly and 25 Update.
27
- Five workflow leaves reuse those operations instead of adding REST operations: issue and article
28
- attachment download, article export, and `issues batch validate/apply`. There are 131 service
29
- leaves: 126 for REST operations plus these five. Two `--direct` selectors each select a second
30
- REST endpoint without adding another leaf.
25
+ YouTrack consumes the exact published `@eyeauras/cli-factory` version declared in package.json. The source revision described here
26
+ provides profiles/auth/permissions and 282 REST operations: 140 ReadOnly and 142 Update.
27
+ Nine workflow leaves reuse operations or manage local secrets: issue and article attachment
28
+ downloads, article export, `issues batch validate/apply`, and initial-password/license import/delete.
29
+ There are 289 service leaves: 280 for REST operations plus these nine. Two `--direct` selectors
30
+ each select a second REST endpoint without adding another leaf.
31
31
  The foundational read projections are:
32
32
 
33
33
  | Command | Default fields |
@@ -38,7 +38,7 @@ The foundational read projections are:
38
38
  | `issues get <issueID>` | Issue-list fields plus `description,created` |
39
39
  | `issues comments list <issueID>` | `id,text,author(id,login),created,updated` |
40
40
 
41
- REST reads support explicit `--fields <projection>`. Projection results retain the server's
41
+ REST reads support explicit `--fields <projection>`, except fixed-document `api-schema get`. Projection results retain the server's
42
42
  field names, `$type` and nullable values; authentication always validates fixed `id,login`.
43
43
  Offset collections use `--page-size 50 --start 0` by default. Page size requests rows per HTTP
44
44
  page; start is the zero-based raw offset. Both must be nonnegative safe integers, with a safe sum.
@@ -48,7 +48,7 @@ onboarding or credential access on CLI, execute and RPC. The static errors are
48
48
  `--page-size must be a nonnegative safe decimal integer.` and
49
49
  `--start must be a nonnegative integer.`; they never include the supplied input.
50
50
  Directly callable service methods retain their own range validation.
51
- All 49 offset lists return `{count,items,hasMore,nextStart}` across library, CLI, execute and RPC.
51
+ All 62 offset lists return `{count,items,hasMore,nextStart}` across library, CLI, execute and RPC.
52
52
  Each ordinary list makes one request without lookahead and rejects an oversized server page.
53
53
  Nonempty pages have `hasMore:null`, including short pages: a server cap is not end evidence.
54
54
  Continue at `nextStart`, which advances by actual returned rows. A positive-size empty page has
@@ -108,51 +108,114 @@ Compressed wire length is syntax-checked but not compared with decoded size. HTT
108
108
  Retry-After, empty/null mutation and UTF-8 BOM behavior are unchanged. No request is retried
109
109
  automatically. Runtime memory and service limits still apply.
110
110
 
111
- ## M01: issue workflows in 0.8.0
112
-
113
- The API inventory is frozen at 282 published operations (281 business routes plus schema metadata).
114
- M01 exposes 128 routes. Complete operation contracts cover 119/282 (42.20%); nine reachable routes
115
- still have explicitly deferred request controls. The [frozen audit](docs/rest-api-coverage/README.md)
116
- and [current mapping](docs/rest-api-coverage/current/coverage.json) keep these measures separate.
117
-
118
- - `issues list --custom-field <name>` is repeatable. Names, order and duplicates are preserved
119
- as repeated native `customFields` parameters, including every request made by `--all`.
120
- - `issues activity list <issueID> --categories <categories>` reads one offset page;
121
- `issues activity get <issueID> <activityID>` reads one item. These differ from the native
122
- `issues activity page` cursor resource. The issue list/page support `--author`,
123
- `--activity-start` and `--activity-end`; only the cursor page accepts `--activity-id`.
124
- Cursor values and direction remain opaque, without automatic traversal. Activity time bounds
125
- remain literal API strings, including native Long values.
126
- - Issue create/update, custom-field set, comment add/update, attachment upload, link add and
127
- work-item add/update accept `--fields` and `--mute-update-notifications [boolean]`.
128
- An omitted notification flag sends no parameter; a bare flag means true, and `false` is sent
129
- as false. The server enforces Apply Commands Silently; this does not mute workflow notifications.
130
- Only issue create and comment add accept `--draft-id`. Keep `--body` required; use `{}` when
131
- publishing a draft without additional fields. Normal issue creation still requires project/summary.
132
- - `work-items list` adds repeatable `--author` and `--creator`, `--start-date`, `--end-date`, `--work-start`,
133
- `--work-end`, `--created-start`, `--created-end`, `--updated-start`, `--updated-end`.
134
- `--start` stays the raw offset; `--work-start` selects the native temporal `start` filter.
135
- Filter values remain literal strings so a native Long does not lose precision in JavaScript.
136
- YouTrack validates date formats, interval semantics and applicability.
137
- - `tags list --query <query>` searches the tag catalogue. `issues tags get <issueID> <tagID>`
138
- inspects one assignment; tag add and existing tag/link remove commands accept `--fields`.
139
- - `issues attachments update <issueID> <attachmentID> --body <json>` updates native metadata.
140
- `issues attachments delete <issueID> <attachmentID>` and
141
- `issues work-items delete <issueID> <itemID>` remove only the selected resource.
142
-
143
- Write failures after submission report an unknown outcome when the reply is lost, unreadable or
144
- invalid, or the server returns 5xx. Check the selected object before retrying; no automatic retry
145
- is performed. HTTP 4xx rejection and local validation keep their distinct diagnostics.
146
- - `issues comments reaction list/get/add/remove` take issue/comment IDs, plus a reaction ID
147
- for get/remove. Add requires `--body` containing native `reaction`; names are not restricted
148
- to a hard-coded list. Reads use ReadOnly; add/remove use Update, even when remote service
149
- permissions call these operations reads.
150
-
151
- Every new read/write supports `--fields`. DELETE projections follow the explicit official
152
- parameter tables; an omitted projection preserves the prior query-free DELETE. Successful empty
153
- write bodies return JSON null; nonempty native results are scrubbed as usual. Optional fields do
154
- not imply response/version guarantees beyond the public contract. All writes stay Update-gated,
155
- with no implicit lookup, automatic retry, target expansion or binary transfer follow-up.
111
+ ## Command guide
112
+
113
+ Use a leaf's `--help` for its exact selectors, options and permission category. One declaration
114
+ supplies human/JSON/execute/RPC; the SDK exports the same concrete operations. Native service
115
+ rights and edition/version applicability are separate from local ReadOnly/Update gates.
116
+
117
+ | Work | Commands and selectors |
118
+ |---|---|
119
+ | Everyday issues | `issues list/get/create/update/delete`, `issues fields list/get/set`, `issues comments`, `issues attachments`, `issues tags`, `issues links`, `issues work-items` |
120
+ | Search and explicit bulk work | `search assist`, `commands assist/apply`, `issues count`, `issues batch validate/apply`, `saved-queries list/get/create/update/delete` |
121
+ | Projects | `project list/get/create/update/delete`, `project issues`, `project field`, `project team`, `project time-tracking`, `project work-item-type`, `project article` |
122
+ | People and access | `user me/list/get/create/update`, `user profile general/notifications/time-tracking`, `user saved-queries/tags`, `group`, `organization`, `role`, `role-assignment`, `permission-catalog` |
123
+ | Knowledge base | `article list/get/create/update/delete/export`, `article child/parent`, `article comment` (including `article comment reaction`), `article tag/attachment`, `project article list` |
124
+ | Iterations | `agile list/get/create/update/delete`, `sprint list/get/create/update/delete` with an agile selector |
125
+ | Fields and bundles | `field list/get/create/update/delete`, `field type/defaults/instance`, `bundle enum/state/version/build/owned/user` and their selected value/member resources |
126
+ | Work time and activity | `work-items list/get`, `work-item-type`, `time-tracking`, `activities list/get/page`, `issues activity list/get/page` |
127
+ | Installation | `api-schema get`, `server telemetry get`, `server-settings get/update`, `server-settings appearance-settings/notification-settings/locale-settings/system-settings/rest-settings` |
128
+ | Backups and licensing | `backup file list/get`, `backup settings get/update`, `backup status get`, `server-settings license get/update/import/delete` |
129
+ | Local configuration | Core `profile`, `auth`, `permissions`; `user initial-password import/delete` and `server-settings license import/delete` |
130
+
131
+ ### Native selectors and controls
132
+
133
+ `--body` is native JSON, with explicit descriptor objects and `$type` where required. Additional
134
+ native fields, nulls, false and repeated selections are preserved; metadata forwarding does not
135
+ promise every read-only attribute is writable. YouTrack resolves service values. The CLI does no
136
+ implicit discovery, field-type guessing, search-to-write expansion, retry or compensation.
137
+
138
+ - Issue/project-issue create/update and lists support repeatable `--custom-field` selectors where
139
+ declared. Write controls include `--fields`, `--mute-update-notifications [boolean]` and draft
140
+ publication `--draft-id` on the applicable leaves. Omission stays omitted; explicit false survives.
141
+ - `commands apply --issues DEMO-1,DEMO-2 --query "State Fixed"` is Update. Optional `--comment`,
142
+ `--visibility <json>`, `--run-as <login>` and `--silent [boolean]` remain native; service rights
143
+ still apply. Assist/count POST requests remain ReadOnly and never poll/apply automatically.
144
+ - Activity filters use `--author`, `--activity-start`, `--activity-end` and, on cursor pages,
145
+ `--activity-id`; global activity adds `--issue-query`. Native categories/cursors remain opaque.
146
+ Work-item filters include repeatable author/creator and date/created/updated bounds; `--start`
147
+ stays the offset and `--work-start` is the native temporal filter. Values stay literal strings.
148
+ - Creation uses native required identities: project name/shortName/leader.id, board name/projects,
149
+ issue/project-issue summary, work-type/value name and user login/initial-password alias.
150
+ Bundle create has no locally invented mandatory name; value creation requires its native name.
151
+ - Link direction labels preserve native `targetToSource:null`; calendar Int32 values/order/duplicates
152
+ have no invented positive/weekday limit. Version/build dates and owned-user descriptors preserve
153
+ documented nulls. Locale changes require `locale.id`; appearance/email use descriptor objects.
154
+ - Project-field detach/global-field delete and relationship removal/global-object delete have
155
+ distinct selectors/scopes. No automatic cascade or rollback is synthesized. Optional DELETE
156
+ `--fields` follows the reference tables; omission stays query-free, without a live-version claim.
157
+
158
+ Detailed native source dispositions and examples are retained in the
159
+ [delivery history](docs/milestone-history.md). Current METHOD/path bindings, controls, permissions,
160
+ all surfaces and tests for every operation are in [current coverage](docs/rest-api-coverage/current/README.md).
161
+
162
+ ### Auxiliary credentials
163
+
164
+ A secure runner supplies `YOUTRACK_INITIAL_PASSWORD` or `YOUTRACK_LICENSE`. After configuring and
165
+ signing in to the selected profile, deliberately enable Update to import/use/remove an alias:
166
+
167
+ ```sh
168
+ youtrack-cli permissions grant Update --profile dev
169
+ youtrack-cli user initial-password import initial-user --from-env --profile dev
170
+ youtrack-cli user create --body '{"login":"new-user"}' --password-secret initial-user --profile dev
171
+ youtrack-cli user initial-password delete initial-user --profile dev
172
+ youtrack-cli server-settings license import server-key --from-env --profile dev
173
+ youtrack-cli server-settings license update --license-secret server-key --profile dev
174
+ youtrack-cli server-settings license delete server-key --profile dev
175
+ ```
176
+
177
+ Import/delete use the selected profile's Core secret store, make no HTTP request for a configured,
178
+ authenticated profile, and return only a scrubbed alias/acknowledgement. Namespaced aliases never
179
+ replace the bearer token or another profile/family. Values retain exact bytes; absent/empty env
180
+ input fails with no plaintext fallback. Writes read only the stored alias, with no env fallback.
181
+ CLI raw password/license material is rejected, including nested root license writes. Native license
182
+ null clearing/username metadata remain available through `--body` without an alias.
183
+
184
+ Delete is idempotent: `{alias,deleted:true}` acknowledges removal, including an already absent
185
+ alias; it does not claim a value previously existed. An import/use never erases an alias implicitly.
186
+ Deleting a CLI profile removes its auth token, not auxiliary entries; delete each retained alias
187
+ while that profile is configured/authenticated, or manage it through the platform store/SDK.
188
+ There is no listing/export of secret values or automatic cleanup of user data.
189
+
190
+ Cancellation checked after integration lookups and before calling the Core mutation prevents that
191
+ call. Once Core delete() is dispatched, its internal lookup and persistence are not abort-aware:
192
+ exit130 may coexist with a removed alias. No value-retention/rollback guarantee is made after
193
+ dispatch. Import likewise makes no rollback promise once Core set() starts. Deletion failures
194
+ report an unknown store outcome and retain useful redacted causes. Nothing is retried automatically. Password/license-bearing JSON
195
+ body dispatches require the original HTTPS origin at every redirect hop. Same-origin redirects and
196
+ redirects discarding the body retain normal behavior. Known input/native license values and their
197
+ raw/JSON/URI/escaped-control copies are masked; unknown secrets are not universally detectable.
198
+
199
+ ### Installation administration
200
+
201
+ `api-schema get` reads one native document; human output shows metadata, machine output retains
202
+ its scrubbed native shape. It does not crawl or prove deployed conformance. Default telemetry
203
+ avoids installation paths/online identities; root settings default to the root ID. System writes
204
+ preserve native null/false/numeric types; changing remote baseUrl never rewrites a CLI profile.
205
+ CORS origin strings retain their hosts, ports and paths. Appearance/locale/email use native objects;
206
+ SSL keys are nullable StorageEntry references, not private-key uploads or invented SMTP passwords.
207
+
208
+ Backup file get/list reads metadata, not archives. Settings/status reads do not start or poll a
209
+ backup. A caller-supplied backupStatus action is sent only in an explicit Update settings request;
210
+ request success does not prove completion. Native archiveFormat is TAR_GZ/ZIP; nullable location,
211
+ Int32 filesToKeep and literal cronExpression are preserved. No restore workflow is provided.
212
+ Server license keys and backup scheduling/retention differ from Cloud's managed single-backup
213
+ export. No edition is guessed from hostnames or guaranteed from a schema version. See JetBrains'
214
+ [optional API reference: backup use-case](https://www.jetbrains.com/help/youtrack/devportal/api-usecase-backup.html),
215
+ [optional API reference: Cloud backups](https://www.jetbrains.com/help/youtrack/cloud/database.html),
216
+ [optional API reference: Server backups](https://www.jetbrains.com/help/youtrack/server/back-up-the-database.html) and
217
+ [optional API reference: Server license](https://www.jetbrains.com/help/youtrack/server/license-details.html).
218
+ Unsupported rights/edition responses remain failures, not successful skips or automatic grants.
156
219
 
157
220
  ## URL and token input
158
221
 
@@ -285,31 +348,31 @@ as comment reads. An empty successful mutation response becomes JSON `null`. No
285
348
  implicit follow-up reads or automatic permission grants occur. Malformed bodies and remote errors
286
349
  use safe diagnostics without echoing submitted JSON or server response text.
287
350
 
288
- ## Additional commands through operation 50
351
+ ## Search, relationships and work items
289
352
 
290
353
  The same tree is available through normal npm commands, JSON and JSON-RPC. Use leaf `--help`
291
354
  for exact arguments and permission categories; no endpoint, header or arbitrary HTTP escape hatch exists.
292
355
 
293
- | Family | Additional commands | Operations |
294
- |---|---|---:|
295
- | Queries and commands | `commands assist/apply`, `search assist`, `issues count`, `saved-queries list/get` | 6 |
296
- | Project, users and fields | `project get`, `project field list/get`, `user list`, `issues fields list/get/set` | 7 |
297
- | Links and tags | `link-types list/get`, `tags list/get`, `issues links list/get/issues/add/remove`, `issues tags list/add/remove` | 12 |
298
- | Activity and context | `activities page`, `issues activity page`, `issues comments get/update`, `issues vcs-changes list/get`, `issues sprints list` | 7 |
299
- | Work time | `issues time-tracking get`, `issues work-items list/get/add/update`, `work-items list/get` | 7 |
300
- | Attachments | `issues attachments list/get/upload` | 3 |
356
+ | Family | Representative commands |
357
+ |---|---|
358
+ | Queries and commands | `commands assist/apply`, `search assist`, `issues count`, `saved-queries list/get` |
359
+ | Project, users and fields | `project get`, `project field list/get`, `user list`, `issues fields list/get/set` |
360
+ | Links and tags | `link-types list/get`, `tags list/get`, `issues links list/get/issues/add/remove`, `issues tags list/add/remove` |
361
+ | Activity and context | `activities page`, `issues activity page`, `issues comments get/update`, `issues vcs-changes list/get`, `issues sprints list` |
362
+ | Work time | `issues time-tracking get`, `issues work-items list/get/add/update`, `work-items list/get` |
363
+ | Attachments | `issues attachments list/get/upload` |
301
364
 
302
365
  `commands assist`, `search assist` and `issues count` use POST on the wire but remain ReadOnly:
303
366
  they compute suggestions or counts without applying changes. Assist is not a dry run or a guarantee
304
367
  that a later command will succeed. Required `--query` is preserved exactly; optional `--caret` uses the API's signed Int type; the server validates position semantics.
305
368
  `commands apply` requires comma-separated explicit issue IDs via
306
- `--issues`, never an implicit search expansion. It has no run-as or silent mode. Count returns the
369
+ `--issues`, never an implicit search expansion. The explicit run-as/silent controls are described above. Count returns the
307
370
  server's `count`, including `-1` (pending) or `null`; the CLI never polls automatically.
308
371
 
309
- Activity commands require `--categories <categories>` and support `--cursor`, `--reverse` and
372
+ Activity cursor commands require `--categories <categories>` and support `--cursor`, `--reverse` and
310
373
  `--fields`. They return one server-defined page with `activities`, before/after cursors and flags.
311
374
  They do not support offset or page-size flags and do not fetch a next page automatically.
312
- Activity time, author and issue-query filters are outside this block.
375
+ Global and issue activity filters, plus offset item list/detail commands, are described in the command guide and delivery history.
313
376
 
314
377
  Project fields expose field types and settings without following bundle references. Issue fields
315
378
  preserve polymorphic values, including scalar, null and array values. `issues fields set` accepts
@@ -334,31 +397,28 @@ fields are `duration`, `date`, `author`, `type`, `text`, `created` and `updated`
334
397
  use integer Unix milliseconds; `author` and `type` use `{ "id": "..." }` or `null`. Text may be
335
398
  empty, multiline or null; `updated` may also be null. Updates preserve additional native fields and
336
399
  leave omitted fields to the server. No client-side date, user or duration conversion is guessed. Work-item
337
- writes accept `--fields`; only global `work-items list` supports `--query`. Other date/author
338
- filters are outside this block. Time-tracking inspection defaults to `id,enabled`, without
400
+ writes accept `--fields`; only global `work-items list` supports `--query`. Native date/author filters are described in the command guide above. Time-tracking inspection defaults to `id,enabled`, without
339
401
  expanding work items.
340
402
 
341
403
  Attachment reads default to `id,name,size,mimeType`; explicit read projections still scrub signed
342
404
  URLs. Upload requires one explicit `--file <path>` and sends one native multipart request, returning
343
405
  metadata only. Missing/empty/NUL path syntax fails before onboarding. Regular-file and read
344
406
  checks occur inside the Update handler before HTTP, so denied uploads do not inspect files.
345
- Only the basename becomes the multipart filename; errors never echo local paths. No attachment
346
- binary download or signed-URL follow-up was included in the first 50 operations; the separate
347
- download capability is documented below.
407
+ Only the basename becomes the multipart filename; errors never echo local paths. The separate binary download capability is documented below; metadata reads never follow links automatically.
348
408
 
349
- ## Additional commands through operation 100
409
+ ## Catalogs, teams and knowledge base
350
410
 
351
- These add fifty REST operations. Two `--direct` switches each select between two documented
352
- read endpoints, so at this stage the tree had 98 service leaves for 100 operations.
411
+ Two `--direct` switches each select between documented direct/aggregated membership endpoints.
412
+ They do not add command aliases or change the offset-page contract.
353
413
 
354
- | Family | Additional commands | Operations |
355
- |---|---|---:|
356
- | Global fields and choices | `field list/get`, `field type list`, `bundle enum/state list/get`, `bundle enum/state value list/get` | 11 |
357
- | User directory and bundles | `user get`, `bundle user list/get`, `bundle user member list`, `bundle user group list/get`, `bundle user individual list/get` | 8 |
358
- | Groups and project teams | `group list/get`, `group member list [--direct]`, `group subgroup list`, `project team get`, `project team group list`, `project team user list [--direct]` | 9 |
359
- | Time metadata | `time-tracking settings get`, `time-tracking work-time get`, `work-item-type list/get`, `project time-tracking get`, `project work-item-type list/get` | 7 |
360
- | Boards and sprints | `agile list/get`, `sprint list/get/create/update` | 6 |
361
- | Articles | `article list/get/create/update`, `article comment list/get/add/update`, `project article list` | 9 |
414
+ | Family | Representative commands |
415
+ |---|---|
416
+ | Global fields and choices | `field list/get`, `field type list`, `bundle enum/state list/get`, `bundle enum/state value list/get` |
417
+ | User directory and bundles | `user get`, `bundle user list/get`, `bundle user member list`, `bundle user group list/get`, `bundle user individual list/get` |
418
+ | Groups and project teams | `group list/get`, `group member list [--direct]`, `group subgroup list`, `project team get`, `project team group list`, `project team user list [--direct]` |
419
+ | Time metadata | `time-tracking settings get`, `time-tracking work-time get`, `work-item-type list/get`, `project time-tracking get`, `project work-item-type list/get` |
420
+ | Boards and sprints | `agile list/get`, `sprint list/get/create/update` |
421
+ | Articles | `article list/get/create/update`, `article comment list/get/add/update`, `project article list` |
362
422
 
363
423
  Every new read supports `--fields`. Offset lists retain one-page `--page-size`/`--start` behavior;
364
424
  details and settings reads have no paging flags. Bundle defaults omit nested values and members:
@@ -385,16 +445,17 @@ preserves supplied native fields. Known fields include `name`, `goal`, `start`,
385
445
  Unix milliseconds or null; flags are booleans. Create additionally accepts
386
446
  `previousSprint: { "id": "..." }`, which explicitly moves unresolved issues from that sprint.
387
447
  It is never inferred; the server validates its applicability. `isDefault: true` affects where matching new
388
- board issues go. Additional native sprint properties are forwarded; separate agile mutations and deletion remain outside
389
- this block. Reads and writes support `--fields`; there is no carryover lookup or polling.
448
+ board issues go. Additional native sprint properties are forwarded. `agile` and `sprint` create/update/delete use
449
+ selected IDs and require Update; reads/writes support `--fields`, without carryover lookup or polling.
390
450
 
391
451
  Article create accepts a native project reference and nullable summary. Article and comment
392
452
  updates preserve additional native fields, including parent, visibility and pinning. Known text
393
453
  fields preserve multiline strings and documented null values; omission leaves API defaults in charge. Article and comment reads/writes
394
454
  support `--fields`; article lists have no query flag. Article attachment transfer and hierarchy
395
- reads are documented below. Native body properties are validated by the API; separate deletion remains outside this command tree.
455
+ reads are documented below. Native body properties are validated by the API. `article delete
456
+ <article>` and `article comment delete <article> <comment>` require Update and affect only selected IDs.
396
457
 
397
- ## Remaining bundles, article hierarchy and attachment transfer
458
+ ## Bundles, article hierarchy and attachment transfer
398
459
 
399
460
  `bundle build/owned/version list/get` and their `value list/get` children expose twelve
400
461
  ReadOnly operations. Lists use the normal bounded page; bundle defaults do not expand values.
@@ -494,8 +555,6 @@ Deliberate differences:
494
555
  - a failed batch never deletes created issues to compensate.
495
556
 
496
557
  Not provided:
497
- - project, user, group and role administration;
498
- - deletion wrappers;
499
558
  - burndown and velocity reports;
500
559
  - interactive tables, themes, tutorials and aliases;
501
560
  - stdin input (JSON-RPC owns stdin).
@@ -533,5 +592,11 @@ Tests inject `AppArguments` rather than redirecting the user's data directories.
533
592
 
534
593
  ## Source development
535
594
 
536
- `npm ci`, `npm test`, and `npm run test:package` build and test this repository independently.
595
+ Repository verification uses Node.js24+ (the installed CLI retains Node.js22+). `npm test` is the
596
+ ordinary offline suite; `npm run test:coverage` builds/runs that suite once with tracing, traverses
597
+ the real tree and regenerates the frozen mapping twice. Only the documented commit-lineage field
598
+ may differ from tracked summary metadata. Drift fails with artifact context and retains ignored
599
+ evidence for explicit reviewed regeneration; the checker never overwrites tracked files or fetches
600
+ public/service schemas. Cake Verify uses this gate, installed-package and release-safety checks.
601
+ `npm ci` and `npm run test:package` retain the registry-based build/distribution boundaries.
537
602
  See [release and Core adoption gates](docs/release.md) and [migration provenance](docs/migration.md).
@@ -0,0 +1,2 @@
1
+ export declare const accessCatalogRootCommands: import("@eyeauras/cli-factory").CommandDefinition[];
2
+ //# sourceMappingURL=access-catalog-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-catalog-commands.d.ts","sourceRoot":"","sources":["../../src/access-catalog-commands.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,yBAAyB,qDAiBrC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { command } from "@eyeauras/cli-factory";
2
+ import { pagedRead, projectedRead, projectedBodyUpdate, projectedDelete } from "./cli-support.js";
3
+ import { createRole, updateRole, deleteRole, createRoleAssignment, deleteRoleAssignment, listRoleAssignments, getRoleAssignment, listPermissions, listRoles, getRole } from "./access-catalog.js";
4
+ import { mutationWritten, namedTable, roleRecord, roleAssignmentRecord, roleAssignmentTable } from "./presentation.js";
5
+ const queryOptions = [{ flags: "--query <query>", description: "Filter with a YouTrack access query" }];
6
+ export const accessCatalogRootCommands = [
7
+ command("role-assignment", "Manage role assignments", [
8
+ projectedBodyUpdate("create", "Assign a role in the selected scope", createRoleAssignment, undefined, roleAssignmentRecord),
9
+ projectedDelete("delete <assignment>", "Revoke a role assignment", deleteRoleAssignment, mutationWritten("Revoked role assignment", "assignment")),
10
+ pagedRead("list", "List role assignments", listRoleAssignments, roleAssignmentTable, queryOptions),
11
+ projectedRead("get <assignment>", "Show a role assignment", getRoleAssignment, roleAssignmentRecord),
12
+ ]),
13
+ command("permission-catalog", "Inspect service permissions", [
14
+ pagedRead("list", "List YouTrack permissions", listPermissions, namedTable("PERMISSION", "No permissions.")),
15
+ ]),
16
+ command("role", "Inspect and manage service roles", [
17
+ projectedBodyUpdate("create", "Create a service role", createRole, undefined, mutationWritten("Created role")),
18
+ projectedBodyUpdate("update <role>", "Update a selected role", updateRole, undefined, mutationWritten("Updated role", "role")),
19
+ projectedDelete("delete <role>", "Delete a selected role", deleteRole, mutationWritten("Deleted role", "role")),
20
+ pagedRead("list", "List YouTrack roles", listRoles, namedTable("ROLE", "No roles."), queryOptions),
21
+ projectedRead("get <role>", "Show a role", getRole, roleRecord),
22
+ ]),
23
+ ];
24
+ //# sourceMappingURL=access-catalog-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-catalog-commands.js","sourceRoot":"","sources":["../../src/access-catalog-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAClM,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEvH,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC,CAAC;AAExG,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,OAAO,CAAC,iBAAiB,EAAE,yBAAyB,EAAE;QACpD,mBAAmB,CAAC,QAAQ,EAAE,qCAAqC,EAAE,oBAAoB,EAAE,SAAS,EAAE,oBAAoB,CAAC;QAC3H,eAAe,CAAC,qBAAqB,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,eAAe,CAAC,yBAAyB,EAAE,YAAY,CAAC,CAAC;QAClJ,SAAS,CAAC,MAAM,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,YAAY,CAAC;QAClG,aAAa,CAAC,kBAAkB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,oBAAoB,CAAC;KACrG,CAAC;IACF,OAAO,CAAC,oBAAoB,EAAE,6BAA6B,EAAE;QAC3D,SAAS,CAAC,MAAM,EAAE,2BAA2B,EAAE,eAAe,EAAE,UAAU,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;KAC7G,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,kCAAkC,EAAE;QAClD,mBAAmB,CAAC,QAAQ,EAAE,uBAAuB,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,CAAC,cAAc,CAAC,CAAC;QAC9G,mBAAmB,CAAC,eAAe,EAAE,wBAAwB,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC9H,eAAe,CAAC,eAAe,EAAE,wBAAwB,EAAE,UAAU,EAAE,eAAe,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;QAC/G,SAAS,CAAC,MAAM,EAAE,qBAAqB,EAAE,SAAS,EAAE,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,YAAY,CAAC;QAClG,aAAa,CAAC,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,CAAC;KAChE,CAAC;CACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type ProjectionOptions, type Connection, type IssueSearchOptions } from "./client.js";
2
+ export declare function listRoleAssignments(connection: Connection, options?: IssueSearchOptions): Promise<import("./client.js").YouTrackPage<import("./client.js").YouTrackObject>>;
3
+ export declare const getRoleAssignment: (connection: Connection, assignmentID: string, options?: ProjectionOptions | undefined) => Promise<import("./client.js").YouTrackObject>;
4
+ export declare const listPermissions: (connection: Connection, options?: import("./client.js").PageOptions | undefined) => Promise<import("./client.js").YouTrackPage>;
5
+ export declare function listRoles(connection: Connection, options?: IssueSearchOptions): Promise<import("./client.js").YouTrackPage<import("./client.js").YouTrackObject>>;
6
+ export declare const getRole: (connection: Connection, roleID: string, options?: ProjectionOptions | undefined) => Promise<import("./client.js").YouTrackObject>;
7
+ export declare function createRoleAssignment(connection: Connection, input: unknown, options?: ProjectionOptions): Promise<import("./client.js").YouTrackObject | null>;
8
+ export declare function deleteRoleAssignment(connection: Connection, assignmentID: string, options?: ProjectionOptions): Promise<import("./client.js").YouTrackObject | null>;
9
+ export declare function createRole(connection: Connection, input: unknown, options?: ProjectionOptions): Promise<import("./client.js").YouTrackObject | null>;
10
+ export declare function updateRole(connection: Connection, roleID: string, input: unknown, options?: ProjectionOptions): Promise<import("./client.js").YouTrackObject | null>;
11
+ export declare function deleteRole(connection: Connection, roleID: string, options?: ProjectionOptions): Promise<import("./client.js").YouTrackObject | null>;
12
+ //# sourceMappingURL=access-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-catalog.d.ts","sourceRoot":"","sources":["../../src/access-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EACqE,KAAK,iBAAiB,EAChG,KAAK,UAAU,EAAE,KAAK,kBAAkB,EACzC,MAAM,aAAa,CAAC;AAMrB,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,GAAE,kBAAuB,qFAKjG;AACD,eAAO,MAAM,iBAAiB,0IAG7B,CAAC;AACF,eAAO,MAAM,eAAe,kIAAwD,CAAC;AACrF,wBAAsB,SAAS,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,GAAE,kBAAuB,qFAKvF;AACD,eAAO,MAAM,OAAO,oIAEnB,CAAC;AAGF,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,wDASjH;AACD,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,wDAEvH;AAGD,wBAAsB,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,wDAEvG;AACD,wBAAsB,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,wDAEvH;AACD,wBAAsB,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,wDAEvG"}
@@ -0,0 +1,44 @@
1
+ import { fields, mutate, deleteObject, mutationBody, namedMutationBody, narrative, encodedID, page, readPage, readCollectionAt, readObjectAt, requiredText, } from "./client.js";
2
+ const assignmentFields = "id,role(id,name),holder(id,$type),scope(id,$type)";
3
+ const roleFields = "id,name,description,immutable,permissions(id,name)";
4
+ const permissionFields = "id,name,description,scope,operation,permissionEntityType";
5
+ export async function listRoleAssignments(connection, options = {}) {
6
+ return readPage(connection, "api/assignedRoles", {
7
+ ...page(options, assignmentFields),
8
+ ...(options.query === undefined ? {} : { query: requiredText(options.query, "query") }),
9
+ });
10
+ }
11
+ export const getRoleAssignment = readObjectAt((assignmentID) => `api/assignedRoles/${encodedID(assignmentID, "role assignment ID")}`, assignmentFields);
12
+ export const listPermissions = readCollectionAt("api/permissions", permissionFields);
13
+ export async function listRoles(connection, options = {}) {
14
+ return readPage(connection, "api/roles", {
15
+ ...page(options, roleFields),
16
+ ...(options.query === undefined ? {} : { query: requiredText(options.query, "query") }),
17
+ });
18
+ }
19
+ export const getRole = readObjectAt((roleID) => `api/roles/${encodedID(roleID, "role ID")}`, roleFields);
20
+ export async function createRoleAssignment(connection, input, options = {}) {
21
+ const body = mutationBody(input);
22
+ requiredText(narrative(mutationBody(body.role).id, "role ID"), "role ID");
23
+ requiredText(narrative(mutationBody(body.holder).id, "holder ID"), "holder ID");
24
+ const scope = mutationBody(body.scope);
25
+ requiredText(narrative(scope.$type, "scope type"), "scope type");
26
+ if (scope.$type === "ProjectScope")
27
+ requiredText(narrative(mutationBody(scope.project).id, "project ID"), "project ID");
28
+ if (scope.$type === "OrganizationScope")
29
+ requiredText(narrative(mutationBody(scope.organization).id, "organization ID"), "organization ID");
30
+ return mutate(connection, "api/assignedRoles", body, fields(options, assignmentFields));
31
+ }
32
+ export async function deleteRoleAssignment(connection, assignmentID, options = {}) {
33
+ return deleteObject(connection, `api/assignedRoles/${encodedID(assignmentID, "role assignment ID")}`, options);
34
+ }
35
+ export async function createRole(connection, input, options = {}) {
36
+ return mutate(connection, "api/roles", namedMutationBody(input, false), fields(options, roleFields));
37
+ }
38
+ export async function updateRole(connection, roleID, input, options = {}) {
39
+ return mutate(connection, `api/roles/${encodedID(roleID, "role ID")}`, namedMutationBody(input, false), fields(options, roleFields));
40
+ }
41
+ export async function deleteRole(connection, roleID, options = {}) {
42
+ return deleteObject(connection, `api/roles/${encodedID(roleID, "role ID")}`, options);
43
+ }
44
+ //# sourceMappingURL=access-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-catalog.js","sourceRoot":"","sources":["../../src/access-catalog.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"agile-commands.d.ts","sourceRoot":"","sources":["../../src/agile-commands.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iBAAiB,qDAW7B,CAAC"}
1
+ {"version":3,"file":"agile-commands.d.ts","sourceRoot":"","sources":["../../src/agile-commands.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iBAAiB,qDAqB7B,CAAC"}
@@ -1,16 +1,25 @@
1
1
  import { command } from "@eyeauras/cli-factory";
2
- import { pagedRead, projectedBodyUpdate, projectedRead } from "./cli-support.js";
3
- import { createSprint, getAgile, getSprint, listAgiles, listSprints, updateSprint } from "./agile.js";
4
- import { agileRecord, agileTable, sprintRecord, sprintTable, sprintWritten } from "./presentation.js";
2
+ import { projectedDelete, pagedRead, projectedBodyUpdate, projectedRead, bodyOptions, projectionOptions, readOptions, updateCommand, notificationOptions } from "./cli-support.js";
3
+ import { agileTemplate, deleteAgile, deleteSprint, createAgile, updateAgile, createSprint, getAgile, getSprint, listAgiles, listSprints, updateSprint } from "./agile.js";
4
+ import { mutationWritten, rememberSubmittedIdentity, agileRecord, agileTable, agileWritten, withView, sprintRecord, sprintTable, sprintWritten } from "./presentation.js";
5
5
  export const agileRootCommands = [
6
- command("agile", "Inspect agile boards", [
6
+ command("agile", "Inspect and manage agile boards", [
7
+ projectedDelete("delete <agile>", "Delete a selected board", deleteAgile, mutationWritten("Deleted board", "agile")),
8
+ withView(agileWritten("Created"), updateCommand("create", "Create an agile board", async (client, input) => {
9
+ const { options } = input;
10
+ const result = await createAgile(client, options.body, { ...readOptions(options), ...(typeof options.template === "string" ? { template: options.template } : {}) });
11
+ rememberSubmittedIdentity(input, client.token);
12
+ return result;
13
+ }, [...bodyOptions, ...projectionOptions, { flags: "--template <name>", description: "Use a board template", parse: agileTemplate }])),
14
+ projectedBodyUpdate("update <agile>", "Update an agile board", updateAgile, undefined, agileWritten("Updated")),
7
15
  pagedRead("list", "List agile boards", listAgiles, agileTable),
8
16
  projectedRead("get <agile>", "Show an agile board", getAgile, agileRecord),
9
17
  ]),
10
18
  command("sprint", "Inspect and manage sprints", [
19
+ projectedDelete("delete <agile> <sprint>", "Delete a selected sprint", deleteSprint, mutationWritten("Deleted sprint", "sprint", "agile")),
11
20
  pagedRead("list <agile>", "List a board's sprints", listSprints, sprintTable),
12
21
  projectedRead("get <agile> <sprint>", "Show a sprint (current for the current one)", getSprint, sprintRecord),
13
- projectedBodyUpdate("create <agile>", "Create a sprint", createSprint, undefined, sprintWritten("Created")),
22
+ projectedBodyUpdate("create <agile>", "Create a sprint", createSprint, undefined, sprintWritten("Created"), notificationOptions),
14
23
  projectedBodyUpdate("update <agile> <sprint>", "Update a sprint", updateSprint, undefined, sprintWritten("Updated")),
15
24
  ]),
16
25
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"agile-commands.js","sourceRoot":"","sources":["../../src/agile-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEtG,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,OAAO,CAAC,OAAO,EAAE,sBAAsB,EAAE;QACvC,SAAS,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,UAAU,CAAC;QAC9D,aAAa,CAAC,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,WAAW,CAAC;KAC3E,CAAC;IACF,OAAO,CAAC,QAAQ,EAAE,4BAA4B,EAAE;QAC9C,SAAS,CAAC,cAAc,EAAE,wBAAwB,EAAE,WAAW,EAAE,WAAW,CAAC;QAC7E,aAAa,CAAC,sBAAsB,EAAE,6CAA6C,EAAE,SAAS,EAAE,YAAY,CAAC;QAC7G,mBAAmB,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QAC3G,mBAAmB,CAAC,yBAAyB,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;KACrH,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"agile-commands.js","sourceRoot":"","sources":["../../src/agile-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACnL,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1K,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE1K,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,OAAO,CAAC,OAAO,EAAE,iCAAiC,EAAE;QAClD,eAAe,CAAC,gBAAgB,EAAE,yBAAyB,EAAE,WAAW,EAAE,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACpH,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,QAAQ,EAAE,uBAAuB,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;YACzG,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;YAC1B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACrK,yBAAyB,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/C,OAAO,MAAM,CAAC;QAChB,CAAC,EACC,CAAC,GAAG,WAAW,EAAE,GAAG,iBAAiB,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,sBAAsB,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;QACrI,mBAAmB,CAAC,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;QAC/G,SAAS,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,UAAU,CAAC;QAC9D,aAAa,CAAC,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,WAAW,CAAC;KAC3E,CAAC;IACF,OAAO,CAAC,QAAQ,EAAE,4BAA4B,EAAE;QAC9C,eAAe,CAAC,yBAAyB,EAAE,0BAA0B,EAAE,YAAY,EAAE,eAAe,CAAC,gBAAgB,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1I,SAAS,CAAC,cAAc,EAAE,wBAAwB,EAAE,WAAW,EAAE,WAAW,CAAC;QAC7E,aAAa,CAAC,sBAAsB,EAAE,6CAA6C,EAAE,SAAS,EAAE,YAAY,CAAC;QAC7G,mBAAmB,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;QAChI,mBAAmB,CAAC,yBAAyB,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;KACrH,CAAC;CACH,CAAC"}
@@ -1,8 +1,17 @@
1
- import { type Connection, type ProjectionOptions, type YouTrackObject } from "./client.js";
1
+ import { type Connection, type ProjectionOptions, type WriteOptions, type YouTrackObject } from "./client.js";
2
2
  export declare const listAgiles: (connection: Connection, options?: import("./client.js").PageOptions | undefined) => Promise<import("./client.js").YouTrackPage>;
3
3
  export declare const getAgile: (connection: Connection, agile: string, options?: ProjectionOptions | undefined) => Promise<YouTrackObject>;
4
4
  export declare const listSprints: (connection: Connection, agile: string, options?: import("./client.js").PageOptions | undefined) => Promise<import("./client.js").YouTrackPage>;
5
5
  export declare const getSprint: (connection: Connection, agile: string, sprint: string, options?: ProjectionOptions | undefined) => Promise<YouTrackObject>;
6
- export declare function createSprint(connection: Connection, agile: string, input: unknown, options?: ProjectionOptions): Promise<YouTrackObject | null>;
6
+ export declare function createSprint(connection: Connection, agile: string, input: unknown, options?: WriteOptions): Promise<YouTrackObject | null>;
7
7
  export declare function updateSprint(connection: Connection, agile: string, sprint: string, input: unknown, options?: ProjectionOptions): Promise<YouTrackObject | null>;
8
+ /** Native board templates from the pinned primary reference. */
9
+ export declare function agileTemplate(value: unknown): string;
10
+ export interface AgileCreateOptions extends ProjectionOptions {
11
+ template?: string;
12
+ }
13
+ export declare function createAgile(connection: Connection, input: unknown, options?: AgileCreateOptions): Promise<YouTrackObject | null>;
14
+ export declare function updateAgile(connection: Connection, agile: string, input: unknown, options?: ProjectionOptions): Promise<YouTrackObject | null>;
15
+ export declare function deleteAgile(connection: Connection, agileID: string, options?: ProjectionOptions): Promise<YouTrackObject | null>;
16
+ export declare function deleteSprint(connection: Connection, agileID: string, sprintID: string, options?: ProjectionOptions): Promise<YouTrackObject | null>;
8
17
  //# sourceMappingURL=agile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agile.d.ts","sourceRoot":"","sources":["../../src/agile.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AASrB,eAAO,MAAM,UAAU,kIAA8C,CAAC;AACtE,eAAO,MAAM,QAAQ,6GAAuC,CAAC;AAC7D,eAAO,MAAM,WAAW,iJAGvB,CAAC;AACF,eAAO,MAAM,SAAS,6HAIrB,CAAC;AA4CF,wBAAsB,YAAY,CAChC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,kCAQhC;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,kCAQhC"}
1
+ {"version":3,"file":"agile.d.ts","sourceRoot":"","sources":["../../src/agile.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AASrB,eAAO,MAAM,UAAU,kIAA8C,CAAC;AACtE,eAAO,MAAM,QAAQ,6GAAuC,CAAC;AAC7D,eAAO,MAAM,WAAW,iJAGvB,CAAC;AACF,eAAO,MAAM,SAAS,6HAIrB,CAAC;AA4CF,wBAAsB,YAAY,CAChC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,YAAiB,kCAS3B;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,iBAAsB,kCAQhC;AAGD,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMpD;AACD,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAAG,QAAQ,CAAC,EAAE,MAAM,CAAC;CAAE;AACpF,wBAAsB,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,kBAAuB,kCASzG;AACD,wBAAsB,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,iBAAsB,kCAEvH;AAGD,wBAAsB,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,kCAEzG;AACD,wBAAsB,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,kCAE5H"}
package/dist/src/agile.js CHANGED
@@ -1,4 +1,4 @@
1
- import { encodedID, fields, mutate, mutationBody, nullableText, readCollectionAt, readObjectAt, requiredText, } from "./client.js";
1
+ import { deleteObject, encodedID, fields, mutate, mutationBody, narrative, namedMutationBody, nullableText, readCollectionAt, readObjectAt, requiredText, } from "./client.js";
2
2
  const agileFields = "id,name,currentSprint(id,name,start,finish,archived),status(valid,hasJobs)";
3
3
  const sprintFields = "id,name,goal,start,finish,archived,isDefault,agile(id,name)";
4
4
  function agilePath(agile) {
@@ -50,9 +50,36 @@ function sprintBody(input, creating) {
50
50
  return result;
51
51
  }
52
52
  export async function createSprint(connection, agile, input, options = {}) {
53
- return mutate(connection, `${agilePath(agile)}/sprints`, sprintBody(input, true), fields(options, sprintFields));
53
+ return mutate(connection, `${agilePath(agile)}/sprints`, sprintBody(input, true), fields(options, sprintFields), options);
54
54
  }
55
55
  export async function updateSprint(connection, agile, sprint, input, options = {}) {
56
56
  return mutate(connection, `${agilePath(agile)}/sprints/${encodedID(sprint, "sprint ID")}`, sprintBody(input, false), fields(options, sprintFields));
57
57
  }
58
+ /** Native board templates from the pinned primary reference. */
59
+ export function agileTemplate(value) {
60
+ const template = narrative(value, "template");
61
+ if (!["kanban", "scrum", "version", "custom", "personal"].includes(template)) {
62
+ throw new Error("The board template must be kanban, scrum, version, custom or personal.");
63
+ }
64
+ return template;
65
+ }
66
+ export async function createAgile(connection, input, options = {}) {
67
+ const body = namedMutationBody(input, true);
68
+ if (!Array.isArray(body.projects))
69
+ throw new Error("A new board requires projects with explicit IDs.");
70
+ const projects = body.projects.map(value => {
71
+ const project = mutationBody(value);
72
+ return { ...project, id: requiredText(project.id, "project ID") };
73
+ });
74
+ return mutate(connection, "api/agiles", { ...body, projects }, agileFields, options, options.template === undefined ? {} : { template: agileTemplate(options.template) });
75
+ }
76
+ export async function updateAgile(connection, agile, input, options = {}) {
77
+ return mutate(connection, agilePath(agile), namedMutationBody(input, false), fields(options, agileFields));
78
+ }
79
+ export async function deleteAgile(connection, agileID, options = {}) {
80
+ return deleteObject(connection, agilePath(agileID), options);
81
+ }
82
+ export async function deleteSprint(connection, agileID, sprintID, options = {}) {
83
+ return deleteObject(connection, `${agilePath(agileID)}/sprints/${encodedID(sprintID, "sprint ID")}`, options);
84
+ }
58
85
  //# sourceMappingURL=agile.js.map