@stoked-ui/github 0.0.0-a.0 → 0.1.0-alpha.11.2

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 (87) hide show
  1. package/GithubBranch/GithubBranch.d.ts +12 -0
  2. package/GithubBranch/GithubBranch.js +177 -0
  3. package/GithubBranch/index.d.ts +2 -0
  4. package/GithubBranch/index.js +2 -0
  5. package/GithubBranch/package.json +6 -0
  6. package/GithubCalendar/GithubCalendar.d.ts +6 -2
  7. package/GithubCalendar/GithubCalendar.js +70 -28
  8. package/GithubCommit/GithubCommit.d.ts +11 -0
  9. package/GithubCommit/GithubCommit.js +170 -0
  10. package/GithubCommit/index.d.ts +2 -0
  11. package/GithubCommit/index.js +2 -0
  12. package/GithubCommit/package.json +6 -0
  13. package/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +1 -1
  14. package/GithubEvents/GithubEvents.d.ts +4 -24
  15. package/GithubEvents/GithubEvents.js +141 -220
  16. package/apiHandlers/createGithubBranchHandler.d.ts +12 -0
  17. package/apiHandlers/createGithubBranchHandler.js +41 -0
  18. package/apiHandlers/createGithubCommitHandler.d.ts +12 -0
  19. package/apiHandlers/createGithubCommitHandler.js +39 -0
  20. package/apiHandlers/createGithubContributionsHandler.d.ts +15 -0
  21. package/apiHandlers/createGithubContributionsHandler.js +41 -0
  22. package/apiHandlers/createGithubEventsHandler.d.ts +15 -0
  23. package/apiHandlers/createGithubEventsHandler.js +50 -0
  24. package/apiHandlers/getBranchCompareDetails.d.ts +9 -0
  25. package/apiHandlers/getBranchCompareDetails.js +29 -0
  26. package/apiHandlers/getCommitDetails.d.ts +8 -0
  27. package/apiHandlers/getCommitDetails.js +34 -0
  28. package/apiHandlers/getGithubContributions.d.ts +8 -0
  29. package/apiHandlers/getGithubContributions.js +126 -0
  30. package/apiHandlers/getGithubEvents.d.ts +25 -0
  31. package/apiHandlers/getGithubEvents.js +142 -0
  32. package/apiHandlers/getPullRequestDetails.js +2 -2
  33. package/apiHandlers/githubApi.d.ts +17 -0
  34. package/apiHandlers/githubApi.js +155 -0
  35. package/apiHandlers/index.d.ts +9 -0
  36. package/apiHandlers/index.js +9 -1
  37. package/components/GithubContributorsList.d.ts +8 -0
  38. package/components/GithubContributorsList.js +72 -0
  39. package/components/fetchGithubViewData.d.ts +1 -0
  40. package/components/fetchGithubViewData.js +10 -0
  41. package/index.d.ts +7 -3
  42. package/index.js +6 -4
  43. package/modern/GithubBranch/GithubBranch.js +177 -0
  44. package/modern/GithubBranch/index.js +2 -0
  45. package/modern/GithubCalendar/GithubCalendar.js +70 -28
  46. package/modern/GithubCommit/GithubCommit.js +170 -0
  47. package/modern/GithubCommit/index.js +2 -0
  48. package/modern/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +1 -1
  49. package/modern/GithubEvents/GithubEvents.js +141 -220
  50. package/modern/apiHandlers/createGithubBranchHandler.js +41 -0
  51. package/modern/apiHandlers/createGithubCommitHandler.js +39 -0
  52. package/modern/apiHandlers/createGithubContributionsHandler.js +41 -0
  53. package/modern/apiHandlers/createGithubEventsHandler.js +50 -0
  54. package/modern/apiHandlers/getBranchCompareDetails.js +29 -0
  55. package/modern/apiHandlers/getCommitDetails.js +34 -0
  56. package/modern/apiHandlers/getGithubContributions.js +126 -0
  57. package/modern/apiHandlers/getGithubEvents.js +142 -0
  58. package/modern/apiHandlers/getPullRequestDetails.js +2 -2
  59. package/modern/apiHandlers/githubApi.js +155 -0
  60. package/modern/apiHandlers/index.js +9 -1
  61. package/modern/components/GithubContributorsList.js +72 -0
  62. package/modern/components/fetchGithubViewData.js +10 -0
  63. package/modern/index.js +6 -4
  64. package/node/GithubBranch/GithubBranch.js +185 -0
  65. package/node/GithubBranch/index.js +9 -0
  66. package/node/GithubCalendar/GithubCalendar.js +70 -28
  67. package/node/GithubCommit/GithubCommit.js +178 -0
  68. package/node/GithubCommit/index.js +9 -0
  69. package/node/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +1 -1
  70. package/node/GithubEvents/GithubEvents.js +148 -223
  71. package/node/apiHandlers/createGithubBranchHandler.js +48 -0
  72. package/node/apiHandlers/createGithubCommitHandler.js +46 -0
  73. package/node/apiHandlers/createGithubContributionsHandler.js +48 -0
  74. package/node/apiHandlers/createGithubEventsHandler.js +57 -0
  75. package/node/apiHandlers/getBranchCompareDetails.js +35 -0
  76. package/node/apiHandlers/getCommitDetails.js +40 -0
  77. package/node/apiHandlers/getGithubContributions.js +132 -0
  78. package/node/apiHandlers/getGithubEvents.js +149 -0
  79. package/node/apiHandlers/getPullRequestDetails.js +2 -2
  80. package/node/apiHandlers/githubApi.js +168 -0
  81. package/node/apiHandlers/index.js +64 -1
  82. package/node/components/GithubContributorsList.js +80 -0
  83. package/node/components/fetchGithubViewData.js +16 -0
  84. package/node/index.js +77 -2
  85. package/package.json +2 -5
  86. package/stoked-ui-github-0.1.0-alpha.11.2.tgz +0 -0
  87. package/types/github.d.ts +75 -11
@@ -6,7 +6,12 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.ErrorDetails = ErrorDetails;
8
8
  exports.default = GithubEvents;
9
- exports.githubEventsQuery = githubEventsQuery;
9
+ Object.defineProperty(exports, "githubEventsQuery", {
10
+ enumerable: true,
11
+ get: function () {
12
+ return _getGithubEvents.githubEventsQuery;
13
+ }
14
+ });
10
15
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
16
  var React = _interopRequireWildcard(require("react"));
12
17
  var _requestError = require("@octokit/request-error");
@@ -29,24 +34,17 @@ var _dateFnsTz = require("date-fns-tz");
29
34
  var _styles = require("@mui/material/styles");
30
35
  var _Autocomplete = _interopRequireDefault(require("@mui/material/Autocomplete"));
31
36
  var _Pagination = _interopRequireDefault(require("@mui/material/Pagination"));
32
- var _dynamic = _interopRequireDefault(require("next/dynamic"));
33
37
  var _PullRequestEvent = _interopRequireDefault(require("./EventTypes/PullRequest/PullRequestEvent"));
34
38
  var _PushEvent = _interopRequireDefault(require("./EventTypes/PushEvent"));
35
39
  var _DeleteEvent = _interopRequireDefault(require("./EventTypes/DeleteEvent"));
36
40
  var _CreateEvent = _interopRequireDefault(require("./EventTypes/CreateEvent"));
37
41
  var _IssuesEvent = _interopRequireDefault(require("./EventTypes/IssuesEvent"));
38
42
  var _IssueCommentEvent = _interopRequireDefault(require("./EventTypes/IssueCommentEvent"));
43
+ var _getGithubEvents = require("../apiHandlers/getGithubEvents");
39
44
  var _Chip2 = _interopRequireDefault(require("@mui/material/Chip"));
40
45
  var _jsxRuntime = require("react/jsx-runtime");
41
- var _div, _Chip, _SmalMi, _SmalMi2, _SmalMi3, _SmalMi4, _SmalMi5, _TableRow, _TableRow2;
42
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } // Extend the EventDetails interface for internal component use
43
- // Import react-json-view dynamically to avoid SSR issues
44
- const ReactJson = (0, _dynamic.default)(() => Promise.resolve().then(() => _interopRequireWildcard(require('react-json-view'))), {
45
- ssr: false,
46
- loading: () => _div || (_div = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
47
- children: "Loading JSON viewer..."
48
- }))
49
- });
46
+ var _Chip, _SmalMi, _SmalMi2, _SmalMi3, _SmalMi4, _SmalMi5, _TableRow, _TableRow2; // Extend the EventDetails interface for internal component use
47
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
50
48
  const MetadataDisplay = (0, _styles.styled)(_Box.default)(({
51
49
  theme
52
50
  }) => {
@@ -64,176 +62,111 @@ const MetadataDisplay = (0, _styles.styled)(_Box.default)(({
64
62
  overflow: 'auto'
65
63
  };
66
64
  });
67
- function parseLinkHeader(header) {
68
- if (!header) return {};
69
- return header.split(',').reduce((links, part) => {
70
- const match = part.match(/<(.+)>;\s*rel="([\w]+)"/);
71
- if (match) {
72
- const [, url, rel] = match;
73
- if (rel === 'next' || rel === 'last') {
74
- links[rel] = url;
75
- }
76
- }
77
- return links;
78
- }, {});
65
+ const CACHE_PERSIST_LIMITS = [200, 150, 100, 50, 25];
66
+ function isStorageQuotaError(error) {
67
+ return error instanceof DOMException && (error.name === 'QuotaExceededError' || error.name === 'NS_ERROR_DOM_QUOTA_REACHED');
79
68
  }
80
- async function githubEventsQuery({
81
- query,
82
- githubUser,
83
- githubToken
84
- }) {
69
+ function getStorageItem(storage, key) {
85
70
  try {
86
- const {
87
- page = query.page || 1,
88
- per_page = query.per_page || 100,
89
- // Default to 100 per page to minimize API calls
90
- repo,
91
- action,
92
- date,
93
- description
94
- } = query;
95
- const queryParams = new URLSearchParams((0, _extends2.default)({
96
- page: String(page),
97
- per_page: String(per_page)
98
- }, repo && {
99
- repo
100
- }, action && {
101
- action
102
- }, date && {
103
- date
104
- }, description && {
105
- description
106
- }));
107
-
108
- // Get GitHub token from environment variables
109
- console.log(`Fetching events for user: ${githubUser}, page: ${page}, per_page: ${per_page}`);
110
-
111
- // Fetch all available pages from GitHub API
112
- let allEvents = [];
113
- let hasMore = true;
114
- let githubPage = 1;
115
- const maxPages = 30; // GitHub's maximum for events endpoint
116
-
117
- while (hasMore && githubPage <= maxPages) {
118
- console.log(`Fetching page ${githubPage}...`);
119
- const fetchOptions = {
120
- headers: {
121
- 'User-Agent': 'brianstoker.com-website'
122
- }
123
- };
124
- if (githubToken) {
125
- fetchOptions.headers.Authorization = `token ${githubToken}`;
126
- }
127
- const response = await fetch(`https://api.github.com/users/${githubUser}/events?${queryParams}`, fetchOptions);
128
- if (!response.ok) {
129
- const errorText = await response.text();
130
- console.error(`GitHub API error: ${response.status}`, errorText);
131
- throw new Error(`GitHub API error: ${response.status} - ${errorText}`);
132
- }
133
- const data = await response.json();
134
- console.log(`Page ${githubPage}: Received ${data.length} events`);
135
- if (data.length === 0) {
136
- hasMore = false;
137
- } else {
138
- allEvents = [...allEvents, ...data];
139
- console.log(`Total events so far: ${allEvents.length}`);
140
-
141
- // Check Link header to see if there are more pages
142
- const linkHeader = response.headers.get('Link');
143
- const links = parseLinkHeader(linkHeader);
144
- hasMore = !!links.next; // Simplified logic
145
-
146
- githubPage++;
147
- }
148
- }
149
- console.log(`Final total events: ${allEvents.length}`);
150
-
151
- // Apply filters
152
- let filteredEvents = allEvents;
153
- if (repo) {
154
- filteredEvents = filteredEvents.filter(event => event.repo.name === repo);
155
- }
156
- if (action) {
157
- filteredEvents = filteredEvents.filter(event => {
158
- const eventAction = event.type.replace('Event', '');
159
- return eventAction === action;
160
- });
161
- }
162
- if (date) {
163
- const now = new Date();
164
- let cutoffDate;
165
- switch (date) {
166
- case 'today':
167
- cutoffDate = new Date(now.setHours(0, 0, 0, 0));
168
- break;
169
- case 'yesterday':
170
- cutoffDate = new Date(now);
171
- cutoffDate.setDate(cutoffDate.getDate() - 1);
172
- cutoffDate.setHours(0, 0, 0, 0);
173
- break;
174
- case 'week':
175
- cutoffDate = new Date(now);
176
- cutoffDate.setDate(cutoffDate.getDate() - 7);
177
- cutoffDate.setHours(0, 0, 0, 0);
178
- break;
179
- case 'month':
180
- cutoffDate = new Date(now);
181
- cutoffDate.setMonth(cutoffDate.getMonth() - 1);
182
- cutoffDate.setHours(0, 0, 0, 0);
183
- break;
184
- default:
185
- cutoffDate = new Date(0);
186
- }
187
- filteredEvents = filteredEvents.filter(event => {
188
- const eventDate = new Date(event.created_at);
189
- return eventDate >= cutoffDate;
190
- });
191
- }
192
- if (description) {
193
- filteredEvents = filteredEvents.filter(event => {
194
- var _event$payload$commit, _event$payload$pull_r, _event$payload$issue, _event$payload$issue2;
195
- let eventDescription = '';
196
- if (event.type === 'PushEvent' && (_event$payload$commit = event.payload.commits) != null && _event$payload$commit.length) {
197
- eventDescription = `Pushed ${event.payload.commits.length} commits`;
198
- } else if (event.type === 'PullRequestEvent' && (_event$payload$pull_r = event.payload.pull_request) != null && _event$payload$pull_r.title) {
199
- eventDescription = event.payload.pull_request.title;
200
- } else if (event.type === 'IssuesEvent' && (_event$payload$issue = event.payload.issue) != null && _event$payload$issue.title) {
201
- eventDescription = event.payload.issue.title;
202
- } else if (event.type === 'IssueCommentEvent' && (_event$payload$issue2 = event.payload.issue) != null && _event$payload$issue2.title) {
203
- eventDescription = `Commented on issue: ${event.payload.issue.title}`;
204
- }
205
- return eventDescription.toLowerCase().includes(description.toLowerCase());
206
- });
207
- }
208
-
209
- // Calculate pagination
210
- const pageNum = Number(page);
211
- const perPage = Number(per_page);
212
- const startIndex = (pageNum - 1) * perPage;
213
- const endIndex = startIndex + perPage;
214
- const paginatedEvents = filteredEvents.slice(startIndex, endIndex);
215
-
216
- // Extract unique values for filters (only on first page)
217
- const repositories = [...new Set(allEvents.map(event => event.repo.name))].sort();
218
- const actionTypes = [...new Set(allEvents.map(event => event.type.replace('Event', '')))].sort();
219
-
220
- // Return paginated results with metadata
71
+ return storage.getItem(key);
72
+ } catch (error) {
73
+ console.warn(`Failed to read storage key "${key}"`, error);
74
+ return null;
75
+ }
76
+ }
77
+ function setStorageItem(storage, key, value) {
78
+ try {
79
+ storage.setItem(key, value);
221
80
  return {
222
- events: paginatedEvents,
223
- total: filteredEvents.length,
224
- repositories,
225
- actionTypes,
226
- page: pageNum,
227
- per_page: perPage,
228
- total_pages: Math.ceil(filteredEvents.length / perPage),
229
- total_fetched_events: allEvents.length,
230
- max_pages_fetched: githubPage - 1
81
+ ok: true,
82
+ quotaExceeded: false
231
83
  };
232
84
  } catch (error) {
233
- console.error('Error fetching GitHub events:', error);
234
- throw new Error(`${error instanceof Error ? error.message : String(error)}`);
85
+ console.warn(`Failed to write storage key "${key}"`, error);
86
+ return {
87
+ ok: false,
88
+ quotaExceeded: isStorageQuotaError(error)
89
+ };
90
+ }
91
+ }
92
+ function removeStorageItem(storage, key) {
93
+ try {
94
+ storage.removeItem(key);
95
+ } catch (error) {
96
+ console.warn(`Failed to remove storage key "${key}"`, error);
97
+ }
98
+ }
99
+ function getStorageKeys(storage) {
100
+ try {
101
+ return Object.keys(storage);
102
+ } catch (error) {
103
+ console.warn('Failed to enumerate storage keys', error);
104
+ return [];
235
105
  }
236
106
  }
107
+ function buildCachePayload(events, limit = events.length) {
108
+ const normalizedLimit = Math.max(0, Math.min(events.length, limit));
109
+ const cachedEvents = normalizedLimit === events.length ? events : events.slice(0, normalizedLimit);
110
+ return {
111
+ events: cachedEvents,
112
+ lastFetched: Date.now(),
113
+ totalCount: cachedEvents.length
114
+ };
115
+ }
116
+ function persistCachedEvents(cacheKey, events) {
117
+ const attempts = Array.from(new Set([Math.min(events.length, CACHE_PERSIST_LIMITS[0]), ...CACHE_PERSIST_LIMITS])).filter(limit => limit > 0 && limit <= events.length);
118
+ let removedExistingCache = false;
119
+ for (const limit of attempts) {
120
+ const payload = buildCachePayload(events, limit);
121
+ const result = setStorageItem(localStorage, cacheKey, JSON.stringify(payload));
122
+ if (result.ok) {
123
+ return payload;
124
+ }
125
+ if (result.quotaExceeded && !removedExistingCache) {
126
+ removeStorageItem(localStorage, cacheKey);
127
+ removedExistingCache = true;
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ function updateCachedEventsTimestamp(cacheKey, payload) {
133
+ if (!payload) {
134
+ return;
135
+ }
136
+ const result = setStorageItem(localStorage, cacheKey, JSON.stringify((0, _extends2.default)({}, payload, {
137
+ lastFetched: Date.now()
138
+ })));
139
+ if (!result.ok) {
140
+ console.warn(`Skipping timestamp update for "${cacheKey}"`);
141
+ }
142
+ }
143
+ function JsonFallbackView({
144
+ value
145
+ }) {
146
+ const json = React.useMemo(() => {
147
+ try {
148
+ return JSON.stringify(value, null, 2);
149
+ } catch (error) {
150
+ return `Failed to serialize event payload: ${error instanceof Error ? error.message : String(error)}`;
151
+ }
152
+ }, [value]);
153
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
154
+ component: "pre",
155
+ sx: {
156
+ backgroundColor: 'transparent',
157
+ fontSize: '0.875rem',
158
+ fontFamily: 'monospace',
159
+ padding: '8px',
160
+ borderRadius: '4px',
161
+ overflow: 'auto',
162
+ maxHeight: 'calc(100vh - 200px)',
163
+ margin: 0,
164
+ whiteSpace: 'pre-wrap',
165
+ wordBreak: 'break-word'
166
+ },
167
+ children: json
168
+ });
169
+ }
237
170
  async function getEvents({
238
171
  githubUser,
239
172
  githubToken,
@@ -262,12 +195,13 @@ async function getEvents({
262
195
  description
263
196
  }));
264
197
  if (apiUrl) {
198
+ queryParams.set('username', githubUser);
265
199
  const url = apiUrl;
266
200
  console.log(`Fetching from custom API URL: ${url}?${queryParams}`);
267
201
  const response = await fetch(`${url}?${queryParams}`);
268
202
  return response.json();
269
203
  }
270
- return githubEventsQuery({
204
+ return (0, _getGithubEvents.githubEventsQuery)({
271
205
  query: {
272
206
  page,
273
207
  per_page: perPage,
@@ -431,14 +365,14 @@ function GithubEvents({
431
365
  uniqueRepos.add(event.repo.name);
432
366
  uniqueActions.add(event.type.replace('Event', ''));
433
367
  if (event.payload) {
434
- var _event$payload$commit2, _event$payload$pull_r2, _event$payload$issue3, _event$payload$issue4;
435
- if (event.type === 'PushEvent' && (_event$payload$commit2 = event.payload.commits) != null && _event$payload$commit2.length) {
368
+ var _event$payload$commit, _event$payload$pull_r, _event$payload$issue, _event$payload$issue2;
369
+ if (event.type === 'PushEvent' && (_event$payload$commit = event.payload.commits) != null && _event$payload$commit.length) {
436
370
  uniqueDescriptions.add(`Pushed ${event.payload.commits.length} commits`);
437
- } else if (event.type === 'PullRequestEvent' && (_event$payload$pull_r2 = event.payload.pull_request) != null && _event$payload$pull_r2.title) {
371
+ } else if (event.type === 'PullRequestEvent' && (_event$payload$pull_r = event.payload.pull_request) != null && _event$payload$pull_r.title) {
438
372
  uniqueDescriptions.add(event.payload.pull_request.title);
439
- } else if (event.type === 'IssuesEvent' && (_event$payload$issue3 = event.payload.issue) != null && _event$payload$issue3.title) {
373
+ } else if (event.type === 'IssuesEvent' && (_event$payload$issue = event.payload.issue) != null && _event$payload$issue.title) {
440
374
  uniqueDescriptions.add(event.payload.issue.title);
441
- } else if (event.type === 'IssueCommentEvent' && (_event$payload$issue4 = event.payload.issue) != null && _event$payload$issue4.title) {
375
+ } else if (event.type === 'IssueCommentEvent' && (_event$payload$issue2 = event.payload.issue) != null && _event$payload$issue2.title) {
442
376
  uniqueDescriptions.add(`Commented on issue: ${event.payload.issue.title}`);
443
377
  }
444
378
  }
@@ -459,7 +393,7 @@ function GithubEvents({
459
393
  console.log('Sample raw event to process:', JSON.stringify(rawEvents[0]).substring(0, 500) + '...');
460
394
  }
461
395
  return rawEvents.map((event, index) => {
462
- var _event$payload$commit3;
396
+ var _event$payload$commit2;
463
397
  try {
464
398
  var _event$repo2;
465
399
  if (!event) {
@@ -481,7 +415,7 @@ function GithubEvents({
481
415
  switch (event.type) {
482
416
  case 'PushEvent':
483
417
  action = 'Push';
484
- description = `Pushed ${((_event$payload$commit3 = event.payload.commits) == null ? void 0 : _event$payload$commit3.length) || 0} commits`;
418
+ description = `Pushed ${((_event$payload$commit2 = event.payload.commits) == null ? void 0 : _event$payload$commit2.length) || 0} commits`;
485
419
  link = `https://github.com/${event.repo.name}/commit/${event.payload.head}`;
486
420
  break;
487
421
  case 'PullRequestEvent':
@@ -583,8 +517,8 @@ function GithubEvents({
583
517
  };
584
518
  const getEventDescription = event => {
585
519
  if (event.type === 'PushEvent') {
586
- var _event$payload$commit4;
587
- return `Pushed ${((_event$payload$commit4 = event.payload.commits) == null ? void 0 : _event$payload$commit4.length) || 0} commits`;
520
+ var _event$payload$commit3;
521
+ return `Pushed ${((_event$payload$commit3 = event.payload.commits) == null ? void 0 : _event$payload$commit3.length) || 0} commits`;
588
522
  } else if (event.type === 'PullRequestEvent') {
589
523
  return event.payload.pull_request.title;
590
524
  } else if (event.type === 'IssuesEvent') {
@@ -679,15 +613,15 @@ function GithubEvents({
679
613
  if (allEvents.length > 0) {
680
614
  // Save all events to cache with user-specific key
681
615
  setCachedEvents(allEvents);
682
- localStorage.setItem(cacheKey, JSON.stringify({
683
- events: allEvents,
684
- lastFetched: Date.now(),
685
- totalCount: allEvents.length
686
- }));
616
+ const persistedCache = persistCachedEvents(cacheKey, allEvents);
617
+ if (persistedCache && persistedCache.events.length < allEvents.length) {
618
+ console.warn(`Persisted a trimmed GitHub events cache for "${cacheKey}" (${persistedCache.events.length}/${allEvents.length} events)`);
619
+ }
687
620
 
688
621
  // Mark that we've fetched this session
689
- sessionStorage.setItem(`${cacheKey}_session_fetched`, 'true');
622
+ setStorageItem(sessionStorage, `${cacheKey}_session_fetched`, 'true');
690
623
  fetchedThisSessionRef.current = true;
624
+ setLastUpdated((0, _dateFns.format)(new Date(), 'MMM d, yyyy h:mm a'));
691
625
 
692
626
  // Update filter options with all data
693
627
  buildFilterOptionsFromEvents(allEvents);
@@ -803,16 +737,15 @@ function GithubEvents({
803
737
  updatedEvents.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
804
738
 
805
739
  // Mark that we've fetched this session
806
- sessionStorage.setItem(`${cacheKey}_session_fetched`, 'true');
740
+ setStorageItem(sessionStorage, `${cacheKey}_session_fetched`, 'true');
807
741
  fetchedThisSessionRef.current = true;
808
742
 
809
743
  // Update cache with new events using user-specific key
810
744
  setCachedEvents(updatedEvents);
811
- localStorage.setItem(cacheKey, JSON.stringify({
812
- events: updatedEvents,
813
- lastFetched: Date.now(),
814
- totalCount: updatedEvents.length
815
- }));
745
+ const persistedCache = persistCachedEvents(cacheKey, updatedEvents);
746
+ if (persistedCache && persistedCache.events.length < updatedEvents.length) {
747
+ console.warn(`Persisted a trimmed GitHub events cache for "${cacheKey}" (${persistedCache.events.length}/${updatedEvents.length} events)`);
748
+ }
816
749
 
817
750
  // Update UI
818
751
  buildFilterOptionsFromEvents(updatedEvents);
@@ -829,14 +762,21 @@ function GithubEvents({
829
762
  console.log('No new events found');
830
763
 
831
764
  // Mark that we've fetched this session even if no new events
832
- sessionStorage.setItem(`${cacheKey}_session_fetched`, 'true');
765
+ setStorageItem(sessionStorage, `${cacheKey}_session_fetched`, 'true');
833
766
  fetchedThisSessionRef.current = true;
834
767
 
835
768
  // Just update the last fetched time with user-specific key
836
- const currentCache = JSON.parse(localStorage.getItem(cacheKey) || '{}');
837
- localStorage.setItem(cacheKey, JSON.stringify((0, _extends2.default)({}, currentCache, {
838
- lastFetched: Date.now()
839
- })));
769
+ const currentCache = getStorageItem(localStorage, cacheKey);
770
+ let parsedCache = null;
771
+ if (currentCache) {
772
+ try {
773
+ parsedCache = JSON.parse(currentCache);
774
+ } catch (parseError) {
775
+ console.warn(`Failed to parse cached GitHub events for "${cacheKey}"`, parseError);
776
+ removeStorageItem(localStorage, cacheKey);
777
+ }
778
+ }
779
+ updateCachedEventsTimestamp(cacheKey, parsedCache);
840
780
  setLastUpdated((0, _dateFns.format)(new Date(), 'MMM d, yyyy h:mm a'));
841
781
 
842
782
  // Use existing cached data for display
@@ -928,13 +868,13 @@ function GithubEvents({
928
868
 
929
869
  // Check session storage to see if we've already fetched this session
930
870
  const sessionKey = `${cacheKey}_session_fetched`;
931
- const fetchedThisSession = sessionStorage.getItem(sessionKey) === 'true';
871
+ const fetchedThisSession = getStorageItem(sessionStorage, sessionKey) === 'true';
932
872
  console.log('Already fetched this session:', fetchedThisSession);
933
873
  fetchedThisSessionRef.current = fetchedThisSession;
934
874
 
935
875
  // Debug all localStorage keys to make sure we're looking at the right one
936
- console.log('All localStorage keys:', Object.keys(localStorage));
937
- const cached = localStorage.getItem(cacheKey);
876
+ console.log('All localStorage keys:', getStorageKeys(localStorage));
877
+ const cached = getStorageItem(localStorage, cacheKey);
938
878
  console.log(`LocalStorage for "${cacheKey}" exists:`, !!cached);
939
879
  if (cached) {
940
880
  try {
@@ -977,7 +917,7 @@ function GithubEvents({
977
917
  setTimeout(() => {
978
918
  fetchNewEvents();
979
919
  // Mark that we've fetched this session
980
- sessionStorage.setItem(sessionKey, 'true');
920
+ setStorageItem(sessionStorage, sessionKey, 'true');
981
921
  fetchedThisSessionRef.current = true;
982
922
  }, 100);
983
923
  } else {
@@ -998,6 +938,7 @@ function GithubEvents({
998
938
  }
999
939
  } catch (err) {
1000
940
  console.error('Failed to parse cached events, fetching new data:', err);
941
+ removeStorageItem(localStorage, cacheKey);
1001
942
  fetchAllGitHubEvents();
1002
943
  }
1003
944
  } else {
@@ -1438,24 +1379,8 @@ function GithubEvents({
1438
1379
  event: selectedEvent
1439
1380
  }) : selectedEvent.actionType === 'IssueCommentEvent' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_IssueCommentEvent.default, {
1440
1381
  event: selectedEvent
1441
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(ReactJson, {
1442
- src: selectedEvent,
1443
- name: false,
1444
- theme: "monokai",
1445
- displayDataTypes: false,
1446
- enableClipboard: false,
1447
- displayObjectSize: false,
1448
- collapsed: 1,
1449
- collapseStringsAfterLength: 50,
1450
- style: {
1451
- backgroundColor: 'transparent',
1452
- fontSize: '0.875rem',
1453
- fontFamily: 'monospace',
1454
- padding: '8px',
1455
- borderRadius: '4px',
1456
- overflow: 'auto',
1457
- maxHeight: 'calc(100vh - 200px)'
1458
- }
1382
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(JsonFallbackView, {
1383
+ value: selectedEvent
1459
1384
  })
1460
1385
  })]
1461
1386
  })]
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = createGithubBranchHandler;
8
+ var _getBranchCompareDetails = _interopRequireDefault(require("./getBranchCompareDetails"));
9
+ function getQueryValue(value) {
10
+ return Array.isArray(value) ? value[0] : value;
11
+ }
12
+ function createGithubBranchHandler() {
13
+ return async function handler(req, res) {
14
+ if (req.method !== 'GET') {
15
+ var _res$setHeader;
16
+ (_res$setHeader = res.setHeader) == null || _res$setHeader.call(res, 'Allow', 'GET');
17
+ return res.status(405).json({
18
+ message: 'Method not allowed'
19
+ });
20
+ }
21
+ const owner = getQueryValue(req.query.owner);
22
+ const repo = getQueryValue(req.query.repo);
23
+ const base = getQueryValue(req.query.base);
24
+ const head = getQueryValue(req.query.head);
25
+ if (!owner || !repo || !base || !head) {
26
+ return res.status(400).json({
27
+ message: 'owner, repo, base, and head are required'
28
+ });
29
+ }
30
+ try {
31
+ var _res$setHeader2;
32
+ const data = await (0, _getBranchCompareDetails.default)({
33
+ owner,
34
+ repo,
35
+ base,
36
+ head
37
+ });
38
+ (_res$setHeader2 = res.setHeader) == null || _res$setHeader2.call(res, 'Cache-Control', 's-maxage=300, stale-while-revalidate=3600');
39
+ return res.status(200).json(data);
40
+ } catch (error) {
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ const status = message.includes('Missing required parameters') ? 400 : 502;
43
+ return res.status(status).json({
44
+ message
45
+ });
46
+ }
47
+ };
48
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = createGithubCommitHandler;
8
+ var _getCommitDetails = _interopRequireDefault(require("./getCommitDetails"));
9
+ function getQueryValue(value) {
10
+ return Array.isArray(value) ? value[0] : value;
11
+ }
12
+ function createGithubCommitHandler() {
13
+ return async function handler(req, res) {
14
+ if (req.method !== 'GET') {
15
+ var _res$setHeader;
16
+ (_res$setHeader = res.setHeader) == null || _res$setHeader.call(res, 'Allow', 'GET');
17
+ return res.status(405).json({
18
+ message: 'Method not allowed'
19
+ });
20
+ }
21
+ const owner = getQueryValue(req.query.owner);
22
+ const repo = getQueryValue(req.query.repo);
23
+ const ref = getQueryValue(req.query.ref);
24
+ if (!owner || !repo || !ref) {
25
+ return res.status(400).json({
26
+ message: 'owner, repo, and ref are required'
27
+ });
28
+ }
29
+ try {
30
+ var _res$setHeader2;
31
+ const data = await (0, _getCommitDetails.default)({
32
+ owner,
33
+ repo,
34
+ ref
35
+ });
36
+ (_res$setHeader2 = res.setHeader) == null || _res$setHeader2.call(res, 'Cache-Control', 's-maxage=300, stale-while-revalidate=3600');
37
+ return res.status(200).json(data);
38
+ } catch (error) {
39
+ const message = error instanceof Error ? error.message : String(error);
40
+ const status = message.includes('Missing required parameters') ? 400 : 502;
41
+ return res.status(status).json({
42
+ message
43
+ });
44
+ }
45
+ };
46
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = createGithubContributionsHandler;
8
+ var _getGithubContributions = _interopRequireDefault(require("./getGithubContributions"));
9
+ function getQueryValue(value) {
10
+ return Array.isArray(value) ? value[0] : value;
11
+ }
12
+ function createGithubContributionsHandler(config = {}) {
13
+ return async function handler(req, res) {
14
+ if (req.method !== 'GET') {
15
+ var _res$setHeader;
16
+ (_res$setHeader = res.setHeader) == null || _res$setHeader.call(res, 'Allow', 'GET');
17
+ return res.status(405).json({
18
+ message: 'Method not allowed'
19
+ });
20
+ }
21
+ const githubUser = getQueryValue(req.query.username);
22
+ const from = getQueryValue(req.query.from);
23
+ const to = getQueryValue(req.query.to);
24
+ if (!githubUser) {
25
+ return res.status(400).json({
26
+ message: 'username is required'
27
+ });
28
+ }
29
+ try {
30
+ var _config$getGithubToke, _res$setHeader2;
31
+ const githubToken = ((_config$getGithubToke = config.getGithubToken) == null ? void 0 : _config$getGithubToke.call(config, req)) || process.env.GITHUB_TOKEN;
32
+ const data = await (0, _getGithubContributions.default)({
33
+ githubUser,
34
+ githubToken,
35
+ from,
36
+ to
37
+ });
38
+ (_res$setHeader2 = res.setHeader) == null || _res$setHeader2.call(res, 'Cache-Control', 's-maxage=3600, stale-while-revalidate=86400');
39
+ return res.status(200).json(data);
40
+ } catch (error) {
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ const status = message.includes('username is required') ? 400 : message.includes('No contribution calendar returned') ? 404 : message.includes('GitHub token not configured') ? 500 : 502;
43
+ return res.status(status).json({
44
+ message
45
+ });
46
+ }
47
+ };
48
+ }