@niledatabase/server 5.1.0 → 5.2.0-alpha.3

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/dist/index.mjs CHANGED
@@ -51,6 +51,7 @@ var appRoutes = (prefix = DEFAULT_PREFIX) => ({
51
51
  CSRF: `${prefix}${"/auth/csrf" /* CSRF */}`,
52
52
  CALLBACK: `${prefix}${"/auth/callback" /* CALLBACK */}`,
53
53
  SIGNOUT: `${prefix}${"/auth/signout" /* SIGNOUT */}`,
54
+ MULTI_FACTOR: `${prefix}${"/auth/mfa" /* MULTI_FACTOR */}`,
54
55
  ERROR: `${prefix}/auth/error`,
55
56
  VERIFY_REQUEST: `${prefix}/auth/verify-request`,
56
57
  VERIFY_EMAIL: `${prefix}${"/auth/verify-email" /* VERIFY_EMAIL */}`,
@@ -90,7 +91,8 @@ var proxyRoutes = (config) => ({
90
91
  ERROR: makeRestUrl(config, "/auth/error"),
91
92
  VERIFY_REQUEST: makeRestUrl(config, "/auth/verify-request"),
92
93
  PASSWORD_RESET: makeRestUrl(config, "/auth/reset-password" /* PASSWORD_RESET */),
93
- VERIFY_EMAIL: makeRestUrl(config, "/auth/verify-email" /* VERIFY_EMAIL */)
94
+ VERIFY_EMAIL: makeRestUrl(config, "/auth/verify-email" /* VERIFY_EMAIL */),
95
+ MULTI_FACTOR: makeRestUrl(config, "/auth/mfa" /* MULTI_FACTOR */)
94
96
  });
95
97
  function filterNullUndefined(obj) {
96
98
  if (!obj) {
@@ -115,9 +117,9 @@ function makeRestUrl(apiUrl, path, qp) {
115
117
  const strParams = params.toString();
116
118
  return `${[url, path.substring(1, path.length)].join("/")}${strParams ? `?${strParams}` : ""}`;
117
119
  }
118
- function urlMatches(requestUrl, route20) {
120
+ function urlMatches(requestUrl, route21) {
119
121
  const url = new URL(requestUrl);
120
- return url.pathname.startsWith(route20);
122
+ return url.pathname.startsWith(route21);
121
123
  }
122
124
  function isUUID(value) {
123
125
  if (!value) {
@@ -249,7 +251,10 @@ function bindRunExtensions(instance) {
249
251
  continue;
250
252
  }
251
253
  const previousHeaders = new Headers(previousContext.headers);
252
- await ext.onRequest(_init.request, ctx);
254
+ try {
255
+ await ext.onRequest(_init.request, ctx);
256
+ } catch {
257
+ }
253
258
  const updatedContext = ctx.get();
254
259
  if (updatedContext?.headers) {
255
260
  const cookie = updatedContext.headers.get("cookie");
@@ -292,8 +297,8 @@ function mergeCookies(...cookieStrings) {
292
297
  for (const str of cookieStrings) {
293
298
  if (!str) continue;
294
299
  for (const part of str.split(";")) {
295
- const [key17, value] = part.split("=").map((s) => s.trim());
296
- if (key17 && value) cookieMap.set(key17, value);
300
+ const [key18, value] = part.split("=").map((s) => s.trim());
301
+ if (key18 && value) cookieMap.set(key18, value);
297
302
  }
298
303
  }
299
304
  return [...cookieMap.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
@@ -353,8 +358,8 @@ var ctx = {
353
358
  if (partial.headers === null) {
354
359
  store.headers = new Headers();
355
360
  } else if (partial.headers && store.headers instanceof Headers) {
356
- for (const [key17, value] of new Headers(partial.headers).entries()) {
357
- if (key17.toLowerCase() === "cookie") {
361
+ for (const [key18, value] of new Headers(partial.headers).entries()) {
362
+ if (key18.toLowerCase() === "cookie") {
358
363
  const existingCookies = parseCookieHeader(
359
364
  store.headers.get("cookie") || ""
360
365
  );
@@ -362,7 +367,7 @@ var ctx = {
362
367
  const mergedCookies = { ...existingCookies, ...newCookies };
363
368
  store.headers.set("cookie", serializeCookies(mergedCookies));
364
369
  } else {
365
- store.headers.set(key17, value);
370
+ store.headers.set(key18, value);
366
371
  }
367
372
  }
368
373
  }
@@ -382,16 +387,16 @@ async function withNileContext(config, fn, name = "unknown") {
382
387
  let tenantId = existing.tenantId;
383
388
  let userId = existing.userId;
384
389
  if (initialContext instanceof Request) {
385
- initialContext.headers.forEach((value, key17) => {
386
- mergedHeaders.set(key17, value);
390
+ initialContext.headers.forEach((value, key18) => {
391
+ mergedHeaders.set(key18, value);
387
392
  });
388
393
  } else {
389
394
  if (initialContext.headers === null) {
390
395
  mergedHeaders = new Headers();
391
396
  } else if (initialContext.headers) {
392
397
  const incoming = initialContext.headers instanceof Headers ? initialContext.headers : new Headers(initialContext.headers);
393
- incoming.forEach((value, key17) => {
394
- mergedHeaders.set(key17, value);
398
+ incoming.forEach((value, key18) => {
399
+ mergedHeaders.set(key18, value);
395
400
  });
396
401
  }
397
402
  if ("tenantId" in initialContext) {
@@ -402,11 +407,11 @@ async function withNileContext(config, fn, name = "unknown") {
402
407
  }
403
408
  }
404
409
  if (extensionOverrides?.headers) {
405
- for (const key17 of extensionOverrides.headers.removed) {
406
- mergedHeaders.delete(key17);
410
+ for (const key18 of extensionOverrides.headers.removed) {
411
+ mergedHeaders.delete(key18);
407
412
  }
408
- for (const [key17, value] of extensionOverrides.headers.set) {
409
- mergedHeaders.set(key17, value);
413
+ for (const [key18, value] of extensionOverrides.headers.set) {
414
+ mergedHeaders.set(key18, value);
410
415
  }
411
416
  }
412
417
  if (extensionOverrides?.tenantId) {
@@ -429,8 +434,8 @@ async function withNileContext(config, fn, name = "unknown") {
429
434
  function serializeContext(context) {
430
435
  const headers = {};
431
436
  const rawHeaders = new Headers(context.headers);
432
- rawHeaders.forEach((value, key17) => {
433
- headers[key17] = value;
437
+ rawHeaders.forEach((value, key18) => {
438
+ headers[key18] = value;
434
439
  });
435
440
  return JSON.stringify({
436
441
  headers,
@@ -440,8 +445,8 @@ function serializeContext(context) {
440
445
  }
441
446
  function parseCookieHeader(header) {
442
447
  return header.split(";").map((c) => c.trim()).filter(Boolean).reduce((acc, curr) => {
443
- const [key17, ...val] = curr.split("=");
444
- if (key17) acc[key17] = val.join("=");
448
+ const [key18, ...val] = curr.split("=");
449
+ if (key18) acc[key18] = val.join("=");
445
450
  return acc;
446
451
  }, {});
447
452
  }
@@ -497,14 +502,14 @@ function diffHeaders(before, after) {
497
502
  const afterMap = headersToMap(after);
498
503
  const set = [];
499
504
  const removed = [];
500
- for (const [key17, value] of afterMap.entries()) {
501
- if (beforeMap.get(key17) !== value) {
502
- set.push([key17, value]);
505
+ for (const [key18, value] of afterMap.entries()) {
506
+ if (beforeMap.get(key18) !== value) {
507
+ set.push([key18, value]);
503
508
  }
504
509
  }
505
- for (const key17 of beforeMap.keys()) {
506
- if (!afterMap.has(key17)) {
507
- removed.push(key17);
510
+ for (const key18 of beforeMap.keys()) {
511
+ if (!afterMap.has(key18)) {
512
+ removed.push(key18);
508
513
  }
509
514
  }
510
515
  if (set.length === 0 && removed.length === 0) {
@@ -514,8 +519,8 @@ function diffHeaders(before, after) {
514
519
  }
515
520
  function headersToMap(headers) {
516
521
  const map = /* @__PURE__ */ new Map();
517
- headers.forEach((value, key17) => {
518
- map.set(key17.toLowerCase(), value);
522
+ headers.forEach((value, key18) => {
523
+ map.set(key18.toLowerCase(), value);
519
524
  });
520
525
  return map;
521
526
  }
@@ -639,7 +644,7 @@ async function request(url, _init, config) {
639
644
  }
640
645
  }
641
646
  function getProtocolFromHeaders(headers) {
642
- const get = (key17) => headers instanceof Headers ? headers.get(key17) : headers[key17.toLowerCase()];
647
+ const get = (key18) => headers instanceof Headers ? headers.get(key18) : headers[key18.toLowerCase()];
643
648
  const xfp = get("x-forwarded-proto");
644
649
  if (xfp) return xfp.toLowerCase();
645
650
  const forwarded = get("forwarded");
@@ -859,11 +864,11 @@ async function route3(request2, config) {
859
864
  function matches3(configRoutes, request2) {
860
865
  const url = new URL(request2.url);
861
866
  const [userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
862
- let route20 = configRoutes[key3].replace("{tenantId}", tenantId).replace("{userId}", userId);
867
+ let route21 = configRoutes[key3].replace("{tenantId}", tenantId).replace("{userId}", userId);
863
868
  if (userId === "users") {
864
- route20 = configRoutes[key3].replace("{tenantId}", possibleTenantId);
869
+ route21 = configRoutes[key3].replace("{tenantId}", possibleTenantId);
865
870
  }
866
- return urlMatches(request2.url, route20);
871
+ return urlMatches(request2.url, route21);
867
872
  }
868
873
  async function fetchTenantUsers(config, method, payload) {
869
874
  const { body, params } = {};
@@ -952,8 +957,8 @@ async function route4(request2, config) {
952
957
  function matches4(configRoutes, request2) {
953
958
  const url = new URL(request2.url);
954
959
  const [, tenantId] = url.pathname.split("/").reverse();
955
- const route20 = configRoutes[key4].replace("{tenantId}", tenantId);
956
- return urlMatches(request2.url, route20);
960
+ const route21 = configRoutes[key4].replace("{tenantId}", tenantId);
961
+ return urlMatches(request2.url, route21);
957
962
  }
958
963
  async function fetchInvite(config, method, body) {
959
964
  const { headers, tenantId } = ctx.get();
@@ -1008,8 +1013,8 @@ async function route5(request2, config) {
1008
1013
  function matches5(configRoutes, request2) {
1009
1014
  const url = new URL(request2.url);
1010
1015
  const [, tenantId] = url.pathname.split("/").reverse();
1011
- const route20 = configRoutes[key5].replace("{tenantId}", tenantId);
1012
- return url.pathname.endsWith(route20);
1016
+ const route21 = configRoutes[key5].replace("{tenantId}", tenantId);
1017
+ return url.pathname.endsWith(route21);
1013
1018
  }
1014
1019
  async function fetchInvites(config) {
1015
1020
  const { tenantId, headers } = ctx.get();
@@ -1466,6 +1471,33 @@ async function fetchVerifyEmail(config, method, body) {
1466
1471
  return await config.handlers[method](req);
1467
1472
  }
1468
1473
 
1474
+ // src/api/routes/auth/mfa.ts
1475
+ var key14 = "MULTI_FACTOR";
1476
+ async function route17(req, config) {
1477
+ return request(
1478
+ proxyRoutes(config.apiUrl)[key14],
1479
+ {
1480
+ method: req.method,
1481
+ request: req
1482
+ },
1483
+ config
1484
+ );
1485
+ }
1486
+ function matches17(configRoutes, request2) {
1487
+ return urlMatches(request2.url, configRoutes[key14]);
1488
+ }
1489
+ async function fetchMfa(config, method, body) {
1490
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/mfa" /* MULTI_FACTOR */}`;
1491
+ const { headers } = ctx.get();
1492
+ const init = {
1493
+ headers,
1494
+ method,
1495
+ body
1496
+ };
1497
+ const req = new Request(clientUrl, init);
1498
+ return await config.handlers[method](req);
1499
+ }
1500
+
1469
1501
  // src/api/handlers/GET.ts
1470
1502
  function GETTER(configRoutes, config) {
1471
1503
  const { error, info, warn: warn2 } = config.logger("[GET MATCHER]");
@@ -1561,8 +1593,8 @@ async function POST5(config, init) {
1561
1593
  }
1562
1594
 
1563
1595
  // src/api/routes/signup/index.tsx
1564
- var key14 = "SIGNUP";
1565
- async function route17(request2, config) {
1596
+ var key15 = "SIGNUP";
1597
+ async function route18(request2, config) {
1566
1598
  switch (request2.method) {
1567
1599
  case "POST":
1568
1600
  return await POST5(config, { request: request2 });
@@ -1570,8 +1602,8 @@ async function route17(request2, config) {
1570
1602
  return new Response("method not allowed", { status: 405 });
1571
1603
  }
1572
1604
  }
1573
- function matches17(configRoutes, request2) {
1574
- return urlMatches(request2.url, configRoutes[key14]);
1605
+ function matches18(configRoutes, request2) {
1606
+ return urlMatches(request2.url, configRoutes[key15]);
1575
1607
  }
1576
1608
  async function fetchSignUp(config, payload) {
1577
1609
  const { body, params } = payload ?? {};
@@ -1626,9 +1658,9 @@ function POSTER(configRoutes, config) {
1626
1658
  info("matches tenant invite");
1627
1659
  return route4(req, config);
1628
1660
  }
1629
- if (matches17(configRoutes, req)) {
1661
+ if (matches18(configRoutes, req)) {
1630
1662
  info("matches signup");
1631
- return route17(req, config);
1663
+ return route18(req, config);
1632
1664
  }
1633
1665
  if (matches6(configRoutes, req)) {
1634
1666
  info("matches tenants");
@@ -1642,6 +1674,10 @@ function POSTER(configRoutes, config) {
1642
1674
  info("matches signin");
1643
1675
  return route7(req, config);
1644
1676
  }
1677
+ if (matches17(configRoutes, req)) {
1678
+ info("matches mfa");
1679
+ return route17(req, config);
1680
+ }
1645
1681
  if (matches15(configRoutes, req)) {
1646
1682
  info("matches password reset");
1647
1683
  return route15(req, config);
@@ -1690,9 +1726,9 @@ async function PUT5(config, init) {
1690
1726
  }
1691
1727
 
1692
1728
  // src/api/routes/tenants/[tenantId]/users/[userId]/index.ts
1693
- var key15 = "TENANT_USER";
1694
- async function route18(request2, config) {
1695
- const { info } = config.logger(`[ROUTES][${key15}]`);
1729
+ var key16 = "TENANT_USER";
1730
+ async function route19(request2, config) {
1731
+ const { info } = config.logger(`[ROUTES][${key16}]`);
1696
1732
  const session = await auth(request2, config);
1697
1733
  if (!session) {
1698
1734
  info("401");
@@ -1713,14 +1749,14 @@ async function route18(request2, config) {
1713
1749
  return new Response("method not allowed", { status: 405 });
1714
1750
  }
1715
1751
  }
1716
- function matches18(configRoutes, request2) {
1752
+ function matches19(configRoutes, request2) {
1717
1753
  const url = new URL(request2.url);
1718
1754
  const [, userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
1719
- let route20 = configRoutes[key15].replace("{tenantId}", tenantId).replace("{userId}", userId);
1755
+ let route21 = configRoutes[key16].replace("{tenantId}", tenantId).replace("{userId}", userId);
1720
1756
  if (userId === "users") {
1721
- route20 = configRoutes[key15].replace("{tenantId}", possibleTenantId);
1757
+ route21 = configRoutes[key16].replace("{tenantId}", possibleTenantId);
1722
1758
  }
1723
- return urlMatches(request2.url, route20);
1759
+ return urlMatches(request2.url, route21);
1724
1760
  }
1725
1761
  async function fetchTenantUser(config, method) {
1726
1762
  const { headers, tenantId, userId } = ctx.get();
@@ -1759,8 +1795,8 @@ async function DELETE4(config, init) {
1759
1795
  }
1760
1796
 
1761
1797
  // src/api/routes/tenants/[tenantId]/invite/[inviteId]/index.ts
1762
- var key16 = "INVITE";
1763
- async function route19(request2, config) {
1798
+ var key17 = "INVITE";
1799
+ async function route20(request2, config) {
1764
1800
  switch (request2.method) {
1765
1801
  case "DELETE":
1766
1802
  return await DELETE4(config, { request: request2 });
@@ -1768,11 +1804,11 @@ async function route19(request2, config) {
1768
1804
  return new Response("method not allowed", { status: 405 });
1769
1805
  }
1770
1806
  }
1771
- function matches19(configRoutes, request2) {
1807
+ function matches20(configRoutes, request2) {
1772
1808
  const url = new URL(request2.url);
1773
1809
  const [inviteId, , tenantId] = url.pathname.split("/").reverse();
1774
- const route20 = configRoutes[key16].replace("{tenantId}", tenantId).replace("{inviteId}", inviteId);
1775
- return urlMatches(request2.url, route20);
1810
+ const route21 = configRoutes[key17].replace("{tenantId}", tenantId).replace("{inviteId}", inviteId);
1811
+ return urlMatches(request2.url, route21);
1776
1812
  }
1777
1813
 
1778
1814
  // src/api/handlers/DELETE.ts
@@ -1792,13 +1828,17 @@ function DELETER(configRoutes, config) {
1792
1828
  error("Proxy requests failed, a Request object was not passed.");
1793
1829
  return;
1794
1830
  }
1795
- if (matches19(configRoutes, req)) {
1831
+ if (matches20(configRoutes, req)) {
1796
1832
  info("matches tenant invite id");
1797
- return route19(req, config);
1833
+ return route20(req, config);
1798
1834
  }
1799
- if (matches18(configRoutes, req)) {
1835
+ if (matches17(configRoutes, req)) {
1836
+ info("matches MFA");
1837
+ return route17(req, config);
1838
+ }
1839
+ if (matches19(configRoutes, req)) {
1800
1840
  info("matches tenant user");
1801
- return route18(req, config);
1841
+ return route19(req, config);
1802
1842
  }
1803
1843
  if (matches6(configRoutes, req)) {
1804
1844
  info("matches tenants");
@@ -1834,9 +1874,9 @@ function PUTER(configRoutes, config) {
1834
1874
  info("matches tenant invite");
1835
1875
  return route4(req, config);
1836
1876
  }
1837
- if (matches18(configRoutes, req)) {
1877
+ if (matches19(configRoutes, req)) {
1838
1878
  info("matches tenant user");
1839
- return route18(req, config);
1879
+ return route19(req, config);
1840
1880
  }
1841
1881
  if (matches3(configRoutes, req)) {
1842
1882
  info("matches tenant users");
@@ -1854,6 +1894,10 @@ function PUTER(configRoutes, config) {
1854
1894
  info("matches reset password");
1855
1895
  return route15(req, config);
1856
1896
  }
1897
+ if (matches17(configRoutes, req)) {
1898
+ info("matches mfa");
1899
+ return route17(req, config);
1900
+ }
1857
1901
  warn2("No PUT routes matched");
1858
1902
  return new Response(null, { status: 404 });
1859
1903
  };
@@ -2805,6 +2849,17 @@ var Auth = class {
2805
2849
  callbackUrl: credentials.callbackUrl
2806
2850
  });
2807
2851
  const signInRes = await this.callback(provider, body);
2852
+ const twoFactor = await is2FA(signInRes);
2853
+ if (twoFactor) {
2854
+ if (rawResponse) {
2855
+ return signInRes;
2856
+ }
2857
+ try {
2858
+ return await signInRes.clone().json();
2859
+ } catch {
2860
+ return signInRes;
2861
+ }
2862
+ }
2808
2863
  const authCookie = signInRes?.headers.get("set-cookie");
2809
2864
  if (!authCookie) {
2810
2865
  throw new Error("authentication failed");
@@ -2856,6 +2911,30 @@ var Auth = class {
2856
2911
  }
2857
2912
  });
2858
2913
  }
2914
+ async mfa(params, rawResponse) {
2915
+ return withNileContext(this.#config, async () => {
2916
+ let method = "POST";
2917
+ if (params.scope === "setup") {
2918
+ method = "PUT";
2919
+ }
2920
+ if (params.remove) {
2921
+ method = "DELETE";
2922
+ }
2923
+ const res = await fetchMfa(
2924
+ this.#config,
2925
+ method,
2926
+ JSON.stringify({ ...params, method: params.method ?? "authenticator" })
2927
+ );
2928
+ if (rawResponse) {
2929
+ return res;
2930
+ }
2931
+ try {
2932
+ return await res.clone().json();
2933
+ } catch {
2934
+ return res;
2935
+ }
2936
+ });
2937
+ }
2859
2938
  };
2860
2939
  function parseCSRF(headers) {
2861
2940
  let cookie = headers?.get("set-cookie");
@@ -2945,6 +3024,17 @@ function fQUrl(path, config) {
2945
3024
  }
2946
3025
  return path;
2947
3026
  }
3027
+ async function is2FA(signInRes) {
3028
+ try {
3029
+ const cloned = await signInRes.clone();
3030
+ const json = await cloned.json();
3031
+ if ("method" in json && "secret" in json) {
3032
+ return signInRes;
3033
+ }
3034
+ } catch {
3035
+ }
3036
+ return null;
3037
+ }
2948
3038
 
2949
3039
  // src/auth/obtainCsrf.ts
2950
3040
  async function obtainCsrf(config, rawResponse = false) {
@@ -3506,8 +3596,8 @@ function updateConfig(response, config) {
3506
3596
  }
3507
3597
  const setCookies = [];
3508
3598
  if (response?.headers) {
3509
- for (const [key17, value] of response.headers) {
3510
- if (key17.toLowerCase() === "set-cookie") {
3599
+ for (const [key18, value] of response.headers) {
3600
+ if (key18.toLowerCase() === "set-cookie") {
3511
3601
  setCookies.push(value);
3512
3602
  }
3513
3603
  }
@@ -3571,9 +3661,10 @@ var Server = class {
3571
3661
  if (typeof create2 !== "function") {
3572
3662
  continue;
3573
3663
  }
3574
- const ext = create2(this);
3575
- if (ext.onConfigure) {
3576
- ext.onConfigure();
3664
+ const ext = create2();
3665
+ if (typeof ext.onConfigure === "function") {
3666
+ this.#config.logger("[EXTENSION]").debug(`configuring for ${ext.id}`);
3667
+ ext.onConfigure(this);
3577
3668
  }
3578
3669
  if (ext?.replace?.handlers) {
3579
3670
  this.#config.logger("[EXTENSION]").debug(`${ext.id} replacing handlers`);
@@ -3613,7 +3704,7 @@ var Server = class {
3613
3704
  return {
3614
3705
  remove: async (id) => {
3615
3706
  if (!this.#config.extensions) return;
3616
- const resolved = this.#config.extensions.map((ext) => ext(this));
3707
+ const resolved = this.#config.extensions.map((ext) => ext());
3617
3708
  const index = resolved.findIndex((ext) => ext.id === id);
3618
3709
  if (index !== -1) {
3619
3710
  this.#config.extensions.splice(index, 1);
@@ -3696,25 +3787,25 @@ var Server = class {
3696
3787
  }
3697
3788
  }
3698
3789
  if (headers instanceof Headers) {
3699
- headers.forEach((value, key17) => {
3700
- updates.push([key17.toLowerCase(), value]);
3790
+ headers.forEach((value, key18) => {
3791
+ updates.push([key18.toLowerCase(), value]);
3701
3792
  });
3702
3793
  } else {
3703
- for (const [key17, value] of Object.entries(headers ?? {})) {
3704
- updates.push([key17.toLowerCase(), value]);
3794
+ for (const [key18, value] of Object.entries(headers ?? {})) {
3795
+ updates.push([key18.toLowerCase(), value]);
3705
3796
  }
3706
3797
  }
3707
3798
  const merged = {};
3708
- this.#config.context.headers?.forEach((value, key17) => {
3709
- if (key17.toLowerCase() !== "cookie") {
3710
- merged[key17.toLowerCase()] = value;
3799
+ this.#config.context.headers?.forEach((value, key18) => {
3800
+ if (key18.toLowerCase() !== "cookie") {
3801
+ merged[key18.toLowerCase()] = value;
3711
3802
  }
3712
3803
  });
3713
- for (const [key17, value] of updates) {
3714
- merged[key17] = value;
3804
+ for (const [key18, value] of updates) {
3805
+ merged[key18] = value;
3715
3806
  }
3716
- for (const [key17, value] of Object.entries(merged)) {
3717
- this.#config.context.headers.set(key17, value);
3807
+ for (const [key18, value] of Object.entries(merged)) {
3808
+ this.#config.context.headers.set(key18, value);
3718
3809
  }
3719
3810
  this.#config.logger("[handleHeaders]").debug(JSON.stringify(merged));
3720
3811
  }