@bretwardjames/ghp-core 0.7.1 → 0.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/dist/index.cjs CHANGED
@@ -1908,6 +1908,7 @@ var GitHubAPI = class {
1908
1908
  */
1909
1909
  async getRecentActivity(repo, since, options) {
1910
1910
  if (!this.graphqlWithAuth) throw new Error("Not authenticated");
1911
+ const filterUser = options?.user || (options?.mine ? this.username : null);
1911
1912
  const projects = await this.getProjects(repo);
1912
1913
  if (projects.length === 0) return [];
1913
1914
  const allItems = [];
@@ -1921,9 +1922,9 @@ var GitHubAPI = class {
1921
1922
  let recentItems = allItems.filter(
1922
1923
  (item) => item.updatedAt && new Date(item.updatedAt).getTime() >= sinceMs
1923
1924
  );
1924
- if (options?.mine && this.username) {
1925
+ if (filterUser) {
1925
1926
  recentItems = recentItems.filter(
1926
- (item) => item.assignees.includes(this.username)
1927
+ (item) => item.assignees.includes(filterUser)
1927
1928
  );
1928
1929
  }
1929
1930
  const seen = /* @__PURE__ */ new Set();
@@ -1968,10 +1969,11 @@ var GitHubAPI = class {
1968
1969
  }
1969
1970
  }
1970
1971
  const activityNumbers = new Set(activities.map((a) => a.issue.number));
1971
- if (this.username) {
1972
+ const prSearchUser = filterUser || this.username;
1973
+ if (prSearchUser) {
1972
1974
  const reviewActivities = await this.fetchReviewedPRs(
1973
1975
  repo,
1974
- this.username,
1976
+ prSearchUser,
1975
1977
  sinceDate,
1976
1978
  sinceMs,
1977
1979
  activityNumbers
@@ -1980,11 +1982,9 @@ var GitHubAPI = class {
1980
1982
  activityNumbers.add(a.issue.number);
1981
1983
  activities.push(a);
1982
1984
  }
1983
- }
1984
- if (this.username) {
1985
1985
  const authoredActivities = await this.fetchAuthoredPRs(
1986
1986
  repo,
1987
- this.username,
1987
+ prSearchUser,
1988
1988
  sinceDate,
1989
1989
  sinceMs,
1990
1990
  activityNumbers
@@ -4244,6 +4244,12 @@ function validateUrl(url) {
4244
4244
 
4245
4245
  // src/standup.ts
4246
4246
  function formatStandupText(activities, options) {
4247
+ if (options.timeline) {
4248
+ return formatTimeline(activities, options);
4249
+ }
4250
+ return formatGrouped(activities, options);
4251
+ }
4252
+ function formatGrouped(activities, options) {
4247
4253
  const { since } = options;
4248
4254
  const lines = [];
4249
4255
  const sinceStr = formatRelativeDate(since);
@@ -4264,6 +4270,35 @@ function formatStandupText(activities, options) {
4264
4270
  }
4265
4271
  return lines.join("\n").trimEnd();
4266
4272
  }
4273
+ function formatTimeline(activities, options) {
4274
+ const { since } = options;
4275
+ const lines = [];
4276
+ const allEvents = [];
4277
+ for (const activity of activities) {
4278
+ for (const event of activity.changes) {
4279
+ allEvents.push({ event, issue: activity.issue });
4280
+ }
4281
+ }
4282
+ allEvents.sort(
4283
+ (a, b) => new Date(b.event.timestamp).getTime() - new Date(a.event.timestamp).getTime()
4284
+ );
4285
+ const sinceStr = formatRelativeDate(since);
4286
+ const eventCount = allEvents.length;
4287
+ const issueCount = activities.length;
4288
+ lines.push(`Since ${sinceStr} \u2014 ${eventCount} event${eventCount !== 1 ? "s" : ""} across ${issueCount} issue${issueCount !== 1 ? "s" : ""}`);
4289
+ lines.push("");
4290
+ if (allEvents.length === 0) {
4291
+ lines.push("No activity found in this time window.");
4292
+ return lines.join("\n");
4293
+ }
4294
+ for (const { event, issue } of allEvents) {
4295
+ const time = formatShortTimestamp(event.timestamp);
4296
+ const desc = formatEventDescription(event);
4297
+ const issueRef = `#${issue.number} ${truncate(issue.title, 50)}`;
4298
+ lines.push(`${time} ${desc} (${issueRef})`);
4299
+ }
4300
+ return lines.join("\n").trimEnd();
4301
+ }
4267
4302
  function parseSince(input) {
4268
4303
  const isoDate = new Date(input);
4269
4304
  if (!isNaN(isoDate.getTime()) && input.includes("-")) {
@@ -4320,6 +4355,41 @@ function formatEventLine(event) {
4320
4355
  return `${arrow} ${event.type} by ${actor} (${timestamp})`;
4321
4356
  }
4322
4357
  }
4358
+ function formatEventDescription(event) {
4359
+ const actor = event.actor;
4360
+ switch (event.type) {
4361
+ case "comment":
4362
+ return `Comment by ${actor}${event.details ? ": " + event.details : ""}`;
4363
+ case "labeled":
4364
+ return `Labeled "${event.details}" by ${actor}`;
4365
+ case "unlabeled":
4366
+ return `Unlabeled "${event.details}" by ${actor}`;
4367
+ case "assigned":
4368
+ return `Assigned to ${event.details || actor}`;
4369
+ case "unassigned":
4370
+ return `Unassigned ${event.details || ""} by ${actor}`;
4371
+ case "closed":
4372
+ return `Closed by ${actor}`;
4373
+ case "reopened":
4374
+ return `Reopened by ${actor}`;
4375
+ case "referenced":
4376
+ return `${event.details} linked by ${actor}`;
4377
+ case "review_submitted":
4378
+ return `${event.details} by ${actor}`;
4379
+ case "review_requested":
4380
+ return `Review requested from ${event.details || "team"} by ${actor}`;
4381
+ case "pr_created":
4382
+ return `PR created by ${actor}`;
4383
+ case "pr_merged":
4384
+ return `PR merged by ${actor}`;
4385
+ default:
4386
+ return `${event.type} by ${actor}`;
4387
+ }
4388
+ }
4389
+ function truncate(str, maxLen) {
4390
+ if (str.length <= maxLen) return str;
4391
+ return str.slice(0, maxLen - 1) + "\u2026";
4392
+ }
4323
4393
  function formatRelativeDate(date) {
4324
4394
  const now = /* @__PURE__ */ new Date();
4325
4395
  const diffMs = now.getTime() - date.getTime();
package/dist/index.d.cts CHANGED
@@ -691,6 +691,7 @@ declare class GitHubAPI {
691
691
  */
692
692
  getRecentActivity(repo: RepoInfo, since: Date, options?: {
693
693
  mine?: boolean;
694
+ user?: string;
694
695
  }): Promise<IssueActivity[]>;
695
696
  /**
696
697
  * Search for PRs the user reviewed that aren't already in the activity list.
@@ -2283,6 +2284,8 @@ declare function validateUrl(url: string): string;
2283
2284
  interface FormatStandupOptions {
2284
2285
  since: Date;
2285
2286
  colorize?: boolean;
2287
+ /** If true, show a flat chronological timeline instead of grouping by issue */
2288
+ timeline?: boolean;
2286
2289
  }
2287
2290
  /**
2288
2291
  * Format a standup summary as human-readable text.
package/dist/index.d.ts CHANGED
@@ -691,6 +691,7 @@ declare class GitHubAPI {
691
691
  */
692
692
  getRecentActivity(repo: RepoInfo, since: Date, options?: {
693
693
  mine?: boolean;
694
+ user?: string;
694
695
  }): Promise<IssueActivity[]>;
695
696
  /**
696
697
  * Search for PRs the user reviewed that aren't already in the activity list.
@@ -2283,6 +2284,8 @@ declare function validateUrl(url: string): string;
2283
2284
  interface FormatStandupOptions {
2284
2285
  since: Date;
2285
2286
  colorize?: boolean;
2287
+ /** If true, show a flat chronological timeline instead of grouping by issue */
2288
+ timeline?: boolean;
2286
2289
  }
2287
2290
  /**
2288
2291
  * Format a standup summary as human-readable text.
package/dist/index.js CHANGED
@@ -1739,6 +1739,7 @@ var GitHubAPI = class {
1739
1739
  */
1740
1740
  async getRecentActivity(repo, since, options) {
1741
1741
  if (!this.graphqlWithAuth) throw new Error("Not authenticated");
1742
+ const filterUser = options?.user || (options?.mine ? this.username : null);
1742
1743
  const projects = await this.getProjects(repo);
1743
1744
  if (projects.length === 0) return [];
1744
1745
  const allItems = [];
@@ -1752,9 +1753,9 @@ var GitHubAPI = class {
1752
1753
  let recentItems = allItems.filter(
1753
1754
  (item) => item.updatedAt && new Date(item.updatedAt).getTime() >= sinceMs
1754
1755
  );
1755
- if (options?.mine && this.username) {
1756
+ if (filterUser) {
1756
1757
  recentItems = recentItems.filter(
1757
- (item) => item.assignees.includes(this.username)
1758
+ (item) => item.assignees.includes(filterUser)
1758
1759
  );
1759
1760
  }
1760
1761
  const seen = /* @__PURE__ */ new Set();
@@ -1799,10 +1800,11 @@ var GitHubAPI = class {
1799
1800
  }
1800
1801
  }
1801
1802
  const activityNumbers = new Set(activities.map((a) => a.issue.number));
1802
- if (this.username) {
1803
+ const prSearchUser = filterUser || this.username;
1804
+ if (prSearchUser) {
1803
1805
  const reviewActivities = await this.fetchReviewedPRs(
1804
1806
  repo,
1805
- this.username,
1807
+ prSearchUser,
1806
1808
  sinceDate,
1807
1809
  sinceMs,
1808
1810
  activityNumbers
@@ -1811,11 +1813,9 @@ var GitHubAPI = class {
1811
1813
  activityNumbers.add(a.issue.number);
1812
1814
  activities.push(a);
1813
1815
  }
1814
- }
1815
- if (this.username) {
1816
1816
  const authoredActivities = await this.fetchAuthoredPRs(
1817
1817
  repo,
1818
- this.username,
1818
+ prSearchUser,
1819
1819
  sinceDate,
1820
1820
  sinceMs,
1821
1821
  activityNumbers
@@ -4075,6 +4075,12 @@ function validateUrl(url) {
4075
4075
 
4076
4076
  // src/standup.ts
4077
4077
  function formatStandupText(activities, options) {
4078
+ if (options.timeline) {
4079
+ return formatTimeline(activities, options);
4080
+ }
4081
+ return formatGrouped(activities, options);
4082
+ }
4083
+ function formatGrouped(activities, options) {
4078
4084
  const { since } = options;
4079
4085
  const lines = [];
4080
4086
  const sinceStr = formatRelativeDate(since);
@@ -4095,6 +4101,35 @@ function formatStandupText(activities, options) {
4095
4101
  }
4096
4102
  return lines.join("\n").trimEnd();
4097
4103
  }
4104
+ function formatTimeline(activities, options) {
4105
+ const { since } = options;
4106
+ const lines = [];
4107
+ const allEvents = [];
4108
+ for (const activity of activities) {
4109
+ for (const event of activity.changes) {
4110
+ allEvents.push({ event, issue: activity.issue });
4111
+ }
4112
+ }
4113
+ allEvents.sort(
4114
+ (a, b) => new Date(b.event.timestamp).getTime() - new Date(a.event.timestamp).getTime()
4115
+ );
4116
+ const sinceStr = formatRelativeDate(since);
4117
+ const eventCount = allEvents.length;
4118
+ const issueCount = activities.length;
4119
+ lines.push(`Since ${sinceStr} \u2014 ${eventCount} event${eventCount !== 1 ? "s" : ""} across ${issueCount} issue${issueCount !== 1 ? "s" : ""}`);
4120
+ lines.push("");
4121
+ if (allEvents.length === 0) {
4122
+ lines.push("No activity found in this time window.");
4123
+ return lines.join("\n");
4124
+ }
4125
+ for (const { event, issue } of allEvents) {
4126
+ const time = formatShortTimestamp(event.timestamp);
4127
+ const desc = formatEventDescription(event);
4128
+ const issueRef = `#${issue.number} ${truncate(issue.title, 50)}`;
4129
+ lines.push(`${time} ${desc} (${issueRef})`);
4130
+ }
4131
+ return lines.join("\n").trimEnd();
4132
+ }
4098
4133
  function parseSince(input) {
4099
4134
  const isoDate = new Date(input);
4100
4135
  if (!isNaN(isoDate.getTime()) && input.includes("-")) {
@@ -4151,6 +4186,41 @@ function formatEventLine(event) {
4151
4186
  return `${arrow} ${event.type} by ${actor} (${timestamp})`;
4152
4187
  }
4153
4188
  }
4189
+ function formatEventDescription(event) {
4190
+ const actor = event.actor;
4191
+ switch (event.type) {
4192
+ case "comment":
4193
+ return `Comment by ${actor}${event.details ? ": " + event.details : ""}`;
4194
+ case "labeled":
4195
+ return `Labeled "${event.details}" by ${actor}`;
4196
+ case "unlabeled":
4197
+ return `Unlabeled "${event.details}" by ${actor}`;
4198
+ case "assigned":
4199
+ return `Assigned to ${event.details || actor}`;
4200
+ case "unassigned":
4201
+ return `Unassigned ${event.details || ""} by ${actor}`;
4202
+ case "closed":
4203
+ return `Closed by ${actor}`;
4204
+ case "reopened":
4205
+ return `Reopened by ${actor}`;
4206
+ case "referenced":
4207
+ return `${event.details} linked by ${actor}`;
4208
+ case "review_submitted":
4209
+ return `${event.details} by ${actor}`;
4210
+ case "review_requested":
4211
+ return `Review requested from ${event.details || "team"} by ${actor}`;
4212
+ case "pr_created":
4213
+ return `PR created by ${actor}`;
4214
+ case "pr_merged":
4215
+ return `PR merged by ${actor}`;
4216
+ default:
4217
+ return `${event.type} by ${actor}`;
4218
+ }
4219
+ }
4220
+ function truncate(str, maxLen) {
4221
+ if (str.length <= maxLen) return str;
4222
+ return str.slice(0, maxLen - 1) + "\u2026";
4223
+ }
4154
4224
  function formatRelativeDate(date) {
4155
4225
  const now = /* @__PURE__ */ new Date();
4156
4226
  const diffMs = now.getTime() - date.getTime();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bretwardjames/ghp-core",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Shared core library for GitHub Projects tools",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",