emulate 0.4.1 → 0.6.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 +198 -27
- package/dist/api.d.ts +2 -1
- package/dist/api.js +675 -103
- package/dist/api.js.map +1 -1
- package/dist/chunk-WVQMFHQM.js +83 -0
- package/dist/chunk-WVQMFHQM.js.map +1 -0
- package/dist/{dist-B674PYKV.js → dist-2ZZGNPJI.js} +22 -43
- package/dist/dist-2ZZGNPJI.js.map +1 -0
- package/dist/{dist-RDFBZ5O6.js → dist-CXRPM6BK.js} +211 -48
- package/dist/dist-CXRPM6BK.js.map +1 -0
- package/dist/{dist-VVXVP5EZ.js → dist-DSJSF3GY.js} +551 -91
- package/dist/dist-DSJSF3GY.js.map +1 -0
- package/dist/{dist-RMK3BS5M.js → dist-IFULY5LE.js} +196 -33
- package/dist/dist-IFULY5LE.js.map +1 -0
- package/dist/dist-IRUBHCZU.js +1898 -0
- package/dist/dist-IRUBHCZU.js.map +1 -0
- package/dist/{dist-YOVM5HEY.js → dist-NJJLJT2N.js} +520 -61
- package/dist/dist-NJJLJT2N.js.map +1 -0
- package/dist/dist-OGSAVJ25.js +4874 -0
- package/dist/dist-OGSAVJ25.js.map +1 -0
- package/dist/{dist-H6JYGQM4.js → dist-PO4CL5SJ.js} +271 -158
- package/dist/dist-PO4CL5SJ.js.map +1 -0
- package/dist/{dist-QMOJM6DV.js → dist-R3TNKUIE.js} +238 -55
- package/dist/dist-R3TNKUIE.js.map +1 -0
- package/dist/{dist-6JFNJPUU.js → dist-WACHAAVU.js} +171 -22
- package/dist/dist-WACHAAVU.js.map +1 -0
- package/dist/{dist-OTJZRQ3Q.js → dist-XWWZVLQQ.js} +216 -75
- package/dist/dist-XWWZVLQQ.js.map +1 -0
- package/dist/{dist-6EW7SSOZ.js → dist-ZY5SZSJ2.js} +397 -223
- package/dist/dist-ZY5SZSJ2.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 +812 -117
- package/dist/index.js.map +1 -1
- package/package.json +17 -15
- package/dist/chunk-TEPNEZ63.js +0 -2143
- 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 +0 -1287
- 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,5 +1,3 @@
|
|
|
1
|
-
import "./chunk-TEPNEZ63.js";
|
|
2
|
-
|
|
3
1
|
// ../@emulators/vercel/dist/index.js
|
|
4
2
|
import { randomBytes } from "crypto";
|
|
5
3
|
import { readFileSync } from "fs";
|
|
@@ -15,7 +13,10 @@ function getVercelStore(store) {
|
|
|
15
13
|
teamMembers: store.collection("vercel.team_members", ["teamId", "userId"]),
|
|
16
14
|
projects: store.collection("vercel.projects", ["uid", "name", "accountId"]),
|
|
17
15
|
deployments: store.collection("vercel.deployments", ["uid", "projectId", "url"]),
|
|
18
|
-
deploymentAliases: store.collection("vercel.deployment_aliases", [
|
|
16
|
+
deploymentAliases: store.collection("vercel.deployment_aliases", [
|
|
17
|
+
"deploymentId",
|
|
18
|
+
"projectId"
|
|
19
|
+
]),
|
|
19
20
|
builds: store.collection("vercel.builds", ["deploymentId"]),
|
|
20
21
|
deploymentEvents: store.collection("vercel.deployment_events", ["deploymentId"]),
|
|
21
22
|
files: store.collection("vercel.files", ["digest"]),
|
|
@@ -57,7 +58,7 @@ function resolveTeamScope(c, vs) {
|
|
|
57
58
|
return { accountId: user.uid, team: null };
|
|
58
59
|
}
|
|
59
60
|
function lookupProject(vs, idOrName, accountId) {
|
|
60
|
-
|
|
61
|
+
const project = vs.projects.findOneBy("uid", idOrName);
|
|
61
62
|
if (project && project.accountId === accountId) return project;
|
|
62
63
|
const byName = vs.projects.findBy("name", idOrName);
|
|
63
64
|
return byName.find((p) => p.accountId === accountId);
|
|
@@ -285,6 +286,7 @@ var FONTS = {
|
|
|
285
286
|
"geist-sans.woff2": readFileSync(join(__dirname, "fonts", "geist-sans.woff2")),
|
|
286
287
|
"GeistPixel-Square.woff2": readFileSync(join(__dirname, "fonts", "GeistPixel-Square.woff2"))
|
|
287
288
|
};
|
|
289
|
+
var FAVICON = readFileSync(join(__dirname, "fonts", "favicon.ico"));
|
|
288
290
|
function escapeHtml(s) {
|
|
289
291
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
290
292
|
}
|
|
@@ -436,6 +438,132 @@ body{
|
|
|
436
438
|
.app-link-name{font-weight:600;font-size:.875rem;color:#33ff00;}
|
|
437
439
|
.app-link-scopes{font-size:.6875rem;color:#1a8c00;margin-top:1px;}
|
|
438
440
|
.empty{color:#1a8c00;text-align:center;padding:28px 0;font-size:.875rem;}
|
|
441
|
+
|
|
442
|
+
.inspector-layout{max-width:960px;margin:0 auto;padding:28px 20px;}
|
|
443
|
+
.inspector-tabs{display:flex;gap:4px;margin-bottom:20px;}
|
|
444
|
+
.inspector-tabs a{
|
|
445
|
+
padding:7px 16px;border-radius:6px;text-decoration:none;
|
|
446
|
+
font-size:.8125rem;color:#1a8c00;border:1px solid transparent;
|
|
447
|
+
transition:color .15s,border-color .15s;
|
|
448
|
+
}
|
|
449
|
+
.inspector-tabs a:hover{color:#33ff00;}
|
|
450
|
+
.inspector-tabs a.active{color:#33ff00;font-weight:600;border-color:#0a3300;background:#0a3300;}
|
|
451
|
+
.inspector-section{margin-bottom:24px;}
|
|
452
|
+
.inspector-section h2{
|
|
453
|
+
font-family:'Geist Pixel',monospace;
|
|
454
|
+
font-size:1rem;font-weight:600;color:#33ff00;margin-bottom:10px;
|
|
455
|
+
}
|
|
456
|
+
.inspector-section h3{
|
|
457
|
+
font-family:'Geist Pixel',monospace;
|
|
458
|
+
font-size:.875rem;font-weight:600;color:#1a8c00;margin:16px 0 8px;
|
|
459
|
+
}
|
|
460
|
+
.inspector-table{width:100%;border-collapse:collapse;margin-bottom:12px;}
|
|
461
|
+
.inspector-table th,.inspector-table td{
|
|
462
|
+
text-align:left;padding:8px 12px;border-bottom:1px solid #0a3300;
|
|
463
|
+
font-size:.8125rem;
|
|
464
|
+
}
|
|
465
|
+
.inspector-table th{color:#1a8c00;font-weight:600;font-size:.75rem;text-transform:uppercase;letter-spacing:.04em;}
|
|
466
|
+
.inspector-table td{color:#33ff00;}
|
|
467
|
+
.inspector-table tbody tr{transition:background .1s;}
|
|
468
|
+
.inspector-table tbody tr:hover{background:#0a3300;}
|
|
469
|
+
.inspector-empty{color:#1a8c00;text-align:center;padding:20px 0;font-size:.8125rem;}
|
|
470
|
+
|
|
471
|
+
.checkout-layout{
|
|
472
|
+
display:flex;min-height:calc(100vh - 42px);
|
|
473
|
+
}
|
|
474
|
+
.checkout-summary{
|
|
475
|
+
flex:1;background:#020;padding:48px 40px 48px 10%;
|
|
476
|
+
display:flex;flex-direction:column;justify-content:center;
|
|
477
|
+
border-right:1px solid #0a3300;
|
|
478
|
+
}
|
|
479
|
+
.checkout-form-side{
|
|
480
|
+
flex:1;background:#000;padding:48px 10% 48px 40px;
|
|
481
|
+
display:flex;flex-direction:column;justify-content:center;
|
|
482
|
+
}
|
|
483
|
+
.checkout-merchant{
|
|
484
|
+
display:flex;align-items:center;gap:10px;margin-bottom:6px;
|
|
485
|
+
}
|
|
486
|
+
.checkout-merchant-name{
|
|
487
|
+
font-family:'Geist Pixel',monospace;
|
|
488
|
+
font-size:.9375rem;font-weight:600;color:#33ff00;
|
|
489
|
+
}
|
|
490
|
+
.checkout-test-badge{
|
|
491
|
+
font-size:.625rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
|
|
492
|
+
background:#0a3300;color:#1a8c00;padding:2px 8px;border-radius:4px;
|
|
493
|
+
}
|
|
494
|
+
.checkout-total{
|
|
495
|
+
font-family:'Geist Pixel',monospace;
|
|
496
|
+
font-size:2rem;font-weight:700;color:#33ff00;margin:8px 0 28px;
|
|
497
|
+
}
|
|
498
|
+
.checkout-line-item{
|
|
499
|
+
display:flex;align-items:center;gap:14px;padding:14px 0;
|
|
500
|
+
border-bottom:1px solid #0a3300;
|
|
501
|
+
}
|
|
502
|
+
.checkout-line-item:first-child{border-top:1px solid #0a3300;}
|
|
503
|
+
.checkout-item-icon{
|
|
504
|
+
width:42px;height:42px;border-radius:6px;background:#0a3300;
|
|
505
|
+
display:flex;align-items:center;justify-content:center;flex-shrink:0;
|
|
506
|
+
font-family:'Geist Pixel',monospace;font-size:.875rem;font-weight:700;color:#116600;
|
|
507
|
+
}
|
|
508
|
+
.checkout-item-details{flex:1;min-width:0;}
|
|
509
|
+
.checkout-item-name{font-size:.875rem;font-weight:600;color:#33ff00;}
|
|
510
|
+
.checkout-item-qty{font-size:.75rem;color:#1a8c00;margin-top:2px;}
|
|
511
|
+
.checkout-item-price{
|
|
512
|
+
font-size:.875rem;font-weight:600;color:#33ff00;text-align:right;white-space:nowrap;
|
|
513
|
+
}
|
|
514
|
+
.checkout-item-unit{font-size:.6875rem;color:#1a8c00;text-align:right;margin-top:2px;}
|
|
515
|
+
.checkout-totals{margin-top:20px;}
|
|
516
|
+
.checkout-totals-row{
|
|
517
|
+
display:flex;justify-content:space-between;padding:6px 0;
|
|
518
|
+
font-size:.8125rem;color:#1a8c00;
|
|
519
|
+
}
|
|
520
|
+
.checkout-totals-row.total{
|
|
521
|
+
border-top:1px solid #0a3300;margin-top:8px;padding-top:14px;
|
|
522
|
+
font-size:.9375rem;font-weight:600;color:#33ff00;
|
|
523
|
+
}
|
|
524
|
+
.checkout-form-section{margin-bottom:24px;}
|
|
525
|
+
.checkout-form-label{
|
|
526
|
+
font-size:.8125rem;font-weight:600;color:#33ff00;margin-bottom:8px;display:block;
|
|
527
|
+
}
|
|
528
|
+
.checkout-input{
|
|
529
|
+
width:100%;padding:10px 12px;border:1px solid #0a3300;border-radius:6px;
|
|
530
|
+
background:#020;color:#33ff00;font:inherit;font-size:.875rem;
|
|
531
|
+
transition:border-color .15s;outline:none;
|
|
532
|
+
}
|
|
533
|
+
.checkout-input:focus{border-color:#33ff00;}
|
|
534
|
+
.checkout-input::placeholder{color:#116600;}
|
|
535
|
+
.checkout-card-box{
|
|
536
|
+
border:1px solid #0a3300;border-radius:6px;padding:14px;
|
|
537
|
+
background:#020;
|
|
538
|
+
}
|
|
539
|
+
.checkout-card-row{
|
|
540
|
+
display:flex;gap:12px;margin-top:10px;
|
|
541
|
+
}
|
|
542
|
+
.checkout-card-row .checkout-input{flex:1;}
|
|
543
|
+
.checkout-sim-note{
|
|
544
|
+
font-size:.6875rem;color:#1a8c00;margin-top:10px;text-align:center;
|
|
545
|
+
font-style:italic;
|
|
546
|
+
}
|
|
547
|
+
.checkout-pay-btn{
|
|
548
|
+
width:100%;padding:14px;border:none;border-radius:8px;
|
|
549
|
+
background:#33ff00;color:#000;font:inherit;font-size:.9375rem;font-weight:700;
|
|
550
|
+
cursor:pointer;transition:background .15s;
|
|
551
|
+
font-family:'Geist Pixel',monospace;
|
|
552
|
+
}
|
|
553
|
+
.checkout-pay-btn:hover{background:#44ff22;}
|
|
554
|
+
.checkout-cancel{
|
|
555
|
+
text-align:center;margin-top:14px;
|
|
556
|
+
}
|
|
557
|
+
.checkout-cancel a{
|
|
558
|
+
color:#1a8c00;text-decoration:none;font-size:.8125rem;
|
|
559
|
+
transition:color .15s;
|
|
560
|
+
}
|
|
561
|
+
.checkout-cancel a:hover{color:#33ff00;}
|
|
562
|
+
@media(max-width:768px){
|
|
563
|
+
.checkout-layout{flex-direction:column;}
|
|
564
|
+
.checkout-summary{padding:32px 20px;border-right:none;border-bottom:1px solid #0a3300;}
|
|
565
|
+
.checkout-form-side{padding:32px 20px;}
|
|
566
|
+
}
|
|
439
567
|
`;
|
|
440
568
|
var POWERED_BY = `<div class="powered-by">Powered by <a href="https://emulate.dev" target="_blank" rel="noopener">emulate</a></div>`;
|
|
441
569
|
function emuBar(service) {
|
|
@@ -455,6 +583,7 @@ function head(title) {
|
|
|
455
583
|
<head>
|
|
456
584
|
<meta charset="utf-8"/>
|
|
457
585
|
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
586
|
+
<link rel="icon" href="/_emulate/favicon.ico"/>
|
|
458
587
|
<title>${escapeHtml(title)} | emulate</title>
|
|
459
588
|
<style>${CSS}</style>
|
|
460
589
|
</head>`;
|
|
@@ -932,7 +1061,9 @@ function projectsRoutes({ app, store, baseUrl }) {
|
|
|
932
1061
|
key,
|
|
933
1062
|
value: typeof ev.value === "string" ? ev.value : String(ev.value ?? ""),
|
|
934
1063
|
type: ev.type === "system" || ev.type === "encrypted" || ev.type === "plain" || ev.type === "secret" || ev.type === "sensitive" ? ev.type : "encrypted",
|
|
935
|
-
target: Array.isArray(ev.target) ? ev.target.filter(
|
|
1064
|
+
target: Array.isArray(ev.target) ? ev.target.filter(
|
|
1065
|
+
(t) => t === "production" || t === "preview" || t === "development"
|
|
1066
|
+
) : ["production", "preview", "development"],
|
|
936
1067
|
gitBranch: typeof ev.gitBranch === "string" ? ev.gitBranch : null,
|
|
937
1068
|
customEnvironmentIds: Array.isArray(ev.customEnvironmentIds) ? ev.customEnvironmentIds : [],
|
|
938
1069
|
comment: typeof ev.comment === "string" ? ev.comment : null,
|
|
@@ -1915,11 +2046,17 @@ function parseEnvRow(body) {
|
|
|
1915
2046
|
}
|
|
1916
2047
|
const type = parseType(body.type);
|
|
1917
2048
|
if (type === "invalid") {
|
|
1918
|
-
return {
|
|
2049
|
+
return {
|
|
2050
|
+
row: {},
|
|
2051
|
+
error: "Invalid value: type must be one of system, encrypted, plain, secret, sensitive"
|
|
2052
|
+
};
|
|
1919
2053
|
}
|
|
1920
2054
|
const target = parseTarget(body.target);
|
|
1921
2055
|
if (target === "invalid") {
|
|
1922
|
-
return {
|
|
2056
|
+
return {
|
|
2057
|
+
row: {},
|
|
2058
|
+
error: "Invalid value: target must be a non-empty array of production, preview, development"
|
|
2059
|
+
};
|
|
1923
2060
|
}
|
|
1924
2061
|
const customEnvironmentIds = parseCustomEnvironmentIds(body.customEnvironmentIds);
|
|
1925
2062
|
if (customEnvironmentIds === "invalid") {
|
|
@@ -2027,9 +2164,7 @@ function envRoutes({ app, store }) {
|
|
|
2027
2164
|
}
|
|
2028
2165
|
const { row } = parsed;
|
|
2029
2166
|
const existingDb = findEnvByKeyAndTargetsOverlap(vs, project.uid, row.key, row.target);
|
|
2030
|
-
const existingPending = pending.find(
|
|
2031
|
-
(e) => e.key === row.key && targetsOverlap(e.target, row.target)
|
|
2032
|
-
);
|
|
2167
|
+
const existingPending = pending.find((e) => e.key === row.key && targetsOverlap(e.target, row.target));
|
|
2033
2168
|
if (upsert) {
|
|
2034
2169
|
const toUpdate = existingDb ?? existingPending;
|
|
2035
2170
|
if (toUpdate) {
|
|
@@ -2128,14 +2263,24 @@ function envRoutes({ app, store }) {
|
|
|
2128
2263
|
if ("type" in body) {
|
|
2129
2264
|
const t = parseType(body.type);
|
|
2130
2265
|
if (t === "invalid") {
|
|
2131
|
-
return vercelErr5(
|
|
2266
|
+
return vercelErr5(
|
|
2267
|
+
c,
|
|
2268
|
+
400,
|
|
2269
|
+
"bad_request",
|
|
2270
|
+
"Invalid value: type must be one of system, encrypted, plain, secret, sensitive"
|
|
2271
|
+
);
|
|
2132
2272
|
}
|
|
2133
2273
|
patch.type = t;
|
|
2134
2274
|
}
|
|
2135
2275
|
if ("target" in body) {
|
|
2136
2276
|
const t = parseTarget(body.target);
|
|
2137
2277
|
if (t === "invalid") {
|
|
2138
|
-
return vercelErr5(
|
|
2278
|
+
return vercelErr5(
|
|
2279
|
+
c,
|
|
2280
|
+
400,
|
|
2281
|
+
"bad_request",
|
|
2282
|
+
"Invalid value: target must be a non-empty array of production, preview, development"
|
|
2283
|
+
);
|
|
2139
2284
|
}
|
|
2140
2285
|
patch.target = t;
|
|
2141
2286
|
}
|
|
@@ -2230,11 +2375,23 @@ function oauthRoutes({ app, store, tokenMap }) {
|
|
|
2230
2375
|
if (integrationsConfigured) {
|
|
2231
2376
|
const integration = vs.integrations.findOneBy("client_id", client_id);
|
|
2232
2377
|
if (!integration) {
|
|
2233
|
-
return c.html(
|
|
2378
|
+
return c.html(
|
|
2379
|
+
renderErrorPage("Application not found", `The client_id '${client_id}' is not registered.`, SERVICE_LABEL),
|
|
2380
|
+
400
|
|
2381
|
+
);
|
|
2234
2382
|
}
|
|
2235
2383
|
if (redirect_uri && !matchesRedirectUri(redirect_uri, integration.redirect_uris)) {
|
|
2236
|
-
console.warn(
|
|
2237
|
-
|
|
2384
|
+
console.warn(
|
|
2385
|
+
`[OAuth] redirect_uri mismatch: got "${redirect_uri}", registered: ${JSON.stringify(integration.redirect_uris)}`
|
|
2386
|
+
);
|
|
2387
|
+
return c.html(
|
|
2388
|
+
renderErrorPage(
|
|
2389
|
+
"Redirect URI mismatch",
|
|
2390
|
+
"The redirect_uri is not registered for this application.",
|
|
2391
|
+
SERVICE_LABEL
|
|
2392
|
+
),
|
|
2393
|
+
400
|
|
2394
|
+
);
|
|
2238
2395
|
}
|
|
2239
2396
|
integrationName = integration.name;
|
|
2240
2397
|
}
|
|
@@ -2282,7 +2439,10 @@ function oauthRoutes({ app, store, tokenMap }) {
|
|
|
2282
2439
|
codeChallengeMethod: code_challenge_method || null,
|
|
2283
2440
|
created_at: Date.now()
|
|
2284
2441
|
});
|
|
2285
|
-
debug(
|
|
2442
|
+
debug(
|
|
2443
|
+
"vercel.oauth",
|
|
2444
|
+
`[Vercel callback] generated code: ${code.slice(0, 8)}... for username=${username}, challenge=${code_challenge ? "present" : "none"}, pendingCodes size: ${pendingCodes.size}`
|
|
2445
|
+
);
|
|
2286
2446
|
const url = new URL(redirect_uri);
|
|
2287
2447
|
url.searchParams.set("code", code);
|
|
2288
2448
|
if (state !== "") url.searchParams.set("state", state);
|
|
@@ -2294,7 +2454,10 @@ function oauthRoutes({ app, store, tokenMap }) {
|
|
|
2294
2454
|
const pendingCodes = getPendingCodes(store);
|
|
2295
2455
|
debug("vercel.oauth", `[Vercel token] Content-Type: ${contentType}`);
|
|
2296
2456
|
debug("vercel.oauth", `[Vercel token] pendingCodes size: ${pendingCodes.size}`);
|
|
2297
|
-
debug(
|
|
2457
|
+
debug(
|
|
2458
|
+
"vercel.oauth",
|
|
2459
|
+
`[Vercel token] pendingCodes keys: ${[...pendingCodes.keys()].map((k) => k.slice(0, 8) + "...").join(", ")}`
|
|
2460
|
+
);
|
|
2298
2461
|
const rawText = await c.req.text();
|
|
2299
2462
|
debug("vercel.oauth", `[Vercel token] raw body: ${rawText.slice(0, 500)}`);
|
|
2300
2463
|
let body;
|
|
@@ -2316,73 +2479,70 @@ function oauthRoutes({ app, store, tokenMap }) {
|
|
|
2316
2479
|
debug("vercel.oauth", `[Vercel token] code: ${code.slice(0, 8)}... (len=${code.length})`);
|
|
2317
2480
|
debug("vercel.oauth", `[Vercel token] client_id: ${bodyClientId}`);
|
|
2318
2481
|
debug("vercel.oauth", `[Vercel token] client_secret: ${bodyClientSecret.slice(0, 4)}****`);
|
|
2319
|
-
debug(
|
|
2482
|
+
debug(
|
|
2483
|
+
"vercel.oauth",
|
|
2484
|
+
`[Vercel token] code_verifier: ${code_verifier ? code_verifier.slice(0, 8) + "..." : "undefined"}`
|
|
2485
|
+
);
|
|
2320
2486
|
const integrationsConfigured = vs.integrations.all().length > 0;
|
|
2321
2487
|
if (integrationsConfigured) {
|
|
2322
2488
|
const integration = vs.integrations.findOneBy("client_id", bodyClientId);
|
|
2323
2489
|
if (!integration) {
|
|
2324
2490
|
debug("vercel.oauth", `[Vercel token] REJECTED: client_id not found`);
|
|
2325
|
-
return c.json(
|
|
2491
|
+
return c.json(
|
|
2492
|
+
{ error: "invalid_client", error_description: "The client_id and/or client_secret passed are incorrect." },
|
|
2493
|
+
401
|
|
2494
|
+
);
|
|
2326
2495
|
}
|
|
2327
2496
|
if (!constantTimeSecretEqual(bodyClientSecret, integration.client_secret)) {
|
|
2328
2497
|
debug("vercel.oauth", `[Vercel token] REJECTED: client_secret mismatch`);
|
|
2329
|
-
return c.json(
|
|
2498
|
+
return c.json(
|
|
2499
|
+
{ error: "invalid_client", error_description: "The client_id and/or client_secret passed are incorrect." },
|
|
2500
|
+
401
|
|
2501
|
+
);
|
|
2330
2502
|
}
|
|
2331
2503
|
debug("vercel.oauth", `[Vercel token] client credentials OK (${integration.name})`);
|
|
2332
2504
|
}
|
|
2333
2505
|
const pending = pendingCodes.get(code);
|
|
2334
2506
|
if (!pending) {
|
|
2335
2507
|
debug("vercel.oauth", `[Vercel token] REJECTED: code not found in pendingCodes`);
|
|
2336
|
-
return c.json(
|
|
2337
|
-
{ error: "invalid_grant", error_description: "The code passed is incorrect or expired." },
|
|
2338
|
-
400
|
|
2339
|
-
);
|
|
2508
|
+
return c.json({ error: "invalid_grant", error_description: "The code passed is incorrect or expired." }, 400);
|
|
2340
2509
|
}
|
|
2341
2510
|
if (isPendingCodeExpired(pending)) {
|
|
2342
2511
|
debug("vercel.oauth", `[Vercel token] REJECTED: code expired`);
|
|
2343
2512
|
pendingCodes.delete(code);
|
|
2344
|
-
return c.json(
|
|
2345
|
-
{ error: "invalid_grant", error_description: "The code passed is incorrect or expired." },
|
|
2346
|
-
400
|
|
2347
|
-
);
|
|
2513
|
+
return c.json({ error: "invalid_grant", error_description: "The code passed is incorrect or expired." }, 400);
|
|
2348
2514
|
}
|
|
2349
2515
|
debug("vercel.oauth", `[Vercel token] code valid, username=${pending.username}, scope=${pending.scope}`);
|
|
2350
2516
|
if (redirect_uri && pending.redirectUri && redirect_uri !== pending.redirectUri) {
|
|
2351
|
-
debug(
|
|
2517
|
+
debug(
|
|
2518
|
+
"vercel.oauth",
|
|
2519
|
+
`[Vercel token] REJECTED: redirect_uri mismatch (got "${redirect_uri}", expected "${pending.redirectUri}")`
|
|
2520
|
+
);
|
|
2352
2521
|
pendingCodes.delete(code);
|
|
2353
2522
|
return c.json(
|
|
2354
|
-
{
|
|
2523
|
+
{
|
|
2524
|
+
error: "invalid_grant",
|
|
2525
|
+
error_description: "The redirect_uri does not match the one used during authorization."
|
|
2526
|
+
},
|
|
2355
2527
|
400
|
|
2356
2528
|
);
|
|
2357
2529
|
}
|
|
2358
2530
|
if (pending.codeChallenge != null) {
|
|
2359
2531
|
if (code_verifier === void 0) {
|
|
2360
|
-
return c.json(
|
|
2361
|
-
{ error: "invalid_grant", error_description: "PKCE verification failed." },
|
|
2362
|
-
400
|
|
2363
|
-
);
|
|
2532
|
+
return c.json({ error: "invalid_grant", error_description: "PKCE verification failed." }, 400);
|
|
2364
2533
|
}
|
|
2365
2534
|
const method = (pending.codeChallengeMethod ?? "plain").toLowerCase();
|
|
2366
2535
|
if (method === "s256") {
|
|
2367
2536
|
const expected = createHash("sha256").update(code_verifier).digest("base64url");
|
|
2368
2537
|
if (expected !== pending.codeChallenge) {
|
|
2369
|
-
return c.json(
|
|
2370
|
-
{ error: "invalid_grant", error_description: "PKCE verification failed." },
|
|
2371
|
-
400
|
|
2372
|
-
);
|
|
2538
|
+
return c.json({ error: "invalid_grant", error_description: "PKCE verification failed." }, 400);
|
|
2373
2539
|
}
|
|
2374
2540
|
} else if (method === "plain") {
|
|
2375
2541
|
if (code_verifier !== pending.codeChallenge) {
|
|
2376
|
-
return c.json(
|
|
2377
|
-
{ error: "invalid_grant", error_description: "PKCE verification failed." },
|
|
2378
|
-
400
|
|
2379
|
-
);
|
|
2542
|
+
return c.json({ error: "invalid_grant", error_description: "PKCE verification failed." }, 400);
|
|
2380
2543
|
}
|
|
2381
2544
|
} else {
|
|
2382
|
-
return c.json(
|
|
2383
|
-
{ error: "invalid_grant", error_description: "PKCE verification failed." },
|
|
2384
|
-
400
|
|
2385
|
-
);
|
|
2545
|
+
return c.json({ error: "invalid_grant", error_description: "PKCE verification failed." }, 400);
|
|
2386
2546
|
}
|
|
2387
2547
|
}
|
|
2388
2548
|
debug("vercel.oauth", `[Vercel token] PKCE OK (challenge=${pending.codeChallenge ? "present" : "none"})`);
|
|
@@ -2400,7 +2560,10 @@ function oauthRoutes({ app, store, tokenMap }) {
|
|
|
2400
2560
|
if (tokenMap) {
|
|
2401
2561
|
tokenMap.set(token, { login: user.username, id: user.id, scopes });
|
|
2402
2562
|
}
|
|
2403
|
-
debug(
|
|
2563
|
+
debug(
|
|
2564
|
+
"vercel.oauth",
|
|
2565
|
+
`[Vercel token] SUCCESS: issued token for ${user.username} (scopes: ${scopes.join(",") || "none"})`
|
|
2566
|
+
);
|
|
2404
2567
|
return c.json({
|
|
2405
2568
|
access_token: token,
|
|
2406
2569
|
token_type: "Bearer",
|
|
@@ -2681,4 +2844,4 @@ export {
|
|
|
2681
2844
|
seedFromConfig,
|
|
2682
2845
|
vercelPlugin
|
|
2683
2846
|
};
|
|
2684
|
-
//# sourceMappingURL=dist-
|
|
2847
|
+
//# sourceMappingURL=dist-CXRPM6BK.js.map
|