@bragduck/cli 2.27.2 → 2.28.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/dist/bin/bragduck.js +29 -134
- package/dist/bin/bragduck.js.map +1 -1
- package/package.json +1 -2
package/dist/bin/bragduck.js
CHANGED
|
@@ -3653,32 +3653,6 @@ var JiraService = class {
|
|
|
3653
3653
|
return null;
|
|
3654
3654
|
}
|
|
3655
3655
|
}
|
|
3656
|
-
/**
|
|
3657
|
-
* Check if a user object matches the given identifier (accountId, email, or username)
|
|
3658
|
-
*/
|
|
3659
|
-
isMatchingUser(candidate, userIdentifier) {
|
|
3660
|
-
return candidate.email === userIdentifier || candidate.emailAddress === userIdentifier || candidate.accountId === userIdentifier || candidate.username === userIdentifier || candidate.name === userIdentifier;
|
|
3661
|
-
}
|
|
3662
|
-
/**
|
|
3663
|
-
* Filter issues to only those where the user made contributions within the date range.
|
|
3664
|
-
* Excludes issues where the user's only involvement is a static role (creator/assignee)
|
|
3665
|
-
* with a date outside the scan period.
|
|
3666
|
-
*/
|
|
3667
|
-
filterIssuesByUserContribution(issues, userIdentifier, sinceDate) {
|
|
3668
|
-
const results = [];
|
|
3669
|
-
for (const issue of issues) {
|
|
3670
|
-
const userChanges = (issue.changelog?.histories || []).filter(
|
|
3671
|
-
(h) => this.isMatchingUser(h.author, userIdentifier) && new Date(h.created) >= sinceDate
|
|
3672
|
-
);
|
|
3673
|
-
const isCreatorInRange = this.isMatchingUser(issue.fields.creator, userIdentifier) && new Date(issue.fields.created) >= sinceDate;
|
|
3674
|
-
if (userChanges.length > 0 || isCreatorInRange) {
|
|
3675
|
-
results.push({ issue, userChanges });
|
|
3676
|
-
} else {
|
|
3677
|
-
logger.debug(`Excluding issue ${issue.key} - no user contributions in date range`);
|
|
3678
|
-
}
|
|
3679
|
-
}
|
|
3680
|
-
return results;
|
|
3681
|
-
}
|
|
3682
3656
|
/**
|
|
3683
3657
|
* Build JQL query from options
|
|
3684
3658
|
*/
|
|
@@ -3808,7 +3782,7 @@ var JiraService = class {
|
|
|
3808
3782
|
);
|
|
3809
3783
|
break;
|
|
3810
3784
|
}
|
|
3811
|
-
const endpoint = `/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}&fields=${fields.join(",")}
|
|
3785
|
+
const endpoint = `/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}&fields=${fields.join(",")}`;
|
|
3812
3786
|
try {
|
|
3813
3787
|
const response = await this.request(endpoint);
|
|
3814
3788
|
if (response.issues.length === 0) {
|
|
@@ -3834,7 +3808,14 @@ var JiraService = class {
|
|
|
3834
3808
|
break;
|
|
3835
3809
|
}
|
|
3836
3810
|
if (options.limit && allIssues.length >= options.limit) {
|
|
3837
|
-
|
|
3811
|
+
const email2 = await this.getCurrentUser();
|
|
3812
|
+
const limitedIssues = allIssues.slice(0, options.limit);
|
|
3813
|
+
const commits2 = [];
|
|
3814
|
+
for (const issue of limitedIssues) {
|
|
3815
|
+
const commit = await this.transformIssueToCommit(issue, void 0, email2 || void 0);
|
|
3816
|
+
commits2.push(commit);
|
|
3817
|
+
}
|
|
3818
|
+
return commits2;
|
|
3838
3819
|
}
|
|
3839
3820
|
startAt += maxResults;
|
|
3840
3821
|
} catch (error) {
|
|
@@ -3858,23 +3839,9 @@ var JiraService = class {
|
|
|
3858
3839
|
throw error;
|
|
3859
3840
|
}
|
|
3860
3841
|
}
|
|
3861
|
-
const issuesToProcess = options.limit ? allIssues.slice(0, options.limit) : allIssues;
|
|
3862
3842
|
const email = await this.getCurrentUser();
|
|
3863
|
-
const sinceDate = options.days ? new Date(Date.now() - options.days * 24 * 60 * 60 * 1e3) : void 0;
|
|
3864
|
-
if (sinceDate && email) {
|
|
3865
|
-
const filtered = this.filterIssuesByUserContribution(issuesToProcess, email, sinceDate);
|
|
3866
|
-
logger.debug(
|
|
3867
|
-
`Date-scoped filtering: ${issuesToProcess.length} issues -> ${filtered.length} with user contributions in range`
|
|
3868
|
-
);
|
|
3869
|
-
const commits2 = [];
|
|
3870
|
-
for (const { issue, userChanges } of filtered) {
|
|
3871
|
-
const commit = await this.transformIssueToCommit(issue, void 0, email, userChanges);
|
|
3872
|
-
commits2.push(commit);
|
|
3873
|
-
}
|
|
3874
|
-
return commits2;
|
|
3875
|
-
}
|
|
3876
3843
|
const commits = [];
|
|
3877
|
-
for (const issue of
|
|
3844
|
+
for (const issue of allIssues) {
|
|
3878
3845
|
const commit = await this.transformIssueToCommit(issue, void 0, email || void 0);
|
|
3879
3846
|
commits.push(commit);
|
|
3880
3847
|
}
|
|
@@ -3896,7 +3863,7 @@ var JiraService = class {
|
|
|
3896
3863
|
/**
|
|
3897
3864
|
* Transform Jira issue to GitCommit format with contribution-specific data
|
|
3898
3865
|
*/
|
|
3899
|
-
async transformIssueToCommit(issue, instanceUrl, userEmail
|
|
3866
|
+
async transformIssueToCommit(issue, instanceUrl, userEmail) {
|
|
3900
3867
|
let contribution = null;
|
|
3901
3868
|
if (userEmail) {
|
|
3902
3869
|
contribution = await this.determineJiraContributionType(issue, userEmail);
|
|
@@ -3938,8 +3905,6 @@ ${truncatedDesc}`;
|
|
|
3938
3905
|
date = issue.fields.created;
|
|
3939
3906
|
} else if (contribution?.type === "assigned-resolved" && issue.fields.resolutiondate) {
|
|
3940
3907
|
date = issue.fields.resolutiondate;
|
|
3941
|
-
} else if (userChanges && userChanges.length > 0) {
|
|
3942
|
-
date = userChanges[userChanges.length - 1].created;
|
|
3943
3908
|
} else {
|
|
3944
3909
|
date = issue.fields.updated;
|
|
3945
3910
|
}
|
|
@@ -4129,59 +4094,6 @@ var ConfluenceService = class {
|
|
|
4129
4094
|
return null;
|
|
4130
4095
|
}
|
|
4131
4096
|
}
|
|
4132
|
-
/**
|
|
4133
|
-
* Check if a user object matches the given identifier (accountId, email, or username)
|
|
4134
|
-
*/
|
|
4135
|
-
isMatchingUser(candidate, userIdentifier) {
|
|
4136
|
-
return candidate.email === userIdentifier || candidate.emailAddress === userIdentifier || candidate.accountId === userIdentifier || candidate.username === userIdentifier || candidate.name === userIdentifier;
|
|
4137
|
-
}
|
|
4138
|
-
/**
|
|
4139
|
-
* Fetch full version history for a page
|
|
4140
|
-
*/
|
|
4141
|
-
async getPageVersionHistory(pageId) {
|
|
4142
|
-
const allVersions = [];
|
|
4143
|
-
let start = 0;
|
|
4144
|
-
const limit = 50;
|
|
4145
|
-
while (true) {
|
|
4146
|
-
const response = await this.request(
|
|
4147
|
-
`/wiki/rest/api/content/${pageId}/version?start=${start}&limit=${limit}`
|
|
4148
|
-
);
|
|
4149
|
-
allVersions.push(...response.results);
|
|
4150
|
-
if (response.size < limit) break;
|
|
4151
|
-
start += limit;
|
|
4152
|
-
}
|
|
4153
|
-
return allVersions;
|
|
4154
|
-
}
|
|
4155
|
-
/**
|
|
4156
|
-
* Filter pages to only those where the user made contributions within the date range.
|
|
4157
|
-
* Fetches version history per page and checks if the user has versions in range.
|
|
4158
|
-
*/
|
|
4159
|
-
async filterPagesByUserContribution(pages, userIdentifier, sinceDate) {
|
|
4160
|
-
const results = [];
|
|
4161
|
-
for (let i = 0; i < pages.length; i++) {
|
|
4162
|
-
const page = pages[i];
|
|
4163
|
-
if (i > 0) {
|
|
4164
|
-
await new Promise((resolve) => globalThis.setTimeout(resolve, 100));
|
|
4165
|
-
}
|
|
4166
|
-
try {
|
|
4167
|
-
const versions = await this.getPageVersionHistory(page.id);
|
|
4168
|
-
const userVersions = versions.filter(
|
|
4169
|
-
(v) => this.isMatchingUser(v.by, userIdentifier) && new Date(v.when) >= sinceDate
|
|
4170
|
-
);
|
|
4171
|
-
const userCommentsInRange = page.children?.comment?.results?.filter(
|
|
4172
|
-
(comment) => this.isMatchingUser(comment.version?.by || {}, userIdentifier) && new Date(comment.version?.when || 0) >= sinceDate
|
|
4173
|
-
) || [];
|
|
4174
|
-
if (userVersions.length > 0 || userCommentsInRange.length > 0) {
|
|
4175
|
-
results.push({ page, userVersions });
|
|
4176
|
-
} else {
|
|
4177
|
-
logger.debug(`Excluding page "${page.title}" - no user contributions in date range`);
|
|
4178
|
-
}
|
|
4179
|
-
} catch (error) {
|
|
4180
|
-
logger.debug(`Skipping version history for page ${page.id}: ${error}`);
|
|
4181
|
-
}
|
|
4182
|
-
}
|
|
4183
|
-
return results;
|
|
4184
|
-
}
|
|
4185
4097
|
/**
|
|
4186
4098
|
* Build CQL query from options
|
|
4187
4099
|
* Returns empty string if no filters need CQL (will use simple endpoint instead)
|
|
@@ -4217,31 +4129,28 @@ var ConfluenceService = class {
|
|
|
4217
4129
|
* Determine the type of contribution the current user made to a page
|
|
4218
4130
|
* Returns: 'created' | 'edited' | 'commented'
|
|
4219
4131
|
*/
|
|
4220
|
-
async determineContributionType(page, userEmail
|
|
4221
|
-
|
|
4222
|
-
if (createdByUser) {
|
|
4132
|
+
async determineContributionType(page, userEmail) {
|
|
4133
|
+
if (page.history?.createdBy?.email === userEmail) {
|
|
4223
4134
|
return {
|
|
4224
4135
|
type: "created",
|
|
4225
4136
|
details: `Created page with ${page.version?.number || 1} version${(page.version?.number || 1) > 1 ? "s" : ""}`
|
|
4226
4137
|
};
|
|
4227
4138
|
}
|
|
4228
|
-
const hasEdits =
|
|
4139
|
+
const hasEdits = page.version?.by?.email === userEmail && (page.version?.number || 0) > 1;
|
|
4229
4140
|
const userComments = page.children?.comment?.results?.filter(
|
|
4230
|
-
(comment) => comment.version?.by
|
|
4141
|
+
(comment) => comment.version?.by?.email === userEmail
|
|
4231
4142
|
) || [];
|
|
4232
4143
|
const hasComments = userComments.length > 0;
|
|
4233
4144
|
if (hasEdits && hasComments) {
|
|
4234
|
-
const editCount = userVersions?.length || 1;
|
|
4235
4145
|
return {
|
|
4236
4146
|
type: "edited",
|
|
4237
|
-
details: `Edited page (${
|
|
4147
|
+
details: `Edited page (v${page.version?.number || 1}) and added ${userComments.length} comment${userComments.length > 1 ? "s" : ""}`
|
|
4238
4148
|
};
|
|
4239
4149
|
}
|
|
4240
4150
|
if (hasEdits) {
|
|
4241
|
-
const editCount = userVersions?.length || 1;
|
|
4242
4151
|
return {
|
|
4243
4152
|
type: "edited",
|
|
4244
|
-
details: `Edited page
|
|
4153
|
+
details: `Edited page to version ${page.version?.number || 1}`
|
|
4245
4154
|
};
|
|
4246
4155
|
}
|
|
4247
4156
|
if (hasComments) {
|
|
@@ -4339,7 +4248,14 @@ var ConfluenceService = class {
|
|
|
4339
4248
|
break;
|
|
4340
4249
|
}
|
|
4341
4250
|
if (options.limit && allPages.length >= options.limit) {
|
|
4342
|
-
|
|
4251
|
+
const email2 = await this.getCurrentUser();
|
|
4252
|
+
const limitedPages = allPages.slice(0, options.limit);
|
|
4253
|
+
const commits2 = [];
|
|
4254
|
+
for (const page of limitedPages) {
|
|
4255
|
+
const commit = await this.transformPageToCommit(page, void 0, email2 || void 0);
|
|
4256
|
+
commits2.push(commit);
|
|
4257
|
+
}
|
|
4258
|
+
return commits2;
|
|
4343
4259
|
}
|
|
4344
4260
|
start += limit;
|
|
4345
4261
|
} catch (error) {
|
|
@@ -4363,23 +4279,9 @@ var ConfluenceService = class {
|
|
|
4363
4279
|
throw error;
|
|
4364
4280
|
}
|
|
4365
4281
|
}
|
|
4366
|
-
const pagesToProcess = options.limit ? allPages.slice(0, options.limit) : allPages;
|
|
4367
4282
|
const email = await this.getCurrentUser();
|
|
4368
|
-
const sinceDate = options.days ? new Date(Date.now() - options.days * 24 * 60 * 60 * 1e3) : void 0;
|
|
4369
|
-
if (sinceDate && email) {
|
|
4370
|
-
const filtered = await this.filterPagesByUserContribution(pagesToProcess, email, sinceDate);
|
|
4371
|
-
logger.debug(
|
|
4372
|
-
`Date-scoped filtering: ${pagesToProcess.length} pages -> ${filtered.length} with user contributions in range`
|
|
4373
|
-
);
|
|
4374
|
-
const commits2 = [];
|
|
4375
|
-
for (const { page, userVersions } of filtered) {
|
|
4376
|
-
const commit = await this.transformPageToCommit(page, void 0, email, userVersions);
|
|
4377
|
-
commits2.push(commit);
|
|
4378
|
-
}
|
|
4379
|
-
return commits2;
|
|
4380
|
-
}
|
|
4381
4283
|
const commits = [];
|
|
4382
|
-
for (const page of
|
|
4284
|
+
for (const page of allPages) {
|
|
4383
4285
|
const commit = await this.transformPageToCommit(page, void 0, email || void 0);
|
|
4384
4286
|
commits.push(commit);
|
|
4385
4287
|
}
|
|
@@ -4401,10 +4303,10 @@ var ConfluenceService = class {
|
|
|
4401
4303
|
/**
|
|
4402
4304
|
* Transform Confluence page to GitCommit format with contribution-specific data
|
|
4403
4305
|
*/
|
|
4404
|
-
async transformPageToCommit(page, instanceUrl, userEmail
|
|
4306
|
+
async transformPageToCommit(page, instanceUrl, userEmail) {
|
|
4405
4307
|
let contribution = null;
|
|
4406
4308
|
if (userEmail) {
|
|
4407
|
-
contribution = await this.determineContributionType(page, userEmail
|
|
4309
|
+
contribution = await this.determineContributionType(page, userEmail);
|
|
4408
4310
|
}
|
|
4409
4311
|
let message;
|
|
4410
4312
|
let contributionPrefix = "";
|
|
@@ -4442,14 +4344,7 @@ ${contribution.details}
|
|
|
4442
4344
|
const impactScore = contribution ? this.calculateContributionImpact(contribution.type, baseSize) : baseSize;
|
|
4443
4345
|
const author = page.history?.createdBy?.displayName || page.version?.by?.displayName || "Unknown Author";
|
|
4444
4346
|
const authorEmail = page.history?.createdBy?.email || page.version?.by?.email || "unknown@example.com";
|
|
4445
|
-
|
|
4446
|
-
if (contribution?.type === "created") {
|
|
4447
|
-
date = page.history?.createdDate || page.version?.when;
|
|
4448
|
-
} else if (userVersions && userVersions.length > 0) {
|
|
4449
|
-
date = userVersions[userVersions.length - 1].when;
|
|
4450
|
-
} else {
|
|
4451
|
-
date = page.version?.when || (/* @__PURE__ */ new Date()).toISOString();
|
|
4452
|
-
}
|
|
4347
|
+
const date = contribution?.type === "created" ? page.history?.createdDate || page.version?.when : page.version?.when || (/* @__PURE__ */ new Date()).toISOString();
|
|
4453
4348
|
return {
|
|
4454
4349
|
sha: page.id,
|
|
4455
4350
|
message,
|