@bragduck/cli 2.27.0 → 2.28.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/dist/bin/bragduck.js +260 -33
- package/dist/bin/bragduck.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/bragduck.js
CHANGED
|
@@ -3653,6 +3653,33 @@ 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
|
+
if (!candidate) return false;
|
|
3661
|
+
return candidate.email === userIdentifier || candidate.emailAddress === userIdentifier || candidate.accountId === userIdentifier || candidate.username === userIdentifier || candidate.name === userIdentifier;
|
|
3662
|
+
}
|
|
3663
|
+
/**
|
|
3664
|
+
* Filter issues to only those where the user made contributions within the date range.
|
|
3665
|
+
* Excludes issues where the user's only involvement is a static role (creator/assignee)
|
|
3666
|
+
* with a date outside the scan period.
|
|
3667
|
+
*/
|
|
3668
|
+
filterIssuesByUserContribution(issues, userIdentifier, sinceDate) {
|
|
3669
|
+
const results = [];
|
|
3670
|
+
for (const issue of issues) {
|
|
3671
|
+
const userChanges = (issue.changelog?.histories || []).filter(
|
|
3672
|
+
(h) => this.isMatchingUser(h.author, userIdentifier) && new Date(h.created) >= sinceDate
|
|
3673
|
+
);
|
|
3674
|
+
const isCreatorInRange = this.isMatchingUser(issue.fields.creator, userIdentifier) && new Date(issue.fields.created) >= sinceDate;
|
|
3675
|
+
if (userChanges.length > 0 || isCreatorInRange) {
|
|
3676
|
+
results.push({ issue, userChanges });
|
|
3677
|
+
} else {
|
|
3678
|
+
logger.debug(`Excluding issue ${issue.key} - no user contributions in date range`);
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
return results;
|
|
3682
|
+
}
|
|
3656
3683
|
/**
|
|
3657
3684
|
* Build JQL query from options
|
|
3658
3685
|
*/
|
|
@@ -3710,7 +3737,7 @@ var JiraService = class {
|
|
|
3710
3737
|
}
|
|
3711
3738
|
const isAssigned = issue.fields.assignee?.emailAddress === userEmail;
|
|
3712
3739
|
const isResolved = issue.fields.resolutiondate !== null && issue.fields.resolutiondate !== void 0;
|
|
3713
|
-
const userEdits = issue.changelog?.histories?.filter((history) => history.author
|
|
3740
|
+
const userEdits = issue.changelog?.histories?.filter((history) => history.author?.emailAddress === userEmail) || [];
|
|
3714
3741
|
const hasEdits = userEdits.length > 0;
|
|
3715
3742
|
if (isAssigned && isResolved) {
|
|
3716
3743
|
return {
|
|
@@ -3745,6 +3772,77 @@ var JiraService = class {
|
|
|
3745
3772
|
};
|
|
3746
3773
|
return Math.ceil(baseComplexity * multipliers[contributionType]);
|
|
3747
3774
|
}
|
|
3775
|
+
/**
|
|
3776
|
+
* Summarize the user's specific changes from changelog entries into human-readable lines.
|
|
3777
|
+
* This enriches the brag message so the AI refinement can generate a more specific brag.
|
|
3778
|
+
*/
|
|
3779
|
+
summarizeUserChanges(userChanges) {
|
|
3780
|
+
const MAX_LINES = 10;
|
|
3781
|
+
const allItems = [];
|
|
3782
|
+
for (const entry of userChanges) {
|
|
3783
|
+
for (const item of entry.items) {
|
|
3784
|
+
allItems.push(item);
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
if (allItems.length === 0) return "";
|
|
3788
|
+
const latestByField = /* @__PURE__ */ new Map();
|
|
3789
|
+
for (const item of allItems) {
|
|
3790
|
+
latestByField.set(item.field, { fromString: item.fromString, toString: item.toString });
|
|
3791
|
+
}
|
|
3792
|
+
const lines = [];
|
|
3793
|
+
for (const [field, change] of latestByField) {
|
|
3794
|
+
if (lines.length >= MAX_LINES) break;
|
|
3795
|
+
const from = change.fromString || "";
|
|
3796
|
+
const to = change.toString || "";
|
|
3797
|
+
switch (field.toLowerCase()) {
|
|
3798
|
+
case "status":
|
|
3799
|
+
lines.push(from ? `Moved status from '${from}' to '${to}'` : `Set status to '${to}'`);
|
|
3800
|
+
break;
|
|
3801
|
+
case "resolution":
|
|
3802
|
+
lines.push(to ? `Resolved as '${to}'` : "Reopened issue");
|
|
3803
|
+
break;
|
|
3804
|
+
case "assignee":
|
|
3805
|
+
lines.push(to ? `Assigned to ${to}` : "Unassigned");
|
|
3806
|
+
break;
|
|
3807
|
+
case "priority":
|
|
3808
|
+
lines.push(
|
|
3809
|
+
from ? `Changed priority from '${from}' to '${to}'` : `Set priority to '${to}'`
|
|
3810
|
+
);
|
|
3811
|
+
break;
|
|
3812
|
+
case "summary":
|
|
3813
|
+
lines.push("Updated issue title");
|
|
3814
|
+
break;
|
|
3815
|
+
case "description":
|
|
3816
|
+
lines.push("Updated description");
|
|
3817
|
+
break;
|
|
3818
|
+
case "comment":
|
|
3819
|
+
lines.push("Added comment");
|
|
3820
|
+
break;
|
|
3821
|
+
case "labels":
|
|
3822
|
+
lines.push(to ? `Updated labels: ${to}` : "Removed labels");
|
|
3823
|
+
break;
|
|
3824
|
+
case "fix version":
|
|
3825
|
+
case "fixversions":
|
|
3826
|
+
lines.push(to ? `Set fix version: ${to}` : "Removed fix version");
|
|
3827
|
+
break;
|
|
3828
|
+
case "sprint":
|
|
3829
|
+
lines.push(to ? `Moved to sprint: ${to}` : "Removed from sprint");
|
|
3830
|
+
break;
|
|
3831
|
+
case "story points":
|
|
3832
|
+
case "story point estimate":
|
|
3833
|
+
lines.push(`Set story points to ${to}`);
|
|
3834
|
+
break;
|
|
3835
|
+
default:
|
|
3836
|
+
if (to) {
|
|
3837
|
+
lines.push(`Updated ${field}`);
|
|
3838
|
+
}
|
|
3839
|
+
break;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
if (lines.length === 0) return "";
|
|
3843
|
+
return `User changes:
|
|
3844
|
+
${lines.map((l) => `- ${l}`).join("\n")}`;
|
|
3845
|
+
}
|
|
3748
3846
|
/**
|
|
3749
3847
|
* Fetch issues with optional filtering
|
|
3750
3848
|
*/
|
|
@@ -3782,7 +3880,7 @@ var JiraService = class {
|
|
|
3782
3880
|
);
|
|
3783
3881
|
break;
|
|
3784
3882
|
}
|
|
3785
|
-
const endpoint = `/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}&fields=${fields.join(",")}`;
|
|
3883
|
+
const endpoint = `/rest/api/3/search/jql?jql=${encodeURIComponent(jql)}&startAt=${startAt}&maxResults=${maxResults}&fields=${fields.join(",")}&expand=changelog`;
|
|
3786
3884
|
try {
|
|
3787
3885
|
const response = await this.request(endpoint);
|
|
3788
3886
|
if (response.issues.length === 0) {
|
|
@@ -3808,14 +3906,7 @@ var JiraService = class {
|
|
|
3808
3906
|
break;
|
|
3809
3907
|
}
|
|
3810
3908
|
if (options.limit && allIssues.length >= options.limit) {
|
|
3811
|
-
|
|
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;
|
|
3909
|
+
break;
|
|
3819
3910
|
}
|
|
3820
3911
|
startAt += maxResults;
|
|
3821
3912
|
} catch (error) {
|
|
@@ -3839,9 +3930,23 @@ var JiraService = class {
|
|
|
3839
3930
|
throw error;
|
|
3840
3931
|
}
|
|
3841
3932
|
}
|
|
3933
|
+
const issuesToProcess = options.limit ? allIssues.slice(0, options.limit) : allIssues;
|
|
3842
3934
|
const email = await this.getCurrentUser();
|
|
3935
|
+
const sinceDate = options.days ? new Date(Date.now() - options.days * 24 * 60 * 60 * 1e3) : void 0;
|
|
3936
|
+
if (sinceDate && email) {
|
|
3937
|
+
const filtered = this.filterIssuesByUserContribution(issuesToProcess, email, sinceDate);
|
|
3938
|
+
logger.debug(
|
|
3939
|
+
`Date-scoped filtering: ${issuesToProcess.length} issues -> ${filtered.length} with user contributions in range`
|
|
3940
|
+
);
|
|
3941
|
+
const commits2 = [];
|
|
3942
|
+
for (const { issue, userChanges } of filtered) {
|
|
3943
|
+
const commit = await this.transformIssueToCommit(issue, void 0, email, userChanges);
|
|
3944
|
+
commits2.push(commit);
|
|
3945
|
+
}
|
|
3946
|
+
return commits2;
|
|
3947
|
+
}
|
|
3843
3948
|
const commits = [];
|
|
3844
|
-
for (const issue of
|
|
3949
|
+
for (const issue of issuesToProcess) {
|
|
3845
3950
|
const commit = await this.transformIssueToCommit(issue, void 0, email || void 0);
|
|
3846
3951
|
commits.push(commit);
|
|
3847
3952
|
}
|
|
@@ -3863,7 +3968,7 @@ var JiraService = class {
|
|
|
3863
3968
|
/**
|
|
3864
3969
|
* Transform Jira issue to GitCommit format with contribution-specific data
|
|
3865
3970
|
*/
|
|
3866
|
-
async transformIssueToCommit(issue, instanceUrl, userEmail) {
|
|
3971
|
+
async transformIssueToCommit(issue, instanceUrl, userEmail, userChanges) {
|
|
3867
3972
|
let contribution = null;
|
|
3868
3973
|
if (userEmail) {
|
|
3869
3974
|
contribution = await this.determineJiraContributionType(issue, userEmail);
|
|
@@ -3900,11 +4005,21 @@ ${contribution.details}`;
|
|
|
3900
4005
|
${truncatedDesc}`;
|
|
3901
4006
|
}
|
|
3902
4007
|
}
|
|
4008
|
+
if (userChanges && userChanges.length > 0) {
|
|
4009
|
+
const changeSummary = this.summarizeUserChanges(userChanges);
|
|
4010
|
+
if (changeSummary) {
|
|
4011
|
+
message += `
|
|
4012
|
+
|
|
4013
|
+
${changeSummary}`;
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
3903
4016
|
let date;
|
|
3904
4017
|
if (contribution?.type === "created" || contribution?.type === "reported") {
|
|
3905
4018
|
date = issue.fields.created;
|
|
3906
4019
|
} else if (contribution?.type === "assigned-resolved" && issue.fields.resolutiondate) {
|
|
3907
4020
|
date = issue.fields.resolutiondate;
|
|
4021
|
+
} else if (userChanges && userChanges.length > 0) {
|
|
4022
|
+
date = userChanges[userChanges.length - 1].created;
|
|
3908
4023
|
} else {
|
|
3909
4024
|
date = issue.fields.updated;
|
|
3910
4025
|
}
|
|
@@ -4094,6 +4209,60 @@ var ConfluenceService = class {
|
|
|
4094
4209
|
return null;
|
|
4095
4210
|
}
|
|
4096
4211
|
}
|
|
4212
|
+
/**
|
|
4213
|
+
* Check if a user object matches the given identifier (accountId, email, or username)
|
|
4214
|
+
*/
|
|
4215
|
+
isMatchingUser(candidate, userIdentifier) {
|
|
4216
|
+
if (!candidate) return false;
|
|
4217
|
+
return candidate.email === userIdentifier || candidate.emailAddress === userIdentifier || candidate.accountId === userIdentifier || candidate.username === userIdentifier || candidate.name === userIdentifier;
|
|
4218
|
+
}
|
|
4219
|
+
/**
|
|
4220
|
+
* Fetch full version history for a page
|
|
4221
|
+
*/
|
|
4222
|
+
async getPageVersionHistory(pageId) {
|
|
4223
|
+
const allVersions = [];
|
|
4224
|
+
let start = 0;
|
|
4225
|
+
const limit = 50;
|
|
4226
|
+
while (true) {
|
|
4227
|
+
const response = await this.request(
|
|
4228
|
+
`/wiki/rest/api/content/${pageId}/version?start=${start}&limit=${limit}`
|
|
4229
|
+
);
|
|
4230
|
+
allVersions.push(...response.results);
|
|
4231
|
+
if (response.size < limit) break;
|
|
4232
|
+
start += limit;
|
|
4233
|
+
}
|
|
4234
|
+
return allVersions;
|
|
4235
|
+
}
|
|
4236
|
+
/**
|
|
4237
|
+
* Filter pages to only those where the user made contributions within the date range.
|
|
4238
|
+
* Fetches version history per page and checks if the user has versions in range.
|
|
4239
|
+
*/
|
|
4240
|
+
async filterPagesByUserContribution(pages, userIdentifier, sinceDate) {
|
|
4241
|
+
const results = [];
|
|
4242
|
+
for (let i = 0; i < pages.length; i++) {
|
|
4243
|
+
const page = pages[i];
|
|
4244
|
+
if (i > 0) {
|
|
4245
|
+
await new Promise((resolve) => globalThis.setTimeout(resolve, 100));
|
|
4246
|
+
}
|
|
4247
|
+
try {
|
|
4248
|
+
const versions = await this.getPageVersionHistory(page.id);
|
|
4249
|
+
const userVersions = versions.filter(
|
|
4250
|
+
(v) => this.isMatchingUser(v.by, userIdentifier) && new Date(v.when) >= sinceDate
|
|
4251
|
+
);
|
|
4252
|
+
const userCommentsInRange = page.children?.comment?.results?.filter(
|
|
4253
|
+
(comment) => this.isMatchingUser(comment.version?.by || {}, userIdentifier) && new Date(comment.version?.when || 0) >= sinceDate
|
|
4254
|
+
) || [];
|
|
4255
|
+
if (userVersions.length > 0 || userCommentsInRange.length > 0) {
|
|
4256
|
+
results.push({ page, userVersions });
|
|
4257
|
+
} else {
|
|
4258
|
+
logger.debug(`Excluding page "${page.title}" - no user contributions in date range`);
|
|
4259
|
+
}
|
|
4260
|
+
} catch (error) {
|
|
4261
|
+
logger.debug(`Skipping version history for page ${page.id}: ${error}`);
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
return results;
|
|
4265
|
+
}
|
|
4097
4266
|
/**
|
|
4098
4267
|
* Build CQL query from options
|
|
4099
4268
|
* Returns empty string if no filters need CQL (will use simple endpoint instead)
|
|
@@ -4129,28 +4298,31 @@ var ConfluenceService = class {
|
|
|
4129
4298
|
* Determine the type of contribution the current user made to a page
|
|
4130
4299
|
* Returns: 'created' | 'edited' | 'commented'
|
|
4131
4300
|
*/
|
|
4132
|
-
async determineContributionType(page, userEmail) {
|
|
4133
|
-
|
|
4301
|
+
async determineContributionType(page, userEmail, userVersions) {
|
|
4302
|
+
const createdByUser = page.history?.createdBy ? this.isMatchingUser(page.history.createdBy, userEmail) : false;
|
|
4303
|
+
if (createdByUser) {
|
|
4134
4304
|
return {
|
|
4135
4305
|
type: "created",
|
|
4136
4306
|
details: `Created page with ${page.version?.number || 1} version${(page.version?.number || 1) > 1 ? "s" : ""}`
|
|
4137
4307
|
};
|
|
4138
4308
|
}
|
|
4139
|
-
const hasEdits = page.version?.by
|
|
4309
|
+
const hasEdits = userVersions ? userVersions.some((v) => !v.minorEdit || v.number > 1) : page.version?.by ? this.isMatchingUser(page.version.by, userEmail) && (page.version?.number || 0) > 1 : false;
|
|
4140
4310
|
const userComments = page.children?.comment?.results?.filter(
|
|
4141
|
-
(comment) => comment.version?.by
|
|
4311
|
+
(comment) => comment.version?.by ? this.isMatchingUser(comment.version.by, userEmail) : false
|
|
4142
4312
|
) || [];
|
|
4143
4313
|
const hasComments = userComments.length > 0;
|
|
4144
4314
|
if (hasEdits && hasComments) {
|
|
4315
|
+
const editCount = userVersions?.length || 1;
|
|
4145
4316
|
return {
|
|
4146
4317
|
type: "edited",
|
|
4147
|
-
details: `Edited page (
|
|
4318
|
+
details: `Edited page (${editCount} edit${editCount > 1 ? "s" : ""}) and added ${userComments.length} comment${userComments.length > 1 ? "s" : ""}`
|
|
4148
4319
|
};
|
|
4149
4320
|
}
|
|
4150
4321
|
if (hasEdits) {
|
|
4322
|
+
const editCount = userVersions?.length || 1;
|
|
4151
4323
|
return {
|
|
4152
4324
|
type: "edited",
|
|
4153
|
-
details: `Edited page
|
|
4325
|
+
details: `Edited page (${editCount} edit${editCount > 1 ? "s" : ""})`
|
|
4154
4326
|
};
|
|
4155
4327
|
}
|
|
4156
4328
|
if (hasComments) {
|
|
@@ -4178,6 +4350,31 @@ var ConfluenceService = class {
|
|
|
4178
4350
|
};
|
|
4179
4351
|
return Math.ceil(baseSize * multipliers[contributionType]);
|
|
4180
4352
|
}
|
|
4353
|
+
/**
|
|
4354
|
+
* Summarize the user's version edits into human-readable lines.
|
|
4355
|
+
* This enriches the brag message so the AI refinement can generate a more specific brag.
|
|
4356
|
+
*/
|
|
4357
|
+
summarizeUserVersions(userVersions) {
|
|
4358
|
+
const MAX_ENTRIES = 5;
|
|
4359
|
+
const versionsWithMessages = userVersions.filter((v) => v.message && v.message.trim());
|
|
4360
|
+
if (versionsWithMessages.length > 0) {
|
|
4361
|
+
const lines = versionsWithMessages.slice(0, MAX_ENTRIES).map((v) => {
|
|
4362
|
+
const suffix = v.minorEdit ? " (minor edit)" : "";
|
|
4363
|
+
return `- v${v.number}: ${v.message.trim()}${suffix}`;
|
|
4364
|
+
});
|
|
4365
|
+
return `Edit notes:
|
|
4366
|
+
${lines.join("\n")}`;
|
|
4367
|
+
}
|
|
4368
|
+
if (userVersions.length > 0) {
|
|
4369
|
+
const major = userVersions.filter((v) => !v.minorEdit).length;
|
|
4370
|
+
const minor = userVersions.filter((v) => v.minorEdit).length;
|
|
4371
|
+
const parts = [];
|
|
4372
|
+
if (major > 0) parts.push(`${major} major`);
|
|
4373
|
+
if (minor > 0) parts.push(`${minor} minor`);
|
|
4374
|
+
return `Made ${userVersions.length} edit${userVersions.length > 1 ? "s" : ""} to this page (${parts.join(", ")})`;
|
|
4375
|
+
}
|
|
4376
|
+
return "";
|
|
4377
|
+
}
|
|
4181
4378
|
/**
|
|
4182
4379
|
* Fetch pages with optional filtering
|
|
4183
4380
|
*/
|
|
@@ -4248,14 +4445,7 @@ var ConfluenceService = class {
|
|
|
4248
4445
|
break;
|
|
4249
4446
|
}
|
|
4250
4447
|
if (options.limit && allPages.length >= options.limit) {
|
|
4251
|
-
|
|
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;
|
|
4448
|
+
break;
|
|
4259
4449
|
}
|
|
4260
4450
|
start += limit;
|
|
4261
4451
|
} catch (error) {
|
|
@@ -4279,9 +4469,23 @@ var ConfluenceService = class {
|
|
|
4279
4469
|
throw error;
|
|
4280
4470
|
}
|
|
4281
4471
|
}
|
|
4472
|
+
const pagesToProcess = options.limit ? allPages.slice(0, options.limit) : allPages;
|
|
4282
4473
|
const email = await this.getCurrentUser();
|
|
4474
|
+
const sinceDate = options.days ? new Date(Date.now() - options.days * 24 * 60 * 60 * 1e3) : void 0;
|
|
4475
|
+
if (sinceDate && email) {
|
|
4476
|
+
const filtered = await this.filterPagesByUserContribution(pagesToProcess, email, sinceDate);
|
|
4477
|
+
logger.debug(
|
|
4478
|
+
`Date-scoped filtering: ${pagesToProcess.length} pages -> ${filtered.length} with user contributions in range`
|
|
4479
|
+
);
|
|
4480
|
+
const commits2 = [];
|
|
4481
|
+
for (const { page, userVersions } of filtered) {
|
|
4482
|
+
const commit = await this.transformPageToCommit(page, void 0, email, userVersions);
|
|
4483
|
+
commits2.push(commit);
|
|
4484
|
+
}
|
|
4485
|
+
return commits2;
|
|
4486
|
+
}
|
|
4283
4487
|
const commits = [];
|
|
4284
|
-
for (const page of
|
|
4488
|
+
for (const page of pagesToProcess) {
|
|
4285
4489
|
const commit = await this.transformPageToCommit(page, void 0, email || void 0);
|
|
4286
4490
|
commits.push(commit);
|
|
4287
4491
|
}
|
|
@@ -4303,10 +4507,10 @@ var ConfluenceService = class {
|
|
|
4303
4507
|
/**
|
|
4304
4508
|
* Transform Confluence page to GitCommit format with contribution-specific data
|
|
4305
4509
|
*/
|
|
4306
|
-
async transformPageToCommit(page, instanceUrl, userEmail) {
|
|
4510
|
+
async transformPageToCommit(page, instanceUrl, userEmail, userVersions) {
|
|
4307
4511
|
let contribution = null;
|
|
4308
4512
|
if (userEmail) {
|
|
4309
|
-
contribution = await this.determineContributionType(page, userEmail);
|
|
4513
|
+
contribution = await this.determineContributionType(page, userEmail, userVersions);
|
|
4310
4514
|
}
|
|
4311
4515
|
let message;
|
|
4312
4516
|
let contributionPrefix = "";
|
|
@@ -4327,6 +4531,14 @@ ${contribution.details}
|
|
|
4327
4531
|
|
|
4328
4532
|
[Confluence Page v${page.version?.number || 1}]`;
|
|
4329
4533
|
}
|
|
4534
|
+
if (userVersions && userVersions.length > 0) {
|
|
4535
|
+
const versionSummary = this.summarizeUserVersions(userVersions);
|
|
4536
|
+
if (versionSummary) {
|
|
4537
|
+
message += `
|
|
4538
|
+
|
|
4539
|
+
${versionSummary}`;
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4330
4542
|
let baseUrl = "https://confluence.atlassian.net";
|
|
4331
4543
|
if (instanceUrl) {
|
|
4332
4544
|
baseUrl = instanceUrl.startsWith("http") ? instanceUrl : `https://${instanceUrl}`;
|
|
@@ -4344,7 +4556,14 @@ ${contribution.details}
|
|
|
4344
4556
|
const impactScore = contribution ? this.calculateContributionImpact(contribution.type, baseSize) : baseSize;
|
|
4345
4557
|
const author = page.history?.createdBy?.displayName || page.version?.by?.displayName || "Unknown Author";
|
|
4346
4558
|
const authorEmail = page.history?.createdBy?.email || page.version?.by?.email || "unknown@example.com";
|
|
4347
|
-
|
|
4559
|
+
let date;
|
|
4560
|
+
if (contribution?.type === "created") {
|
|
4561
|
+
date = page.history?.createdDate || page.version?.when;
|
|
4562
|
+
} else if (userVersions && userVersions.length > 0) {
|
|
4563
|
+
date = userVersions[userVersions.length - 1].when;
|
|
4564
|
+
} else {
|
|
4565
|
+
date = page.version?.when || (/* @__PURE__ */ new Date()).toISOString();
|
|
4566
|
+
}
|
|
4348
4567
|
return {
|
|
4349
4568
|
sha: page.id,
|
|
4350
4569
|
message,
|
|
@@ -5917,9 +6136,17 @@ async function syncAllAuthenticatedServices(options) {
|
|
|
5917
6136
|
);
|
|
5918
6137
|
for (const result of successful) {
|
|
5919
6138
|
const serviceLabel = result.service.charAt(0).toUpperCase() + result.service.slice(1);
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
6139
|
+
if (result.created === 0 && result.skipped > 0) {
|
|
6140
|
+
logger.info(
|
|
6141
|
+
` \u2022 ${serviceLabel}: ${colors.dim(`All ${result.skipped} item${result.skipped !== 1 ? "s" : ""} already synced`)}`
|
|
6142
|
+
);
|
|
6143
|
+
} else if (result.created === 0 && result.skipped === 0) {
|
|
6144
|
+
logger.info(` \u2022 ${serviceLabel}: ${colors.dim("No items found")}`);
|
|
6145
|
+
} else {
|
|
6146
|
+
logger.info(
|
|
6147
|
+
` \u2022 ${serviceLabel}: ${result.created} brag${result.created !== 1 ? "s" : ""} created${result.skipped > 0 ? `, ${result.skipped} skipped` : ""}`
|
|
6148
|
+
);
|
|
6149
|
+
}
|
|
5923
6150
|
}
|
|
5924
6151
|
logger.log("");
|
|
5925
6152
|
}
|