emulate 0.4.1 → 0.5.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/README.md +59 -10
- package/dist/api.d.ts +2 -1
- package/dist/api.js +232 -96
- package/dist/api.js.map +1 -1
- package/dist/{chunk-TEPNEZ63.js → chunk-AQ2CLRU3.js} +26 -23
- package/dist/chunk-AQ2CLRU3.js.map +1 -0
- package/dist/chunk-WVQMFHQM.js +83 -0
- package/dist/chunk-WVQMFHQM.js.map +1 -0
- package/dist/{dist-RDFBZ5O6.js → dist-4X2KPMAJ.js} +212 -47
- package/dist/dist-4X2KPMAJ.js.map +1 -0
- package/dist/{dist-OTJZRQ3Q.js → dist-5JVGPOL3.js} +217 -75
- package/dist/dist-5JVGPOL3.js.map +1 -0
- package/dist/{dist-G7WQPZ3Y.js → dist-CE6BUCWQ.js} +211 -60
- package/dist/dist-CE6BUCWQ.js.map +1 -0
- package/dist/{dist-6JFNJPUU.js → dist-CFST4X4K.js} +172 -22
- package/dist/dist-CFST4X4K.js.map +1 -0
- package/dist/{dist-YOVM5HEY.js → dist-ENKE2S7V.js} +521 -60
- package/dist/dist-ENKE2S7V.js.map +1 -0
- package/dist/{dist-RMK3BS5M.js → dist-ETHHYBGF.js} +197 -33
- package/dist/dist-ETHHYBGF.js.map +1 -0
- package/dist/{dist-QMOJM6DV.js → dist-IBXD3O6A.js} +239 -54
- package/dist/dist-IBXD3O6A.js.map +1 -0
- package/dist/dist-J6LHUR52.js +1899 -0
- package/dist/dist-J6LHUR52.js.map +1 -0
- package/dist/{dist-6EW7SSOZ.js → dist-KKTYBE5S.js} +391 -222
- package/dist/dist-KKTYBE5S.js.map +1 -0
- package/dist/{dist-VVXVP5EZ.js → dist-LDUHEJAN.js} +553 -91
- package/dist/dist-LDUHEJAN.js.map +1 -0
- package/dist/{dist-B674PYKV.js → dist-PWGOAQC6.js} +22 -43
- package/dist/dist-PWGOAQC6.js.map +1 -0
- package/dist/{dist-H6JYGQM4.js → dist-REDHDZ3V.js} +272 -157
- package/dist/dist-REDHDZ3V.js.map +1 -0
- package/dist/fonts/favicon.ico +0 -0
- package/dist/helpers-LXLP3DFE-LBOTATT5.js +17 -0
- package/dist/helpers-LXLP3DFE-LBOTATT5.js.map +1 -0
- package/dist/index.js +365 -108
- package/dist/index.js.map +1 -1
- package/package.json +17 -14
- package/dist/chunk-TEPNEZ63.js.map +0 -1
- package/dist/dist-6EW7SSOZ.js.map +0 -1
- package/dist/dist-6JFNJPUU.js.map +0 -1
- package/dist/dist-B674PYKV.js.map +0 -1
- package/dist/dist-G7WQPZ3Y.js.map +0 -1
- package/dist/dist-H6JYGQM4.js.map +0 -1
- package/dist/dist-OTJZRQ3Q.js.map +0 -1
- package/dist/dist-QMOJM6DV.js.map +0 -1
- package/dist/dist-RDFBZ5O6.js.map +0 -1
- package/dist/dist-RMK3BS5M.js.map +0 -1
- package/dist/dist-VVXVP5EZ.js.map +0 -1
- package/dist/dist-YOVM5HEY.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-AQ2CLRU3.js";
|
|
2
2
|
|
|
3
3
|
// ../@emulators/github/dist/index.js
|
|
4
4
|
import { createHmac } from "crypto";
|
|
@@ -44,7 +44,10 @@ function getGitHubStore(store) {
|
|
|
44
44
|
checkSuites: store.collection("github.check_suites", ["repo_id", "head_sha"]),
|
|
45
45
|
oauthApps: store.collection("github.oauth_apps", ["client_id"]),
|
|
46
46
|
apps: store.collection("github.apps", ["slug"]),
|
|
47
|
-
appInstallations: store.collection("github.app_installations", [
|
|
47
|
+
appInstallations: store.collection("github.app_installations", [
|
|
48
|
+
"app_id",
|
|
49
|
+
"installation_id"
|
|
50
|
+
]),
|
|
48
51
|
oauthGrants: store.collection("github.oauth_grants", ["user_id", "client_id"])
|
|
49
52
|
};
|
|
50
53
|
}
|
|
@@ -740,6 +743,7 @@ var FONTS = {
|
|
|
740
743
|
"geist-sans.woff2": readFileSync(join(__dirname, "fonts", "geist-sans.woff2")),
|
|
741
744
|
"GeistPixel-Square.woff2": readFileSync(join(__dirname, "fonts", "GeistPixel-Square.woff2"))
|
|
742
745
|
};
|
|
746
|
+
var FAVICON = readFileSync(join(__dirname, "fonts", "favicon.ico"));
|
|
743
747
|
function parsePagination(c) {
|
|
744
748
|
const page = Math.max(1, parseInt(c.req.query("page") ?? "1", 10) || 1);
|
|
745
749
|
const per_page = Math.min(100, Math.max(1, parseInt(c.req.query("per_page") ?? "30", 10) || 30));
|
|
@@ -917,6 +921,132 @@ body{
|
|
|
917
921
|
.app-link-name{font-weight:600;font-size:.875rem;color:#33ff00;}
|
|
918
922
|
.app-link-scopes{font-size:.6875rem;color:#1a8c00;margin-top:1px;}
|
|
919
923
|
.empty{color:#1a8c00;text-align:center;padding:28px 0;font-size:.875rem;}
|
|
924
|
+
|
|
925
|
+
.inspector-layout{max-width:960px;margin:0 auto;padding:28px 20px;}
|
|
926
|
+
.inspector-tabs{display:flex;gap:4px;margin-bottom:20px;}
|
|
927
|
+
.inspector-tabs a{
|
|
928
|
+
padding:7px 16px;border-radius:6px;text-decoration:none;
|
|
929
|
+
font-size:.8125rem;color:#1a8c00;border:1px solid transparent;
|
|
930
|
+
transition:color .15s,border-color .15s;
|
|
931
|
+
}
|
|
932
|
+
.inspector-tabs a:hover{color:#33ff00;}
|
|
933
|
+
.inspector-tabs a.active{color:#33ff00;font-weight:600;border-color:#0a3300;background:#0a3300;}
|
|
934
|
+
.inspector-section{margin-bottom:24px;}
|
|
935
|
+
.inspector-section h2{
|
|
936
|
+
font-family:'Geist Pixel',monospace;
|
|
937
|
+
font-size:1rem;font-weight:600;color:#33ff00;margin-bottom:10px;
|
|
938
|
+
}
|
|
939
|
+
.inspector-section h3{
|
|
940
|
+
font-family:'Geist Pixel',monospace;
|
|
941
|
+
font-size:.875rem;font-weight:600;color:#1a8c00;margin:16px 0 8px;
|
|
942
|
+
}
|
|
943
|
+
.inspector-table{width:100%;border-collapse:collapse;margin-bottom:12px;}
|
|
944
|
+
.inspector-table th,.inspector-table td{
|
|
945
|
+
text-align:left;padding:8px 12px;border-bottom:1px solid #0a3300;
|
|
946
|
+
font-size:.8125rem;
|
|
947
|
+
}
|
|
948
|
+
.inspector-table th{color:#1a8c00;font-weight:600;font-size:.75rem;text-transform:uppercase;letter-spacing:.04em;}
|
|
949
|
+
.inspector-table td{color:#33ff00;}
|
|
950
|
+
.inspector-table tbody tr{transition:background .1s;}
|
|
951
|
+
.inspector-table tbody tr:hover{background:#0a3300;}
|
|
952
|
+
.inspector-empty{color:#1a8c00;text-align:center;padding:20px 0;font-size:.8125rem;}
|
|
953
|
+
|
|
954
|
+
.checkout-layout{
|
|
955
|
+
display:flex;min-height:calc(100vh - 42px);
|
|
956
|
+
}
|
|
957
|
+
.checkout-summary{
|
|
958
|
+
flex:1;background:#020;padding:48px 40px 48px 10%;
|
|
959
|
+
display:flex;flex-direction:column;justify-content:center;
|
|
960
|
+
border-right:1px solid #0a3300;
|
|
961
|
+
}
|
|
962
|
+
.checkout-form-side{
|
|
963
|
+
flex:1;background:#000;padding:48px 10% 48px 40px;
|
|
964
|
+
display:flex;flex-direction:column;justify-content:center;
|
|
965
|
+
}
|
|
966
|
+
.checkout-merchant{
|
|
967
|
+
display:flex;align-items:center;gap:10px;margin-bottom:6px;
|
|
968
|
+
}
|
|
969
|
+
.checkout-merchant-name{
|
|
970
|
+
font-family:'Geist Pixel',monospace;
|
|
971
|
+
font-size:.9375rem;font-weight:600;color:#33ff00;
|
|
972
|
+
}
|
|
973
|
+
.checkout-test-badge{
|
|
974
|
+
font-size:.625rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
|
|
975
|
+
background:#0a3300;color:#1a8c00;padding:2px 8px;border-radius:4px;
|
|
976
|
+
}
|
|
977
|
+
.checkout-total{
|
|
978
|
+
font-family:'Geist Pixel',monospace;
|
|
979
|
+
font-size:2rem;font-weight:700;color:#33ff00;margin:8px 0 28px;
|
|
980
|
+
}
|
|
981
|
+
.checkout-line-item{
|
|
982
|
+
display:flex;align-items:center;gap:14px;padding:14px 0;
|
|
983
|
+
border-bottom:1px solid #0a3300;
|
|
984
|
+
}
|
|
985
|
+
.checkout-line-item:first-child{border-top:1px solid #0a3300;}
|
|
986
|
+
.checkout-item-icon{
|
|
987
|
+
width:42px;height:42px;border-radius:6px;background:#0a3300;
|
|
988
|
+
display:flex;align-items:center;justify-content:center;flex-shrink:0;
|
|
989
|
+
font-family:'Geist Pixel',monospace;font-size:.875rem;font-weight:700;color:#116600;
|
|
990
|
+
}
|
|
991
|
+
.checkout-item-details{flex:1;min-width:0;}
|
|
992
|
+
.checkout-item-name{font-size:.875rem;font-weight:600;color:#33ff00;}
|
|
993
|
+
.checkout-item-qty{font-size:.75rem;color:#1a8c00;margin-top:2px;}
|
|
994
|
+
.checkout-item-price{
|
|
995
|
+
font-size:.875rem;font-weight:600;color:#33ff00;text-align:right;white-space:nowrap;
|
|
996
|
+
}
|
|
997
|
+
.checkout-item-unit{font-size:.6875rem;color:#1a8c00;text-align:right;margin-top:2px;}
|
|
998
|
+
.checkout-totals{margin-top:20px;}
|
|
999
|
+
.checkout-totals-row{
|
|
1000
|
+
display:flex;justify-content:space-between;padding:6px 0;
|
|
1001
|
+
font-size:.8125rem;color:#1a8c00;
|
|
1002
|
+
}
|
|
1003
|
+
.checkout-totals-row.total{
|
|
1004
|
+
border-top:1px solid #0a3300;margin-top:8px;padding-top:14px;
|
|
1005
|
+
font-size:.9375rem;font-weight:600;color:#33ff00;
|
|
1006
|
+
}
|
|
1007
|
+
.checkout-form-section{margin-bottom:24px;}
|
|
1008
|
+
.checkout-form-label{
|
|
1009
|
+
font-size:.8125rem;font-weight:600;color:#33ff00;margin-bottom:8px;display:block;
|
|
1010
|
+
}
|
|
1011
|
+
.checkout-input{
|
|
1012
|
+
width:100%;padding:10px 12px;border:1px solid #0a3300;border-radius:6px;
|
|
1013
|
+
background:#020;color:#33ff00;font:inherit;font-size:.875rem;
|
|
1014
|
+
transition:border-color .15s;outline:none;
|
|
1015
|
+
}
|
|
1016
|
+
.checkout-input:focus{border-color:#33ff00;}
|
|
1017
|
+
.checkout-input::placeholder{color:#116600;}
|
|
1018
|
+
.checkout-card-box{
|
|
1019
|
+
border:1px solid #0a3300;border-radius:6px;padding:14px;
|
|
1020
|
+
background:#020;
|
|
1021
|
+
}
|
|
1022
|
+
.checkout-card-row{
|
|
1023
|
+
display:flex;gap:12px;margin-top:10px;
|
|
1024
|
+
}
|
|
1025
|
+
.checkout-card-row .checkout-input{flex:1;}
|
|
1026
|
+
.checkout-sim-note{
|
|
1027
|
+
font-size:.6875rem;color:#1a8c00;margin-top:10px;text-align:center;
|
|
1028
|
+
font-style:italic;
|
|
1029
|
+
}
|
|
1030
|
+
.checkout-pay-btn{
|
|
1031
|
+
width:100%;padding:14px;border:none;border-radius:8px;
|
|
1032
|
+
background:#33ff00;color:#000;font:inherit;font-size:.9375rem;font-weight:700;
|
|
1033
|
+
cursor:pointer;transition:background .15s;
|
|
1034
|
+
font-family:'Geist Pixel',monospace;
|
|
1035
|
+
}
|
|
1036
|
+
.checkout-pay-btn:hover{background:#44ff22;}
|
|
1037
|
+
.checkout-cancel{
|
|
1038
|
+
text-align:center;margin-top:14px;
|
|
1039
|
+
}
|
|
1040
|
+
.checkout-cancel a{
|
|
1041
|
+
color:#1a8c00;text-decoration:none;font-size:.8125rem;
|
|
1042
|
+
transition:color .15s;
|
|
1043
|
+
}
|
|
1044
|
+
.checkout-cancel a:hover{color:#33ff00;}
|
|
1045
|
+
@media(max-width:768px){
|
|
1046
|
+
.checkout-layout{flex-direction:column;}
|
|
1047
|
+
.checkout-summary{padding:32px 20px;border-right:none;border-bottom:1px solid #0a3300;}
|
|
1048
|
+
.checkout-form-side{padding:32px 20px;}
|
|
1049
|
+
}
|
|
920
1050
|
`;
|
|
921
1051
|
var POWERED_BY = `<div class="powered-by">Powered by <a href="https://emulate.dev" target="_blank" rel="noopener">emulate</a></div>`;
|
|
922
1052
|
function emuBar(service) {
|
|
@@ -936,6 +1066,7 @@ function head(title) {
|
|
|
936
1066
|
<head>
|
|
937
1067
|
<meta charset="utf-8"/>
|
|
938
1068
|
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
1069
|
+
<link rel="icon" href="/_emulate/favicon.ico"/>
|
|
939
1070
|
<title>${escapeHtml(title)} | emulate</title>
|
|
940
1071
|
<style>${CSS}</style>
|
|
941
1072
|
</head>`;
|
|
@@ -1043,9 +1174,7 @@ function canAccessRepo(gh, authUser, repo) {
|
|
|
1043
1174
|
if (!user) return false;
|
|
1044
1175
|
if (repo.owner_type === "User" && repo.owner_id === user.id) return true;
|
|
1045
1176
|
if (repo.owner_type === "Organization" && isOrgMember(gh, user.id, repo.owner_id)) return true;
|
|
1046
|
-
return Boolean(
|
|
1047
|
-
gh.collaborators.findBy("repo_id", repo.id).find((c) => c.user_id === user.id)
|
|
1048
|
-
);
|
|
1177
|
+
return Boolean(gh.collaborators.findBy("repo_id", repo.id).find((c) => c.user_id === user.id));
|
|
1049
1178
|
}
|
|
1050
1179
|
function assertRepoRead(gh, authUser, repo) {
|
|
1051
1180
|
if (canAccessRepo(gh, authUser, repo)) return;
|
|
@@ -1084,9 +1213,7 @@ function assertIssueWrite(gh, authUser, repo) {
|
|
|
1084
1213
|
return user;
|
|
1085
1214
|
}
|
|
1086
1215
|
function listReposForUser(gh, user, type) {
|
|
1087
|
-
const owned = gh.repos.all().filter(
|
|
1088
|
-
(r) => r.owner_id === user.id && r.owner_type === "User"
|
|
1089
|
-
);
|
|
1216
|
+
const owned = gh.repos.all().filter((r) => r.owner_id === user.id && r.owner_type === "User");
|
|
1090
1217
|
const member = gh.collaborators.findBy("user_id", user.id).map((c) => gh.repos.get(c.repo_id)).filter((r) => Boolean(r)).filter((r) => !(r.owner_id === user.id && r.owner_type === "User"));
|
|
1091
1218
|
if (type === "owner") return owned;
|
|
1092
1219
|
if (type === "member") return member;
|
|
@@ -1214,10 +1341,7 @@ function usersRoutes({ app, store, baseUrl }) {
|
|
|
1214
1341
|
});
|
|
1215
1342
|
app.get("/users", (c) => {
|
|
1216
1343
|
const since = Math.max(0, parseInt(c.req.query("since") ?? "0", 10) || 0);
|
|
1217
|
-
const perPage = Math.min(
|
|
1218
|
-
100,
|
|
1219
|
-
Math.max(1, parseInt(c.req.query("per_page") ?? "30", 10) || 30)
|
|
1220
|
-
);
|
|
1344
|
+
const perPage = Math.min(100, Math.max(1, parseInt(c.req.query("per_page") ?? "30", 10) || 30));
|
|
1221
1345
|
const ordered = gh.users.all().filter((u) => u.id > since).sort((a, b) => a.id - b.id);
|
|
1222
1346
|
const page = ordered.slice(0, perPage);
|
|
1223
1347
|
if (page.length === perPage && ordered.length > perPage) {
|
|
@@ -1803,7 +1927,7 @@ function reposRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
1803
1927
|
let ownerType = "User";
|
|
1804
1928
|
let ownerId = user.id;
|
|
1805
1929
|
let fullName = "";
|
|
1806
|
-
|
|
1930
|
+
const forkName = typeof body.name === "string" && body.name.trim() ? validateRepoName(body.name) : parent.name;
|
|
1807
1931
|
if (typeof body.organization === "string" && body.organization.trim()) {
|
|
1808
1932
|
const org = gh.orgs.findOneBy("login", body.organization.trim());
|
|
1809
1933
|
if (!org) throw notFound();
|
|
@@ -1886,9 +2010,7 @@ function reposRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
1886
2010
|
const u = gh.users.get(col.user_id);
|
|
1887
2011
|
if (!u) return null;
|
|
1888
2012
|
return { user: u, permission: col.permission };
|
|
1889
|
-
}).filter(
|
|
1890
|
-
(x) => Boolean(x)
|
|
1891
|
-
).sort((a, b) => a.user.login.localeCompare(b.user.login));
|
|
2013
|
+
}).filter((x) => Boolean(x)).sort((a, b) => a.user.login.localeCompare(b.user.login));
|
|
1892
2014
|
const { page, per_page } = parsePagination(c);
|
|
1893
2015
|
const total = users.length;
|
|
1894
2016
|
const start = (page - 1) * per_page;
|
|
@@ -2009,9 +2131,7 @@ function reposRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
2009
2131
|
const repo = lookupRepo(gh, owner, repoName);
|
|
2010
2132
|
if (!repo) throw notFound();
|
|
2011
2133
|
assertRepoRead(gh, c.get("authUser"), repo);
|
|
2012
|
-
const tags = [...gh.tags.findBy("repo_id", repo.id)].sort(
|
|
2013
|
-
(a, b) => a.tag.localeCompare(b.tag)
|
|
2014
|
-
);
|
|
2134
|
+
const tags = [...gh.tags.findBy("repo_id", repo.id)].sort((a, b) => a.tag.localeCompare(b.tag));
|
|
2015
2135
|
const { page, per_page } = parsePagination(c);
|
|
2016
2136
|
const total = tags.length;
|
|
2017
2137
|
const start = (page - 1) * per_page;
|
|
@@ -2917,9 +3037,7 @@ function checkMergeRequirements(gh, pr) {
|
|
|
2917
3037
|
if (checks && checks.contexts.length > 0) {
|
|
2918
3038
|
const runs = gh.checkRuns.findBy("repo_id", baseRepo.id).filter((r) => r.head_sha === pr.head_sha);
|
|
2919
3039
|
for (const ctx of checks.contexts) {
|
|
2920
|
-
const ok = runs.some(
|
|
2921
|
-
(r) => r.name === ctx && r.status === "completed" && r.conclusion === "success"
|
|
2922
|
-
);
|
|
3040
|
+
const ok = runs.some((r) => r.name === ctx && r.status === "completed" && r.conclusion === "success");
|
|
2923
3041
|
if (!ok) {
|
|
2924
3042
|
throw new ApiError(422, "Required status checks have not succeeded.");
|
|
2925
3043
|
}
|
|
@@ -3353,9 +3471,7 @@ ${commitMessage}` : commitTitle;
|
|
|
3353
3471
|
changes: 1,
|
|
3354
3472
|
blob_url: `${baseUrl}/${repo.full_name}/blob/${pr.head_sha}/${filename}`,
|
|
3355
3473
|
raw_url: `${baseUrl}/${repo.full_name}/raw/${pr.head_sha}/${filename}`,
|
|
3356
|
-
contents_url: `${baseUrl}/repos/${repo.full_name}/contents/${encodeURIComponent(
|
|
3357
|
-
filename
|
|
3358
|
-
)}?ref=${pr.head_ref}`,
|
|
3474
|
+
contents_url: `${baseUrl}/repos/${repo.full_name}/contents/${encodeURIComponent(filename)}?ref=${pr.head_ref}`,
|
|
3359
3475
|
patch: ""
|
|
3360
3476
|
}))
|
|
3361
3477
|
);
|
|
@@ -4088,7 +4204,7 @@ function reviewsRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
4088
4204
|
const pr = findPull3(gh, repo.id, pullNumber);
|
|
4089
4205
|
if (!pr) throw notFound();
|
|
4090
4206
|
const { page, per_page } = parsePagination(c);
|
|
4091
|
-
|
|
4207
|
+
const list = gh.reviews.findBy("repo_id", repo.id).filter((r) => r.pull_number === pullNumber);
|
|
4092
4208
|
list.sort((a, b) => a.id - b.id);
|
|
4093
4209
|
const total = list.length;
|
|
4094
4210
|
setLinkHeader(c, total, page, per_page);
|
|
@@ -4283,9 +4399,7 @@ function reviewsRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
4283
4399
|
if (!review) throw notFound();
|
|
4284
4400
|
const { page, per_page } = parsePagination(c);
|
|
4285
4401
|
const { sort, direction } = parseCommentSort2(c, "asc");
|
|
4286
|
-
let list = gh.comments.findBy("repo_id", repo.id).filter(
|
|
4287
|
-
(x) => x.comment_type === "review" && x.pull_number === pullNumber && x.review_id === reviewId
|
|
4288
|
-
);
|
|
4402
|
+
let list = gh.comments.findBy("repo_id", repo.id).filter((x) => x.comment_type === "review" && x.pull_number === pullNumber && x.review_id === reviewId);
|
|
4289
4403
|
list = sortComments2(list, sort, direction);
|
|
4290
4404
|
const total = list.length;
|
|
4291
4405
|
setLinkHeader(c, total, page, per_page);
|
|
@@ -4340,7 +4454,7 @@ function normalizeColor(raw) {
|
|
|
4340
4454
|
if (typeof raw !== "string" || !raw.trim()) {
|
|
4341
4455
|
throw new ApiError(422, "Validation failed");
|
|
4342
4456
|
}
|
|
4343
|
-
|
|
4457
|
+
const s = raw.trim().replace(/^#/, "");
|
|
4344
4458
|
if (!/^[0-9a-fA-F]{6}$/.test(s)) {
|
|
4345
4459
|
throw new ApiError(422, "Validation failed");
|
|
4346
4460
|
}
|
|
@@ -4426,7 +4540,7 @@ function labelsAndMilestonesRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
4426
4540
|
if (!repo) throw notFound();
|
|
4427
4541
|
assertRepoRead(gh, c.get("authUser"), repo);
|
|
4428
4542
|
const { page, per_page } = parsePagination(c);
|
|
4429
|
-
|
|
4543
|
+
const list = gh.labels.findBy("repo_id", repo.id).slice();
|
|
4430
4544
|
list.sort((a, b) => a.name.localeCompare(b.name));
|
|
4431
4545
|
const total = list.length;
|
|
4432
4546
|
setLinkHeader(c, total, page, per_page);
|
|
@@ -4786,7 +4900,7 @@ function labelsAndMilestonesRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
4786
4900
|
creator_id: actor.id
|
|
4787
4901
|
});
|
|
4788
4902
|
gh.milestones.update(row.id, { node_id: generateNodeId("Milestone", row.id) });
|
|
4789
|
-
|
|
4903
|
+
const m = recalcMilestoneIssueCounts(gh, repo.id, row.id);
|
|
4790
4904
|
const ownerLogin2 = ownerLoginOf(gh, repo);
|
|
4791
4905
|
webhooks.dispatch(
|
|
4792
4906
|
"milestone",
|
|
@@ -4943,7 +5057,7 @@ function labelsAndMilestonesRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
4943
5057
|
if (i.milestone_id !== ms.id) continue;
|
|
4944
5058
|
for (const lid of i.label_ids) labelIdSet.add(lid);
|
|
4945
5059
|
}
|
|
4946
|
-
|
|
5060
|
+
const labels = [...labelIdSet].map((id) => gh.labels.get(id)).filter(Boolean);
|
|
4947
5061
|
labels.sort((a, b) => a.name.localeCompare(b.name));
|
|
4948
5062
|
const total = labels.length;
|
|
4949
5063
|
setLinkHeader(c, total, page, per_page);
|
|
@@ -5424,9 +5538,7 @@ function branchesAndGitRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
5424
5538
|
const repo = lookupRepo(gh, owner, repoName);
|
|
5425
5539
|
if (!repo) throw notFound();
|
|
5426
5540
|
assertRepoRead(gh, c.get("authUser"), repo);
|
|
5427
|
-
let list = [...gh.branches.findBy("repo_id", repo.id)].sort(
|
|
5428
|
-
(a, b) => a.name.localeCompare(b.name)
|
|
5429
|
-
);
|
|
5541
|
+
let list = [...gh.branches.findBy("repo_id", repo.id)].sort((a, b) => a.name.localeCompare(b.name));
|
|
5430
5542
|
const prot = c.req.query("protected");
|
|
5431
5543
|
if (prot === "true") list = list.filter((b) => b.protected);
|
|
5432
5544
|
else if (prot === "false") list = list.filter((b) => !b.protected);
|
|
@@ -5829,12 +5941,7 @@ function branchesAndGitRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
5829
5941
|
object: {
|
|
5830
5942
|
type: tag.object_type,
|
|
5831
5943
|
sha: tag.object_sha,
|
|
5832
|
-
url: objectApiUrl(
|
|
5833
|
-
repo,
|
|
5834
|
-
baseUrl,
|
|
5835
|
-
resolveGitObjectType(gh, repo.id, tag.object_sha),
|
|
5836
|
-
tag.object_sha
|
|
5837
|
-
)
|
|
5944
|
+
url: objectApiUrl(repo, baseUrl, resolveGitObjectType(gh, repo.id, tag.object_sha), tag.object_sha)
|
|
5838
5945
|
},
|
|
5839
5946
|
verification: { verified: false, reason: "unsigned", signature: null, payload: null, verified_at: null }
|
|
5840
5947
|
});
|
|
@@ -5890,12 +5997,7 @@ function branchesAndGitRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
5890
5997
|
object: {
|
|
5891
5998
|
type: saved.object_type,
|
|
5892
5999
|
sha: saved.object_sha,
|
|
5893
|
-
url: objectApiUrl(
|
|
5894
|
-
repo,
|
|
5895
|
-
baseUrl,
|
|
5896
|
-
resolveGitObjectType(gh, repo.id, saved.object_sha),
|
|
5897
|
-
saved.object_sha
|
|
5898
|
-
)
|
|
6000
|
+
url: objectApiUrl(repo, baseUrl, resolveGitObjectType(gh, repo.id, saved.object_sha), saved.object_sha)
|
|
5899
6001
|
},
|
|
5900
6002
|
verification: { verified: false, reason: "unsigned", signature: null, payload: null, verified_at: null }
|
|
5901
6003
|
},
|
|
@@ -6044,10 +6146,7 @@ function orgsAndTeamsRoutes({ app, store, baseUrl }) {
|
|
|
6044
6146
|
const gh = getGitHubStore(store);
|
|
6045
6147
|
app.get("/organizations", (c) => {
|
|
6046
6148
|
const since = Math.max(0, parseInt(c.req.query("since") ?? "0", 10) || 0);
|
|
6047
|
-
const perPage = Math.min(
|
|
6048
|
-
100,
|
|
6049
|
-
Math.max(1, parseInt(c.req.query("per_page") ?? "30", 10) || 30)
|
|
6050
|
-
);
|
|
6149
|
+
const perPage = Math.min(100, Math.max(1, parseInt(c.req.query("per_page") ?? "30", 10) || 30));
|
|
6051
6150
|
const ordered = gh.orgs.all().filter((o) => o.id > since).sort((a, b) => a.id - b.id);
|
|
6052
6151
|
const page = ordered.slice(0, perPage);
|
|
6053
6152
|
if (page.length === perPage && ordered.length > perPage) {
|
|
@@ -6549,9 +6648,7 @@ _Auto-generated release notes (stub)._
|
|
|
6549
6648
|
const repo = lookupRepo(gh, owner, repoName);
|
|
6550
6649
|
if (!repo) throw notFound();
|
|
6551
6650
|
assertRepoRead(gh, c.get("authUser"), repo);
|
|
6552
|
-
const candidates = releasesForRepo(gh, repo.id).filter(
|
|
6553
|
-
(r) => !r.draft && !r.prerelease && r.published_at
|
|
6554
|
-
);
|
|
6651
|
+
const candidates = releasesForRepo(gh, repo.id).filter((r) => !r.draft && !r.prerelease && r.published_at);
|
|
6555
6652
|
if (candidates.length === 0) throw notFound();
|
|
6556
6653
|
candidates.sort((a, b) => {
|
|
6557
6654
|
const pa = a.published_at ?? a.created_at;
|
|
@@ -7762,9 +7859,7 @@ function searchRoutes({ app, store, baseUrl }) {
|
|
|
7762
7859
|
(a, b) => order === "desc" ? b.stargazers_count - a.stargazers_count : a.stargazers_count - b.stargazers_count
|
|
7763
7860
|
);
|
|
7764
7861
|
} else if (sortRaw === "forks") {
|
|
7765
|
-
list.sort(
|
|
7766
|
-
(a, b) => order === "desc" ? b.forks_count - a.forks_count : a.forks_count - b.forks_count
|
|
7767
|
-
);
|
|
7862
|
+
list.sort((a, b) => order === "desc" ? b.forks_count - a.forks_count : a.forks_count - b.forks_count);
|
|
7768
7863
|
} else if (sortRaw === "updated") {
|
|
7769
7864
|
list.sort(
|
|
7770
7865
|
(a, b) => order === "desc" ? b.updated_at.localeCompare(a.updated_at) : a.updated_at.localeCompare(b.updated_at)
|
|
@@ -7816,7 +7911,7 @@ function searchRoutes({ app, store, baseUrl }) {
|
|
|
7816
7911
|
if (body.toLowerCase().includes(t)) s += 1;
|
|
7817
7912
|
return s;
|
|
7818
7913
|
}
|
|
7819
|
-
|
|
7914
|
+
const sorted = [...hits];
|
|
7820
7915
|
if (sortRaw === "created") {
|
|
7821
7916
|
sorted.sort((a, b) => {
|
|
7822
7917
|
const ca = a.kind === "issue" ? a.issue.created_at : a.pr.created_at;
|
|
@@ -7891,7 +7986,7 @@ function searchRoutes({ app, store, baseUrl }) {
|
|
|
7891
7986
|
if (h.o.name?.toLowerCase().includes(text)) s += 1;
|
|
7892
7987
|
return s;
|
|
7893
7988
|
}
|
|
7894
|
-
|
|
7989
|
+
const list = [...hits];
|
|
7895
7990
|
if (sortRaw === "followers") {
|
|
7896
7991
|
list.sort((a, b) => {
|
|
7897
7992
|
const fa = a.kind === "user" ? a.u.followers : a.o.followers;
|
|
@@ -7917,9 +8012,7 @@ function searchRoutes({ app, store, baseUrl }) {
|
|
|
7917
8012
|
const total = list.length;
|
|
7918
8013
|
const slice = list.slice((page - 1) * per_page, (page - 1) * per_page + per_page);
|
|
7919
8014
|
setLinkHeader(c, total, page, per_page);
|
|
7920
|
-
const items = slice.map(
|
|
7921
|
-
(h) => h.kind === "user" ? formatUser(h.u, baseUrl) : formatOrgBrief(h.o, baseUrl)
|
|
7922
|
-
);
|
|
8015
|
+
const items = slice.map((h) => h.kind === "user" ? formatUser(h.u, baseUrl) : formatOrgBrief(h.o, baseUrl));
|
|
7923
8016
|
return c.json({
|
|
7924
8017
|
total_count: total,
|
|
7925
8018
|
incomplete_results: false,
|
|
@@ -8368,7 +8461,13 @@ function formatArtifact(a, repo, gh, baseUrl) {
|
|
|
8368
8461
|
digest: null,
|
|
8369
8462
|
created_at: a.created_at,
|
|
8370
8463
|
expires_at: a.expires_at,
|
|
8371
|
-
workflow_run: run ? {
|
|
8464
|
+
workflow_run: run ? {
|
|
8465
|
+
id: run.id,
|
|
8466
|
+
repository_id: repo.id,
|
|
8467
|
+
head_repository_id: repo.id,
|
|
8468
|
+
head_branch: run.head_branch,
|
|
8469
|
+
head_sha: run.head_sha
|
|
8470
|
+
} : null
|
|
8372
8471
|
};
|
|
8373
8472
|
}
|
|
8374
8473
|
function filterRuns(gh, runs, q) {
|
|
@@ -8486,7 +8585,11 @@ function actionsRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
8486
8585
|
void webhooks.dispatch(
|
|
8487
8586
|
"workflow_run",
|
|
8488
8587
|
"requested",
|
|
8489
|
-
{
|
|
8588
|
+
{
|
|
8589
|
+
workflow_run: formatWorkflowRun(created, repo, gh, baseUrl),
|
|
8590
|
+
repository: formatRepo(repo, gh, baseUrl),
|
|
8591
|
+
sender: formatUser(actor, baseUrl)
|
|
8592
|
+
},
|
|
8490
8593
|
ownerLogin2,
|
|
8491
8594
|
repo.name
|
|
8492
8595
|
);
|
|
@@ -8642,13 +8745,11 @@ function actionsRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
8642
8745
|
const runId = parseInt(c.req.param("run_id"), 10);
|
|
8643
8746
|
const run = gh.workflowRuns.get(runId);
|
|
8644
8747
|
if (!run || run.repo_id !== repo.id) throw notFound();
|
|
8645
|
-
return c.text(
|
|
8646
|
-
`2025-01-01T00:00:00.0000000Z Workflow run ${run.id} logs (stub)
|
|
8748
|
+
return c.text(`2025-01-01T00:00:00.0000000Z Workflow run ${run.id} logs (stub)
|
|
8647
8749
|
${run.head_sha}
|
|
8648
|
-
`,
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
);
|
|
8750
|
+
`, 200, {
|
|
8751
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
8752
|
+
});
|
|
8652
8753
|
});
|
|
8653
8754
|
app.get("/repos/:owner/:repo/actions/runs/:run_id/jobs", (c) => {
|
|
8654
8755
|
const owner = c.req.param("owner");
|
|
@@ -8967,15 +9068,7 @@ function parseConclusion(raw) {
|
|
|
8967
9068
|
if (raw === void 0) return void 0;
|
|
8968
9069
|
if (raw === null) return null;
|
|
8969
9070
|
if (typeof raw !== "string") throw new ApiError(422, "Invalid conclusion");
|
|
8970
|
-
const allowed = /* @__PURE__ */ new Set([
|
|
8971
|
-
"success",
|
|
8972
|
-
"failure",
|
|
8973
|
-
"neutral",
|
|
8974
|
-
"cancelled",
|
|
8975
|
-
"skipped",
|
|
8976
|
-
"timed_out",
|
|
8977
|
-
"action_required"
|
|
8978
|
-
]);
|
|
9071
|
+
const allowed = /* @__PURE__ */ new Set(["success", "failure", "neutral", "cancelled", "skipped", "timed_out", "action_required"]);
|
|
8979
9072
|
if (!allowed.has(raw)) throw new ApiError(422, "Invalid conclusion");
|
|
8980
9073
|
return raw;
|
|
8981
9074
|
}
|
|
@@ -9359,7 +9452,7 @@ function checksRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
9359
9452
|
};
|
|
9360
9453
|
}
|
|
9361
9454
|
const nextStatus = patch.status ?? prev.status;
|
|
9362
|
-
|
|
9455
|
+
const nextConclusion = patch.conclusion !== void 0 ? patch.conclusion : prev.conclusion;
|
|
9363
9456
|
if (patch.head_sha && patch.head_sha !== prev.head_sha) {
|
|
9364
9457
|
const newSuite = getOrCreateCheckSuite(gh, repo, patch.head_sha, null);
|
|
9365
9458
|
patch.check_suite_id = newSuite.id;
|
|
@@ -9369,7 +9462,7 @@ function checksRoutes({ app, store, webhooks, baseUrl }) {
|
|
|
9369
9462
|
throw new ApiError(422, "conclusion is required when status is completed");
|
|
9370
9463
|
}
|
|
9371
9464
|
patch.conclusion = nextConclusion;
|
|
9372
|
-
|
|
9465
|
+
const nextCompleted = patch.completed_at !== void 0 ? patch.completed_at : prev.completed_at;
|
|
9373
9466
|
if (!nextCompleted) {
|
|
9374
9467
|
patch.completed_at = timestamp();
|
|
9375
9468
|
}
|
|
@@ -9506,7 +9599,13 @@ function rateLimitRoutes({ app }) {
|
|
|
9506
9599
|
integration_manifest: { limit: 5e3, remaining: 4999, reset, used: 1, resource: "integration_manifest" },
|
|
9507
9600
|
source_import: { limit: 100, remaining: 99, reset, used: 1, resource: "source_import" },
|
|
9508
9601
|
code_scanning_upload: { limit: 500, remaining: 499, reset, used: 1, resource: "code_scanning_upload" },
|
|
9509
|
-
actions_runner_registration: {
|
|
9602
|
+
actions_runner_registration: {
|
|
9603
|
+
limit: 1e4,
|
|
9604
|
+
remaining: 9999,
|
|
9605
|
+
reset,
|
|
9606
|
+
used: 1,
|
|
9607
|
+
resource: "actions_runner_registration"
|
|
9608
|
+
},
|
|
9510
9609
|
scim: { limit: 15e3, remaining: 14999, reset, used: 1, resource: "scim" }
|
|
9511
9610
|
},
|
|
9512
9611
|
rate: rateLimit
|
|
@@ -9582,13 +9681,13 @@ function metaRoutes({ app, baseUrl }) {
|
|
|
9582
9681
|
"+1": `${baseUrl}/emojis/+1.png`,
|
|
9583
9682
|
"-1": `${baseUrl}/emojis/-1.png`,
|
|
9584
9683
|
"100": `${baseUrl}/emojis/100.png`,
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9684
|
+
tada: `${baseUrl}/emojis/tada.png`,
|
|
9685
|
+
rocket: `${baseUrl}/emojis/rocket.png`,
|
|
9686
|
+
heart: `${baseUrl}/emojis/heart.png`,
|
|
9687
|
+
eyes: `${baseUrl}/emojis/eyes.png`,
|
|
9688
|
+
thinking: `${baseUrl}/emojis/thinking.png`,
|
|
9689
|
+
thumbsup: `${baseUrl}/emojis/thumbsup.png`,
|
|
9690
|
+
thumbsdown: `${baseUrl}/emojis/thumbsdown.png`
|
|
9592
9691
|
});
|
|
9593
9692
|
});
|
|
9594
9693
|
app.get("/zen", (c) => {
|
|
@@ -9685,9 +9784,15 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9685
9784
|
);
|
|
9686
9785
|
}
|
|
9687
9786
|
if (redirect_uri && !matchesRedirectUri(redirect_uri, oauthApp.redirect_uris)) {
|
|
9688
|
-
console.warn(
|
|
9787
|
+
console.warn(
|
|
9788
|
+
`[OAuth] redirect_uri mismatch: got "${redirect_uri}", registered: ${JSON.stringify(oauthApp.redirect_uris)}`
|
|
9789
|
+
);
|
|
9689
9790
|
return c.html(
|
|
9690
|
-
renderErrorPage(
|
|
9791
|
+
renderErrorPage(
|
|
9792
|
+
"Redirect URI mismatch",
|
|
9793
|
+
"The redirect_uri is not registered for this application.",
|
|
9794
|
+
SERVICE_LABEL
|
|
9795
|
+
),
|
|
9691
9796
|
400
|
|
9692
9797
|
);
|
|
9693
9798
|
}
|
|
@@ -9731,7 +9836,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9731
9836
|
clientId: client_id,
|
|
9732
9837
|
created_at: Date.now()
|
|
9733
9838
|
});
|
|
9734
|
-
debug(
|
|
9839
|
+
debug(
|
|
9840
|
+
"github.oauth",
|
|
9841
|
+
`[OAuth callback] generated code: ${code.slice(0, 8)}... for login=${login}, pendingCodes size: ${getPendingCodes(store).size}`
|
|
9842
|
+
);
|
|
9735
9843
|
const sessionId = randomBytes2(24).toString("base64url");
|
|
9736
9844
|
getSessionMap(store).set(sessionId, login);
|
|
9737
9845
|
c.header("Set-Cookie", `_emu_session=${sessionId}; Path=/; HttpOnly; SameSite=Lax`);
|
|
@@ -9746,7 +9854,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9746
9854
|
debug("github.oauth", `[OAuth token] Content-Type: ${contentType}`);
|
|
9747
9855
|
debug("github.oauth", `[OAuth token] Accept: ${accept}`);
|
|
9748
9856
|
debug("github.oauth", `[OAuth token] pendingCodes size: ${getPendingCodes(store).size}`);
|
|
9749
|
-
debug(
|
|
9857
|
+
debug(
|
|
9858
|
+
"github.oauth",
|
|
9859
|
+
`[OAuth token] pendingCodes keys: ${[...getPendingCodes(store).keys()].map((k) => k.slice(0, 8) + "...").join(", ")}`
|
|
9860
|
+
);
|
|
9750
9861
|
const rawText = await c.req.text();
|
|
9751
9862
|
debug("github.oauth", `[OAuth token] raw body: ${rawText.slice(0, 500)}`);
|
|
9752
9863
|
let raw;
|
|
@@ -9817,14 +9928,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9817
9928
|
}
|
|
9818
9929
|
const oauthApp = gh.oauthApps.findOneBy("client_id", pending.clientId);
|
|
9819
9930
|
if (oauthApp) {
|
|
9820
|
-
const existingGrant = gh.oauthGrants.all().find(
|
|
9821
|
-
(g) => g.user_id === user.id && g.client_id === pending.clientId
|
|
9822
|
-
);
|
|
9931
|
+
const existingGrant = gh.oauthGrants.all().find((g) => g.user_id === user.id && g.client_id === pending.clientId);
|
|
9823
9932
|
const orgAccess = {};
|
|
9824
9933
|
for (const org of gh.orgs.all()) {
|
|
9825
|
-
const isMember = gh.teamMembers.all().some(
|
|
9826
|
-
(tm) => tm.user_id === user.id && gh.teams.get(tm.team_id)?.org_id === org.id
|
|
9827
|
-
);
|
|
9934
|
+
const isMember = gh.teamMembers.all().some((tm) => tm.user_id === user.id && gh.teams.get(tm.team_id)?.org_id === org.id);
|
|
9828
9935
|
if (isMember) orgAccess[org.login] = "granted";
|
|
9829
9936
|
}
|
|
9830
9937
|
if (existingGrant) {
|
|
@@ -9874,19 +9981,19 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9874
9981
|
]);
|
|
9875
9982
|
});
|
|
9876
9983
|
const SCOPE_LABELS = {
|
|
9877
|
-
|
|
9984
|
+
repo: "Full control of private repositories",
|
|
9878
9985
|
"read:user": "Read all user profile data",
|
|
9879
9986
|
"user:email": "Access user email addresses (read-only)",
|
|
9880
|
-
|
|
9881
|
-
|
|
9987
|
+
user: "Full control of user profile",
|
|
9988
|
+
workflow: "Update GitHub action workflows",
|
|
9882
9989
|
"admin:org": "Full control of orgs and teams",
|
|
9883
9990
|
"admin:repo_hook": "Full control of repository hooks",
|
|
9884
9991
|
"read:org": "Read org and team membership",
|
|
9885
9992
|
"write:repo_hook": "Write repository hooks",
|
|
9886
9993
|
"read:repo_hook": "Read repository hooks",
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9994
|
+
delete_repo: "Delete repositories",
|
|
9995
|
+
gist: "Create gists",
|
|
9996
|
+
notifications: "Access notifications",
|
|
9890
9997
|
"write:packages": "Upload packages",
|
|
9891
9998
|
"read:packages": "Download packages",
|
|
9892
9999
|
"admin:gpg_key": "Full control of GPG keys",
|
|
@@ -9900,7 +10007,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9900
10007
|
app.get("/settings/applications", (c) => {
|
|
9901
10008
|
const sessionUser = resolveSessionUser(c);
|
|
9902
10009
|
if (!sessionUser) {
|
|
9903
|
-
return c.html(
|
|
10010
|
+
return c.html(
|
|
10011
|
+
renderErrorPage("Unauthorized", "You must be authenticated to view this page.", SERVICE_LABEL),
|
|
10012
|
+
401
|
|
10013
|
+
);
|
|
9904
10014
|
}
|
|
9905
10015
|
const grants = gh.oauthGrants.findBy("user_id", sessionUser.id);
|
|
9906
10016
|
let bodyHtml;
|
|
@@ -9933,12 +10043,13 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9933
10043
|
app.get("/settings/connections/applications/:client_id", (c) => {
|
|
9934
10044
|
const sessionUser = resolveSessionUser(c);
|
|
9935
10045
|
if (!sessionUser) {
|
|
9936
|
-
return c.html(
|
|
10046
|
+
return c.html(
|
|
10047
|
+
renderErrorPage("Unauthorized", "You must be authenticated to view this page.", SERVICE_LABEL),
|
|
10048
|
+
401
|
|
10049
|
+
);
|
|
9937
10050
|
}
|
|
9938
10051
|
const clientId = c.req.param("client_id");
|
|
9939
|
-
const grant = gh.oauthGrants.all().find(
|
|
9940
|
-
(g) => g.user_id === sessionUser.id && g.client_id === clientId
|
|
9941
|
-
);
|
|
10052
|
+
const grant = gh.oauthGrants.all().find((g) => g.user_id === sessionUser.id && g.client_id === clientId);
|
|
9942
10053
|
if (!grant) {
|
|
9943
10054
|
return c.html(renderErrorPage("Not Found", "No authorization found for this application.", SERVICE_LABEL), 404);
|
|
9944
10055
|
}
|
|
@@ -9950,9 +10061,7 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9950
10061
|
month: "long",
|
|
9951
10062
|
day: "numeric"
|
|
9952
10063
|
});
|
|
9953
|
-
const permRows = grant.scopes.map(
|
|
9954
|
-
(s) => `<li><span class="check">✓</span> ${escapeHtml(scopeLabel(s))}</li>`
|
|
9955
|
-
).join("\n");
|
|
10064
|
+
const permRows = grant.scopes.map((s) => `<li><span class="check">✓</span> ${escapeHtml(scopeLabel(s))}</li>`).join("\n");
|
|
9956
10065
|
const orgRows = Object.entries(grant.org_access).map(([org, status]) => {
|
|
9957
10066
|
const letter = escapeHtml((org[0] ?? "?").toUpperCase());
|
|
9958
10067
|
const badgeClass = status === "granted" ? "badge-granted" : status === "denied" ? "badge-denied" : "badge-requested";
|
|
@@ -9996,12 +10105,13 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
9996
10105
|
app.post("/settings/connections/applications/:client_id/revoke", (c) => {
|
|
9997
10106
|
const sessionUser = resolveSessionUser(c);
|
|
9998
10107
|
if (!sessionUser) {
|
|
9999
|
-
return c.html(
|
|
10108
|
+
return c.html(
|
|
10109
|
+
renderErrorPage("Unauthorized", "You must be authenticated to perform this action.", SERVICE_LABEL),
|
|
10110
|
+
401
|
|
10111
|
+
);
|
|
10000
10112
|
}
|
|
10001
10113
|
const clientId = c.req.param("client_id");
|
|
10002
|
-
const grant = gh.oauthGrants.all().find(
|
|
10003
|
-
(g) => g.user_id === sessionUser.id && g.client_id === clientId
|
|
10004
|
-
);
|
|
10114
|
+
const grant = gh.oauthGrants.all().find((g) => g.user_id === sessionUser.id && g.client_id === clientId);
|
|
10005
10115
|
if (grant) {
|
|
10006
10116
|
gh.oauthGrants.delete(grant.id);
|
|
10007
10117
|
}
|
|
@@ -10029,10 +10139,13 @@ function appsRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
10029
10139
|
app.get("/app", (c) => {
|
|
10030
10140
|
const authApp = requireApp(c);
|
|
10031
10141
|
if (!authApp) {
|
|
10032
|
-
return c.json(
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10142
|
+
return c.json(
|
|
10143
|
+
{
|
|
10144
|
+
message: "A JSON web token could not be decoded",
|
|
10145
|
+
documentation_url: "https://docs.github.com/rest"
|
|
10146
|
+
},
|
|
10147
|
+
401
|
|
10148
|
+
);
|
|
10036
10149
|
}
|
|
10037
10150
|
const ghApp = gh.apps.all().find((a) => a.app_id === authApp.appId);
|
|
10038
10151
|
if (!ghApp) {
|
|
@@ -10058,29 +10171,31 @@ function appsRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
10058
10171
|
app.get("/app/installations", (c) => {
|
|
10059
10172
|
const authApp = requireApp(c);
|
|
10060
10173
|
if (!authApp) {
|
|
10061
|
-
return c.json(
|
|
10062
|
-
|
|
10063
|
-
|
|
10064
|
-
|
|
10174
|
+
return c.json(
|
|
10175
|
+
{
|
|
10176
|
+
message: "A JSON web token could not be decoded",
|
|
10177
|
+
documentation_url: "https://docs.github.com/rest"
|
|
10178
|
+
},
|
|
10179
|
+
401
|
|
10180
|
+
);
|
|
10065
10181
|
}
|
|
10066
10182
|
const installations = gh.appInstallations.findBy("app_id", authApp.appId);
|
|
10067
10183
|
const ghApp = gh.apps.all().find((a) => a.app_id === authApp.appId);
|
|
10068
|
-
return c.json(
|
|
10069
|
-
installations.map((inst) => formatInstallation(inst, ghApp, baseUrl))
|
|
10070
|
-
);
|
|
10184
|
+
return c.json(installations.map((inst) => formatInstallation(inst, ghApp, baseUrl)));
|
|
10071
10185
|
});
|
|
10072
10186
|
app.get("/app/installations/:installation_id", (c) => {
|
|
10073
10187
|
const authApp = requireApp(c);
|
|
10074
10188
|
if (!authApp) {
|
|
10075
|
-
return c.json(
|
|
10076
|
-
|
|
10077
|
-
|
|
10078
|
-
|
|
10189
|
+
return c.json(
|
|
10190
|
+
{
|
|
10191
|
+
message: "A JSON web token could not be decoded",
|
|
10192
|
+
documentation_url: "https://docs.github.com/rest"
|
|
10193
|
+
},
|
|
10194
|
+
401
|
|
10195
|
+
);
|
|
10079
10196
|
}
|
|
10080
10197
|
const installationId = parseInt(c.req.param("installation_id"), 10);
|
|
10081
|
-
const inst = gh.appInstallations.all().find(
|
|
10082
|
-
(i) => i.installation_id === installationId && i.app_id === authApp.appId
|
|
10083
|
-
);
|
|
10198
|
+
const inst = gh.appInstallations.all().find((i) => i.installation_id === installationId && i.app_id === authApp.appId);
|
|
10084
10199
|
if (!inst) {
|
|
10085
10200
|
return c.json({ message: "Not Found", documentation_url: "https://docs.github.com/rest" }, 404);
|
|
10086
10201
|
}
|
|
@@ -10090,15 +10205,16 @@ function appsRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
10090
10205
|
app.post("/app/installations/:installation_id/access_tokens", async (c) => {
|
|
10091
10206
|
const authApp = requireApp(c);
|
|
10092
10207
|
if (!authApp) {
|
|
10093
|
-
return c.json(
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10208
|
+
return c.json(
|
|
10209
|
+
{
|
|
10210
|
+
message: "A JSON web token could not be decoded",
|
|
10211
|
+
documentation_url: "https://docs.github.com/rest"
|
|
10212
|
+
},
|
|
10213
|
+
401
|
|
10214
|
+
);
|
|
10097
10215
|
}
|
|
10098
10216
|
const installationId = parseInt(c.req.param("installation_id"), 10);
|
|
10099
|
-
const inst = gh.appInstallations.all().find(
|
|
10100
|
-
(i) => i.installation_id === installationId && i.app_id === authApp.appId
|
|
10101
|
-
);
|
|
10217
|
+
const inst = gh.appInstallations.all().find((i) => i.installation_id === installationId && i.app_id === authApp.appId);
|
|
10102
10218
|
if (!inst) {
|
|
10103
10219
|
return c.json({ message: "Not Found", documentation_url: "https://docs.github.com/rest" }, 404);
|
|
10104
10220
|
}
|
|
@@ -10132,13 +10248,16 @@ function appsRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
10132
10248
|
full_name: r.full_name,
|
|
10133
10249
|
private: r.private
|
|
10134
10250
|
}));
|
|
10135
|
-
return c.json(
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10251
|
+
return c.json(
|
|
10252
|
+
{
|
|
10253
|
+
token,
|
|
10254
|
+
expires_at: expiresAt,
|
|
10255
|
+
permissions: requestedPermissions,
|
|
10256
|
+
repository_selection: inst.repository_selection,
|
|
10257
|
+
...inst.repository_selection === "selected" ? { repositories: repos } : {}
|
|
10258
|
+
},
|
|
10259
|
+
201
|
|
10260
|
+
);
|
|
10142
10261
|
});
|
|
10143
10262
|
app.get("/repos/:owner/:repo/installation", (c) => {
|
|
10144
10263
|
const owner = c.req.param("owner");
|
|
@@ -10167,9 +10286,7 @@ function appsRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
10167
10286
|
if (!org) {
|
|
10168
10287
|
return c.json({ message: "Not Found", documentation_url: "https://docs.github.com/rest" }, 404);
|
|
10169
10288
|
}
|
|
10170
|
-
const inst = gh.appInstallations.all().find(
|
|
10171
|
-
(i) => i.account_id === org.id && i.account_type === "Organization"
|
|
10172
|
-
);
|
|
10289
|
+
const inst = gh.appInstallations.all().find((i) => i.account_id === org.id && i.account_type === "Organization");
|
|
10173
10290
|
if (!inst) {
|
|
10174
10291
|
return c.json({ message: "Not Found", documentation_url: "https://docs.github.com/rest" }, 404);
|
|
10175
10292
|
}
|
|
@@ -10182,9 +10299,7 @@ function appsRoutes({ app, store, baseUrl, tokenMap }) {
|
|
|
10182
10299
|
if (!user) {
|
|
10183
10300
|
return c.json({ message: "Not Found", documentation_url: "https://docs.github.com/rest" }, 404);
|
|
10184
10301
|
}
|
|
10185
|
-
const inst = gh.appInstallations.all().find(
|
|
10186
|
-
(i) => i.account_id === user.id && i.account_type === "User"
|
|
10187
|
-
);
|
|
10302
|
+
const inst = gh.appInstallations.all().find((i) => i.account_id === user.id && i.account_type === "User");
|
|
10188
10303
|
if (!inst) {
|
|
10189
10304
|
return c.json({ message: "Not Found", documentation_url: "https://docs.github.com/rest" }, 404);
|
|
10190
10305
|
}
|
|
@@ -10583,4 +10698,4 @@ export {
|
|
|
10583
10698
|
githubPlugin,
|
|
10584
10699
|
seedFromConfig
|
|
10585
10700
|
};
|
|
10586
|
-
//# sourceMappingURL=dist-
|
|
10701
|
+
//# sourceMappingURL=dist-REDHDZ3V.js.map
|