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.
Files changed (50) hide show
  1. package/README.md +198 -27
  2. package/dist/api.d.ts +2 -1
  3. package/dist/api.js +675 -103
  4. package/dist/api.js.map +1 -1
  5. package/dist/chunk-WVQMFHQM.js +83 -0
  6. package/dist/chunk-WVQMFHQM.js.map +1 -0
  7. package/dist/{dist-B674PYKV.js → dist-2ZZGNPJI.js} +22 -43
  8. package/dist/dist-2ZZGNPJI.js.map +1 -0
  9. package/dist/{dist-RDFBZ5O6.js → dist-CXRPM6BK.js} +211 -48
  10. package/dist/dist-CXRPM6BK.js.map +1 -0
  11. package/dist/{dist-VVXVP5EZ.js → dist-DSJSF3GY.js} +551 -91
  12. package/dist/dist-DSJSF3GY.js.map +1 -0
  13. package/dist/{dist-RMK3BS5M.js → dist-IFULY5LE.js} +196 -33
  14. package/dist/dist-IFULY5LE.js.map +1 -0
  15. package/dist/dist-IRUBHCZU.js +1898 -0
  16. package/dist/dist-IRUBHCZU.js.map +1 -0
  17. package/dist/{dist-YOVM5HEY.js → dist-NJJLJT2N.js} +520 -61
  18. package/dist/dist-NJJLJT2N.js.map +1 -0
  19. package/dist/dist-OGSAVJ25.js +4874 -0
  20. package/dist/dist-OGSAVJ25.js.map +1 -0
  21. package/dist/{dist-H6JYGQM4.js → dist-PO4CL5SJ.js} +271 -158
  22. package/dist/dist-PO4CL5SJ.js.map +1 -0
  23. package/dist/{dist-QMOJM6DV.js → dist-R3TNKUIE.js} +238 -55
  24. package/dist/dist-R3TNKUIE.js.map +1 -0
  25. package/dist/{dist-6JFNJPUU.js → dist-WACHAAVU.js} +171 -22
  26. package/dist/dist-WACHAAVU.js.map +1 -0
  27. package/dist/{dist-OTJZRQ3Q.js → dist-XWWZVLQQ.js} +216 -75
  28. package/dist/dist-XWWZVLQQ.js.map +1 -0
  29. package/dist/{dist-6EW7SSOZ.js → dist-ZY5SZSJ2.js} +397 -223
  30. package/dist/dist-ZY5SZSJ2.js.map +1 -0
  31. package/dist/fonts/favicon.ico +0 -0
  32. package/dist/helpers-LXLP3DFE-LBOTATT5.js +17 -0
  33. package/dist/helpers-LXLP3DFE-LBOTATT5.js.map +1 -0
  34. package/dist/index.js +812 -117
  35. package/dist/index.js.map +1 -1
  36. package/package.json +17 -15
  37. package/dist/chunk-TEPNEZ63.js +0 -2143
  38. package/dist/chunk-TEPNEZ63.js.map +0 -1
  39. package/dist/dist-6EW7SSOZ.js.map +0 -1
  40. package/dist/dist-6JFNJPUU.js.map +0 -1
  41. package/dist/dist-B674PYKV.js.map +0 -1
  42. package/dist/dist-G7WQPZ3Y.js +0 -1287
  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,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", ["deploymentId", "projectId"]),
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
- let project = vs.projects.findOneBy("uid", idOrName);
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
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((t) => t === "production" || t === "preview" || t === "development") : ["production", "preview", "development"],
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 { row: {}, error: "Invalid value: type must be one of system, encrypted, plain, secret, sensitive" };
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 { row: {}, error: "Invalid value: target must be a non-empty array of production, preview, development" };
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(c, 400, "bad_request", "Invalid value: type must be one of system, encrypted, plain, secret, sensitive");
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(c, 400, "bad_request", "Invalid value: target must be a non-empty array of production, preview, development");
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(renderErrorPage("Application not found", `The client_id '${client_id}' is not registered.`, SERVICE_LABEL), 400);
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(`[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);
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("vercel.oauth", `[Vercel callback] generated code: ${code.slice(0, 8)}... for username=${username}, challenge=${code_challenge ? "present" : "none"}, pendingCodes size: ${pendingCodes.size}`);
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("vercel.oauth", `[Vercel token] pendingCodes keys: ${[...pendingCodes.keys()].map((k) => k.slice(0, 8) + "...").join(", ")}`);
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("vercel.oauth", `[Vercel token] code_verifier: ${code_verifier ? code_verifier.slice(0, 8) + "..." : "undefined"}`);
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({ error: "invalid_client", error_description: "The client_id and/or client_secret passed are incorrect." }, 401);
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({ error: "invalid_client", error_description: "The client_id and/or client_secret passed are incorrect." }, 401);
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("vercel.oauth", `[Vercel token] REJECTED: redirect_uri mismatch (got "${redirect_uri}", expected "${pending.redirectUri}")`);
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
- { error: "invalid_grant", error_description: "The redirect_uri does not match the one used during authorization." },
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("vercel.oauth", `[Vercel token] SUCCESS: issued token for ${user.username} (scopes: ${scopes.join(",") || "none"})`);
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-RDFBZ5O6.js.map
2847
+ //# sourceMappingURL=dist-CXRPM6BK.js.map