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