jira-ai 1.7.1 → 1.8.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.
- package/README.md +77 -1
- package/dist/cli.js +21 -4
- package/dist/commands/get-person-worklog.js +7 -3
- package/dist/commands/run-jql.js +14 -1
- package/dist/commands/user-activity.js +67 -0
- package/dist/lib/jira-client.js +39 -0
- package/dist/lib/presets.js +2 -0
- package/dist/lib/validation.js +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -209,6 +209,46 @@ jira-ai issue comments PROJ-123 --since 2026-01-01T00:00:00Z --reverse --limit 2
|
|
|
209
209
|
|
|
210
210
|
**Activity types:** `status_change`, `field_change`, `comment_added`, `comment_updated`, `attachment_added`, `attachment_removed`, `link_added`, `link_removed`
|
|
211
211
|
|
|
212
|
+
### User Activity
|
|
213
|
+
|
|
214
|
+
Retrieve a user's activity across all issues in a timeframe — comments, status changes, field changes, and more:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
jira-ai user activity "Jane Smith" 7d
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Filter by project:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
jira-ai user activity "Jane Smith" 7d --project PS
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Filter by activity type:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
jira-ai user activity "Jane Smith" 7d --types comment_added,status_change
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Group results by issue instead of a flat timeline:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
jira-ai user activity "Jane Smith" 14d --project PS --group-by-issue
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Use `--compact` to strip comment bodies for token efficiency:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
jira-ai --compact user activity "Jane Smith" 30d --types comment_added
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Set a result limit:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
jira-ai user activity "Jane Smith" 7d --limit 100
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Permission:** `user.activity` — must be explicitly granted (not covered by `user.worklog`).
|
|
251
|
+
|
|
212
252
|
### Worklog Management
|
|
213
253
|
|
|
214
254
|
Log time against issues with full CRUD support:
|
|
@@ -277,6 +317,42 @@ jira-ai issue worklog add PROJ-123 --time 2h --dry-run
|
|
|
277
317
|
|
|
278
318
|
Duration format uses Jira-style notation: `1w` (5 working days), `1d` (8 hours), `1h`, `30m`, or combinations like `1d2h30m`.
|
|
279
319
|
|
|
320
|
+
### User Worklog
|
|
321
|
+
|
|
322
|
+
Retrieve worklogs for a specific user over a timeframe:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
jira-ai user worklog "Jane Smith" 7d
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Group results by issue:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
jira-ai user worklog "Jane Smith" 30d --group-by-issue
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Restrict to a specific project:
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
jira-ai user worklog "Jane Smith" 30d --project PS
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Issue Search Enhancements
|
|
341
|
+
|
|
342
|
+
Search issues with JQL and filter by comment author:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
jira-ai issue search 'project = PS AND updated >= -7d' --comment-author "Jane Smith"
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Use `--comment-author` without a JQL query to find all issues commented on by a user:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
jira-ai issue search --comment-author "Jane Smith" --limit 50
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
`--comment-author` can be combined with both positional JQL and `--query` (saved queries).
|
|
355
|
+
|
|
280
356
|
## Service Account Authentication
|
|
281
357
|
|
|
282
358
|
Atlassian service accounts use scoped API tokens that must authenticate through the `api.atlassian.com` gateway rather than direct site URLs.
|
|
@@ -382,7 +458,7 @@ The `--preset`, `--list-presets`, `--detect-preset`, `--apply`, `--validate`, an
|
|
|
382
458
|
|
|
383
459
|
#### What each preset allows
|
|
384
460
|
|
|
385
|
-
- **`read-only`** — `issue get/search/stats/comments/activity/tree/worklog.list/link.list/link.types/attach/list`, `project list/statuses/types/fields`, `user me/search/worklog`, `confl get/spaces/pages/search`, `epic list/get/issues/progress`, `board list/get/config/issues`, `sprint list/get/issues/tree`
|
|
461
|
+
- **`read-only`** — `issue get/search/stats/comments/activity/tree/worklog.list/link.list/link.types/attach/list`, `project list/statuses/types/fields`, `user me/search/worklog/activity`, `confl get/spaces/pages/search`, `epic list/get/issues/progress`, `board list/get/config/issues`, `sprint list/get/issues/tree`
|
|
386
462
|
- **`standard`** — Everything in `read-only`, plus `issue create/update/transition/comment/assign/label.add/label.remove/link.create/attach.upload/attach.download/worklog.add/worklog.update`, `confl create/comment/update`, `epic create/update/link/unlink`, `sprint update`
|
|
387
463
|
- **`my-tasks`** — All commands across all domains (`issue`, `project`, `user`, `confl`, `epic`, `board`, `sprint`, `backlog`), but issue visibility is filtered to those where the user participated (see [globalParticipationFilter](#globalparticipationfilter) below)
|
|
388
464
|
- **`yolo`** — All commands, all projects, all Confluence spaces. No restrictions.
|
package/dist/cli.js
CHANGED
|
@@ -25,6 +25,7 @@ import { sprintTreeCommand } from './commands/sprint-tree.js';
|
|
|
25
25
|
import { uploadAttachmentCommand, listAttachmentsCommand, downloadAttachmentCommand, deleteAttachmentCommand, } from './commands/attach.js';
|
|
26
26
|
import { getIssueStatisticsCommand } from './commands/get-issue-statistics.js';
|
|
27
27
|
import { getPersonWorklogCommand } from './commands/get-person-worklog.js';
|
|
28
|
+
import { userActivityCommand } from './commands/user-activity.js';
|
|
28
29
|
import { isCommandAllowed, getAllowedCommands } from './lib/settings.js';
|
|
29
30
|
import { confluenceGetPageCommand, confluenceListSpacesCommand, confluenceGetSpacePagesHierarchyCommand, confluenceAddCommentCommand, confluenceCreatePageCommand, confluenceUpdateDescriptionCommand, confluenceSearchCommand } from './commands/confluence.js';
|
|
30
31
|
import { epicListCommand, epicGetCommand, epicCreateCommand, epicUpdateCommand, epicIssuesCommand, epicLinkCommand, epicUnlinkCommand, epicProgressCommand, } from './commands/epic.js';
|
|
@@ -42,7 +43,7 @@ import { checkForUpdate, formatUpdateMessage, checkForUpdateSync } from './lib/u
|
|
|
42
43
|
import { CliError } from './types/errors.js';
|
|
43
44
|
import { CommandError } from './lib/errors.js';
|
|
44
45
|
import { initJsonMode, outputError } from './lib/json-mode.js';
|
|
45
|
-
import { CreateTaskSchema, UpdateDescriptionSchema, ProjectFieldsSchema, ConfluenceAddCommentSchema, RunJqlSchema, GetPersonWorklogSchema, GetIssueStatisticsSchema, EpicListSchema, EpicCreateSchema, EpicUpdateSchema, EpicLinkSchema, EpicMaxSchema, validateOptions, IssueKeySchema, ProjectKeySchema, TimeframeSchema, BoardListSchema, BoardIssuesSchema, BoardRankSchema, SprintListSchema, SprintCreateSchema, SprintUpdateSchema, SprintIssuesSchema, SprintMoveSchema, BacklogMoveSchema, AttachUploadSchema, AttachDownloadSchema, } from './lib/validation.js';
|
|
46
|
+
import { CreateTaskSchema, UpdateDescriptionSchema, ProjectFieldsSchema, ConfluenceAddCommentSchema, RunJqlSchema, GetPersonWorklogSchema, UserActivitySchema, GetIssueStatisticsSchema, EpicListSchema, EpicCreateSchema, EpicUpdateSchema, EpicLinkSchema, EpicMaxSchema, validateOptions, IssueKeySchema, ProjectKeySchema, TimeframeSchema, BoardListSchema, BoardIssuesSchema, BoardRankSchema, SprintListSchema, SprintCreateSchema, SprintUpdateSchema, SprintIssuesSchema, SprintMoveSchema, BacklogMoveSchema, AttachUploadSchema, AttachDownloadSchema, } from './lib/validation.js';
|
|
46
47
|
import { realpathSync } from 'fs';
|
|
47
48
|
// Create CLI program
|
|
48
49
|
const program = new Command();
|
|
@@ -142,6 +143,7 @@ issue
|
|
|
142
143
|
.option('-l, --limit <number>', 'Maximum number of results (default: 50)', '50')
|
|
143
144
|
.option('--query <name>', 'Use a saved query by name (mutually exclusive with positional JQL)')
|
|
144
145
|
.option('--list-queries', 'List all available saved queries')
|
|
146
|
+
.option('--comment-author <name>', 'Filter to issues commented on by this user (display name or account ID)')
|
|
145
147
|
.action(withPermission('issue.search', runJqlCommand, {
|
|
146
148
|
schema: RunJqlSchema,
|
|
147
149
|
validateArgs: (args) => {
|
|
@@ -149,8 +151,9 @@ issue
|
|
|
149
151
|
const opts = args[args.length - 2];
|
|
150
152
|
const hasQuery = opts && opts.query;
|
|
151
153
|
const hasListQueries = opts && opts.listQueries;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
const hasCommentAuthor = opts && opts.commentAuthor;
|
|
155
|
+
if (!hasQuery && !hasListQueries && !hasCommentAuthor && (typeof jqlQuery !== 'string' || jqlQuery.trim() === '')) {
|
|
156
|
+
throw new CliError('JQL query cannot be empty. Provide a JQL query, use --query <name>, --comment-author <name>, or use --list-queries.');
|
|
154
157
|
}
|
|
155
158
|
}
|
|
156
159
|
}));
|
|
@@ -522,12 +525,26 @@ user
|
|
|
522
525
|
.command('worklog <person> <timeframe>')
|
|
523
526
|
.description('Retrieve worklogs for a user over a timeframe (e.g., "7d", "2w").')
|
|
524
527
|
.option('--group-by-issue', 'Group the output by issue')
|
|
528
|
+
.option('--project <key>', 'Filter worklogs to a specific project key')
|
|
525
529
|
.action(withPermission('user.worklog', getPersonWorklogCommand, {
|
|
526
530
|
schema: GetPersonWorklogSchema,
|
|
527
531
|
validateArgs: (args) => {
|
|
528
532
|
validateOptions(TimeframeSchema, args[1]);
|
|
529
533
|
}
|
|
530
534
|
}));
|
|
535
|
+
user
|
|
536
|
+
.command('activity <person> <timeframe>')
|
|
537
|
+
.description('Show activity (comments, status changes, field changes) for a user over a timeframe.')
|
|
538
|
+
.option('--project <key>', 'Filter to a specific project key')
|
|
539
|
+
.option('--types <types>', 'Comma-separated activity types to include (e.g., "comment_added,status_change")')
|
|
540
|
+
.option('--limit <number>', 'Maximum number of activity entries to return')
|
|
541
|
+
.option('--group-by-issue', 'Group activities by issue')
|
|
542
|
+
.action(withPermission('user.activity', userActivityCommand, {
|
|
543
|
+
schema: UserActivitySchema,
|
|
544
|
+
validateArgs: (args) => {
|
|
545
|
+
validateOptions(TimeframeSchema, args[1]);
|
|
546
|
+
}
|
|
547
|
+
}));
|
|
531
548
|
// =============================================================================
|
|
532
549
|
// CONFLUENCE COMMANDS
|
|
533
550
|
// =============================================================================
|
|
@@ -789,7 +806,7 @@ Settings File Structure:
|
|
|
789
806
|
Command Groups (use in allowed-commands):
|
|
790
807
|
issue - get, create, search, transition, update, comment, stats, assign, label
|
|
791
808
|
project - list, statuses, types
|
|
792
|
-
user - me, search, worklog
|
|
809
|
+
user - me, search, worklog, activity
|
|
793
810
|
epic - list, get, create, update, issues, link, unlink, progress
|
|
794
811
|
confl - get, spaces, pages, create, comment, update
|
|
795
812
|
board - list, get, config, issues, rank
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { searchIssuesByJql, getIssueWorklogs } from '../lib/jira-client.js';
|
|
1
|
+
import { searchIssuesByJql, getIssueWorklogs, resolveUserByName } from '../lib/jira-client.js';
|
|
2
2
|
import { parseTimeframe, formatDateForJql } from '../lib/utils.js';
|
|
3
3
|
import { CommandError } from '../lib/errors.js';
|
|
4
4
|
import { outputResult } from '../lib/json-mode.js';
|
|
@@ -7,9 +7,13 @@ export async function getPersonWorklogCommand(person, timeframe, options) {
|
|
|
7
7
|
const { startDate, endDate } = parseTimeframe(timeframe);
|
|
8
8
|
const startJql = formatDateForJql(startDate);
|
|
9
9
|
const endJql = formatDateForJql(endDate);
|
|
10
|
+
// Resolve person to accountId for consistent JQL and in-memory filtering
|
|
11
|
+
const resolved = await resolveUserByName(person);
|
|
12
|
+
const worklogAuthor = resolved ?? person;
|
|
10
13
|
// 1. Search for issues where the person has tracked time in the timeframe
|
|
11
14
|
// We use a broader search first to find relevant issues
|
|
12
|
-
const
|
|
15
|
+
const projectClause = options.project ? ` AND project = "${options.project}"` : '';
|
|
16
|
+
const jql = `worklogAuthor = "${worklogAuthor}" AND worklogDate >= "${startJql}" AND worklogDate <= "${endJql}"${projectClause}`;
|
|
13
17
|
const issues = await searchIssuesByJql(jql, 100);
|
|
14
18
|
if (issues.length === 0) {
|
|
15
19
|
outputResult([]);
|
|
@@ -20,7 +24,7 @@ export async function getPersonWorklogCommand(person, timeframe, options) {
|
|
|
20
24
|
for (const issue of issues) {
|
|
21
25
|
const worklogs = await getIssueWorklogs(issue.key);
|
|
22
26
|
const filteredWorklogs = worklogs.filter(w => {
|
|
23
|
-
const matchesPerson = w.author.accountId ===
|
|
27
|
+
const matchesPerson = w.author.accountId === worklogAuthor || w.author.emailAddress === worklogAuthor;
|
|
24
28
|
const worklogDate = new Date(w.started);
|
|
25
29
|
const matchesDate = worklogDate >= startDate && worklogDate <= endDate;
|
|
26
30
|
return matchesPerson && matchesDate;
|
package/dist/commands/run-jql.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { searchIssuesByJql } from '../lib/jira-client.js';
|
|
1
|
+
import { searchIssuesByJql, resolveUserByName } from '../lib/jira-client.js';
|
|
2
2
|
import { outputResult } from '../lib/json-mode.js';
|
|
3
3
|
import { getSavedQuery, listSavedQueries } from '../lib/settings.js';
|
|
4
4
|
import { CliError } from '../types/errors.js';
|
|
@@ -24,8 +24,21 @@ export async function runJqlCommand(jqlQuery, options) {
|
|
|
24
24
|
resolvedJql = savedJql;
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
27
|
+
if (!jqlQuery || jqlQuery.trim() === '') {
|
|
28
|
+
throw new CliError('A JQL query is required. Provide a JQL string or use --query <name>.');
|
|
29
|
+
}
|
|
27
30
|
resolvedJql = jqlQuery;
|
|
28
31
|
}
|
|
32
|
+
// Append commentAuthor filter if provided (not mutually exclusive with other options)
|
|
33
|
+
if (options.commentAuthor) {
|
|
34
|
+
const accountId = (await resolveUserByName(options.commentAuthor)) ?? options.commentAuthor;
|
|
35
|
+
if (resolvedJql && resolvedJql.trim() !== '') {
|
|
36
|
+
resolvedJql = `(${resolvedJql}) AND commentAuthor = "${accountId}"`;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
resolvedJql = `commentAuthor = "${accountId}"`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
29
42
|
let maxResults = options.limit || 50;
|
|
30
43
|
if (maxResults > 1000) {
|
|
31
44
|
maxResults = 1000;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { searchIssuesByJql, resolveUserByName, buildUserActivityJql, getUserActivity, } from '../lib/jira-client.js';
|
|
2
|
+
import { parseTimeframe, formatDateForJql } from '../lib/utils.js';
|
|
3
|
+
import { CommandError } from '../lib/errors.js';
|
|
4
|
+
import { outputResult } from '../lib/json-mode.js';
|
|
5
|
+
const VALID_ACTIVITY_TYPES = [
|
|
6
|
+
'status_change',
|
|
7
|
+
'field_change',
|
|
8
|
+
'link_added',
|
|
9
|
+
'link_removed',
|
|
10
|
+
'attachment_added',
|
|
11
|
+
'attachment_removed',
|
|
12
|
+
'comment_added',
|
|
13
|
+
'comment_updated',
|
|
14
|
+
];
|
|
15
|
+
export async function userActivityCommand(person, timeframe, options) {
|
|
16
|
+
const { project, types, limit, groupByIssue } = options;
|
|
17
|
+
if (limit !== undefined && limit <= 0) {
|
|
18
|
+
throw new CommandError('--limit must be greater than 0');
|
|
19
|
+
}
|
|
20
|
+
if (types) {
|
|
21
|
+
const requestedTypes = types.split(',').map((t) => t.trim());
|
|
22
|
+
const invalid = requestedTypes.filter((t) => !VALID_ACTIVITY_TYPES.includes(t));
|
|
23
|
+
if (invalid.length > 0) {
|
|
24
|
+
throw new CommandError(`Invalid --types value(s): ${invalid.join(', ')}. Valid types: ${VALID_ACTIVITY_TYPES.join(', ')}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const { startDate, endDate } = parseTimeframe(timeframe);
|
|
28
|
+
const startJql = formatDateForJql(startDate);
|
|
29
|
+
const endJql = formatDateForJql(endDate);
|
|
30
|
+
// Resolve person to accountId, fall back to raw string
|
|
31
|
+
const accountId = (await resolveUserByName(person)) ?? person;
|
|
32
|
+
const jql = buildUserActivityJql(accountId, startJql, endJql, project);
|
|
33
|
+
const issues = await searchIssuesByJql(jql, 100);
|
|
34
|
+
if (issues.length === 0) {
|
|
35
|
+
outputResult({ activities: [], skipped: 0 });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const feedOptions = {
|
|
39
|
+
since: startDate.toISOString(),
|
|
40
|
+
author: accountId,
|
|
41
|
+
...(types ? { types } : {}),
|
|
42
|
+
...(limit ? { limit: limit * 2 } : {}), // fetch extra to allow for sorting + slicing
|
|
43
|
+
};
|
|
44
|
+
const { entries, skipped } = await getUserActivity(accountId, issues, feedOptions);
|
|
45
|
+
// Sort by timestamp descending
|
|
46
|
+
entries.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
47
|
+
// Apply limit (applies to activities, not issues)
|
|
48
|
+
const limited = limit ? entries.slice(0, limit) : entries;
|
|
49
|
+
if (groupByIssue) {
|
|
50
|
+
const grouped = new Map();
|
|
51
|
+
for (const entry of limited) {
|
|
52
|
+
if (!grouped.has(entry.issueKey)) {
|
|
53
|
+
grouped.set(entry.issueKey, {
|
|
54
|
+
issueKey: entry.issueKey,
|
|
55
|
+
summary: entry.issueSummary,
|
|
56
|
+
activities: [],
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const { issueKey: _k, issueSummary: _s, ...rest } = entry;
|
|
60
|
+
grouped.get(entry.issueKey).activities.push(rest);
|
|
61
|
+
}
|
|
62
|
+
outputResult({ issues: Array.from(grouped.values()), skipped });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
outputResult({ activities: limited, skipped });
|
|
66
|
+
}
|
|
67
|
+
}
|
package/dist/lib/jira-client.js
CHANGED
|
@@ -1366,3 +1366,42 @@ export async function deleteWorklogEntry(issueIdOrKey, worklogId, options = {})
|
|
|
1366
1366
|
params.increaseBy = increaseBy;
|
|
1367
1367
|
await client.issueWorklogs.deleteWorklog(params);
|
|
1368
1368
|
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Build JQL to find issues where the given user has had activity in the timeframe.
|
|
1371
|
+
* Uses commentAuthor for comment-based search (valid JQL field).
|
|
1372
|
+
*/
|
|
1373
|
+
export function buildUserActivityJql(accountId, startJql, endJql, projectKey) {
|
|
1374
|
+
const projectClause = projectKey ? ` AND project = "${projectKey}"` : '';
|
|
1375
|
+
return (`(` +
|
|
1376
|
+
`worklogAuthor = "${accountId}" AND worklogDate >= "${startJql}" AND worklogDate <= "${endJql}"` +
|
|
1377
|
+
` OR commentAuthor = "${accountId}" AND updated >= "${startJql}" AND updated <= "${endJql}"` +
|
|
1378
|
+
` OR assignee = "${accountId}" AND updated >= "${startJql}" AND updated <= "${endJql}"` +
|
|
1379
|
+
`)` +
|
|
1380
|
+
projectClause);
|
|
1381
|
+
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Fetch activity for a user across issues, using batch parallelism of 5 concurrent requests.
|
|
1384
|
+
* Skips issues that fail (partial failure tolerance).
|
|
1385
|
+
*/
|
|
1386
|
+
export async function getUserActivity(accountId, issues, feedOptions) {
|
|
1387
|
+
const BATCH_SIZE = 5;
|
|
1388
|
+
let skipped = 0;
|
|
1389
|
+
const allEntries = [];
|
|
1390
|
+
for (let i = 0; i < issues.length; i += BATCH_SIZE) {
|
|
1391
|
+
const batch = issues.slice(i, i + BATCH_SIZE);
|
|
1392
|
+
const results = await Promise.allSettled(batch.map((issue) => getIssueActivityFeed(issue.key, feedOptions)));
|
|
1393
|
+
for (let j = 0; j < results.length; j++) {
|
|
1394
|
+
const result = results[j];
|
|
1395
|
+
const issue = batch[j];
|
|
1396
|
+
if (result.status === 'fulfilled') {
|
|
1397
|
+
for (const entry of result.value.activities) {
|
|
1398
|
+
allEntries.push({ ...entry, issueKey: issue.key, issueSummary: issue.summary });
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
else {
|
|
1402
|
+
skipped++;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
return { entries: allEntries, skipped };
|
|
1407
|
+
}
|
package/dist/lib/presets.js
CHANGED
|
@@ -21,6 +21,7 @@ export const PRESETS = {
|
|
|
21
21
|
'user.me',
|
|
22
22
|
'user.search',
|
|
23
23
|
'user.worklog',
|
|
24
|
+
'user.activity',
|
|
24
25
|
'confl.get',
|
|
25
26
|
'confl.spaces',
|
|
26
27
|
'confl.pages',
|
|
@@ -75,6 +76,7 @@ export const PRESETS = {
|
|
|
75
76
|
'user.me',
|
|
76
77
|
'user.search',
|
|
77
78
|
'user.worklog',
|
|
79
|
+
'user.activity',
|
|
78
80
|
'confl.get',
|
|
79
81
|
'confl.spaces',
|
|
80
82
|
'confl.pages',
|
package/dist/lib/validation.js
CHANGED
|
@@ -115,10 +115,18 @@ export const RunJqlSchema = z.object({
|
|
|
115
115
|
limit: NumericStringSchema.optional(),
|
|
116
116
|
query: z.string().optional(),
|
|
117
117
|
listQueries: z.boolean().optional(),
|
|
118
|
+
commentAuthor: z.string().optional(),
|
|
118
119
|
});
|
|
119
120
|
export const TimeframeSchema = z.string().regex(/^\d+d$/, 'Timeframe must be in format like "7d" or "30d"');
|
|
120
121
|
export const GetPersonWorklogSchema = z.object({
|
|
121
122
|
groupByIssue: z.boolean().optional(),
|
|
123
|
+
project: z.string().optional(),
|
|
124
|
+
});
|
|
125
|
+
export const UserActivitySchema = z.object({
|
|
126
|
+
project: z.string().optional(),
|
|
127
|
+
types: z.string().optional(),
|
|
128
|
+
limit: NumericStringSchema.optional(),
|
|
129
|
+
groupByIssue: z.boolean().optional(),
|
|
122
130
|
});
|
|
123
131
|
export const GetIssueStatisticsSchema = z.object({
|
|
124
132
|
fullBreakdown: z.boolean().optional(),
|