@niledatabase/server 5.0.0-alpha.26 → 5.0.0-alpha.28

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
@@ -1,3 +1,4 @@
1
+ import { AsyncLocalStorage } from 'async_hooks';
1
2
  import 'dotenv/config';
2
3
  import pg from 'pg';
3
4
 
@@ -6,6 +7,7 @@ var ExtensionState = /* @__PURE__ */ ((ExtensionState2) => {
6
7
  ExtensionState2["onHandleRequest"] = "onHandleRequest";
7
8
  ExtensionState2["onRequest"] = "onRequest";
8
9
  ExtensionState2["onResponse"] = "onResponse";
10
+ ExtensionState2["withContext"] = "withContext";
9
11
  return ExtensionState2;
10
12
  })(ExtensionState || {});
11
13
  var APIErrorErrorCodeEnum = {
@@ -63,21 +65,18 @@ var appRoutes = (prefix = DEFAULT_PREFIX) => ({
63
65
  INVITE: `${prefix}${"/tenants/{tenantId}/invite" /* INVITE */}`,
64
66
  LOG: `${prefix}/_log`
65
67
  });
66
- var apiRoutes = (config) => ({
67
- ME: makeRestUrl(config, "/me"),
68
- USERS: (qp) => makeRestUrl(config, "/users", qp),
69
- USER: (userId) => makeRestUrl(config, `/users/${userId}`),
70
- TENANTS: makeRestUrl(config, "/tenants"),
71
- TENANT: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}`),
72
- SIGNUP: makeRestUrl(config, "/signup"),
73
- TENANT_USERS: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/users`),
74
- INVITES: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/invites`),
75
- INVITE: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/invite`),
76
- TENANT_USER: makeRestUrl(
77
- config,
78
- `/tenants/${config.tenantId}/users/${config.userId}`
79
- ),
80
- USER_TENANTS: (userId) => makeRestUrl(config, `/users/${userId}/tenants`)
68
+ var apiRoutes = (apiUrl) => ({
69
+ ME: makeRestUrl(apiUrl, "/me"),
70
+ USERS: (qp) => makeRestUrl(apiUrl, "/users", qp),
71
+ USER: (userId) => makeRestUrl(apiUrl, `/users/${userId}`),
72
+ TENANTS: makeRestUrl(apiUrl, "/tenants"),
73
+ TENANT: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}`),
74
+ SIGNUP: makeRestUrl(apiUrl, "/signup"),
75
+ TENANT_USERS: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/users`),
76
+ INVITES: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/invites`),
77
+ INVITE: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/invite`),
78
+ TENANT_USER: (tenantId, userId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/users/${userId}`),
79
+ USER_TENANTS: (userId) => makeRestUrl(apiUrl, `/users/${userId}/tenants`)
81
80
  });
82
81
  var proxyRoutes = (config) => ({
83
82
  SIGNIN: makeRestUrl(config, "/auth/signin" /* SIGNIN */),
@@ -101,8 +100,8 @@ function filterNullUndefined(obj) {
101
100
  )
102
101
  );
103
102
  }
104
- function makeRestUrl(config, path, qp) {
105
- const url = config.apiUrl || NILEDB_API_URL;
103
+ function makeRestUrl(apiUrl, path, qp) {
104
+ const url = apiUrl || NILEDB_API_URL;
106
105
  if (!url) {
107
106
  throw new Error(
108
107
  "An API url is required. Set it via NILEDB_API_URL. Was auto configuration run?"
@@ -259,10 +258,309 @@ async function auth(req, config) {
259
258
  }
260
259
  }
261
260
 
261
+ // src/utils/Logger.ts
262
+ var red = "\x1B[31m";
263
+ var yellow = "\x1B[38;2;255;255;0m";
264
+ var purple = "\x1B[38;2;200;160;255m";
265
+ var orange = "\x1B[38;2;255;165;0m";
266
+ var reset = "\x1B[0m";
267
+ var baseLogger = (config, ...params) => ({
268
+ silly(message, meta) {
269
+ if (config?.debug && process.env.LOG_LEVEL === "silly") {
270
+ console.log(
271
+ `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
272
+ ""
273
+ )}${reset} ${message}`,
274
+ meta ? `${JSON.stringify(meta)}` : ""
275
+ );
276
+ }
277
+ },
278
+ info(message, meta) {
279
+ if (config?.debug) {
280
+ console.info(
281
+ `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
282
+ ""
283
+ )}${reset} ${message}`,
284
+ meta ? `${JSON.stringify(meta)}` : ""
285
+ );
286
+ }
287
+ },
288
+ debug(message, meta) {
289
+ if (config?.debug) {
290
+ console.log(
291
+ `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
292
+ ""
293
+ )}${reset} ${message}`,
294
+ meta ? `${JSON.stringify(meta)}` : ""
295
+ );
296
+ }
297
+ },
298
+ warn(message, meta) {
299
+ if (config?.debug) {
300
+ console.warn(
301
+ `${orange}[niledb]${reset}${yellow}[WARN]${reset}${params.join(
302
+ ""
303
+ )}${reset} ${message}`,
304
+ meta ? JSON.stringify(meta) : ""
305
+ );
306
+ }
307
+ },
308
+ error(message, meta) {
309
+ console.error(
310
+ `${orange}[niledb]${reset}${red}[ERROR]${reset}${params.join(
311
+ ""
312
+ )}${red} ${message}`,
313
+ meta ? meta : "",
314
+ `${reset}`
315
+ );
316
+ }
317
+ });
318
+ function Logger(config) {
319
+ return (prefixes) => {
320
+ const { info, debug, warn: warn2, error, silly: silly2 } = config && typeof config?.logger === "function" ? config.logger(prefixes) : baseLogger(config, prefixes);
321
+ return {
322
+ info,
323
+ debug,
324
+ warn: warn2,
325
+ error,
326
+ silly: silly2
327
+ };
328
+ };
329
+ }
330
+ function matchesLog(configRoutes, request2) {
331
+ return urlMatches(request2.url, configRoutes.LOG);
332
+ }
333
+
334
+ // src/api/utils/extensions.ts
335
+ function getRequestConfig(params) {
336
+ if (typeof params[1] === "object") {
337
+ return params[1];
338
+ }
339
+ return {};
340
+ }
341
+ function bindRunExtensions(instance) {
342
+ return async function runExtensions(toRun, config, params, _init) {
343
+ const { debug } = config.logger("[EXTENSIONS]");
344
+ const extensionConfig = getRequestConfig(
345
+ Array.isArray(params) ? params : [null, params]
346
+ );
347
+ if (config.extensions) {
348
+ for (const create2 of config.extensions) {
349
+ if (typeof create2 !== "function") {
350
+ continue;
351
+ }
352
+ const ext = create2(instance);
353
+ if (extensionConfig.disableExtensions?.includes(ext.id)) {
354
+ continue;
355
+ }
356
+ if (ext.withContext && toRun === "withContext" /* withContext */) {
357
+ await ext.withContext(ctx);
358
+ }
359
+ if (ext.onHandleRequest && toRun === "onHandleRequest" /* onHandleRequest */) {
360
+ const result = await ext.onHandleRequest(
361
+ Array.isArray(params) ? params : [params]
362
+ );
363
+ debug(`${ext.id ?? create2.name} ran onHandleRequest`);
364
+ if (result != null) {
365
+ return result;
366
+ }
367
+ }
368
+ const [param] = Array.isArray(params) ? params : [params];
369
+ if (ext.onRequest && toRun === "onRequest" /* onRequest */) {
370
+ const { ...previousContext } = ctx.get();
371
+ const preserveHeaders = previousContext.preserveHeaders;
372
+ if (preserveHeaders) {
373
+ ctx.set({ preserveHeaders: false });
374
+ }
375
+ if (!_init) {
376
+ continue;
377
+ }
378
+ const previousHeaders = new Headers(previousContext.headers);
379
+ await ext.onRequest(_init.request, ctx);
380
+ const updatedContext = ctx.get();
381
+ if (updatedContext?.headers) {
382
+ const cookie = updatedContext.headers.get("cookie");
383
+ if (cookie && param.headers) {
384
+ const updatedCookies = mergeCookies(
385
+ preserveHeaders ? previousHeaders?.get("cookie") : null,
386
+ updatedContext.headers.get("cookie")
387
+ );
388
+ param.headers.set("cookie", updatedCookies);
389
+ }
390
+ if (updatedContext.tenantId && param.headers) {
391
+ param.headers.set(
392
+ TENANT_COOKIE,
393
+ String(updatedContext.headers.get(TENANT_COOKIE))
394
+ );
395
+ }
396
+ ctx.set({ headers: param.headers });
397
+ }
398
+ debug(`${ext.id ?? create2.name} ran onRequest`);
399
+ }
400
+ if (ext.onResponse && toRun === "onResponse" /* onResponse */) {
401
+ const result = await ext.onResponse(param, ctx);
402
+ debug(`${ext.id ?? create2.name} ran onResponse`);
403
+ if (result != null) {
404
+ return result;
405
+ }
406
+ }
407
+ }
408
+ }
409
+ return void 0;
410
+ };
411
+ }
412
+ function buildExtensionConfig(instance) {
413
+ return {
414
+ runExtensions: bindRunExtensions(instance)
415
+ };
416
+ }
417
+ function mergeCookies(...cookieStrings) {
418
+ const cookieMap = /* @__PURE__ */ new Map();
419
+ for (const str of cookieStrings) {
420
+ if (!str) continue;
421
+ for (const part of str.split(";")) {
422
+ const [key17, value] = part.split("=").map((s) => s.trim());
423
+ if (key17 && value) cookieMap.set(key17, value);
424
+ }
425
+ }
426
+ return [...cookieMap.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
427
+ }
428
+ async function runExtensionContext(config) {
429
+ await config?.extensionCtx?.runExtensions("withContext" /* withContext */, config);
430
+ }
431
+
432
+ // src/api/utils/request-context.ts
433
+ var { warn, silly } = Logger({ debug: true })("[REQUEST CONTEXT]");
434
+ var storage = new AsyncLocalStorage();
435
+ var defaultContext = {
436
+ headers: new Headers(),
437
+ tenantId: void 0,
438
+ userId: void 0,
439
+ preserveHeaders: false
440
+ };
441
+ var lastUsedContext = defaultContext;
442
+ var ctx = {
443
+ run(ctx2, fn) {
444
+ const merged = {
445
+ ...defaultContext,
446
+ ...ctx2,
447
+ headers: ctx2.headers instanceof Headers ? ctx2.headers : new Headers(ctx2.headers)
448
+ };
449
+ lastUsedContext = merged;
450
+ return storage.run(merged, fn);
451
+ },
452
+ get: () => {
453
+ const ctx2 = storage.getStore();
454
+ if (!ctx2) {
455
+ return { ...defaultContext };
456
+ }
457
+ silly(`[GET] ${serializeContext(ctx2)}`);
458
+ return ctx2;
459
+ },
460
+ /**
461
+ * This is a mirror of Server.getContext, but only for requests. We keep only the request
462
+ * information around, everything else is :above_my_pay_grade:
463
+ * @param partial A partial context to override
464
+ */
465
+ set: (partial) => {
466
+ const store = storage.getStore();
467
+ if (!store) {
468
+ warn("ctx.set() called outside of ctx.run(). This will not persist.");
469
+ return;
470
+ }
471
+ if (partial.headers === null) {
472
+ store.headers = new Headers();
473
+ } else if (partial.headers && store.headers instanceof Headers) {
474
+ for (const [key17, value] of new Headers(partial.headers).entries()) {
475
+ if (key17.toLowerCase() === "cookie") {
476
+ const existingCookies = parseCookieHeader(
477
+ store.headers.get("cookie") || ""
478
+ );
479
+ const newCookies = parseCookieHeader(value);
480
+ const mergedCookies = { ...existingCookies, ...newCookies };
481
+ store.headers.set("cookie", serializeCookies(mergedCookies));
482
+ } else {
483
+ store.headers.set(key17, value);
484
+ }
485
+ }
486
+ }
487
+ if ("tenantId" in partial)
488
+ store.tenantId = partial.tenantId ?? store.tenantId;
489
+ if ("userId" in partial) store.userId = partial.userId ?? store.userId;
490
+ if ("preserveHeaders" in partial)
491
+ store.preserveHeaders = Boolean(partial.preserveHeaders);
492
+ silly(`[SET] ${serializeContext(store)}`);
493
+ lastUsedContext = { ...store };
494
+ },
495
+ // for convenience only
496
+ getLastUsed: () => lastUsedContext
497
+ };
498
+ function withNileContext(config, fn, name = "unknown") {
499
+ const initialContext = config.context;
500
+ const existing = ctx.get();
501
+ const mergedHeaders = new Headers(existing.headers);
502
+ if (initialContext instanceof Request) {
503
+ initialContext.headers.forEach((value, key17) => {
504
+ mergedHeaders.set(key17, value);
505
+ });
506
+ const context2 = {
507
+ headers: mergedHeaders,
508
+ tenantId: existing.tenantId,
509
+ userId: existing.userId,
510
+ preserveHeaders: existing.preserveHeaders ?? false
511
+ };
512
+ silly(`${name} [INITIAL - Request] ${serializeContext(context2)}`);
513
+ return ctx.run(context2, fn);
514
+ }
515
+ if (initialContext.headers) {
516
+ const incoming = initialContext.headers instanceof Headers ? initialContext.headers : new Headers(initialContext.headers);
517
+ incoming.forEach((value, key17) => {
518
+ mergedHeaders.set(key17, value);
519
+ });
520
+ }
521
+ const tenantId = "tenantId" in initialContext && initialContext.tenantId;
522
+ const userId = "userId" in initialContext && initialContext.userId;
523
+ const preserveHeaders = "preserveHeaders" in initialContext && initialContext.preserveHeaders;
524
+ const context = {
525
+ headers: mergedHeaders,
526
+ tenantId: tenantId ? tenantId : existing.tenantId,
527
+ userId: userId ? userId : existing.userId,
528
+ preserveHeaders: preserveHeaders ? preserveHeaders : existing.preserveHeaders ?? false
529
+ };
530
+ silly(`${name} [INITIAL - Partial<Context>] ${serializeContext(context)}`);
531
+ return ctx.run(context, async () => {
532
+ await runExtensionContext(config);
533
+ return fn();
534
+ });
535
+ }
536
+ function serializeContext(context) {
537
+ const headers = {};
538
+ const rawHeaders = new Headers(context.headers);
539
+ rawHeaders.forEach((value, key17) => {
540
+ headers[key17] = value;
541
+ });
542
+ return JSON.stringify({
543
+ headers,
544
+ tenantId: context.tenantId,
545
+ userId: context.userId,
546
+ preserveHeaders: context.preserveHeaders
547
+ });
548
+ }
549
+ function parseCookieHeader(header) {
550
+ return header.split(";").map((c) => c.trim()).filter(Boolean).reduce((acc, curr) => {
551
+ const [key17, ...val] = curr.split("=");
552
+ if (key17) acc[key17] = val.join("=");
553
+ return acc;
554
+ }, {});
555
+ }
556
+ function serializeCookies(cookies) {
557
+ return Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join("; ");
558
+ }
559
+
262
560
  // src/api/routes/me/index.ts
263
561
  var key = "ME";
264
562
  async function route(request2, config) {
265
- const url = apiRoutes(config)[key];
563
+ const url = apiRoutes(config.apiUrl)[key];
266
564
  if (request2.method === "GET") {
267
565
  return await GET(url, { request: request2 }, config);
268
566
  }
@@ -283,8 +581,9 @@ function matches(configRoutes, request2) {
283
581
  }
284
582
  async function fetchMe(config, method, body) {
285
583
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/me" /* ME */}`;
584
+ const { headers } = ctx.get();
286
585
  const init = {
287
- headers: config.headers,
586
+ headers,
288
587
  method: method ?? "GET"
289
588
  };
290
589
  if (method === "PUT") {
@@ -336,9 +635,9 @@ function getTokenFromCookie(headers, cookieKey) {
336
635
  return _cookies[cookieKey];
337
636
  }
338
637
  }
339
- function getTenantFromHttp(headers, config) {
638
+ function getTenantFromHttp(headers, context) {
340
639
  const cookieTenant = getTokenFromCookie(headers, TENANT_COOKIE);
341
- return cookieTenant ? cookieTenant : config?.tenantId;
640
+ return cookieTenant ? cookieTenant : context?.tenantId;
342
641
  }
343
642
 
344
643
  // src/api/routes/users/POST.ts
@@ -348,8 +647,11 @@ async function POST(config, init) {
348
647
  const yurl = new URL(init.request.url);
349
648
  const tenantId = yurl.searchParams.get("tenantId");
350
649
  const newTenantName = yurl.searchParams.get("newTenantName");
351
- const tenant = tenantId ?? getTenantFromHttp(init.request.headers, config);
352
- const url = apiRoutes(config).USERS({ tenantId: tenant, newTenantName });
650
+ const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
651
+ const url = apiRoutes(config.apiUrl).USERS({
652
+ tenantId: tenant,
653
+ newTenantName
654
+ });
353
655
  return await request(url, init, config);
354
656
  }
355
657
 
@@ -357,13 +659,13 @@ async function POST(config, init) {
357
659
  async function GET2(config, init, log) {
358
660
  const yurl = new URL(init.request.url);
359
661
  const tenantId = yurl.searchParams.get("tenantId");
360
- const tenant = tenantId ?? getTenantFromHttp(init.request.headers, config);
662
+ const tenant = tenantId ?? getTenantFromHttp(init.request.headers, config.context);
361
663
  if (!tenant) {
362
664
  log("[GET] No tenant id provided.");
363
665
  return new Response(null, { status: 404 });
364
666
  }
365
667
  init.method = "GET";
366
- const url = apiRoutes(config).TENANT_USERS(tenant);
668
+ const url = apiRoutes(config.apiUrl).TENANT_USERS(tenant);
367
669
  return await request(url, init, config);
368
670
  }
369
671
 
@@ -372,7 +674,7 @@ async function PUT2(config, init) {
372
674
  init.body = init.request.body;
373
675
  init.method = "PUT";
374
676
  const [userId] = new URL(init.request.url).pathname.split("/").reverse();
375
- const url = apiRoutes(config).USER(userId);
677
+ const url = apiRoutes(config.apiUrl).USER(userId);
376
678
  return await request(url, init, config);
377
679
  }
378
680
 
@@ -399,7 +701,7 @@ function matches2(configRoutes, request2) {
399
701
  async function GET3(config, init) {
400
702
  const yurl = new URL(init.request.url);
401
703
  const [, tenantId] = yurl.pathname.split("/").reverse();
402
- const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
704
+ const url = `${apiRoutes(config.apiUrl).TENANT_USERS(tenantId)}`;
403
705
  return await request(url, init, config);
404
706
  }
405
707
 
@@ -413,7 +715,7 @@ async function POST2(config, init) {
413
715
  const [, tenantId] = yurl.pathname.split("/").reverse();
414
716
  init.body = JSON.stringify({ email: session.email });
415
717
  init.method = "POST";
416
- const url = apiRoutes(config).TENANT_USERS(tenantId);
718
+ const url = apiRoutes(config.apiUrl).TENANT_USERS(tenantId);
417
719
  return await request(url, init, config);
418
720
  }
419
721
 
@@ -447,12 +749,13 @@ function matches3(configRoutes, request2) {
447
749
  }
448
750
  async function fetchTenantUsers(config, method, payload) {
449
751
  const { body, params } = {};
450
- if (!config.tenantId) {
752
+ const { tenantId, headers } = ctx.get();
753
+ if (!tenantId) {
451
754
  throw new Error(
452
755
  "Unable to fetch the user's tenants, the tenantId context is missing. Call nile.setContext({ tenantId })"
453
756
  );
454
757
  }
455
- if (!isUUID(config.tenantId)) {
758
+ if (!isUUID(tenantId)) {
456
759
  config.logger("fetchTenantUsers").warn(
457
760
  "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
458
761
  );
@@ -464,14 +767,11 @@ async function fetchTenantUsers(config, method, payload) {
464
767
  if (params?.tenantId) {
465
768
  q.set("tenantId", params.tenantId);
466
769
  }
467
- const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */.replace(
468
- "{tenantId}",
469
- config.tenantId
470
- )}`;
770
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */.replace("{tenantId}", tenantId)}`;
471
771
  const m = method;
472
772
  const init = {
473
773
  method: m,
474
- headers: config.headers
774
+ headers
475
775
  };
476
776
  const req = new Request(clientUrl, init);
477
777
  return await config.handlers[m](req);
@@ -488,7 +788,7 @@ async function PUT3(config, init) {
488
788
  init.body = new URLSearchParams(yurl.searchParams).toString();
489
789
  }
490
790
  init.method = "PUT";
491
- const url = `${apiRoutes(config).INVITE(tenantId)}`;
791
+ const url = `${apiRoutes(config.apiUrl).INVITE(tenantId)}`;
492
792
  const res = await request(url, init, config);
493
793
  const location = res?.headers?.get("location");
494
794
  if (location) {
@@ -512,7 +812,7 @@ async function POST3(config, init) {
512
812
  }
513
813
  init.method = "POST";
514
814
  init.body = init.request.body;
515
- const url = `${apiRoutes(config).INVITE(tenantId)}`;
815
+ const url = `${apiRoutes(config.apiUrl).INVITE(tenantId)}`;
516
816
  return await request(url, init, config);
517
817
  }
518
818
 
@@ -538,21 +838,22 @@ function matches4(configRoutes, request2) {
538
838
  return urlMatches(request2.url, route20);
539
839
  }
540
840
  async function fetchInvite(config, method, body) {
541
- if (!config.tenantId) {
841
+ const { headers, tenantId } = ctx.get();
842
+ if (!tenantId) {
542
843
  throw new Error(
543
844
  "Unable to fetch the invite for the tenant, the tenantId context is missing. Call nile.setContext({ tenantId })"
544
845
  );
545
846
  }
546
- if (!isUUID(config.tenantId)) {
847
+ if (!isUUID(tenantId)) {
547
848
  config.logger("fetchInvite").warn(
548
849
  "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
549
850
  );
550
851
  }
551
- let clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace("{tenantId}", config.tenantId)}`;
852
+ let clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace("{tenantId}", tenantId)}`;
552
853
  const m = method ?? "GET";
553
854
  const init = {
554
855
  method: m,
555
- headers: config.headers
856
+ headers
556
857
  };
557
858
  if (method === "POST" || method === "PUT") {
558
859
  init.body = body;
@@ -572,7 +873,7 @@ async function GET4(config, init) {
572
873
  return new Response(null, { status: 404 });
573
874
  }
574
875
  init.method = "GET";
575
- const url = `${apiRoutes(config).INVITES(tenantId)}`;
876
+ const url = `${apiRoutes(config.apiUrl).INVITES(tenantId)}`;
576
877
  return await request(url, init, config);
577
878
  }
578
879
 
@@ -593,29 +894,29 @@ function matches5(configRoutes, request2) {
593
894
  return url.pathname.endsWith(route20);
594
895
  }
595
896
  async function fetchInvites(config) {
596
- if (!config.tenantId) {
897
+ const { tenantId, headers } = ctx.get();
898
+ if (!tenantId) {
597
899
  throw new Error(
598
900
  "Unable to fetch invites for the tenant, the tenantId context is missing. Call nile.setContext({ tenantId })"
599
901
  );
600
902
  }
601
- if (!isUUID(config.tenantId)) {
903
+ if (!isUUID(tenantId)) {
602
904
  config.logger("fetchInvites").warn(
603
905
  "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
604
906
  );
605
907
  }
606
- const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invites" /* INVITES */.replace("{tenantId}", config.tenantId)}`;
607
- const req = new Request(clientUrl, { headers: config.headers });
908
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invites" /* INVITES */.replace("{tenantId}", tenantId)}`;
909
+ const req = new Request(clientUrl, { headers });
608
910
  return await config.handlers.GET(req);
609
911
  }
610
912
 
611
913
  // src/api/routes/tenants/GET.ts
612
914
  async function GET5(config, session, init) {
613
- let url = `${apiRoutes(config).USER_TENANTS(session.id)}`;
915
+ let url = `${apiRoutes(config.apiUrl).USER_TENANTS(session.id)}`;
614
916
  if (typeof session === "object" && "user" in session && session.user) {
615
- url = `${apiRoutes(config).USER_TENANTS(session.user.id)}`;
917
+ url = `${apiRoutes(config.apiUrl).USER_TENANTS(session.user.id)}`;
616
918
  }
617
- const res = await request(url, init, config);
618
- return res;
919
+ return await request(url, init, config);
619
920
  }
620
921
 
621
922
  // src/api/routes/tenants/[tenantId]/GET.ts
@@ -627,7 +928,7 @@ async function GET6(config, init, log) {
627
928
  return new Response(null, { status: 404 });
628
929
  }
629
930
  init.method = "GET";
630
- const url = `${apiRoutes(config).TENANT(tenantId)}`;
931
+ const url = `${apiRoutes(config.apiUrl).TENANT(tenantId)}`;
631
932
  return await request(url, init, config);
632
933
  }
633
934
 
@@ -639,7 +940,7 @@ async function DELETE2(config, init) {
639
940
  return new Response(null, { status: 404 });
640
941
  }
641
942
  init.method = "DELETE";
642
- const url = `${apiRoutes(config).TENANT(tenantId)}`;
943
+ const url = `${apiRoutes(config.apiUrl).TENANT(tenantId)}`;
643
944
  return await request(url, init, config);
644
945
  }
645
946
 
@@ -652,7 +953,7 @@ async function PUT4(config, init) {
652
953
  }
653
954
  init.body = init.request.body;
654
955
  init.method = "PUT";
655
- const url = `${apiRoutes(config).TENANT(tenantId)}`;
956
+ const url = `${apiRoutes(config.apiUrl).TENANT(tenantId)}`;
656
957
  return await request(url, init, config);
657
958
  }
658
959
 
@@ -660,7 +961,7 @@ async function PUT4(config, init) {
660
961
  async function POST4(config, init) {
661
962
  init.body = init.request.body;
662
963
  init.method = "POST";
663
- const url = `${apiRoutes(config).TENANTS}`;
964
+ const url = `${apiRoutes(config.apiUrl).TENANTS}`;
664
965
  return await request(url, init, config);
665
966
  }
666
967
 
@@ -694,10 +995,11 @@ function matches6(configRoutes, request2) {
694
995
  return urlMatches(request2.url, configRoutes[key6]);
695
996
  }
696
997
  async function fetchTenants(config, method, body) {
998
+ const { headers } = ctx.get();
697
999
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants" /* TENANTS */}`;
698
1000
  const init = {
699
1001
  method,
700
- headers: config.headers
1002
+ headers
701
1003
  };
702
1004
  {
703
1005
  init.body = body;
@@ -706,21 +1008,22 @@ async function fetchTenants(config, method, body) {
706
1008
  return await config.handlers.POST(req);
707
1009
  }
708
1010
  async function fetchTenant(config, method, body) {
709
- if (!config.tenantId) {
1011
+ const { headers, tenantId } = ctx.get();
1012
+ if (!tenantId) {
710
1013
  throw new Error(
711
1014
  "Unable to fetch tenants, the tenantId context is missing. Call nile.setContext({ tenantId })"
712
1015
  );
713
1016
  }
714
- if (!isUUID(config.tenantId)) {
1017
+ if (!isUUID(tenantId)) {
715
1018
  config.logger("fetch tenant").warn(
716
1019
  "nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
717
1020
  );
718
1021
  }
719
- const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}" /* TENANT */.replace("{tenantId}", config.tenantId)}`;
1022
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}" /* TENANT */.replace("{tenantId}", tenantId)}`;
720
1023
  const m = method ?? "GET";
721
1024
  const init = {
722
1025
  method: m,
723
- headers: config.headers
1026
+ headers
724
1027
  };
725
1028
  if (m === "PUT") {
726
1029
  init.body = body;
@@ -729,32 +1032,33 @@ async function fetchTenant(config, method, body) {
729
1032
  return await config.handlers[m](req);
730
1033
  }
731
1034
  async function fetchTenantsByUser(config) {
732
- const { warn } = config.logger("fetchTenantsByUser");
733
- if (!config.userId) {
734
- warn(
1035
+ const { warn: warn2 } = config.logger(" fetchTenantsByUser ");
1036
+ const { userId, headers } = ctx.get();
1037
+ if (!userId) {
1038
+ warn2(
735
1039
  "nile.userId is not set. The call will still work for the API, but the database context is not set properly and may lead to unexpected behavior in your application."
736
1040
  );
737
- } else if (!isUUID(config.userId)) {
738
- warn(
1041
+ } else if (!isUUID(userId)) {
1042
+ warn2(
739
1043
  "nile.userId is not a valid UUID. This may lead to unexpected behavior in your application."
740
1044
  );
741
1045
  }
742
1046
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants" /* TENANTS */}`;
743
- const req = new Request(clientUrl, { headers: config.headers });
1047
+ const req = new Request(clientUrl, { headers });
744
1048
  return await config.handlers.GET(req);
745
1049
  }
746
1050
 
747
1051
  // src/api/routes/auth/signin.ts
748
1052
  var key7 = "SIGNIN";
749
1053
  async function route7(req, config) {
750
- let url = proxyRoutes(config)[key7];
1054
+ let url = proxyRoutes(config.apiUrl)[key7];
751
1055
  const init = {
752
1056
  method: req.method,
753
1057
  headers: req.headers
754
1058
  };
755
1059
  if (req.method === "POST") {
756
1060
  const [provider] = new URL(req.url).pathname.split("/").reverse();
757
- url = `${proxyRoutes(config)[key7]}/${provider}`;
1061
+ url = `${proxyRoutes(config.apiUrl)[key7]}/${provider}`;
758
1062
  }
759
1063
  const passThroughUrl = new URL(req.url);
760
1064
  const params = new URLSearchParams(passThroughUrl.search);
@@ -767,10 +1071,11 @@ function matches7(configRoutes, request2) {
767
1071
  }
768
1072
  async function fetchSignIn(config, provider, body) {
769
1073
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/signin" /* SIGNIN */}/${provider}`;
1074
+ const { headers } = ctx.get();
770
1075
  const req = new Request(clientUrl, {
771
1076
  method: "POST",
772
- headers: config.headers,
773
- body
1077
+ body,
1078
+ headers
774
1079
  });
775
1080
  return await config.handlers.POST(req);
776
1081
  }
@@ -778,7 +1083,7 @@ async function fetchSignIn(config, provider, body) {
778
1083
  // src/api/routes/auth/session.ts
779
1084
  async function route8(req, config) {
780
1085
  return request(
781
- proxyRoutes(config).SESSION,
1086
+ proxyRoutes(config.apiUrl).SESSION,
782
1087
  {
783
1088
  method: req.method,
784
1089
  request: req
@@ -791,9 +1096,10 @@ function matches8(configRoutes, request2) {
791
1096
  }
792
1097
  async function fetchSession(config) {
793
1098
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/session" /* SESSION */}`;
1099
+ const { headers } = ctx.get();
794
1100
  const req = new Request(clientUrl, {
795
1101
  method: "GET",
796
- headers: config.headers
1102
+ headers
797
1103
  });
798
1104
  return await config.handlers.GET(req);
799
1105
  }
@@ -801,7 +1107,7 @@ async function fetchSession(config) {
801
1107
  // src/api/routes/auth/providers.ts
802
1108
  async function route9(req, config) {
803
1109
  return request(
804
- proxyRoutes(config).PROVIDERS,
1110
+ proxyRoutes(config.apiUrl).PROVIDERS,
805
1111
  {
806
1112
  method: req.method,
807
1113
  request: req
@@ -814,9 +1120,10 @@ function matches9(configRoutes, request2) {
814
1120
  }
815
1121
  async function fetchProviders(config) {
816
1122
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/providers" /* PROVIDERS */}`;
1123
+ const { headers } = ctx.get();
817
1124
  const req = new Request(clientUrl, {
818
1125
  method: "GET",
819
- headers: config.headers
1126
+ headers
820
1127
  });
821
1128
  return await config.handlers.GET(req);
822
1129
  }
@@ -824,7 +1131,7 @@ async function fetchProviders(config) {
824
1131
  // src/api/routes/auth/csrf.ts
825
1132
  async function route10(req, config) {
826
1133
  return request(
827
- proxyRoutes(config).CSRF,
1134
+ proxyRoutes(config.apiUrl).CSRF,
828
1135
  {
829
1136
  method: req.method,
830
1137
  request: req
@@ -837,9 +1144,10 @@ function matches10(configRoutes, request2) {
837
1144
  }
838
1145
  async function fetchCsrf(config) {
839
1146
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/csrf" /* CSRF */}`;
1147
+ const { headers } = ctx.get();
840
1148
  const req = new Request(clientUrl, {
841
1149
  method: "GET",
842
- headers: config.headers
1150
+ headers
843
1151
  });
844
1152
  return await config.handlers.GET(req);
845
1153
  }
@@ -852,7 +1160,7 @@ async function route11(req, config) {
852
1160
  try {
853
1161
  const passThroughUrl = new URL(req.url);
854
1162
  const params = new URLSearchParams(passThroughUrl.search);
855
- const url = `${proxyRoutes(config)[key8]}/${provider}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
1163
+ const url = `${proxyRoutes(config.apiUrl)[key8]}/${provider}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
856
1164
  const res = await request(
857
1165
  url,
858
1166
  {
@@ -883,10 +1191,11 @@ function matches11(configRoutes, request2) {
883
1191
  return urlMatches(request2.url, configRoutes.CALLBACK);
884
1192
  }
885
1193
  async function fetchCallback(config, provider, body, request2, method = "POST") {
1194
+ const { headers } = ctx.get();
886
1195
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/callback" /* CALLBACK */}/${provider}${request2 ? `?${new URL(request2.url).searchParams}` : ""}`;
887
1196
  const req = new Request(clientUrl, {
888
1197
  method,
889
- headers: config.headers,
1198
+ headers,
890
1199
  body
891
1200
  });
892
1201
  return await config.handlers.POST(req);
@@ -895,14 +1204,14 @@ async function fetchCallback(config, provider, body, request2, method = "POST")
895
1204
  // src/api/routes/auth/signout.ts
896
1205
  var key9 = "SIGNOUT";
897
1206
  async function route12(request2, config) {
898
- let url = proxyRoutes(config)[key9];
1207
+ let url = proxyRoutes(config.apiUrl)[key9];
899
1208
  const init = {
900
1209
  method: request2.method
901
1210
  };
902
1211
  if (request2.method === "POST") {
903
1212
  init.body = request2.body;
904
1213
  const [provider] = new URL(request2.url).pathname.split("/").reverse();
905
- url = `${proxyRoutes(config)[key9]}${provider !== "signout" ? `/${provider}` : ""}`;
1214
+ url = `${proxyRoutes(config.apiUrl)[key9]}${provider !== "signout" ? `/${provider}` : ""}`;
906
1215
  }
907
1216
  const res = await request(url, { ...init, request: request2 }, config);
908
1217
  return res;
@@ -912,10 +1221,11 @@ function matches12(configRoutes, request2) {
912
1221
  }
913
1222
  async function fetchSignOut(config, body) {
914
1223
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/signout" /* SIGNOUT */}`;
1224
+ const { headers } = ctx.get();
915
1225
  const req = new Request(clientUrl, {
916
1226
  method: "POST",
917
1227
  body,
918
- headers: config.headers
1228
+ headers
919
1229
  });
920
1230
  return await config.handlers.POST(req);
921
1231
  }
@@ -924,7 +1234,7 @@ async function fetchSignOut(config, body) {
924
1234
  var key10 = "ERROR";
925
1235
  async function route13(req, config) {
926
1236
  return request(
927
- proxyRoutes(config)[key10],
1237
+ proxyRoutes(config.apiUrl)[key10],
928
1238
  {
929
1239
  method: req.method,
930
1240
  request: req
@@ -940,7 +1250,7 @@ function matches13(configRoutes, request2) {
940
1250
  var key11 = "VERIFY_REQUEST";
941
1251
  async function route14(req, config) {
942
1252
  return request(
943
- proxyRoutes(config)[key11],
1253
+ proxyRoutes(config.apiUrl)[key11],
944
1254
  {
945
1255
  method: req.method,
946
1256
  request: req
@@ -955,7 +1265,7 @@ function matches14(configRoutes, request2) {
955
1265
  // src/api/routes/auth/password-reset.ts
956
1266
  var key12 = "PASSWORD_RESET";
957
1267
  async function route15(req, config) {
958
- const url = proxyRoutes(config)[key12];
1268
+ const url = proxyRoutes(config.apiUrl)[key12];
959
1269
  const res = await request(
960
1270
  url,
961
1271
  {
@@ -984,10 +1294,11 @@ async function fetchResetPassword(config, method, body, params, useJson = true)
984
1294
  if (useJson) {
985
1295
  authParams?.set("json", "true");
986
1296
  }
1297
+ const { headers } = ctx.get();
987
1298
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/reset-password" /* PASSWORD_RESET */}?${authParams?.toString()}`;
988
1299
  const init = {
989
1300
  method,
990
- headers: config.headers
1301
+ headers
991
1302
  };
992
1303
  if (body && method !== "GET") {
993
1304
  init.body = body;
@@ -999,7 +1310,7 @@ async function fetchResetPassword(config, method, body, params, useJson = true)
999
1310
  // src/api/routes/auth/verify-email.ts
1000
1311
  var key13 = "VERIFY_EMAIL";
1001
1312
  async function route16(req, config) {
1002
- const url = proxyRoutes(config)[key13];
1313
+ const url = proxyRoutes(config.apiUrl)[key13];
1003
1314
  const res = await request(
1004
1315
  url,
1005
1316
  {
@@ -1025,9 +1336,10 @@ function matches16(configRoutes, request2) {
1025
1336
  }
1026
1337
  async function fetchVerifyEmail(config, method, body) {
1027
1338
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/verify-email" /* VERIFY_EMAIL */}`;
1339
+ const { headers } = ctx.get();
1028
1340
  const init = {
1029
1341
  method,
1030
- headers: config.headers
1342
+ headers
1031
1343
  };
1032
1344
  if (body) {
1033
1345
  init.body = body;
@@ -1038,7 +1350,7 @@ async function fetchVerifyEmail(config, method, body) {
1038
1350
 
1039
1351
  // src/api/handlers/GET.ts
1040
1352
  function GETTER(configRoutes, config) {
1041
- const { error, info, warn } = config.logger("[GET MATCHER]");
1353
+ const { error, info, warn: warn2 } = config.logger("[GET MATCHER]");
1042
1354
  return async function GET7(...params) {
1043
1355
  const handledRequest = await config.extensionCtx?.runExtensions(
1044
1356
  "onHandleRequest" /* onHandleRequest */,
@@ -1117,78 +1429,16 @@ function GETTER(configRoutes, config) {
1117
1429
  info("matches error");
1118
1430
  return route13(req, config);
1119
1431
  }
1120
- warn(`No GET routes matched ${req.url}`);
1432
+ warn2(`No GET routes matched ${req.url}`);
1121
1433
  return new Response(null, { status: 404 });
1122
1434
  };
1123
1435
  }
1124
1436
 
1125
- // src/utils/Logger.ts
1126
- var red = "\x1B[31m";
1127
- var yellow = "\x1B[38;2;255;255;0m";
1128
- var purple = "\x1B[38;2;200;160;255m";
1129
- var orange = "\x1B[38;2;255;165;0m";
1130
- var reset = "\x1B[0m";
1131
- var baseLogger = (config, ...params) => ({
1132
- info(message, meta) {
1133
- if (config?.debug) {
1134
- console.info(
1135
- `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
1136
- ""
1137
- )}${reset} ${message}`,
1138
- meta ? `${JSON.stringify(meta)}` : ""
1139
- );
1140
- }
1141
- },
1142
- debug(message, meta) {
1143
- if (config?.debug) {
1144
- console.info(
1145
- `${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
1146
- ""
1147
- )}${reset} ${message}`,
1148
- meta ? `${JSON.stringify(meta)}` : ""
1149
- );
1150
- }
1151
- },
1152
- warn(message, meta) {
1153
- if (config?.debug) {
1154
- console.warn(
1155
- `${orange}[niledb]${reset}${yellow}[WARN]${reset}${params.join(
1156
- ""
1157
- )}${reset} ${message}`,
1158
- meta ? JSON.stringify(meta) : ""
1159
- );
1160
- }
1161
- },
1162
- error(message, meta) {
1163
- console.error(
1164
- `${orange}[niledb]${reset}${red}[ERROR]${reset}${params.join(
1165
- ""
1166
- )}${red} ${message}`,
1167
- meta ? meta : "",
1168
- `${reset}`
1169
- );
1170
- }
1171
- });
1172
- function Logger(config) {
1173
- return (prefixes) => {
1174
- const { info, debug, warn, error } = config && typeof config?.logger === "function" ? config.logger(prefixes) : baseLogger(config, prefixes);
1175
- return {
1176
- info,
1177
- debug,
1178
- warn,
1179
- error
1180
- };
1181
- };
1182
- }
1183
- function matchesLog(configRoutes, request2) {
1184
- return urlMatches(request2.url, configRoutes.LOG);
1185
- }
1186
-
1187
1437
  // src/api/routes/signup/POST.ts
1188
1438
  async function POST5(config, init) {
1189
1439
  init.body = init.request.body;
1190
1440
  init.method = "POST";
1191
- const url = `${apiRoutes(config).SIGNUP}`;
1441
+ const url = `${apiRoutes(config.apiUrl).SIGNUP}`;
1192
1442
  return await request(url, init, config);
1193
1443
  }
1194
1444
 
@@ -1215,9 +1465,10 @@ async function fetchSignUp(config, payload) {
1215
1465
  q.set("tenantId", params.tenantId);
1216
1466
  }
1217
1467
  const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/signup" /* SIGNUP */}${q.size > 0 ? `?${q}` : ""}`;
1468
+ const { headers } = ctx.get();
1218
1469
  const req = new Request(clientUrl, {
1219
1470
  method: "POST",
1220
- headers: config.headers,
1471
+ headers,
1221
1472
  body
1222
1473
  });
1223
1474
  return await config.handlers.POST(req);
@@ -1225,7 +1476,7 @@ async function fetchSignUp(config, payload) {
1225
1476
 
1226
1477
  // src/api/handlers/POST.ts
1227
1478
  function POSTER(configRoutes, config) {
1228
- const { info, warn, error } = config.logger("[POST MATCHER]");
1479
+ const { info, warn: warn2, error } = config.logger("[POST MATCHER]");
1229
1480
  return async function POST6(...params) {
1230
1481
  const handledRequest = await config.extensionCtx?.runExtensions(
1231
1482
  "onHandleRequest" /* onHandleRequest */,
@@ -1261,10 +1512,6 @@ function POSTER(configRoutes, config) {
1261
1512
  info("matches signup");
1262
1513
  return route17(req, config);
1263
1514
  }
1264
- if (matches2(configRoutes, req)) {
1265
- info("matches users");
1266
- return route2(req, config);
1267
- }
1268
1515
  if (matches6(configRoutes, req)) {
1269
1516
  info("matches tenants");
1270
1517
  return route6(req, config);
@@ -1301,7 +1548,7 @@ function POSTER(configRoutes, config) {
1301
1548
  info("matches verify-email");
1302
1549
  return route16(req, config);
1303
1550
  }
1304
- warn(`No POST routes matched ${req.url}`);
1551
+ warn2(`No POST routes matched ${req.url}`);
1305
1552
  return new Response(null, { status: 404 });
1306
1553
  };
1307
1554
  }
@@ -1310,10 +1557,8 @@ function POSTER(configRoutes, config) {
1310
1557
  async function DELETE3(config, init) {
1311
1558
  const yurl = new URL(init.request.url);
1312
1559
  const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
1313
- config.tenantId = tenantId;
1314
- config.userId = userId;
1315
1560
  init.method = "DELETE";
1316
- const url = `${apiRoutes(config).TENANT_USER}/link`;
1561
+ const url = `${apiRoutes(config.apiUrl).TENANT_USER(tenantId, userId)}/link`;
1317
1562
  return await request(url, init, config);
1318
1563
  }
1319
1564
 
@@ -1321,10 +1566,8 @@ async function DELETE3(config, init) {
1321
1566
  async function PUT5(config, init) {
1322
1567
  const yurl = new URL(init.request.url);
1323
1568
  const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
1324
- config.tenantId = tenantId;
1325
- config.userId = userId;
1326
1569
  init.method = "PUT";
1327
- const url = `${apiRoutes(config).TENANT_USER}/link`;
1570
+ const url = `${apiRoutes(config.apiUrl).TENANT_USER(tenantId, userId)}/link`;
1328
1571
  return await request(url, init, config);
1329
1572
  }
1330
1573
 
@@ -1362,22 +1605,24 @@ function matches18(configRoutes, request2) {
1362
1605
  return urlMatches(request2.url, route20);
1363
1606
  }
1364
1607
  async function fetchTenantUser(config, method) {
1365
- if (!config.tenantId) {
1608
+ const { headers, tenantId, userId } = ctx.get();
1609
+ const action = method === "PUT" ? "add" : "delete";
1610
+ if (!tenantId) {
1366
1611
  throw new Error(
1367
- "The tenantId context is missing. Call nile.setContext({ tenantId })"
1612
+ `Unable to ${action} user to the tenant, the tenantId context is missing. Use nile.withContext({ tenantId })`
1368
1613
  );
1369
1614
  }
1370
- if (!config.userId) {
1615
+ if (!userId) {
1371
1616
  throw new Error(
1372
- "the userId context is missing. Call nile.setContext({ userId })"
1617
+ `Unable to ${action} user to tenant. The userId context is missing. Use nile.withContext({ userId })`
1373
1618
  );
1374
1619
  }
1375
- const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */.replace(
1376
- "{tenantId}",
1377
- config.tenantId
1378
- ).replace("{userId}", config.userId)}/link`;
1620
+ const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */.replace("{tenantId}", tenantId).replace(
1621
+ "{userId}",
1622
+ userId
1623
+ )}/link`;
1379
1624
  const req = new Request(clientUrl, {
1380
- headers: config.headers,
1625
+ headers,
1381
1626
  method
1382
1627
  });
1383
1628
  return await config.handlers[method](req);
@@ -1391,7 +1636,7 @@ async function DELETE4(config, init) {
1391
1636
  return new Response(null, { status: 404 });
1392
1637
  }
1393
1638
  init.method = "DELETE";
1394
- const url = `${apiRoutes(config).INVITE(tenantId)}/${inviteId}`;
1639
+ const url = `${apiRoutes(config.apiUrl).INVITE(tenantId)}/${inviteId}`;
1395
1640
  return await request(url, init, config);
1396
1641
  }
1397
1642
 
@@ -1414,7 +1659,7 @@ function matches19(configRoutes, request2) {
1414
1659
 
1415
1660
  // src/api/handlers/DELETE.ts
1416
1661
  function DELETER(configRoutes, config) {
1417
- const { error, info, warn } = config.logger("[DELETE MATCHER]");
1662
+ const { error, info, warn: warn2 } = config.logger("[DELETE MATCHER]");
1418
1663
  return async function DELETE5(...params) {
1419
1664
  const handledRequest = await config.extensionCtx?.runExtensions(
1420
1665
  "onHandleRequest" /* onHandleRequest */,
@@ -1445,14 +1690,14 @@ function DELETER(configRoutes, config) {
1445
1690
  info("matches me");
1446
1691
  return route(req, config);
1447
1692
  }
1448
- warn("No DELETE routes matched");
1693
+ warn2("No DELETE routes matched");
1449
1694
  return new Response(null, { status: 404 });
1450
1695
  };
1451
1696
  }
1452
1697
 
1453
1698
  // src/api/handlers/PUT.ts
1454
1699
  function PUTER(configRoutes, config) {
1455
- const { error, info, warn } = config.logger("[PUT MATCHER]");
1700
+ const { error, info, warn: warn2 } = config.logger("[PUT MATCHER]");
1456
1701
  return async function PUT6(...params) {
1457
1702
  const handledRequest = await config.extensionCtx?.runExtensions(
1458
1703
  "onHandleRequest" /* onHandleRequest */,
@@ -1479,10 +1724,6 @@ function PUTER(configRoutes, config) {
1479
1724
  info("matches tenant users");
1480
1725
  return route3(req, config);
1481
1726
  }
1482
- if (matches2(configRoutes, req)) {
1483
- info("matches users");
1484
- return route2(req, config);
1485
- }
1486
1727
  if (matches(configRoutes, req)) {
1487
1728
  info("matches me");
1488
1729
  return route(req, config);
@@ -1495,7 +1736,7 @@ function PUTER(configRoutes, config) {
1495
1736
  info("matches reset password");
1496
1737
  return route15(req, config);
1497
1738
  }
1498
- warn("No PUT routes matched");
1739
+ warn2("No PUT routes matched");
1499
1740
  return new Response(null, { status: 404 });
1500
1741
  };
1501
1742
  }
@@ -1699,18 +1940,7 @@ var Config = class {
1699
1940
  extensionCtx;
1700
1941
  extensions;
1701
1942
  logger;
1702
- /**
1703
- * Stores the set tenant id from Server for use in sub classes
1704
- */
1705
- tenantId;
1706
- /**
1707
- * Stores the set user id from Server for use in sub classes
1708
- */
1709
- userId;
1710
- /**
1711
- * Stores the headers to be used in `fetch` calls
1712
- */
1713
- headers;
1943
+ context;
1714
1944
  /**
1715
1945
  * The nile-auth url
1716
1946
  */
@@ -1761,11 +1991,12 @@ var Config = class {
1761
1991
  if (databaseName) {
1762
1992
  this.db.database = databaseName;
1763
1993
  }
1764
- if (config?.headers) {
1765
- this.headers = config?.headers;
1766
- } else {
1767
- this.headers = new Headers();
1768
- }
1994
+ this.context = {
1995
+ tenantId: config?.tenantId,
1996
+ userId: config?.userId,
1997
+ headers: config?.headers ? new Headers(config.headers) : new Headers(),
1998
+ preserveHeaders: false
1999
+ };
1769
2000
  this.routes = {
1770
2001
  ...appRoutes(config?.routePrefix),
1771
2002
  ...config?.routes
@@ -1808,8 +2039,6 @@ var Config = class {
1808
2039
  ],
1809
2040
  delete: [this.routes.TENANT_USER, this.routes.TENANT]
1810
2041
  };
1811
- this.tenantId = config?.tenantId;
1812
- this.userId = config?.userId;
1813
2042
  }
1814
2043
  };
1815
2044
 
@@ -1876,7 +2105,15 @@ function createProxyForPool(pool, config) {
1876
2105
  }
1877
2106
  const caller = target[property];
1878
2107
  return function query(...args) {
1879
- info("query", ...args);
2108
+ let log = "[QUERY]";
2109
+ const { userId, tenantId } = config.context;
2110
+ if (tenantId) {
2111
+ log = `${log}[TENANT:${tenantId}]`;
2112
+ }
2113
+ if (userId) {
2114
+ log = `${log}[USER:${userId}]`;
2115
+ }
2116
+ info(log, ...args);
1880
2117
  const called = caller.apply(this, args);
1881
2118
  return called;
1882
2119
  };
@@ -1895,7 +2132,7 @@ var NileDatabase = class {
1895
2132
  config;
1896
2133
  timer;
1897
2134
  constructor(config, id) {
1898
- const { warn, info, debug } = config.logger("[NileInstance]");
2135
+ const { warn: warn2, info, debug } = config.logger("[NileInstance]");
1899
2136
  this.id = id;
1900
2137
  const poolConfig = {
1901
2138
  min: 0,
@@ -1911,7 +2148,7 @@ var NileDatabase = class {
1911
2148
  debug(`Connection pool config ${JSON.stringify(cloned)}`);
1912
2149
  this.pool = createProxyForPool(new pg.Pool(remaining), this.config);
1913
2150
  if (typeof afterCreate === "function") {
1914
- warn(
2151
+ warn2(
1915
2152
  "Providing an pool configuration will stop automatic tenant context setting."
1916
2153
  );
1917
2154
  }
@@ -1977,7 +2214,7 @@ var NileDatabase = class {
1977
2214
  };
1978
2215
  var NileInstance_default = NileDatabase;
1979
2216
  function makeAfterCreate(config, id) {
1980
- const { error, warn, debug } = config.logger("[afterCreate]");
2217
+ const { error, warn: warn2, debug } = config.logger("[afterCreate]");
1981
2218
  return (conn, done) => {
1982
2219
  conn.on("error", function errorHandler(e) {
1983
2220
  error(`Connection ${id} was terminated by server`, {
@@ -1986,13 +2223,15 @@ function makeAfterCreate(config, id) {
1986
2223
  });
1987
2224
  done(e, conn);
1988
2225
  });
1989
- if (config.tenantId) {
1990
- const query = [`SET nile.tenant_id = '${config.tenantId}'`];
1991
- if (config.userId) {
1992
- if (!config.tenantId) {
1993
- warn("A user id cannot be set in context without a tenant id");
2226
+ const tenantId = config.context.tenantId;
2227
+ const userId = config.context.userId;
2228
+ if (tenantId) {
2229
+ const query = [`SET nile.tenant_id = '${tenantId}'`];
2230
+ if (userId) {
2231
+ if (!tenantId) {
2232
+ warn2("A user id cannot be set in context without a tenant id");
1994
2233
  }
1995
- query.push(`SET nile.user_id = '${config.userId}'`);
2234
+ query.push(`SET nile.user_id = '${userId}'`);
1996
2235
  }
1997
2236
  conn.query(query.join(";"), function(err) {
1998
2237
  if (err) {
@@ -2005,11 +2244,11 @@ function makeAfterCreate(config, id) {
2005
2244
  });
2006
2245
  } else {
2007
2246
  if (query.length === 1) {
2008
- debug(`connection context set: tenantId=${config.tenantId}`);
2247
+ debug(`connection context set: tenantId=${tenantId}`);
2009
2248
  }
2010
2249
  if (query.length === 2) {
2011
2250
  debug(
2012
- `connection context set: tenantId=${config.tenantId} userId=${config.userId}`
2251
+ `connection context set: tenantId=${tenantId} userId=${userId}`
2013
2252
  );
2014
2253
  }
2015
2254
  }
@@ -2041,19 +2280,19 @@ var DBManager = class {
2041
2280
  watchEvictPool(this.poolWatcherFn);
2042
2281
  }
2043
2282
  poolWatcher = (config) => (id) => {
2044
- const { info, warn } = Logger(config)("[DBManager]");
2283
+ const { info, warn: warn2 } = Logger(config)("[DBManager]");
2045
2284
  if (id && this.connections.has(id)) {
2046
2285
  info(`Removing ${id} from db connection pool.`);
2047
2286
  const connection = this.connections.get(id);
2048
2287
  connection?.shutdown();
2049
2288
  this.connections.delete(id);
2050
2289
  } else {
2051
- warn(`missed eviction of ${id}`);
2290
+ warn2(`missed eviction of ${id}`);
2052
2291
  }
2053
2292
  };
2054
2293
  getConnection = (config) => {
2055
2294
  const { info } = Logger(config)("[DBManager]");
2056
- const id = this.makeId(config.tenantId, config.userId);
2295
+ const id = this.makeId(config.context.tenantId, config.context.userId);
2057
2296
  const existing = this.connections.get(id);
2058
2297
  info(`# of instances: ${this.connections.size}`);
2059
2298
  if (existing) {
@@ -2061,7 +2300,7 @@ var DBManager = class {
2061
2300
  existing.startTimeout();
2062
2301
  return existing.pool;
2063
2302
  }
2064
- const newOne = new NileInstance_default(new Config(config), id);
2303
+ const newOne = new NileInstance_default(config, id);
2065
2304
  this.connections.set(id, newOne);
2066
2305
  info(`created new ${id}`);
2067
2306
  info(`# of instances: ${this.connections.size}`);
@@ -2096,33 +2335,39 @@ var Auth = class {
2096
2335
  this.#logger = config.logger("[auth]");
2097
2336
  }
2098
2337
  async getSession(rawResponse = false) {
2099
- const res = await fetchSession(this.#config);
2100
- if (rawResponse) {
2101
- return res;
2102
- }
2103
- try {
2104
- const session = await res.clone().json();
2105
- if (Object.keys(session).length === 0) {
2106
- return void 0;
2338
+ return withNileContext(this.#config, async () => {
2339
+ const res = await fetchSession(this.#config);
2340
+ if (rawResponse) {
2341
+ return res;
2107
2342
  }
2108
- return session;
2109
- } catch {
2110
- return res;
2111
- }
2343
+ try {
2344
+ const session = await res.clone().json();
2345
+ if (Object.keys(session).length === 0) {
2346
+ return void 0;
2347
+ }
2348
+ return session;
2349
+ } catch {
2350
+ return res;
2351
+ }
2352
+ });
2112
2353
  }
2113
2354
  async getCsrf(rawResponse = false) {
2114
- return await obtainCsrf(this.#config, rawResponse);
2355
+ return withNileContext(this.#config, async () => {
2356
+ return await obtainCsrf(this.#config, rawResponse);
2357
+ });
2115
2358
  }
2116
2359
  async listProviders(rawResponse = false) {
2117
- const res = await fetchProviders(this.#config);
2118
- if (rawResponse) {
2119
- return res;
2120
- }
2121
- try {
2122
- return await res.clone().json();
2123
- } catch {
2124
- return res;
2125
- }
2360
+ return withNileContext(this.#config, async () => {
2361
+ const res = await fetchProviders(this.#config);
2362
+ if (rawResponse) {
2363
+ return res;
2364
+ }
2365
+ try {
2366
+ return await res.clone().json();
2367
+ } catch {
2368
+ return res;
2369
+ }
2370
+ });
2126
2371
  }
2127
2372
  /**
2128
2373
  * Sign the current user out by calling `/api/auth/signout`.
@@ -2131,73 +2376,79 @@ var Auth = class {
2131
2376
  * from the internal configuration once the request completes.
2132
2377
  */
2133
2378
  async signOut() {
2134
- const csrfRes = await this.getCsrf();
2135
- if (!("csrfToken" in csrfRes)) {
2136
- throw new Error("Unable to obtain CSRF token. Sign out failed.");
2137
- }
2138
- const body = JSON.stringify({
2139
- csrfToken: csrfRes.csrfToken,
2140
- json: true
2379
+ return withNileContext(this.#config, async () => {
2380
+ const csrfRes = await this.getCsrf();
2381
+ if (!("csrfToken" in csrfRes)) {
2382
+ throw new Error("Unable to obtain CSRF token. Sign out failed.");
2383
+ }
2384
+ const body = JSON.stringify({
2385
+ csrfToken: csrfRes.csrfToken,
2386
+ json: true
2387
+ });
2388
+ const res = await fetchSignOut(this.#config, body);
2389
+ updateHeaders(new Headers({}));
2390
+ ctx.set({ headers: null });
2391
+ return res;
2141
2392
  });
2142
- const res = await fetchSignOut(this.#config, body);
2143
- updateHeaders(new Headers({}));
2144
- this.#config.headers = new Headers();
2145
- return res;
2146
2393
  }
2147
2394
  async signUp(payload, rawResponse) {
2148
- this.#config.headers = new Headers();
2149
- const { email, password, ...params } = payload;
2150
- if (!email || !password) {
2151
- throw new Error(
2152
- "Server side sign up requires a user email and password."
2153
- );
2154
- }
2155
- const providers = await this.listProviders();
2156
- const { credentials } = providers ?? {};
2157
- if (!credentials) {
2158
- throw new Error(
2159
- "Unable to obtain credential provider. Aborting server side sign up."
2160
- );
2161
- }
2162
- const csrf = await this.getCsrf();
2163
- let csrfToken;
2164
- if ("csrfToken" in csrf) {
2165
- csrfToken = csrf.csrfToken;
2166
- } else {
2167
- throw new Error("Unable to obtain parse CSRF. Request blocked.");
2168
- }
2169
- const body = JSON.stringify({
2170
- email,
2171
- password,
2172
- csrfToken,
2173
- callbackUrl: credentials.callbackUrl
2174
- });
2175
- const res = await fetchSignUp(this.#config, { body, params });
2176
- if (res.status > 299) {
2177
- this.#logger.error(await res.clone().text());
2178
- return void 0;
2179
- }
2180
- const token = parseToken(res.headers);
2181
- if (!token) {
2182
- throw new Error("Server side sign up failed. Session token not found");
2183
- }
2184
- this.#config.headers?.append("cookie", token);
2185
- updateHeaders(this.#config.headers);
2186
- if (rawResponse) {
2187
- return res;
2188
- }
2189
- try {
2190
- const json = await res.clone().json();
2191
- if (json && typeof json === "object" && "tenants" in json) {
2192
- const tenantId = json.tenants[0];
2193
- if (tenantId) {
2194
- updateTenantId(tenantId);
2395
+ return withNileContext(this.#config, async () => {
2396
+ ctx.set({ headers: null });
2397
+ const { email, password, ...params } = payload;
2398
+ if (!email || !password) {
2399
+ throw new Error(
2400
+ "Server side sign up requires a user email and password."
2401
+ );
2402
+ }
2403
+ const providers = await this.listProviders();
2404
+ const { credentials } = providers ?? {};
2405
+ if (!credentials) {
2406
+ throw new Error(
2407
+ "Unable to obtain credential provider. Aborting server side sign up."
2408
+ );
2409
+ }
2410
+ const csrf = await obtainCsrf(this.#config);
2411
+ let csrfToken;
2412
+ if ("csrfToken" in csrf) {
2413
+ csrfToken = csrf.csrfToken;
2414
+ } else {
2415
+ throw new Error("Unable to obtain parse CSRF. Request blocked.");
2416
+ }
2417
+ const body = JSON.stringify({
2418
+ email,
2419
+ password,
2420
+ csrfToken,
2421
+ callbackUrl: credentials.callbackUrl
2422
+ });
2423
+ const res = await fetchSignUp(this.#config, { body, params });
2424
+ if (res.status > 299) {
2425
+ this.#logger.error(await res.clone().text());
2426
+ return void 0;
2427
+ }
2428
+ const token = parseToken(res.headers);
2429
+ if (!token) {
2430
+ throw new Error("Server side sign up failed. Session token not found");
2431
+ }
2432
+ const { headers } = ctx.get();
2433
+ headers?.append("cookie", token);
2434
+ ctx.set({ headers });
2435
+ updateHeaders(headers);
2436
+ if (rawResponse) {
2437
+ return res;
2438
+ }
2439
+ try {
2440
+ const json = await res.clone().json();
2441
+ if (json && typeof json === "object" && "tenants" in json) {
2442
+ const tenantId = json.tenants[0];
2443
+ if (tenantId) {
2444
+ updateTenantId(tenantId);
2445
+ }
2195
2446
  }
2447
+ return json;
2448
+ } catch {
2449
+ return res;
2196
2450
  }
2197
- return json;
2198
- } catch {
2199
- return res;
2200
- }
2451
+ });
2201
2452
  }
2202
2453
  /**
2203
2454
  * Request a password reset email.
@@ -2207,34 +2458,34 @@ var Auth = class {
2207
2458
  * which is returned as a {@link Response} object.
2208
2459
  */
2209
2460
  async forgotPassword(req) {
2210
- let email = "";
2211
- const defaults = defaultCallbackUrl({
2212
- config: this.#config
2213
- });
2214
- let callbackUrl = defaults.callbackUrl;
2215
- let redirectUrl = defaults.redirectUrl;
2216
- if ("email" in req) {
2217
- email = req.email;
2218
- }
2219
- if ("callbackUrl" in req) {
2220
- callbackUrl = req.callbackUrl ? req.callbackUrl : null;
2221
- }
2222
- if ("redirectUrl" in req) {
2223
- redirectUrl = req.redirectUrl ? req.redirectUrl : null;
2224
- }
2225
- const body = JSON.stringify({
2226
- email,
2227
- redirectUrl,
2228
- callbackUrl
2461
+ return withNileContext(this.#config, async () => {
2462
+ let email = "";
2463
+ const defaults = defaultCallbackUrl(this.#config);
2464
+ let callbackUrl = defaults.callbackUrl;
2465
+ let redirectUrl = defaults.redirectUrl;
2466
+ if ("email" in req) {
2467
+ email = req.email;
2468
+ }
2469
+ if ("callbackUrl" in req) {
2470
+ callbackUrl = fQUrl(req.callbackUrl ?? "", this.#config);
2471
+ }
2472
+ if ("redirectUrl" in req) {
2473
+ redirectUrl = fQUrl(req.redirectUrl ?? "", this.#config);
2474
+ }
2475
+ const body = JSON.stringify({
2476
+ email,
2477
+ redirectUrl,
2478
+ callbackUrl
2479
+ });
2480
+ const data = await fetchResetPassword(
2481
+ this.#config,
2482
+ "POST",
2483
+ body,
2484
+ new URLSearchParams(),
2485
+ false
2486
+ );
2487
+ return data;
2229
2488
  });
2230
- const data = await fetchResetPassword(
2231
- this.#config,
2232
- "POST",
2233
- body,
2234
- new URLSearchParams(),
2235
- false
2236
- );
2237
- return data;
2238
2489
  }
2239
2490
  /**
2240
2491
  * Complete a password reset.
@@ -2247,93 +2498,98 @@ var Auth = class {
2247
2498
  * containing the necessary fields.
2248
2499
  */
2249
2500
  async resetPassword(req) {
2250
- let email = "";
2251
- let password = "";
2252
- const defaults = defaultCallbackUrl({ config: this.#config });
2253
- let callbackUrl = defaults.callbackUrl;
2254
- let redirectUrl = defaults.redirectUrl;
2255
- if (req instanceof Request) {
2256
- const body2 = await req.json();
2257
- email = body2.email;
2258
- password = body2.password;
2259
- const cbFromHeaders = parseCallback(req.headers);
2260
- if (cbFromHeaders) {
2261
- callbackUrl = cbFromHeaders;
2262
- }
2263
- if (body2.callbackUrl) {
2264
- callbackUrl = body2.callbackUrl;
2265
- }
2266
- if (body2.redirectUrl) {
2267
- redirectUrl = body2.redirectUrl;
2501
+ return withNileContext(this.#config, async () => {
2502
+ let email = "";
2503
+ let password = "";
2504
+ const defaults = defaultCallbackUrl(this.#config);
2505
+ let callbackUrl = defaults.callbackUrl;
2506
+ let redirectUrl = defaults.redirectUrl;
2507
+ if (req instanceof Request) {
2508
+ const body2 = await req.json();
2509
+ email = body2.email;
2510
+ password = body2.password;
2511
+ const cbFromHeaders = parseCallback(req.headers);
2512
+ if (cbFromHeaders) {
2513
+ callbackUrl = cbFromHeaders;
2514
+ }
2515
+ if (body2.callbackUrl) {
2516
+ callbackUrl = body2.callbackUrl;
2517
+ }
2518
+ if (body2.redirectUrl) {
2519
+ redirectUrl = body2.redirectUrl;
2520
+ }
2521
+ } else {
2522
+ if ("email" in req) {
2523
+ email = req.email;
2524
+ }
2525
+ if ("password" in req) {
2526
+ password = req.password;
2527
+ }
2528
+ if ("callbackUrl" in req) {
2529
+ callbackUrl = req.callbackUrl ? req.callbackUrl : null;
2530
+ }
2531
+ if ("redirectUrl" in req) {
2532
+ redirectUrl = req.redirectUrl ? req.redirectUrl : null;
2533
+ }
2268
2534
  }
2269
- } else {
2270
- if ("email" in req) {
2271
- email = req.email;
2535
+ await this.getCsrf();
2536
+ const body = JSON.stringify({
2537
+ email,
2538
+ password,
2539
+ redirectUrl,
2540
+ callbackUrl
2541
+ });
2542
+ let urlWithParams;
2543
+ try {
2544
+ const data = await fetchResetPassword(this.#config, "POST", body);
2545
+ const cloned = data.clone();
2546
+ if (data.status === 400) {
2547
+ const text = await cloned.text();
2548
+ this.#logger.error(text);
2549
+ return data;
2550
+ }
2551
+ const { url } = await data.json();
2552
+ urlWithParams = url;
2553
+ } catch {
2272
2554
  }
2273
- if ("password" in req) {
2274
- password = req.password;
2555
+ let token;
2556
+ try {
2557
+ const worthyParams = new URL(urlWithParams).searchParams;
2558
+ const answer = await fetchResetPassword(
2559
+ this.#config,
2560
+ "GET",
2561
+ null,
2562
+ worthyParams
2563
+ );
2564
+ token = parseResetToken(answer.headers);
2565
+ } catch {
2566
+ this.#logger.warn(
2567
+ "Unable to parse reset password url. Password not reset."
2568
+ );
2275
2569
  }
2276
- if ("callbackUrl" in req) {
2277
- callbackUrl = req.callbackUrl ? req.callbackUrl : null;
2570
+ const { headers } = ctx.get();
2571
+ const cookie = headers?.get("cookie")?.split("; ");
2572
+ if (token) {
2573
+ cookie?.push(token);
2574
+ } else {
2575
+ throw new Error(
2576
+ "Unable to reset password, reset token is missing from response"
2577
+ );
2278
2578
  }
2279
- if ("redirectUrl" in req) {
2280
- redirectUrl = req.redirectUrl ? req.redirectUrl : null;
2579
+ if (cookie) {
2580
+ headers?.set("cookie", cookie?.join("; "));
2581
+ ctx.set({
2582
+ headers
2583
+ });
2281
2584
  }
2282
- }
2283
- await this.getCsrf();
2284
- const body = JSON.stringify({
2285
- email,
2286
- password,
2287
- redirectUrl,
2288
- callbackUrl
2289
- });
2290
- let urlWithParams;
2291
- try {
2292
- const data = await fetchResetPassword(this.#config, "POST", body);
2293
- const cloned = data.clone();
2294
- if (data.status === 400) {
2295
- const text = await cloned.text();
2296
- this.#logger.error(text);
2297
- return data;
2298
- }
2299
- const { url } = await data.json();
2300
- urlWithParams = url;
2301
- } catch {
2302
- }
2303
- let token;
2304
- try {
2305
- const worthyParams = new URL(urlWithParams).searchParams;
2306
- const answer = await fetchResetPassword(
2307
- this.#config,
2308
- "GET",
2309
- null,
2310
- worthyParams
2311
- );
2312
- token = parseResetToken(answer.headers);
2313
- } catch {
2314
- this.#logger.warn(
2315
- "Unable to parse reset password url. Password not reset."
2316
- );
2317
- }
2318
- const cookie = this.#config.headers.get("cookie")?.split("; ");
2319
- if (token) {
2320
- cookie?.push(token);
2321
- } else {
2322
- throw new Error(
2323
- "Unable to reset password, reset token is missing from response"
2324
- );
2325
- }
2326
- this.#config.headers = new Headers({
2327
- ...this.#config.headers,
2328
- cookie: cookie?.join("; ")
2585
+ const res = await fetchResetPassword(this.#config, "PUT", body);
2586
+ cookie?.pop();
2587
+ const cleaned = cookie?.filter((c) => !c.includes("nile.session")) ?? [];
2588
+ cleaned.push(String(parseToken(res.headers)));
2589
+ const updatedHeaders = new Headers({ cookie: cleaned.join("; ") });
2590
+ updateHeaders(updatedHeaders);
2591
+ return res;
2329
2592
  });
2330
- const res = await fetchResetPassword(this.#config, "PUT", body);
2331
- cookie?.pop();
2332
- const cleaned = cookie?.filter((c) => !c.includes("nile.session")) ?? [];
2333
- cleaned.push(String(parseToken(res.headers)));
2334
- const updatedHeaders = new Headers({ cookie: cleaned.join("; ") });
2335
- updateHeaders(updatedHeaders);
2336
- return res;
2337
2593
  }
2338
2594
  /**
2339
2595
  * Low level helper used by {@link signIn} to complete provider flows.
@@ -2343,7 +2599,9 @@ var Auth = class {
2343
2599
  */
2344
2600
  async callback(provider, body) {
2345
2601
  if (body instanceof Request) {
2346
- this.#config.headers = body.headers;
2602
+ ctx.set({
2603
+ headers: body.headers
2604
+ });
2347
2605
  return await fetchCallback(
2348
2606
  this.#config,
2349
2607
  provider,
@@ -2355,112 +2613,115 @@ var Auth = class {
2355
2613
  return await fetchCallback(this.#config, provider, body);
2356
2614
  }
2357
2615
  async signIn(provider, payload, rawResponse) {
2358
- if (payload instanceof Request) {
2359
- const body2 = new URLSearchParams(await payload.text());
2360
- const origin = new URL(payload.url).origin;
2361
- const payloadUrl = body2?.get("callbackUrl");
2362
- const csrfToken2 = body2?.get("csrfToken");
2363
- const callbackUrl = `${!payloadUrl?.startsWith("http") ? origin : ""}${payloadUrl}`;
2364
- if (!csrfToken2) {
2616
+ return withNileContext(this.#config, async () => {
2617
+ if (payload instanceof Request) {
2618
+ const body2 = new URLSearchParams(await payload.text());
2619
+ const origin = new URL(payload.url).origin;
2620
+ const payloadUrl = body2?.get("callbackUrl");
2621
+ const csrfToken2 = body2?.get("csrfToken");
2622
+ const callbackUrl = `${!payloadUrl?.startsWith("http") ? origin : ""}${payloadUrl}`;
2623
+ if (!csrfToken2) {
2624
+ throw new Error(
2625
+ "CSRF token in missing from request. Request it by the client before calling sign in"
2626
+ );
2627
+ }
2628
+ const updatedHeaders = new Headers(payload.headers);
2629
+ updatedHeaders.set("Content-Type", "application/x-www-form-urlencoded");
2630
+ ctx.set({ headers: updatedHeaders });
2631
+ const params = new URLSearchParams({
2632
+ csrfToken: csrfToken2,
2633
+ json: String(true)
2634
+ });
2635
+ if (payloadUrl) {
2636
+ params.set("callbackUrl", callbackUrl);
2637
+ }
2638
+ return await fetchSignIn(this.#config, provider, params);
2639
+ }
2640
+ ctx.set({ headers: null });
2641
+ const { info, error } = this.#logger;
2642
+ const providers = await this.listProviders();
2643
+ info("Obtaining csrf");
2644
+ const csrf = await obtainCsrf(this.#config);
2645
+ let csrfToken;
2646
+ if ("csrfToken" in csrf) {
2647
+ csrfToken = csrf.csrfToken;
2648
+ } else {
2649
+ throw new Error("Unable to obtain parse CSRF. Request blocked.");
2650
+ }
2651
+ const { credentials } = providers ?? {};
2652
+ if (!credentials) {
2365
2653
  throw new Error(
2366
- "CSRF token in missing from request. Request it by the client before calling sign in"
2654
+ "Unable to obtain credential provider. Aborting server side sign in."
2367
2655
  );
2368
2656
  }
2369
- this.#config.headers = new Headers(payload.headers);
2370
- this.#config.headers.set(
2371
- "Content-Type",
2372
- "application/x-www-form-urlencoded"
2373
- );
2374
- const params = new URLSearchParams({
2375
- csrfToken: csrfToken2,
2376
- json: String(true)
2657
+ const { email, password } = payload ?? {};
2658
+ if (provider === "email" && (!email || !password)) {
2659
+ throw new Error(
2660
+ "Server side sign in requires a user email and password."
2661
+ );
2662
+ }
2663
+ info(`Obtaining providers for ${email}`);
2664
+ info(`Attempting sign in with email ${email}`);
2665
+ if (!email) {
2666
+ throw new Error("Email missing from payload, unable to sign in");
2667
+ }
2668
+ const body = JSON.stringify({
2669
+ email,
2670
+ password,
2671
+ csrfToken,
2672
+ callbackUrl: credentials.callbackUrl
2377
2673
  });
2378
- if (payloadUrl) {
2379
- params.set("callbackUrl", callbackUrl);
2380
- }
2381
- return await fetchSignIn(this.#config, provider, params);
2382
- }
2383
- this.#config.headers = new Headers();
2384
- const { info, error } = this.#logger;
2385
- const providers = await this.listProviders();
2386
- info("Obtaining csrf");
2387
- const csrf = await this.getCsrf();
2388
- let csrfToken;
2389
- if ("csrfToken" in csrf) {
2390
- csrfToken = csrf.csrfToken;
2391
- } else {
2392
- throw new Error("Unable to obtain parse CSRF. Request blocked.");
2393
- }
2394
- const { credentials } = providers ?? {};
2395
- if (!credentials) {
2396
- throw new Error(
2397
- "Unable to obtain credential provider. Aborting server side sign in."
2398
- );
2399
- }
2400
- const { email, password } = payload ?? {};
2401
- if (provider === "email" && (!email || !password)) {
2402
- throw new Error(
2403
- "Server side sign in requires a user email and password."
2404
- );
2405
- }
2406
- info(`Obtaining providers for ${email}`);
2407
- info(`Attempting sign in with email ${email}`);
2408
- if (!email) {
2409
- throw new Error("Email missing from payload, unable to sign in");
2410
- }
2411
- const body = JSON.stringify({
2412
- email,
2413
- password,
2414
- csrfToken,
2415
- callbackUrl: credentials.callbackUrl
2416
- });
2417
- const signInRes = await this.callback(provider, body);
2418
- const authCookie = signInRes?.headers.get("set-cookie");
2419
- if (!authCookie) {
2420
- throw new Error("authentication failed");
2421
- }
2422
- const token = parseToken(signInRes?.headers);
2423
- const possibleError = signInRes?.headers.get("location");
2424
- if (possibleError) {
2425
- let urlError;
2674
+ const signInRes = await this.callback(provider, body);
2675
+ const authCookie = signInRes?.headers.get("set-cookie");
2676
+ if (!authCookie) {
2677
+ throw new Error("authentication failed");
2678
+ }
2679
+ const token = parseToken(signInRes?.headers);
2680
+ const possibleError = signInRes?.headers.get("location");
2681
+ if (possibleError) {
2682
+ let urlError;
2683
+ try {
2684
+ urlError = new URL(possibleError).searchParams.get("error");
2685
+ } catch {
2686
+ }
2687
+ if (urlError) {
2688
+ error("Unable to log user in", { error: urlError });
2689
+ return new Response(urlError, { status: signInRes.status });
2690
+ }
2691
+ }
2692
+ if (!token) {
2693
+ error("Unable to obtain auth token", {
2694
+ authCookie,
2695
+ signInRes
2696
+ });
2697
+ throw new Error("Server login failed");
2698
+ }
2699
+ info("Server sign in successful", { authCookie });
2700
+ const setCookie = signInRes.headers.get("set-cookie");
2701
+ const { headers } = ctx.get();
2702
+ if (setCookie) {
2703
+ const cookie = [
2704
+ parseCSRF(headers),
2705
+ parseCallback(signInRes.headers),
2706
+ parseToken(signInRes.headers)
2707
+ ].filter(Boolean).join("; ");
2708
+ const uHeaders = new Headers({ cookie });
2709
+ updateHeaders(uHeaders);
2710
+ ctx.set({ headers: uHeaders, preserveHeaders: true });
2711
+ } else {
2712
+ error("Unable to set context after sign in", {
2713
+ headers: signInRes.headers
2714
+ });
2715
+ }
2716
+ if (rawResponse) {
2717
+ return signInRes;
2718
+ }
2426
2719
  try {
2427
- urlError = new URL(possibleError).searchParams.get("error");
2720
+ return await signInRes.clone().json();
2428
2721
  } catch {
2722
+ return signInRes;
2429
2723
  }
2430
- if (urlError) {
2431
- error("Unable to log user in", { error: urlError });
2432
- return new Response(urlError, { status: signInRes.status });
2433
- }
2434
- }
2435
- if (!token) {
2436
- error("Unable to obtain auth token", {
2437
- authCookie,
2438
- signInRes
2439
- });
2440
- throw new Error("Server login failed");
2441
- }
2442
- info("Server sign in successful", { authCookie });
2443
- const setCookie = signInRes.headers.get("set-cookie");
2444
- if (setCookie) {
2445
- const cookie = [
2446
- parseCSRF(this.#config.headers),
2447
- parseCallback(signInRes.headers),
2448
- parseToken(signInRes.headers)
2449
- ].filter(Boolean).join("; ");
2450
- updateHeaders(new Headers({ cookie }));
2451
- } else {
2452
- error("Unable to set context after sign in", {
2453
- headers: signInRes.headers
2454
- });
2455
- }
2456
- if (rawResponse) {
2457
- return signInRes;
2458
- }
2459
- try {
2460
- return await signInRes.clone().json();
2461
- } catch {
2462
- return signInRes;
2463
- }
2724
+ });
2464
2725
  }
2465
2726
  };
2466
2727
  function parseCSRF(headers) {
@@ -2507,25 +2768,56 @@ function parseResetToken(headers) {
2507
2768
  const [, token] = /((__Secure-)?nile\.reset=[^;]+)/.exec(authCookie) ?? [];
2508
2769
  return token;
2509
2770
  }
2510
- function defaultCallbackUrl({ config }) {
2771
+ function parseTenantId(headers) {
2772
+ let authCookie = headers?.get("set-cookie");
2773
+ if (!authCookie) {
2774
+ authCookie = headers?.get("cookie");
2775
+ }
2776
+ if (!authCookie) {
2777
+ return void 0;
2778
+ }
2779
+ const [, token] = /((__Secure-)?nile\.tenant-id=[^;]+)/.exec(authCookie) ?? [];
2780
+ if (token) {
2781
+ const [, tenantId] = token.split("=");
2782
+ return tenantId;
2783
+ }
2784
+ return null;
2785
+ }
2786
+ function defaultCallbackUrl(config) {
2511
2787
  let cb = null;
2512
2788
  let redirect = null;
2513
- const fallbackCb = parseCallback(config.headers);
2789
+ const { headers } = ctx.get();
2790
+ const fallbackCb = parseCallback(headers);
2514
2791
  if (fallbackCb) {
2515
2792
  const [, value] = fallbackCb.split("=");
2516
2793
  cb = decodeURIComponent(value);
2517
2794
  if (value) {
2518
- redirect = `${new URL(cb).origin}${"/auth/reset-password" /* PASSWORD_RESET */}`;
2795
+ redirect = `${new URL(cb).origin}${config.routePrefix}${"/auth/reset-password" /* PASSWORD_RESET */}`;
2519
2796
  }
2520
2797
  }
2521
2798
  return { callbackUrl: cb, redirectUrl: redirect };
2522
2799
  }
2800
+ function fQUrl(path, config) {
2801
+ if (path.startsWith("/")) {
2802
+ const { callbackUrl } = defaultCallbackUrl(config);
2803
+ if (callbackUrl) {
2804
+ const { origin } = new URL(callbackUrl);
2805
+ return `${origin}${path}`;
2806
+ }
2807
+ }
2808
+ try {
2809
+ new URL(path);
2810
+ } catch {
2811
+ throw new Error("An invalid URL has been passed.");
2812
+ }
2813
+ return path;
2814
+ }
2523
2815
 
2524
2816
  // src/auth/obtainCsrf.ts
2525
2817
  async function obtainCsrf(config, rawResponse = false) {
2818
+ const { headers } = ctx.get();
2526
2819
  const res = await fetchCsrf(config);
2527
2820
  const csrfCook = parseCSRF(res.headers);
2528
- const h = new Headers();
2529
2821
  if (csrfCook) {
2530
2822
  const [, value] = csrfCook.split("=");
2531
2823
  const [token] = decodeURIComponent(value).split("|");
@@ -2536,29 +2828,27 @@ async function obtainCsrf(config, rawResponse = false) {
2536
2828
  parseCallback(res.headers),
2537
2829
  parseToken(res.headers)
2538
2830
  ].filter(Boolean).join("; ");
2539
- config.headers.set("cookie", cookie);
2540
- h.set("cookie", cookie);
2541
- updateHeaders(h);
2831
+ headers.set("cookie", cookie);
2832
+ ctx.set({ headers, preserveHeaders: true });
2833
+ updateHeaders(headers);
2542
2834
  }
2543
2835
  if (!rawResponse) {
2544
2836
  return { csrfToken: token };
2545
2837
  }
2546
2838
  } else {
2547
- const existingCookie = config.headers.get("cookie");
2839
+ const existingCookie = headers.get("cookie");
2548
2840
  const cookieParts = [];
2549
2841
  if (existingCookie) {
2550
- cookieParts.push(
2551
- parseToken(config.headers),
2552
- parseCallback(config.headers)
2553
- );
2842
+ cookieParts.push(parseToken(headers), parseCallback(headers));
2554
2843
  }
2555
2844
  if (csrfCook) {
2556
2845
  cookieParts.push(csrfCook);
2557
2846
  } else {
2558
- cookieParts.push(parseCSRF(config.headers));
2847
+ cookieParts.push(parseCSRF(headers));
2559
2848
  }
2560
2849
  const cookie = cookieParts.filter(Boolean).join("; ");
2561
- config.headers.set("cookie", cookie);
2850
+ headers.set("cookie", cookie);
2851
+ ctx.set({ headers, preserveHeaders: true });
2562
2852
  updateHeaders(new Headers({ cookie }));
2563
2853
  }
2564
2854
  if (rawResponse) {
@@ -2571,6 +2861,22 @@ async function obtainCsrf(config, rawResponse = false) {
2571
2861
  }
2572
2862
  }
2573
2863
 
2864
+ // src/utils/qualifyDomain.ts
2865
+ function fQUrl2(callbackUrl, path) {
2866
+ if (path.startsWith("/")) {
2867
+ if (callbackUrl) {
2868
+ const { origin } = new URL(callbackUrl);
2869
+ return `${origin}${path}`;
2870
+ }
2871
+ }
2872
+ try {
2873
+ new URL(path);
2874
+ } catch {
2875
+ throw new Error("An invalid URL has been passed.");
2876
+ }
2877
+ return path;
2878
+ }
2879
+
2574
2880
  // src/users/index.ts
2575
2881
  var Users = class {
2576
2882
  #config;
@@ -2593,15 +2899,17 @@ var Users = class {
2593
2899
  * @param [rawResponse] - When `true`, return the raw {@link Response}.
2594
2900
  */
2595
2901
  async updateSelf(req, rawResponse) {
2596
- const res = await fetchMe(this.#config, "PUT", JSON.stringify(req));
2597
- if (rawResponse) {
2598
- return res;
2599
- }
2600
- try {
2601
- return await res?.clone().json();
2602
- } catch {
2603
- return res;
2604
- }
2902
+ return withNileContext(this.#config, async () => {
2903
+ const res = await fetchMe(this.#config, "PUT", JSON.stringify(req));
2904
+ if (rawResponse) {
2905
+ return res;
2906
+ }
2907
+ try {
2908
+ return await res?.clone().json();
2909
+ } catch {
2910
+ return res;
2911
+ }
2912
+ });
2605
2913
  }
2606
2914
  /**
2607
2915
  * Remove the current user using `DELETE /api/me`.
@@ -2611,59 +2919,73 @@ var Users = class {
2611
2919
  * `packages/server/src/api/routes/me/index.ts` under `removeSelf`.
2612
2920
  */
2613
2921
  async removeSelf() {
2614
- const me = await this.getSelf();
2615
- if ("id" in me) {
2616
- this.#config.userId = me.id;
2617
- }
2618
- const res = await fetchMe(this.#config, "DELETE");
2619
- updateHeaders(new Headers());
2620
- return res;
2922
+ return withNileContext(this.#config, async () => {
2923
+ const me = await this.getSelf();
2924
+ if ("id" in me) {
2925
+ const userId = me.id;
2926
+ ctx.set({ userId });
2927
+ }
2928
+ const res = await fetchMe(this.#config, "DELETE");
2929
+ updateHeaders(new Headers());
2930
+ return res;
2931
+ });
2621
2932
  }
2622
2933
  async getSelf(rawResponse) {
2623
- const res = await fetchMe(this.#config);
2624
- if (rawResponse) {
2625
- return res;
2626
- }
2627
- try {
2628
- return await res?.clone().json();
2629
- } catch {
2630
- return res;
2631
- }
2934
+ return withNileContext(this.#config, async () => {
2935
+ const res = await fetchMe(this.#config);
2936
+ if (rawResponse) {
2937
+ return res;
2938
+ }
2939
+ try {
2940
+ return await res?.clone().json();
2941
+ } catch {
2942
+ return res;
2943
+ }
2944
+ });
2632
2945
  }
2633
2946
  async verifySelf(options, rawResponse = false) {
2634
- const bypassEmail = typeof options === "object" && options?.bypassEmail === true;
2635
- const callbackUrl = typeof options === "object" ? options.callbackUrl : defaultCallbackUrl2(this.#config).callbackUrl;
2636
- let res;
2637
- try {
2638
- const me = await this.getSelf();
2639
- if (me instanceof Response) {
2640
- return me;
2641
- }
2642
- res = await verifyEmailAddress(this.#config, me, String(callbackUrl));
2643
- return res;
2644
- } catch (e) {
2645
- if (!bypassEmail) {
2646
- let message = "Unable to verify email.";
2647
- if (e instanceof Error) {
2648
- message = e.message;
2947
+ return withNileContext(this.#config, async () => {
2948
+ const bypassEmail = typeof options === "object" && options?.bypassEmail === true;
2949
+ const callbackUrl = fQUrl2(
2950
+ defaultCallbackUrl2().callbackUrl,
2951
+ typeof options === "object" ? String(options.callbackUrl) : "/"
2952
+ );
2953
+ let res;
2954
+ try {
2955
+ const me = await this.getSelf();
2956
+ if (me instanceof Response) {
2957
+ return me;
2649
2958
  }
2650
- this.#logger?.error(
2651
- `${message} you can bypass this message by setting bypassEmail: true when calling 'verifySelf'`
2959
+ res = await verifyEmailAddress(this.#config, me, String(callbackUrl));
2960
+ return res;
2961
+ } catch (e) {
2962
+ if (!bypassEmail) {
2963
+ let message = "Unable to verify email.";
2964
+ if (e instanceof Error) {
2965
+ message = e.message;
2966
+ }
2967
+ this.#logger?.error(
2968
+ `${message} you can bypass this message by setting bypassEmail: true when calling 'verifySelf'`
2969
+ );
2970
+ res = new Response(message, { status: 400 });
2971
+ }
2972
+ }
2973
+ if (bypassEmail) {
2974
+ this.#logger?.info(
2975
+ "bypassing email requirements for email verification"
2652
2976
  );
2653
- res = new Response(message, { status: 400 });
2977
+ res = this.updateSelf({ emailVerified: true }, rawResponse);
2654
2978
  }
2655
- }
2656
- if (bypassEmail) {
2657
- this.#logger?.info("bypassing email requirements for email verification");
2658
- res = this.updateSelf({ emailVerified: true }, rawResponse);
2659
- }
2660
- return res;
2979
+ return res;
2980
+ });
2661
2981
  }
2662
2982
  };
2663
2983
  async function verifyEmailAddress(config, user, callback) {
2664
- config.headers.set("content-type", "application/x-www-form-urlencoded");
2984
+ const { headers } = ctx.get();
2985
+ headers?.set("content-type", "application/x-www-form-urlencoded");
2986
+ ctx.set({ headers });
2665
2987
  const { csrfToken } = await obtainCsrf(config);
2666
- const defaults = defaultCallbackUrl2(config);
2988
+ const defaults = defaultCallbackUrl2();
2667
2989
  const callbackUrl = callback ?? String(defaults.callbackUrl);
2668
2990
  const res = await fetchVerifyEmail(
2669
2991
  config,
@@ -2679,9 +3001,10 @@ async function verifyEmailAddress(config, user, callback) {
2679
3001
  }
2680
3002
  return res;
2681
3003
  }
2682
- function defaultCallbackUrl2(config) {
3004
+ function defaultCallbackUrl2() {
2683
3005
  let cb = null;
2684
- const fallbackCb = parseCallback(config.headers);
3006
+ const { headers } = ctx.get();
3007
+ const fallbackCb = parseCallback(headers);
2685
3008
  if (fallbackCb) {
2686
3009
  const [, value] = fallbackCb.split("=");
2687
3010
  cb = decodeURIComponent(value);
@@ -2701,24 +3024,26 @@ var Tenants = class {
2701
3024
  * `createTenant` operation definition.
2702
3025
  */
2703
3026
  async create(req, rawResponse) {
2704
- let res;
2705
- if (typeof req === "string") {
2706
- res = await fetchTenants(
2707
- this.#config,
2708
- "POST",
2709
- JSON.stringify({ name: req })
2710
- );
2711
- } else if (typeof req === "object" && ("name" in req || "id" in req)) {
2712
- res = await fetchTenants(this.#config, "POST", JSON.stringify(req));
2713
- }
2714
- if (rawResponse) {
2715
- return res;
2716
- }
2717
- try {
2718
- return await res?.clone().json();
2719
- } catch {
2720
- return res;
2721
- }
3027
+ return withNileContext(this.#config, async () => {
3028
+ let res;
3029
+ if (typeof req === "string") {
3030
+ res = await fetchTenants(
3031
+ this.#config,
3032
+ "POST",
3033
+ JSON.stringify({ name: req })
3034
+ );
3035
+ } else if (typeof req === "object" && ("name" in req || "id" in req)) {
3036
+ res = await fetchTenants(this.#config, "POST", JSON.stringify(req));
3037
+ }
3038
+ if (rawResponse) {
3039
+ return res;
3040
+ }
3041
+ try {
3042
+ return await res?.clone().json();
3043
+ } catch {
3044
+ return res;
3045
+ }
3046
+ });
2722
3047
  }
2723
3048
  /**
2724
3049
  * Remove a tenant via `DELETE /api/tenants/{tenantId}`.
@@ -2726,14 +3051,16 @@ var Tenants = class {
2726
3051
  * @param req - The tenant to remove or context containing the id.
2727
3052
  */
2728
3053
  async delete(req) {
2729
- if (typeof req === "string") {
2730
- this.#config.tenantId = req;
2731
- }
2732
- if (typeof req === "object" && "id" in req) {
2733
- this.#config.tenantId = req.id;
2734
- }
2735
- const res = await fetchTenant(this.#config, "DELETE");
2736
- return res;
3054
+ return withNileContext(this.#config, async () => {
3055
+ if (typeof req === "string") {
3056
+ ctx.set({ tenantId: req });
3057
+ }
3058
+ if (typeof req === "object" && "id" in req) {
3059
+ ctx.set({ tenantId: req.id });
3060
+ }
3061
+ const res = await fetchTenant(this.#config, "DELETE");
3062
+ return res;
3063
+ });
2737
3064
  }
2738
3065
  /**
2739
3066
  * Fetch details for a tenant using `GET /api/tenants/{tenantId}`.
@@ -2742,53 +3069,63 @@ var Tenants = class {
2742
3069
  * @param [rawResponse] - When true, return the raw {@link Response}.
2743
3070
  */
2744
3071
  async get(req, rawResponse) {
2745
- if (typeof req === "string") {
2746
- this.#config.tenantId = req;
2747
- } else if (typeof req === "object" && "id" in req) {
2748
- this.#config.tenantId = req.id;
2749
- }
2750
- const res = await fetchTenant(this.#config, "GET");
2751
- if (rawResponse === true || req === true) {
2752
- return res;
2753
- }
2754
- try {
2755
- return await res?.clone().json();
2756
- } catch {
2757
- return res;
2758
- }
3072
+ return withNileContext(this.#config, async () => {
3073
+ if (typeof req === "string") {
3074
+ ctx.set({ tenantId: req });
3075
+ } else if (typeof req === "object" && "id" in req) {
3076
+ ctx.set({ tenantId: req.id });
3077
+ }
3078
+ const res = await fetchTenant(this.#config, "GET");
3079
+ if (rawResponse === true || req === true) {
3080
+ return res;
3081
+ }
3082
+ try {
3083
+ return await res?.clone().json();
3084
+ } catch {
3085
+ return res;
3086
+ }
3087
+ });
2759
3088
  }
2760
3089
  async update(req, rawResponse) {
2761
- let res;
2762
- if (typeof req === "object" && ("name" in req || "id" in req)) {
2763
- const { id, ...remaining } = req;
2764
- if (id) {
2765
- this.#config.tenantId = id;
3090
+ return withNileContext(this.#config, async () => {
3091
+ let res;
3092
+ if (typeof req === "object" && ("name" in req || "id" in req)) {
3093
+ const { id, ...remaining } = req;
3094
+ if (id) {
3095
+ ctx.set({ tenantId: id });
3096
+ }
3097
+ res = await fetchTenant(this.#config, "PUT", JSON.stringify(remaining));
2766
3098
  }
2767
- res = await fetchTenant(this.#config, "PUT", JSON.stringify(remaining));
2768
- }
2769
- if (rawResponse) {
2770
- return res;
2771
- }
2772
- try {
2773
- return await res?.clone().json();
2774
- } catch {
2775
- return res;
2776
- }
3099
+ if (rawResponse) {
3100
+ return res;
3101
+ }
3102
+ try {
3103
+ return await res?.clone().json();
3104
+ } catch {
3105
+ return res;
3106
+ }
3107
+ });
2777
3108
  }
2778
3109
  /**
2779
3110
  * List tenants for the current user via `GET /api/tenants`.
2780
3111
  * See `packages/server/src/api/routes/tenants/GET.ts` for details.
2781
3112
  */
2782
3113
  async list(req) {
2783
- const res = await fetchTenantsByUser(this.#config);
2784
- if (req === true) {
2785
- return res;
2786
- }
2787
- try {
2788
- return await res?.clone().json();
2789
- } catch {
2790
- return res;
2791
- }
3114
+ return withNileContext(
3115
+ this.#config,
3116
+ async () => {
3117
+ const res = await fetchTenantsByUser(this.#config);
3118
+ if (req === true) {
3119
+ return res;
3120
+ }
3121
+ try {
3122
+ return await res?.clone().json();
3123
+ } catch {
3124
+ return res;
3125
+ }
3126
+ },
3127
+ "listTenants"
3128
+ );
2792
3129
  }
2793
3130
  /**
2794
3131
  * Leave the current tenant using `DELETE /api/tenants/{tenantId}/users/{userId}`.
@@ -2796,29 +3133,33 @@ var Tenants = class {
2796
3133
  * @param [req] - Optionally specify the tenant id to leave.
2797
3134
  */
2798
3135
  async leaveTenant(req) {
2799
- const me = await fetchMe(this.#config);
2800
- try {
2801
- const json = await me.json();
2802
- if ("id" in json) {
2803
- this.#config.userId = json.id;
3136
+ return withNileContext(this.#config, async () => {
3137
+ const me = await fetchMe(this.#config);
3138
+ try {
3139
+ const json = await me.json();
3140
+ if ("id" in json) {
3141
+ ctx.set({ userId: json.id, preserveHeaders: true });
3142
+ }
3143
+ } catch {
2804
3144
  }
2805
- } catch {
2806
- }
2807
- if (typeof req === "string") {
2808
- this.#config.tenantId = req;
2809
- } else {
2810
- this.#handleContext(req);
2811
- }
2812
- return await fetchTenantUser(this.#config, "DELETE");
3145
+ if (typeof req === "string") {
3146
+ ctx.set({ tenantId: req, preserveHeaders: true });
3147
+ } else {
3148
+ this.#handleContext(req);
3149
+ }
3150
+ return await fetchTenantUser(this.#config, "DELETE");
3151
+ });
2813
3152
  }
2814
3153
  async addMember(req, rawResponse) {
2815
- if (typeof req === "string") {
2816
- this.#config.userId = req;
2817
- } else {
2818
- this.#handleContext(req);
2819
- }
2820
- const res = await fetchTenantUser(this.#config, "PUT");
2821
- return responseHandler(res, rawResponse);
3154
+ return withNileContext(this.#config, async () => {
3155
+ if (typeof req === "string") {
3156
+ ctx.set({ userId: req, preserveHeaders: true });
3157
+ } else {
3158
+ this.#handleContext(req);
3159
+ }
3160
+ const res = await fetchTenantUser(this.#config, "PUT");
3161
+ return responseHandler(res, rawResponse);
3162
+ });
2822
3163
  }
2823
3164
  /**
2824
3165
  * Remove a user from a tenant with `DELETE /api/tenants/{tenantId}/users/{userId}`.
@@ -2827,57 +3168,83 @@ var Tenants = class {
2827
3168
  * @param [rawResponse] - When true, return the raw {@link Response}.
2828
3169
  */
2829
3170
  async removeMember(req, rawResponse) {
2830
- this.#handleContext(req);
2831
- const res = await fetchTenantUser(this.#config, "DELETE");
2832
- return responseHandler(res, rawResponse);
3171
+ return withNileContext(this.#config, async () => {
3172
+ this.#handleContext(req);
3173
+ if (typeof req === "string") {
3174
+ ctx.set({ userId: req, preserveHeaders: true });
3175
+ }
3176
+ const res = await fetchTenantUser(this.#config, "DELETE");
3177
+ return responseHandler(res, rawResponse);
3178
+ });
2833
3179
  }
2834
3180
  async users(req, rawResponse) {
2835
- this.#handleContext(req);
2836
- const res = await fetchTenantUsers(this.#config, "GET");
2837
- return responseHandler(
2838
- res,
2839
- rawResponse || typeof req === "boolean" && req
3181
+ return withNileContext(
3182
+ this.#config,
3183
+ async () => {
3184
+ this.#handleContext(req);
3185
+ const res = await fetchTenantUsers(this.#config, "GET");
3186
+ return responseHandler(
3187
+ res,
3188
+ rawResponse || typeof req === "boolean" && req
3189
+ );
3190
+ },
3191
+ "users"
2840
3192
  );
2841
3193
  }
2842
3194
  /**
2843
3195
  * List invites for the current tenant via `GET /api/tenants/{tenantId}/invites`.
2844
3196
  */
2845
3197
  async invites() {
2846
- const res = await fetchInvites(this.#config);
2847
- return responseHandler(res);
3198
+ return withNileContext(
3199
+ this.#config,
3200
+ async () => {
3201
+ const res = await fetchInvites(this.#config);
3202
+ return responseHandler(res);
3203
+ },
3204
+ "invites"
3205
+ );
2848
3206
  }
2849
3207
  async invite(req, rawResponse) {
2850
- const { csrfToken } = await obtainCsrf(this.#config);
2851
- const defaults = defaultCallbackUrl3(this.#config);
2852
- let identifier = req;
2853
- let callbackUrl = defaults.callbackUrl;
2854
- let redirectUrl = defaults.redirectUrl;
2855
- if (typeof req === "object") {
2856
- if ("email" in req) {
2857
- identifier = req.email;
2858
- }
2859
- if ("callbackUrl" in req) {
2860
- callbackUrl = req.callbackUrl ? req.callbackUrl : "";
2861
- }
2862
- if ("redirectUrl" in req) {
2863
- redirectUrl = req.redirectUrl ? req.redirectUrl : "";
2864
- }
2865
- }
2866
- this.#config.headers.set(
2867
- "Content-Type",
2868
- "application/x-www-form-urlencoded"
2869
- );
2870
- const res = await fetchInvite(
3208
+ return withNileContext(
2871
3209
  this.#config,
2872
- "POST",
2873
- new URLSearchParams({
2874
- identifier,
2875
- csrfToken,
2876
- callbackUrl,
2877
- redirectUrl
2878
- }).toString()
3210
+ async () => {
3211
+ await runExtensionContext(this.#config);
3212
+ const { csrfToken } = await obtainCsrf(
3213
+ this.#config
3214
+ );
3215
+ const defaults = defaultCallbackUrl3(this.#config);
3216
+ let identifier = req;
3217
+ let callbackUrl = defaults.callbackUrl;
3218
+ let redirectUrl = defaults.redirectUrl;
3219
+ if (typeof req === "object") {
3220
+ if ("email" in req) {
3221
+ identifier = req.email;
3222
+ }
3223
+ const { callbackUrl: cbUrl } = defaultCallbackUrl3(this.#config);
3224
+ if ("callbackUrl" in req) {
3225
+ callbackUrl = fQUrl2(cbUrl, req.callbackUrl ?? "/");
3226
+ }
3227
+ if ("redirectUrl" in req) {
3228
+ redirectUrl = fQUrl2(cbUrl, req.redirectUrl ?? "/");
3229
+ }
3230
+ }
3231
+ const { headers } = ctx.get();
3232
+ headers?.set("Content-Type", "application/x-www-form-urlencoded");
3233
+ ctx.set({ headers });
3234
+ const res = await fetchInvite(
3235
+ this.#config,
3236
+ "POST",
3237
+ new URLSearchParams({
3238
+ identifier,
3239
+ csrfToken,
3240
+ callbackUrl,
3241
+ redirectUrl
3242
+ }).toString()
3243
+ );
3244
+ return responseHandler(res, rawResponse);
3245
+ },
3246
+ "invites"
2879
3247
  );
2880
- return responseHandler(res, rawResponse);
2881
3248
  }
2882
3249
  /**
2883
3250
  * Accept an invite using `PUT /api/tenants/{tenantId}/invite`.
@@ -2886,22 +3253,24 @@ var Tenants = class {
2886
3253
  * @param [rawResponse] - When true, return the raw {@link Response}.
2887
3254
  */
2888
3255
  async acceptInvite(req, rawResponse) {
2889
- if (!req) {
2890
- throw new Error("The identifier and token are required.");
2891
- }
2892
- const { identifier, token } = req;
2893
- const defaults = defaultCallbackUrl3(this.#config);
2894
- const callbackUrl = String(defaults.callbackUrl);
2895
- const res = await fetchInvite(
2896
- this.#config,
2897
- "PUT",
2898
- new URLSearchParams({
2899
- identifier,
2900
- token,
2901
- callbackUrl
2902
- }).toString()
2903
- );
2904
- return responseHandler(res, rawResponse);
3256
+ return withNileContext(this.#config, async () => {
3257
+ if (!req) {
3258
+ throw new Error("The identifier and token are required.");
3259
+ }
3260
+ const { identifier, token } = req;
3261
+ const defaults = defaultCallbackUrl3(this.#config);
3262
+ const callbackUrl = String(defaults.callbackUrl);
3263
+ const res = await fetchInvite(
3264
+ this.#config,
3265
+ "PUT",
3266
+ new URLSearchParams({
3267
+ identifier,
3268
+ token,
3269
+ callbackUrl
3270
+ }).toString()
3271
+ );
3272
+ return responseHandler(res, rawResponse);
3273
+ });
2905
3274
  }
2906
3275
  /**
2907
3276
  * Delete a pending invite using `DELETE /api/tenants/{tenantId}/invite/{inviteId}`.
@@ -2909,25 +3278,27 @@ var Tenants = class {
2909
3278
  * @param req - Identifier of the invite to remove.
2910
3279
  */
2911
3280
  async deleteInvite(req) {
2912
- let id = "";
2913
- if (typeof req === "object") {
2914
- id = req.id;
2915
- } else {
2916
- id = req;
2917
- }
2918
- if (!id) {
2919
- throw new Error("An invite id is required.");
2920
- }
2921
- const res = await fetchInvite(this.#config, "DELETE", id);
2922
- return responseHandler(res, true);
3281
+ return withNileContext(this.#config, async () => {
3282
+ let id = "";
3283
+ if (typeof req === "object") {
3284
+ id = req.id;
3285
+ } else {
3286
+ id = req;
3287
+ }
3288
+ if (!id) {
3289
+ throw new Error("An invite id is required.");
3290
+ }
3291
+ const res = await fetchInvite(this.#config, "DELETE", id);
3292
+ return responseHandler(res, true);
3293
+ });
2923
3294
  }
2924
3295
  #handleContext(req) {
2925
3296
  if (typeof req === "object") {
2926
3297
  if ("tenantId" in req) {
2927
- this.#config.tenantId = req.tenantId;
3298
+ ctx.set({ tenantId: req.tenantId, preserveHeaders: true });
2928
3299
  }
2929
3300
  if ("userId" in req) {
2930
- this.#config.tenantId = req.tenantId;
3301
+ ctx.set({ userId: req.userId, preserveHeaders: true });
2931
3302
  }
2932
3303
  }
2933
3304
  }
@@ -2945,15 +3316,13 @@ async function responseHandler(res, rawResponse) {
2945
3316
  function defaultCallbackUrl3(config) {
2946
3317
  let cb = null;
2947
3318
  let redirect = null;
2948
- const fallbackCb = parseCallback(config.headers);
3319
+ const { headers, tenantId } = ctx.get();
3320
+ const fallbackCb = parseCallback(headers);
2949
3321
  if (fallbackCb) {
2950
3322
  const [, value] = fallbackCb.split("=");
2951
3323
  cb = decodeURIComponent(value);
2952
3324
  if (value) {
2953
- redirect = `${new URL(cb).origin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace(
2954
- "{tenantId}",
2955
- String(config.tenantId)
2956
- )}`;
3325
+ redirect = `${new URL(cb).origin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace("{tenantId}", String(tenantId))}`;
2957
3326
  }
2958
3327
  }
2959
3328
  return { callbackUrl: cb, redirectUrl: redirect };
@@ -3020,97 +3389,6 @@ function updateConfig(response, config) {
3020
3389
  };
3021
3390
  }
3022
3391
 
3023
- // src/api/utils/extensions.ts
3024
- function getRequestConfig(params) {
3025
- if (typeof params[1] === "object") {
3026
- return params[1];
3027
- }
3028
- return {};
3029
- }
3030
- function bindRunExtensions(instance) {
3031
- return async function runExtensions(toRun, config, params, _init) {
3032
- const { debug } = config.logger("[EXTENSIONS]");
3033
- const extensionConfig = getRequestConfig(
3034
- Array.isArray(params) ? params : [null, params]
3035
- );
3036
- if (config.extensions) {
3037
- for (const create2 of config.extensions) {
3038
- if (typeof create2 !== "function") {
3039
- continue;
3040
- }
3041
- const ext = create2(instance);
3042
- if (extensionConfig.disableExtensions?.includes(ext.id)) {
3043
- continue;
3044
- }
3045
- if (ext.onHandleRequest && toRun === "onHandleRequest" /* onHandleRequest */) {
3046
- const result = await ext.onHandleRequest(
3047
- ...Array.isArray(params) ? params : [params]
3048
- );
3049
- debug(`${ext.id ?? create2.name} ran onHandleRequest`);
3050
- if (result != null) {
3051
- return result;
3052
- }
3053
- }
3054
- const [param] = Array.isArray(params) ? params : [params];
3055
- if (ext.onRequest && toRun === "onRequest" /* onRequest */) {
3056
- const previousContext = instance.getContext();
3057
- if (previousContext.preserveHeaders) {
3058
- instance.setContext({ preserveHeaders: false });
3059
- }
3060
- if (!_init) {
3061
- continue;
3062
- }
3063
- await ext.onRequest(_init.request);
3064
- const updatedContext = instance.getContext();
3065
- if (updatedContext?.headers) {
3066
- const cookie = updatedContext.headers.get("cookie");
3067
- if (cookie && param.headers) {
3068
- param.headers.set(
3069
- "cookie",
3070
- mergeCookies(
3071
- previousContext.preserveHeaders ? previousContext.headers?.get("cookie") : null,
3072
- updatedContext.headers.get("cookie")
3073
- )
3074
- );
3075
- }
3076
- if (updatedContext.tenantId && param.headers) {
3077
- param.headers.set(
3078
- TENANT_COOKIE,
3079
- String(updatedContext.headers.get(TENANT_COOKIE))
3080
- );
3081
- }
3082
- }
3083
- debug(`${ext.id ?? create2.name} ran onRequest`);
3084
- }
3085
- if (ext.onResponse && toRun === "onResponse" /* onResponse */) {
3086
- const result = await ext.onResponse(param);
3087
- debug(`${ext.id ?? create2.name} ran onResponse`);
3088
- if (result != null) {
3089
- return result;
3090
- }
3091
- }
3092
- }
3093
- }
3094
- return void 0;
3095
- };
3096
- }
3097
- function buildExtensionConfig(instance) {
3098
- return {
3099
- runExtensions: bindRunExtensions(instance)
3100
- };
3101
- }
3102
- function mergeCookies(...cookieStrings) {
3103
- const cookieMap = /* @__PURE__ */ new Map();
3104
- for (const str of cookieStrings) {
3105
- if (!str) continue;
3106
- for (const part of str.split(";")) {
3107
- const [key17, value] = part.split("=").map((s) => s.trim());
3108
- if (key17 && value) cookieMap.set(key17, value);
3109
- }
3110
- }
3111
- return [...cookieMap.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
3112
- }
3113
-
3114
3392
  // src/Server.ts
3115
3393
  var Server = class {
3116
3394
  users;
@@ -3119,35 +3397,38 @@ var Server = class {
3119
3397
  #config;
3120
3398
  #handlers;
3121
3399
  #manager;
3122
- #headers;
3123
- #preserveHeaders;
3400
+ // #headers: undefined | Headers;
3401
+ // #preserveHeaders: boolean;
3124
3402
  constructor(config) {
3125
3403
  this.#config = new Config({
3126
3404
  ...config,
3127
3405
  extensionCtx: buildExtensionConfig(this)
3128
3406
  });
3129
3407
  watchTenantId((tenantId) => {
3130
- if (tenantId !== this.#config.tenantId) {
3131
- this.#config.tenantId = tenantId;
3408
+ if (tenantId !== this.#config.context.tenantId) {
3409
+ this.#config.context.tenantId = String(tenantId);
3132
3410
  this.#reset();
3133
3411
  }
3134
3412
  });
3135
3413
  watchUserId((userId) => {
3136
- if (userId !== this.#config.userId) {
3137
- this.#config.userId = userId;
3414
+ if (userId !== this.#config.context.userId) {
3415
+ this.#config.context.userId = String(userId);
3138
3416
  this.#reset();
3139
3417
  }
3140
3418
  });
3141
3419
  watchHeaders((headers) => {
3142
- this.setContext(headers);
3143
- this.#reset();
3420
+ if (headers) {
3421
+ this.#config.context.headers = new Headers(headers);
3422
+ this.#config.context.preserveHeaders = true;
3423
+ this.#reset();
3424
+ }
3144
3425
  });
3145
3426
  this.#handlers = {
3146
3427
  ...this.#config.handlers,
3147
3428
  withContext: handlersWithContext(this.#config)
3148
3429
  };
3149
- this.#preserveHeaders = config?.preserveHeaders ?? false;
3150
- this.#config.tenantId = getTenantId({ config: this.#config });
3430
+ this.#config.context.preserveHeaders = config?.preserveHeaders ?? false;
3431
+ this.#config.context.tenantId = getTenantId({ config: this.#config });
3151
3432
  this.#manager = new DBManager(this.#config);
3152
3433
  this.#handleHeaders(config);
3153
3434
  this.users = new Users(this.#config);
@@ -3202,21 +3483,6 @@ var Server = class {
3202
3483
  }
3203
3484
  };
3204
3485
  }
3205
- /**
3206
- * A convenience function that applies a config and ensures whatever was passed is set properly
3207
- */
3208
- getInstance(config, req) {
3209
- const _config = { ...this.#config, ...config };
3210
- const updatedConfig = new Config(_config);
3211
- this.#config = new Config(updatedConfig);
3212
- this.#config.tenantId = config.tenantId;
3213
- this.#config.userId = config.userId;
3214
- if (req) {
3215
- this.setContext(req);
3216
- }
3217
- this.#reset();
3218
- return this;
3219
- }
3220
3486
  get handlers() {
3221
3487
  return this.#handlers;
3222
3488
  }
@@ -3226,98 +3492,30 @@ var Server = class {
3226
3492
  set paths(paths) {
3227
3493
  this.#config.paths = paths;
3228
3494
  }
3229
- /**
3230
- * Allow the setting of headers from a req or header object.
3231
- * Makes it possible to handle REST requests easily
3232
- * Also makes it easy to set user + tenant in some way
3233
- * @param req
3234
- * @returns undefined
3235
- */
3236
- setContext = (req, ...remaining) => {
3237
- let ok = false;
3238
- if (req && typeof req === "object" && "tenantId" in req) {
3239
- ok = true;
3240
- this.#config.tenantId = req.tenantId;
3241
- }
3242
- if (req && typeof req === "object" && "userId" in req) {
3243
- ok = true;
3244
- this.#config.userId = req.userId;
3245
- }
3246
- if (req && typeof req === "object" && "preserveHeaders" in req) {
3247
- ok = true;
3248
- this.#preserveHeaders = Boolean(req.preserveHeaders);
3249
- }
3250
- let atLeastOne = false;
3251
- if (this.#config?.extensions) {
3252
- for (const create2 of this.#config.extensions) {
3253
- if (typeof create2 !== "function") {
3254
- continue;
3255
- }
3256
- const ext = create2(this);
3257
- if (typeof ext.onSetContext === "function") {
3258
- if (req) {
3259
- ext.onSetContext(req, ...remaining);
3260
- atLeastOne = true;
3261
- } else {
3262
- this.#config.logger("extension").warn("attempted to call onSetContext without a value");
3263
- }
3264
- }
3265
- }
3266
- }
3267
- if (atLeastOne) {
3268
- return;
3269
- }
3270
- try {
3271
- if (req instanceof Headers) {
3272
- this.#handleHeaders(req);
3273
- this.#reset();
3274
- return;
3275
- } else if (req instanceof Request) {
3276
- this.#handleHeaders(new Headers(req.headers));
3277
- this.#reset();
3278
- return;
3279
- }
3280
- } catch {
3495
+ async withContext(context, fn) {
3496
+ const { ddl, ...ctx2 } = context ?? defaultContext;
3497
+ this.#config.context = { ...ctx2 };
3498
+ const preserve = (context && "preserveHeaders" in context && context.preserveHeaders) ?? true;
3499
+ if (preserve) {
3500
+ this.#config.context = { ...this.getContext(), ...context };
3281
3501
  }
3282
- if (ok) {
3283
- return;
3502
+ if (ddl) {
3503
+ delete this.#config.context.tenantId;
3504
+ delete this.#config.context.userId;
3284
3505
  }
3285
- if (typeof req === "object") {
3286
- try {
3287
- const headers = new Headers(req);
3288
- if (headers) {
3289
- this.#handleHeaders(headers);
3290
- this.#reset();
3291
- return;
3292
- }
3293
- } catch {
3506
+ return withNileContext(this.#config, async () => {
3507
+ if (fn) {
3508
+ return fn(this);
3294
3509
  }
3295
- }
3296
- const { warn } = Logger(this.#config)("[API]");
3297
- if (warn) {
3298
- warn(
3299
- "Set context expects a Request, Header instance or an object of Record<string, string>"
3300
- );
3301
- }
3302
- };
3510
+ return this;
3511
+ });
3512
+ }
3513
+ /**
3514
+ *
3515
+ * @returns the last used (basically global) context object, useful for debugging or making your own context
3516
+ */
3303
3517
  getContext() {
3304
- if (this.#config?.extensions) {
3305
- for (const create2 of this.#config.extensions) {
3306
- if (typeof create2 !== "function") {
3307
- continue;
3308
- }
3309
- const ext = create2(this);
3310
- if (typeof ext.onGetContext === "function") {
3311
- return ext.onGetContext();
3312
- }
3313
- }
3314
- }
3315
- return {
3316
- headers: this.#headers,
3317
- userId: this.#config?.userId,
3318
- tenantId: this.#config?.tenantId,
3319
- preserveHeaders: this.#preserveHeaders
3320
- };
3518
+ return ctx.getLastUsed();
3321
3519
  }
3322
3520
  /**
3323
3521
  * Merge headers together
@@ -3326,16 +3524,19 @@ var Server = class {
3326
3524
  #handleHeaders(config) {
3327
3525
  const updates = [];
3328
3526
  let headers;
3329
- this.#headers = new Headers();
3527
+ this.#config.context.headers = new Headers();
3330
3528
  if (config instanceof Headers) {
3331
3529
  headers = config;
3332
3530
  } else if (config?.headers) {
3333
3531
  headers = config?.headers;
3334
3532
  if (config && config.origin) {
3335
- this.#headers.set(HEADER_ORIGIN, config.origin);
3533
+ this.#config.context.headers.set(HEADER_ORIGIN, config.origin);
3336
3534
  }
3337
3535
  if (config && config.secureCookies != null) {
3338
- this.#headers.set(HEADER_SECURE_COOKIES, String(config.secureCookies));
3536
+ this.#config.context.headers.set(
3537
+ HEADER_SECURE_COOKIES,
3538
+ String(config.secureCookies)
3539
+ );
3339
3540
  }
3340
3541
  }
3341
3542
  if (headers instanceof Headers) {
@@ -3348,8 +3549,7 @@ var Server = class {
3348
3549
  }
3349
3550
  }
3350
3551
  const merged = {};
3351
- this.#config.tenantId = getTenantFromHttp(this.#headers, this.#config);
3352
- this.#headers?.forEach((value, key17) => {
3552
+ this.#config.context.headers?.forEach((value, key17) => {
3353
3553
  if (key17.toLowerCase() !== "cookie") {
3354
3554
  merged[key17.toLowerCase()] = value;
3355
3555
  }
@@ -3358,16 +3558,14 @@ var Server = class {
3358
3558
  merged[key17] = value;
3359
3559
  }
3360
3560
  for (const [key17, value] of Object.entries(merged)) {
3361
- this.#headers.set(key17, value);
3561
+ this.#config.context.headers.set(key17, value);
3362
3562
  }
3363
3563
  this.#config.logger("[handleHeaders]").debug(JSON.stringify(merged));
3364
- this.#config.headers = this.#headers;
3365
3564
  }
3366
3565
  /**
3367
3566
  * Allow some internal mutations to reset our config + headers
3368
3567
  */
3369
3568
  #reset = () => {
3370
- this.#config.headers = this.#headers ?? new Headers();
3371
3569
  this.#config.extensionCtx = buildExtensionConfig(this);
3372
3570
  this.users = new Users(this.#config);
3373
3571
  this.tenants = new Tenants(this.#config);
@@ -3382,6 +3580,6 @@ function create(config) {
3382
3580
  return server;
3383
3581
  }
3384
3582
 
3385
- export { APIErrorErrorCodeEnum, ExtensionState, HEADER_ORIGIN, HEADER_SECURE_COOKIES, LoginUserResponseTokenTypeEnum, create as Nile, Server, TENANT_COOKIE, USER_COOKIE, parseCSRF, parseCallback, parseResetToken, parseToken };
3583
+ export { APIErrorErrorCodeEnum, ExtensionState, HEADER_ORIGIN, HEADER_SECURE_COOKIES, LoginUserResponseTokenTypeEnum, create as Nile, Server, TENANT_COOKIE, USER_COOKIE, parseCSRF, parseCallback, parseResetToken, parseTenantId, parseToken };
3386
3584
  //# sourceMappingURL=index.mjs.map
3387
3585
  //# sourceMappingURL=index.mjs.map