@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.
- package/GithubBranch/GithubBranch.d.ts +12 -0
- package/GithubBranch/GithubBranch.js +177 -0
- package/GithubBranch/index.d.ts +2 -0
- package/GithubBranch/index.js +2 -0
- package/GithubBranch/package.json +6 -0
- package/GithubCalendar/GithubCalendar.d.ts +6 -2
- package/GithubCalendar/GithubCalendar.js +70 -28
- package/GithubCommit/GithubCommit.d.ts +11 -0
- package/GithubCommit/GithubCommit.js +170 -0
- package/GithubCommit/index.d.ts +2 -0
- package/GithubCommit/index.js +2 -0
- package/GithubCommit/package.json +6 -0
- package/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +1 -1
- package/GithubEvents/GithubEvents.d.ts +4 -24
- package/GithubEvents/GithubEvents.js +141 -220
- package/apiHandlers/createGithubBranchHandler.d.ts +12 -0
- package/apiHandlers/createGithubBranchHandler.js +41 -0
- package/apiHandlers/createGithubCommitHandler.d.ts +12 -0
- package/apiHandlers/createGithubCommitHandler.js +39 -0
- package/apiHandlers/createGithubContributionsHandler.d.ts +15 -0
- package/apiHandlers/createGithubContributionsHandler.js +41 -0
- package/apiHandlers/createGithubEventsHandler.d.ts +15 -0
- package/apiHandlers/createGithubEventsHandler.js +50 -0
- package/apiHandlers/getBranchCompareDetails.d.ts +9 -0
- package/apiHandlers/getBranchCompareDetails.js +29 -0
- package/apiHandlers/getCommitDetails.d.ts +8 -0
- package/apiHandlers/getCommitDetails.js +34 -0
- package/apiHandlers/getGithubContributions.d.ts +8 -0
- package/apiHandlers/getGithubContributions.js +126 -0
- package/apiHandlers/getGithubEvents.d.ts +25 -0
- package/apiHandlers/getGithubEvents.js +142 -0
- package/apiHandlers/getPullRequestDetails.js +2 -2
- package/apiHandlers/githubApi.d.ts +17 -0
- package/apiHandlers/githubApi.js +155 -0
- package/apiHandlers/index.d.ts +9 -0
- package/apiHandlers/index.js +9 -1
- package/components/GithubContributorsList.d.ts +8 -0
- package/components/GithubContributorsList.js +72 -0
- package/components/fetchGithubViewData.d.ts +1 -0
- package/components/fetchGithubViewData.js +10 -0
- package/index.d.ts +7 -3
- package/index.js +6 -4
- package/modern/GithubBranch/GithubBranch.js +177 -0
- package/modern/GithubBranch/index.js +2 -0
- package/modern/GithubCalendar/GithubCalendar.js +70 -28
- package/modern/GithubCommit/GithubCommit.js +170 -0
- package/modern/GithubCommit/index.js +2 -0
- package/modern/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +1 -1
- package/modern/GithubEvents/GithubEvents.js +141 -220
- package/modern/apiHandlers/createGithubBranchHandler.js +41 -0
- package/modern/apiHandlers/createGithubCommitHandler.js +39 -0
- package/modern/apiHandlers/createGithubContributionsHandler.js +41 -0
- package/modern/apiHandlers/createGithubEventsHandler.js +50 -0
- package/modern/apiHandlers/getBranchCompareDetails.js +29 -0
- package/modern/apiHandlers/getCommitDetails.js +34 -0
- package/modern/apiHandlers/getGithubContributions.js +126 -0
- package/modern/apiHandlers/getGithubEvents.js +142 -0
- package/modern/apiHandlers/getPullRequestDetails.js +2 -2
- package/modern/apiHandlers/githubApi.js +155 -0
- package/modern/apiHandlers/index.js +9 -1
- package/modern/components/GithubContributorsList.js +72 -0
- package/modern/components/fetchGithubViewData.js +10 -0
- package/modern/index.js +6 -4
- package/node/GithubBranch/GithubBranch.js +185 -0
- package/node/GithubBranch/index.js +9 -0
- package/node/GithubCalendar/GithubCalendar.js +70 -28
- package/node/GithubCommit/GithubCommit.js +178 -0
- package/node/GithubCommit/index.js +9 -0
- package/node/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +1 -1
- package/node/GithubEvents/GithubEvents.js +148 -223
- package/node/apiHandlers/createGithubBranchHandler.js +48 -0
- package/node/apiHandlers/createGithubCommitHandler.js +46 -0
- package/node/apiHandlers/createGithubContributionsHandler.js +48 -0
- package/node/apiHandlers/createGithubEventsHandler.js +57 -0
- package/node/apiHandlers/getBranchCompareDetails.js +35 -0
- package/node/apiHandlers/getCommitDetails.js +40 -0
- package/node/apiHandlers/getGithubContributions.js +132 -0
- package/node/apiHandlers/getGithubEvents.js +149 -0
- package/node/apiHandlers/getPullRequestDetails.js +2 -2
- package/node/apiHandlers/githubApi.js +168 -0
- package/node/apiHandlers/index.js +64 -1
- package/node/components/GithubContributorsList.js +80 -0
- package/node/components/fetchGithubViewData.js +16 -0
- package/node/index.js +77 -2
- package/package.json +2 -5
- package/stoked-ui-github-0.1.0-alpha.11.2.tgz +0 -0
- package/types/github.d.ts +75 -11
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
-
var
|
|
2
|
+
var _Chip, _SmalMi, _SmalMi2, _SmalMi3, _SmalMi4, _SmalMi5, _TableRow, _TableRow2;
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { RequestError } from '@octokit/request-error';
|
|
5
5
|
import Box from "@mui/material/Box";
|
|
@@ -21,23 +21,16 @@ import { toZonedTime } from 'date-fns-tz';
|
|
|
21
21
|
import { styled, useTheme } from '@mui/material/styles';
|
|
22
22
|
import Autocomplete from '@mui/material/Autocomplete';
|
|
23
23
|
import Pagination from '@mui/material/Pagination';
|
|
24
|
-
import dynamic from 'next/dynamic';
|
|
25
24
|
import PullRequestEvent from './EventTypes/PullRequest/PullRequestEvent';
|
|
26
25
|
import PushEvent from './EventTypes/PushEvent';
|
|
27
26
|
import DeleteEvent from './EventTypes/DeleteEvent';
|
|
28
27
|
import CreateEvent from './EventTypes/CreateEvent';
|
|
29
28
|
import IssuesEvent from './EventTypes/IssuesEvent';
|
|
30
29
|
import IssueCommentEvent from './EventTypes/IssueCommentEvent';
|
|
30
|
+
import { githubEventsQuery } from '../apiHandlers/getGithubEvents';
|
|
31
31
|
import Chip from '@mui/material/Chip';
|
|
32
32
|
// Extend the EventDetails interface for internal component use
|
|
33
33
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
34
|
-
// Import react-json-view dynamically to avoid SSR issues
|
|
35
|
-
const ReactJson = dynamic(() => import('react-json-view'), {
|
|
36
|
-
ssr: false,
|
|
37
|
-
loading: () => _div || (_div = /*#__PURE__*/_jsx("div", {
|
|
38
|
-
children: "Loading JSON viewer..."
|
|
39
|
-
}))
|
|
40
|
-
});
|
|
41
34
|
const MetadataDisplay = styled(Box)(({
|
|
42
35
|
theme
|
|
43
36
|
}) => {
|
|
@@ -55,176 +48,112 @@ const MetadataDisplay = styled(Box)(({
|
|
|
55
48
|
overflow: 'auto'
|
|
56
49
|
};
|
|
57
50
|
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (match) {
|
|
63
|
-
const [, url, rel] = match;
|
|
64
|
-
if (rel === 'next' || rel === 'last') {
|
|
65
|
-
links[rel] = url;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return links;
|
|
69
|
-
}, {});
|
|
51
|
+
export { githubEventsQuery };
|
|
52
|
+
const CACHE_PERSIST_LIMITS = [200, 150, 100, 50, 25];
|
|
53
|
+
function isStorageQuotaError(error) {
|
|
54
|
+
return error instanceof DOMException && (error.name === 'QuotaExceededError' || error.name === 'NS_ERROR_DOM_QUOTA_REACHED');
|
|
70
55
|
}
|
|
71
|
-
|
|
72
|
-
query,
|
|
73
|
-
githubUser,
|
|
74
|
-
githubToken
|
|
75
|
-
}) {
|
|
56
|
+
function getStorageItem(storage, key) {
|
|
76
57
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const queryParams = new URLSearchParams(_extends({
|
|
87
|
-
page: String(page),
|
|
88
|
-
per_page: String(per_page)
|
|
89
|
-
}, repo && {
|
|
90
|
-
repo
|
|
91
|
-
}, action && {
|
|
92
|
-
action
|
|
93
|
-
}, date && {
|
|
94
|
-
date
|
|
95
|
-
}, description && {
|
|
96
|
-
description
|
|
97
|
-
}));
|
|
98
|
-
|
|
99
|
-
// Get GitHub token from environment variables
|
|
100
|
-
console.log(`Fetching events for user: ${githubUser}, page: ${page}, per_page: ${per_page}`);
|
|
101
|
-
|
|
102
|
-
// Fetch all available pages from GitHub API
|
|
103
|
-
let allEvents = [];
|
|
104
|
-
let hasMore = true;
|
|
105
|
-
let githubPage = 1;
|
|
106
|
-
const maxPages = 30; // GitHub's maximum for events endpoint
|
|
107
|
-
|
|
108
|
-
while (hasMore && githubPage <= maxPages) {
|
|
109
|
-
console.log(`Fetching page ${githubPage}...`);
|
|
110
|
-
const fetchOptions = {
|
|
111
|
-
headers: {
|
|
112
|
-
'User-Agent': 'brianstoker.com-website'
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
if (githubToken) {
|
|
116
|
-
fetchOptions.headers.Authorization = `token ${githubToken}`;
|
|
117
|
-
}
|
|
118
|
-
const response = await fetch(`https://api.github.com/users/${githubUser}/events?${queryParams}`, fetchOptions);
|
|
119
|
-
if (!response.ok) {
|
|
120
|
-
const errorText = await response.text();
|
|
121
|
-
console.error(`GitHub API error: ${response.status}`, errorText);
|
|
122
|
-
throw new Error(`GitHub API error: ${response.status} - ${errorText}`);
|
|
123
|
-
}
|
|
124
|
-
const data = await response.json();
|
|
125
|
-
console.log(`Page ${githubPage}: Received ${data.length} events`);
|
|
126
|
-
if (data.length === 0) {
|
|
127
|
-
hasMore = false;
|
|
128
|
-
} else {
|
|
129
|
-
allEvents = [...allEvents, ...data];
|
|
130
|
-
console.log(`Total events so far: ${allEvents.length}`);
|
|
131
|
-
|
|
132
|
-
// Check Link header to see if there are more pages
|
|
133
|
-
const linkHeader = response.headers.get('Link');
|
|
134
|
-
const links = parseLinkHeader(linkHeader);
|
|
135
|
-
hasMore = !!links.next; // Simplified logic
|
|
136
|
-
|
|
137
|
-
githubPage++;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
console.log(`Final total events: ${allEvents.length}`);
|
|
141
|
-
|
|
142
|
-
// Apply filters
|
|
143
|
-
let filteredEvents = allEvents;
|
|
144
|
-
if (repo) {
|
|
145
|
-
filteredEvents = filteredEvents.filter(event => event.repo.name === repo);
|
|
146
|
-
}
|
|
147
|
-
if (action) {
|
|
148
|
-
filteredEvents = filteredEvents.filter(event => {
|
|
149
|
-
const eventAction = event.type.replace('Event', '');
|
|
150
|
-
return eventAction === action;
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
if (date) {
|
|
154
|
-
const now = new Date();
|
|
155
|
-
let cutoffDate;
|
|
156
|
-
switch (date) {
|
|
157
|
-
case 'today':
|
|
158
|
-
cutoffDate = new Date(now.setHours(0, 0, 0, 0));
|
|
159
|
-
break;
|
|
160
|
-
case 'yesterday':
|
|
161
|
-
cutoffDate = new Date(now);
|
|
162
|
-
cutoffDate.setDate(cutoffDate.getDate() - 1);
|
|
163
|
-
cutoffDate.setHours(0, 0, 0, 0);
|
|
164
|
-
break;
|
|
165
|
-
case 'week':
|
|
166
|
-
cutoffDate = new Date(now);
|
|
167
|
-
cutoffDate.setDate(cutoffDate.getDate() - 7);
|
|
168
|
-
cutoffDate.setHours(0, 0, 0, 0);
|
|
169
|
-
break;
|
|
170
|
-
case 'month':
|
|
171
|
-
cutoffDate = new Date(now);
|
|
172
|
-
cutoffDate.setMonth(cutoffDate.getMonth() - 1);
|
|
173
|
-
cutoffDate.setHours(0, 0, 0, 0);
|
|
174
|
-
break;
|
|
175
|
-
default:
|
|
176
|
-
cutoffDate = new Date(0);
|
|
177
|
-
}
|
|
178
|
-
filteredEvents = filteredEvents.filter(event => {
|
|
179
|
-
const eventDate = new Date(event.created_at);
|
|
180
|
-
return eventDate >= cutoffDate;
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
if (description) {
|
|
184
|
-
filteredEvents = filteredEvents.filter(event => {
|
|
185
|
-
var _event$payload$commit, _event$payload$pull_r, _event$payload$issue, _event$payload$issue2;
|
|
186
|
-
let eventDescription = '';
|
|
187
|
-
if (event.type === 'PushEvent' && (_event$payload$commit = event.payload.commits) != null && _event$payload$commit.length) {
|
|
188
|
-
eventDescription = `Pushed ${event.payload.commits.length} commits`;
|
|
189
|
-
} else if (event.type === 'PullRequestEvent' && (_event$payload$pull_r = event.payload.pull_request) != null && _event$payload$pull_r.title) {
|
|
190
|
-
eventDescription = event.payload.pull_request.title;
|
|
191
|
-
} else if (event.type === 'IssuesEvent' && (_event$payload$issue = event.payload.issue) != null && _event$payload$issue.title) {
|
|
192
|
-
eventDescription = event.payload.issue.title;
|
|
193
|
-
} else if (event.type === 'IssueCommentEvent' && (_event$payload$issue2 = event.payload.issue) != null && _event$payload$issue2.title) {
|
|
194
|
-
eventDescription = `Commented on issue: ${event.payload.issue.title}`;
|
|
195
|
-
}
|
|
196
|
-
return eventDescription.toLowerCase().includes(description.toLowerCase());
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Calculate pagination
|
|
201
|
-
const pageNum = Number(page);
|
|
202
|
-
const perPage = Number(per_page);
|
|
203
|
-
const startIndex = (pageNum - 1) * perPage;
|
|
204
|
-
const endIndex = startIndex + perPage;
|
|
205
|
-
const paginatedEvents = filteredEvents.slice(startIndex, endIndex);
|
|
206
|
-
|
|
207
|
-
// Extract unique values for filters (only on first page)
|
|
208
|
-
const repositories = [...new Set(allEvents.map(event => event.repo.name))].sort();
|
|
209
|
-
const actionTypes = [...new Set(allEvents.map(event => event.type.replace('Event', '')))].sort();
|
|
210
|
-
|
|
211
|
-
// Return paginated results with metadata
|
|
58
|
+
return storage.getItem(key);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.warn(`Failed to read storage key "${key}"`, error);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function setStorageItem(storage, key, value) {
|
|
65
|
+
try {
|
|
66
|
+
storage.setItem(key, value);
|
|
212
67
|
return {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
repositories,
|
|
216
|
-
actionTypes,
|
|
217
|
-
page: pageNum,
|
|
218
|
-
per_page: perPage,
|
|
219
|
-
total_pages: Math.ceil(filteredEvents.length / perPage),
|
|
220
|
-
total_fetched_events: allEvents.length,
|
|
221
|
-
max_pages_fetched: githubPage - 1
|
|
68
|
+
ok: true,
|
|
69
|
+
quotaExceeded: false
|
|
222
70
|
};
|
|
223
71
|
} catch (error) {
|
|
224
|
-
console.
|
|
225
|
-
|
|
72
|
+
console.warn(`Failed to write storage key "${key}"`, error);
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
quotaExceeded: isStorageQuotaError(error)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function removeStorageItem(storage, key) {
|
|
80
|
+
try {
|
|
81
|
+
storage.removeItem(key);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.warn(`Failed to remove storage key "${key}"`, error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function getStorageKeys(storage) {
|
|
87
|
+
try {
|
|
88
|
+
return Object.keys(storage);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.warn('Failed to enumerate storage keys', error);
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function buildCachePayload(events, limit = events.length) {
|
|
95
|
+
const normalizedLimit = Math.max(0, Math.min(events.length, limit));
|
|
96
|
+
const cachedEvents = normalizedLimit === events.length ? events : events.slice(0, normalizedLimit);
|
|
97
|
+
return {
|
|
98
|
+
events: cachedEvents,
|
|
99
|
+
lastFetched: Date.now(),
|
|
100
|
+
totalCount: cachedEvents.length
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function persistCachedEvents(cacheKey, events) {
|
|
104
|
+
const attempts = Array.from(new Set([Math.min(events.length, CACHE_PERSIST_LIMITS[0]), ...CACHE_PERSIST_LIMITS])).filter(limit => limit > 0 && limit <= events.length);
|
|
105
|
+
let removedExistingCache = false;
|
|
106
|
+
for (const limit of attempts) {
|
|
107
|
+
const payload = buildCachePayload(events, limit);
|
|
108
|
+
const result = setStorageItem(localStorage, cacheKey, JSON.stringify(payload));
|
|
109
|
+
if (result.ok) {
|
|
110
|
+
return payload;
|
|
111
|
+
}
|
|
112
|
+
if (result.quotaExceeded && !removedExistingCache) {
|
|
113
|
+
removeStorageItem(localStorage, cacheKey);
|
|
114
|
+
removedExistingCache = true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
function updateCachedEventsTimestamp(cacheKey, payload) {
|
|
120
|
+
if (!payload) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const result = setStorageItem(localStorage, cacheKey, JSON.stringify(_extends({}, payload, {
|
|
124
|
+
lastFetched: Date.now()
|
|
125
|
+
})));
|
|
126
|
+
if (!result.ok) {
|
|
127
|
+
console.warn(`Skipping timestamp update for "${cacheKey}"`);
|
|
226
128
|
}
|
|
227
129
|
}
|
|
130
|
+
function JsonFallbackView({
|
|
131
|
+
value
|
|
132
|
+
}) {
|
|
133
|
+
const json = React.useMemo(() => {
|
|
134
|
+
try {
|
|
135
|
+
return JSON.stringify(value, null, 2);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
return `Failed to serialize event payload: ${error instanceof Error ? error.message : String(error)}`;
|
|
138
|
+
}
|
|
139
|
+
}, [value]);
|
|
140
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
141
|
+
component: "pre",
|
|
142
|
+
sx: {
|
|
143
|
+
backgroundColor: 'transparent',
|
|
144
|
+
fontSize: '0.875rem',
|
|
145
|
+
fontFamily: 'monospace',
|
|
146
|
+
padding: '8px',
|
|
147
|
+
borderRadius: '4px',
|
|
148
|
+
overflow: 'auto',
|
|
149
|
+
maxHeight: 'calc(100vh - 200px)',
|
|
150
|
+
margin: 0,
|
|
151
|
+
whiteSpace: 'pre-wrap',
|
|
152
|
+
wordBreak: 'break-word'
|
|
153
|
+
},
|
|
154
|
+
children: json
|
|
155
|
+
});
|
|
156
|
+
}
|
|
228
157
|
async function getEvents({
|
|
229
158
|
githubUser,
|
|
230
159
|
githubToken,
|
|
@@ -253,6 +182,7 @@ async function getEvents({
|
|
|
253
182
|
description
|
|
254
183
|
}));
|
|
255
184
|
if (apiUrl) {
|
|
185
|
+
queryParams.set('username', githubUser);
|
|
256
186
|
const url = apiUrl;
|
|
257
187
|
console.log(`Fetching from custom API URL: ${url}?${queryParams}`);
|
|
258
188
|
const response = await fetch(`${url}?${queryParams}`);
|
|
@@ -422,14 +352,14 @@ export default function GithubEvents({
|
|
|
422
352
|
uniqueRepos.add(event.repo.name);
|
|
423
353
|
uniqueActions.add(event.type.replace('Event', ''));
|
|
424
354
|
if (event.payload) {
|
|
425
|
-
var _event$payload$
|
|
426
|
-
if (event.type === 'PushEvent' && (_event$payload$
|
|
355
|
+
var _event$payload$commit, _event$payload$pull_r, _event$payload$issue, _event$payload$issue2;
|
|
356
|
+
if (event.type === 'PushEvent' && (_event$payload$commit = event.payload.commits) != null && _event$payload$commit.length) {
|
|
427
357
|
uniqueDescriptions.add(`Pushed ${event.payload.commits.length} commits`);
|
|
428
|
-
} else if (event.type === 'PullRequestEvent' && (_event$payload$
|
|
358
|
+
} else if (event.type === 'PullRequestEvent' && (_event$payload$pull_r = event.payload.pull_request) != null && _event$payload$pull_r.title) {
|
|
429
359
|
uniqueDescriptions.add(event.payload.pull_request.title);
|
|
430
|
-
} else if (event.type === 'IssuesEvent' && (_event$payload$
|
|
360
|
+
} else if (event.type === 'IssuesEvent' && (_event$payload$issue = event.payload.issue) != null && _event$payload$issue.title) {
|
|
431
361
|
uniqueDescriptions.add(event.payload.issue.title);
|
|
432
|
-
} else if (event.type === 'IssueCommentEvent' && (_event$payload$
|
|
362
|
+
} else if (event.type === 'IssueCommentEvent' && (_event$payload$issue2 = event.payload.issue) != null && _event$payload$issue2.title) {
|
|
433
363
|
uniqueDescriptions.add(`Commented on issue: ${event.payload.issue.title}`);
|
|
434
364
|
}
|
|
435
365
|
}
|
|
@@ -450,7 +380,7 @@ export default function GithubEvents({
|
|
|
450
380
|
console.log('Sample raw event to process:', JSON.stringify(rawEvents[0]).substring(0, 500) + '...');
|
|
451
381
|
}
|
|
452
382
|
return rawEvents.map((event, index) => {
|
|
453
|
-
var _event$payload$
|
|
383
|
+
var _event$payload$commit2;
|
|
454
384
|
try {
|
|
455
385
|
var _event$repo2;
|
|
456
386
|
if (!event) {
|
|
@@ -472,7 +402,7 @@ export default function GithubEvents({
|
|
|
472
402
|
switch (event.type) {
|
|
473
403
|
case 'PushEvent':
|
|
474
404
|
action = 'Push';
|
|
475
|
-
description = `Pushed ${((_event$payload$
|
|
405
|
+
description = `Pushed ${((_event$payload$commit2 = event.payload.commits) == null ? void 0 : _event$payload$commit2.length) || 0} commits`;
|
|
476
406
|
link = `https://github.com/${event.repo.name}/commit/${event.payload.head}`;
|
|
477
407
|
break;
|
|
478
408
|
case 'PullRequestEvent':
|
|
@@ -574,8 +504,8 @@ export default function GithubEvents({
|
|
|
574
504
|
};
|
|
575
505
|
const getEventDescription = event => {
|
|
576
506
|
if (event.type === 'PushEvent') {
|
|
577
|
-
var _event$payload$
|
|
578
|
-
return `Pushed ${((_event$payload$
|
|
507
|
+
var _event$payload$commit3;
|
|
508
|
+
return `Pushed ${((_event$payload$commit3 = event.payload.commits) == null ? void 0 : _event$payload$commit3.length) || 0} commits`;
|
|
579
509
|
} else if (event.type === 'PullRequestEvent') {
|
|
580
510
|
return event.payload.pull_request.title;
|
|
581
511
|
} else if (event.type === 'IssuesEvent') {
|
|
@@ -670,15 +600,15 @@ export default function GithubEvents({
|
|
|
670
600
|
if (allEvents.length > 0) {
|
|
671
601
|
// Save all events to cache with user-specific key
|
|
672
602
|
setCachedEvents(allEvents);
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
}));
|
|
603
|
+
const persistedCache = persistCachedEvents(cacheKey, allEvents);
|
|
604
|
+
if (persistedCache && persistedCache.events.length < allEvents.length) {
|
|
605
|
+
console.warn(`Persisted a trimmed GitHub events cache for "${cacheKey}" (${persistedCache.events.length}/${allEvents.length} events)`);
|
|
606
|
+
}
|
|
678
607
|
|
|
679
608
|
// Mark that we've fetched this session
|
|
680
|
-
sessionStorage
|
|
609
|
+
setStorageItem(sessionStorage, `${cacheKey}_session_fetched`, 'true');
|
|
681
610
|
fetchedThisSessionRef.current = true;
|
|
611
|
+
setLastUpdated(format(new Date(), 'MMM d, yyyy h:mm a'));
|
|
682
612
|
|
|
683
613
|
// Update filter options with all data
|
|
684
614
|
buildFilterOptionsFromEvents(allEvents);
|
|
@@ -794,16 +724,15 @@ export default function GithubEvents({
|
|
|
794
724
|
updatedEvents.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
795
725
|
|
|
796
726
|
// Mark that we've fetched this session
|
|
797
|
-
sessionStorage
|
|
727
|
+
setStorageItem(sessionStorage, `${cacheKey}_session_fetched`, 'true');
|
|
798
728
|
fetchedThisSessionRef.current = true;
|
|
799
729
|
|
|
800
730
|
// Update cache with new events using user-specific key
|
|
801
731
|
setCachedEvents(updatedEvents);
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}));
|
|
732
|
+
const persistedCache = persistCachedEvents(cacheKey, updatedEvents);
|
|
733
|
+
if (persistedCache && persistedCache.events.length < updatedEvents.length) {
|
|
734
|
+
console.warn(`Persisted a trimmed GitHub events cache for "${cacheKey}" (${persistedCache.events.length}/${updatedEvents.length} events)`);
|
|
735
|
+
}
|
|
807
736
|
|
|
808
737
|
// Update UI
|
|
809
738
|
buildFilterOptionsFromEvents(updatedEvents);
|
|
@@ -820,14 +749,21 @@ export default function GithubEvents({
|
|
|
820
749
|
console.log('No new events found');
|
|
821
750
|
|
|
822
751
|
// Mark that we've fetched this session even if no new events
|
|
823
|
-
sessionStorage
|
|
752
|
+
setStorageItem(sessionStorage, `${cacheKey}_session_fetched`, 'true');
|
|
824
753
|
fetchedThisSessionRef.current = true;
|
|
825
754
|
|
|
826
755
|
// Just update the last fetched time with user-specific key
|
|
827
|
-
const currentCache =
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
756
|
+
const currentCache = getStorageItem(localStorage, cacheKey);
|
|
757
|
+
let parsedCache = null;
|
|
758
|
+
if (currentCache) {
|
|
759
|
+
try {
|
|
760
|
+
parsedCache = JSON.parse(currentCache);
|
|
761
|
+
} catch (parseError) {
|
|
762
|
+
console.warn(`Failed to parse cached GitHub events for "${cacheKey}"`, parseError);
|
|
763
|
+
removeStorageItem(localStorage, cacheKey);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
updateCachedEventsTimestamp(cacheKey, parsedCache);
|
|
831
767
|
setLastUpdated(format(new Date(), 'MMM d, yyyy h:mm a'));
|
|
832
768
|
|
|
833
769
|
// Use existing cached data for display
|
|
@@ -919,13 +855,13 @@ export default function GithubEvents({
|
|
|
919
855
|
|
|
920
856
|
// Check session storage to see if we've already fetched this session
|
|
921
857
|
const sessionKey = `${cacheKey}_session_fetched`;
|
|
922
|
-
const fetchedThisSession = sessionStorage
|
|
858
|
+
const fetchedThisSession = getStorageItem(sessionStorage, sessionKey) === 'true';
|
|
923
859
|
console.log('Already fetched this session:', fetchedThisSession);
|
|
924
860
|
fetchedThisSessionRef.current = fetchedThisSession;
|
|
925
861
|
|
|
926
862
|
// Debug all localStorage keys to make sure we're looking at the right one
|
|
927
|
-
console.log('All localStorage keys:',
|
|
928
|
-
const cached = localStorage
|
|
863
|
+
console.log('All localStorage keys:', getStorageKeys(localStorage));
|
|
864
|
+
const cached = getStorageItem(localStorage, cacheKey);
|
|
929
865
|
console.log(`LocalStorage for "${cacheKey}" exists:`, !!cached);
|
|
930
866
|
if (cached) {
|
|
931
867
|
try {
|
|
@@ -968,7 +904,7 @@ export default function GithubEvents({
|
|
|
968
904
|
setTimeout(() => {
|
|
969
905
|
fetchNewEvents();
|
|
970
906
|
// Mark that we've fetched this session
|
|
971
|
-
sessionStorage
|
|
907
|
+
setStorageItem(sessionStorage, sessionKey, 'true');
|
|
972
908
|
fetchedThisSessionRef.current = true;
|
|
973
909
|
}, 100);
|
|
974
910
|
} else {
|
|
@@ -989,6 +925,7 @@ export default function GithubEvents({
|
|
|
989
925
|
}
|
|
990
926
|
} catch (err) {
|
|
991
927
|
console.error('Failed to parse cached events, fetching new data:', err);
|
|
928
|
+
removeStorageItem(localStorage, cacheKey);
|
|
992
929
|
fetchAllGitHubEvents();
|
|
993
930
|
}
|
|
994
931
|
} else {
|
|
@@ -1429,24 +1366,8 @@ export default function GithubEvents({
|
|
|
1429
1366
|
event: selectedEvent
|
|
1430
1367
|
}) : selectedEvent.actionType === 'IssueCommentEvent' ? /*#__PURE__*/_jsx(IssueCommentEvent, {
|
|
1431
1368
|
event: selectedEvent
|
|
1432
|
-
}) : /*#__PURE__*/_jsx(
|
|
1433
|
-
|
|
1434
|
-
name: false,
|
|
1435
|
-
theme: "monokai",
|
|
1436
|
-
displayDataTypes: false,
|
|
1437
|
-
enableClipboard: false,
|
|
1438
|
-
displayObjectSize: false,
|
|
1439
|
-
collapsed: 1,
|
|
1440
|
-
collapseStringsAfterLength: 50,
|
|
1441
|
-
style: {
|
|
1442
|
-
backgroundColor: 'transparent',
|
|
1443
|
-
fontSize: '0.875rem',
|
|
1444
|
-
fontFamily: 'monospace',
|
|
1445
|
-
padding: '8px',
|
|
1446
|
-
borderRadius: '4px',
|
|
1447
|
-
overflow: 'auto',
|
|
1448
|
-
maxHeight: 'calc(100vh - 200px)'
|
|
1449
|
-
}
|
|
1369
|
+
}) : /*#__PURE__*/_jsx(JsonFallbackView, {
|
|
1370
|
+
value: selectedEvent
|
|
1450
1371
|
})
|
|
1451
1372
|
})]
|
|
1452
1373
|
})]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import getBranchCompareDetails from './getBranchCompareDetails';
|
|
2
|
+
function getQueryValue(value) {
|
|
3
|
+
return Array.isArray(value) ? value[0] : value;
|
|
4
|
+
}
|
|
5
|
+
export default function createGithubBranchHandler() {
|
|
6
|
+
return async function handler(req, res) {
|
|
7
|
+
if (req.method !== 'GET') {
|
|
8
|
+
var _res$setHeader;
|
|
9
|
+
(_res$setHeader = res.setHeader) == null || _res$setHeader.call(res, 'Allow', 'GET');
|
|
10
|
+
return res.status(405).json({
|
|
11
|
+
message: 'Method not allowed'
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
const owner = getQueryValue(req.query.owner);
|
|
15
|
+
const repo = getQueryValue(req.query.repo);
|
|
16
|
+
const base = getQueryValue(req.query.base);
|
|
17
|
+
const head = getQueryValue(req.query.head);
|
|
18
|
+
if (!owner || !repo || !base || !head) {
|
|
19
|
+
return res.status(400).json({
|
|
20
|
+
message: 'owner, repo, base, and head are required'
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
var _res$setHeader2;
|
|
25
|
+
const data = await getBranchCompareDetails({
|
|
26
|
+
owner,
|
|
27
|
+
repo,
|
|
28
|
+
base,
|
|
29
|
+
head
|
|
30
|
+
});
|
|
31
|
+
(_res$setHeader2 = res.setHeader) == null || _res$setHeader2.call(res, 'Cache-Control', 's-maxage=300, stale-while-revalidate=3600');
|
|
32
|
+
return res.status(200).json(data);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
35
|
+
const status = message.includes('Missing required parameters') ? 400 : 502;
|
|
36
|
+
return res.status(status).json({
|
|
37
|
+
message
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import getCommitDetails from './getCommitDetails';
|
|
2
|
+
function getQueryValue(value) {
|
|
3
|
+
return Array.isArray(value) ? value[0] : value;
|
|
4
|
+
}
|
|
5
|
+
export default function createGithubCommitHandler() {
|
|
6
|
+
return async function handler(req, res) {
|
|
7
|
+
if (req.method !== 'GET') {
|
|
8
|
+
var _res$setHeader;
|
|
9
|
+
(_res$setHeader = res.setHeader) == null || _res$setHeader.call(res, 'Allow', 'GET');
|
|
10
|
+
return res.status(405).json({
|
|
11
|
+
message: 'Method not allowed'
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
const owner = getQueryValue(req.query.owner);
|
|
15
|
+
const repo = getQueryValue(req.query.repo);
|
|
16
|
+
const ref = getQueryValue(req.query.ref);
|
|
17
|
+
if (!owner || !repo || !ref) {
|
|
18
|
+
return res.status(400).json({
|
|
19
|
+
message: 'owner, repo, and ref are required'
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
var _res$setHeader2;
|
|
24
|
+
const data = await getCommitDetails({
|
|
25
|
+
owner,
|
|
26
|
+
repo,
|
|
27
|
+
ref
|
|
28
|
+
});
|
|
29
|
+
(_res$setHeader2 = res.setHeader) == null || _res$setHeader2.call(res, 'Cache-Control', 's-maxage=300, stale-while-revalidate=3600');
|
|
30
|
+
return res.status(200).json(data);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
33
|
+
const status = message.includes('Missing required parameters') ? 400 : 502;
|
|
34
|
+
return res.status(status).json({
|
|
35
|
+
message
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import getGithubContributions from './getGithubContributions';
|
|
2
|
+
function getQueryValue(value) {
|
|
3
|
+
return Array.isArray(value) ? value[0] : value;
|
|
4
|
+
}
|
|
5
|
+
export default function createGithubContributionsHandler(config = {}) {
|
|
6
|
+
return async function handler(req, res) {
|
|
7
|
+
if (req.method !== 'GET') {
|
|
8
|
+
var _res$setHeader;
|
|
9
|
+
(_res$setHeader = res.setHeader) == null || _res$setHeader.call(res, 'Allow', 'GET');
|
|
10
|
+
return res.status(405).json({
|
|
11
|
+
message: 'Method not allowed'
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
const githubUser = getQueryValue(req.query.username);
|
|
15
|
+
const from = getQueryValue(req.query.from);
|
|
16
|
+
const to = getQueryValue(req.query.to);
|
|
17
|
+
if (!githubUser) {
|
|
18
|
+
return res.status(400).json({
|
|
19
|
+
message: 'username is required'
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
var _config$getGithubToke, _res$setHeader2;
|
|
24
|
+
const githubToken = ((_config$getGithubToke = config.getGithubToken) == null ? void 0 : _config$getGithubToke.call(config, req)) || process.env.GITHUB_TOKEN;
|
|
25
|
+
const data = await getGithubContributions({
|
|
26
|
+
githubUser,
|
|
27
|
+
githubToken,
|
|
28
|
+
from,
|
|
29
|
+
to
|
|
30
|
+
});
|
|
31
|
+
(_res$setHeader2 = res.setHeader) == null || _res$setHeader2.call(res, 'Cache-Control', 's-maxage=3600, stale-while-revalidate=86400');
|
|
32
|
+
return res.status(200).json(data);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
35
|
+
const status = message.includes('username is required') ? 400 : message.includes('No contribution calendar returned') ? 404 : message.includes('GitHub token not configured') ? 500 : 502;
|
|
36
|
+
return res.status(status).json({
|
|
37
|
+
message
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import githubEventsQuery from './getGithubEvents';
|
|
2
|
+
function getQueryValue(value) {
|
|
3
|
+
return Array.isArray(value) ? value[0] : value;
|
|
4
|
+
}
|
|
5
|
+
function parseNumber(value, fallback) {
|
|
6
|
+
const parsed = Number(getQueryValue(value));
|
|
7
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
8
|
+
}
|
|
9
|
+
export default function createGithubEventsHandler(config = {}) {
|
|
10
|
+
return async function handler(req, res) {
|
|
11
|
+
if (req.method !== 'GET') {
|
|
12
|
+
var _res$setHeader;
|
|
13
|
+
(_res$setHeader = res.setHeader) == null || _res$setHeader.call(res, 'Allow', 'GET');
|
|
14
|
+
return res.status(405).json({
|
|
15
|
+
message: 'Method not allowed'
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const githubUser = getQueryValue(req.query.username);
|
|
19
|
+
if (!githubUser) {
|
|
20
|
+
return res.status(400).json({
|
|
21
|
+
message: 'username is required'
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const query = {
|
|
25
|
+
page: parseNumber(req.query.page, 1),
|
|
26
|
+
per_page: parseNumber(req.query.per_page, 40),
|
|
27
|
+
repo: getQueryValue(req.query.repo) || undefined,
|
|
28
|
+
action: getQueryValue(req.query.action) || undefined,
|
|
29
|
+
date: getQueryValue(req.query.date) || undefined,
|
|
30
|
+
description: getQueryValue(req.query.description) || undefined
|
|
31
|
+
};
|
|
32
|
+
try {
|
|
33
|
+
var _config$getGithubToke, _res$setHeader2;
|
|
34
|
+
const githubToken = ((_config$getGithubToke = config.getGithubToken) == null ? void 0 : _config$getGithubToke.call(config, req)) || process.env.GITHUB_TOKEN;
|
|
35
|
+
const data = await githubEventsQuery({
|
|
36
|
+
query,
|
|
37
|
+
githubUser,
|
|
38
|
+
githubToken
|
|
39
|
+
});
|
|
40
|
+
(_res$setHeader2 = res.setHeader) == null || _res$setHeader2.call(res, 'Cache-Control', 's-maxage=300, stale-while-revalidate=3600');
|
|
41
|
+
return res.status(200).json(data);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
44
|
+
const status = message.includes('username is required') ? 400 : 502;
|
|
45
|
+
return res.status(status).json({
|
|
46
|
+
message
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|