@usebetterdev/tenant-core 0.1.0 → 0.2.0-beta.12

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.cjs CHANGED
@@ -24,15 +24,13 @@ __export(index_exports, {
24
24
  TenantNotResolvedError: () => TenantNotResolvedError,
25
25
  betterTenant: () => betterTenant,
26
26
  createTenantApi: () => createTenantApi,
27
+ describeStrategies: () => describeStrategies,
27
28
  getContext: () => getContext,
28
- getDatabase: () => getDatabase,
29
29
  handleRequest: () => handleRequest,
30
30
  resolveTenant: () => resolveTenant,
31
- resolveTenantAsync: () => resolveTenantAsync,
32
31
  runAs: () => runAs,
33
32
  runAsSystem: () => runAsSystem,
34
33
  runWithTenant: () => runWithTenant,
35
- runWithTenantAndDatabase: () => runWithTenantAndDatabase,
36
34
  sendCliTelemetry: () => sendCliTelemetry,
37
35
  toResolvableRequest: () => toResolvableRequest
38
36
  });
@@ -55,8 +53,7 @@ function getTelemetryTenantConfig(config) {
55
53
  jwt: !!r.jwt,
56
54
  custom: !!r.custom
57
55
  },
58
- tenantTablesCount: config.tenantTables?.length ?? 0,
59
- hasGetTenantRepository: !!config.getTenantRepository,
56
+ tenantTablesCount: 0,
60
57
  loadTenant: config.loadTenant,
61
58
  basePathSet: !!config.basePath,
62
59
  plugins: (config.plugins ?? []).map((p) => String(p.id))
@@ -72,7 +69,9 @@ function getTelemetryCliConfig(config) {
72
69
  function getAnonymousId(cwd) {
73
70
  try {
74
71
  const pkgPath = (0, import_node_path.join)(cwd, "package.json");
75
- if (!(0, import_node_fs.existsSync)(pkgPath)) return void 0;
72
+ if (!(0, import_node_fs.existsSync)(pkgPath)) {
73
+ return void 0;
74
+ }
76
75
  const pkg = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
77
76
  const name = typeof pkg?.name === "string" ? pkg.name : "";
78
77
  const basePath = typeof pkg?.betterTenant?.basePath === "string" ? pkg.betterTenant.basePath : "";
@@ -101,22 +100,34 @@ function detectRuntime() {
101
100
  }
102
101
  function detectEnvironment() {
103
102
  const env = process.env.NODE_ENV || "development";
104
- if (env === "test") return "test";
103
+ if (env === "test") {
104
+ return "test";
105
+ }
105
106
  if (process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true" || process.env.GITLAB_CI === "true" || process.env.CIRCLECI === "true") {
106
107
  return "ci";
107
108
  }
108
- if (env === "production") return "production";
109
+ if (env === "production") {
110
+ return "production";
111
+ }
109
112
  return "development";
110
113
  }
111
114
  function detectFramework(cwd) {
112
115
  try {
113
116
  const pkgPath = (0, import_node_path.join)(cwd, "package.json");
114
- if (!(0, import_node_fs.existsSync)(pkgPath)) return void 0;
117
+ if (!(0, import_node_fs.existsSync)(pkgPath)) {
118
+ return void 0;
119
+ }
115
120
  const pkg = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
116
121
  const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
117
- if (deps["next"]) return { name: "next", version: deps["next"] };
118
- if (deps["hono"]) return { name: "hono", version: deps["hono"] };
119
- if (deps["express"]) return { name: "express", version: deps["express"] };
122
+ if (deps["next"]) {
123
+ return { name: "next", version: deps["next"] };
124
+ }
125
+ if (deps["hono"]) {
126
+ return { name: "hono", version: deps["hono"] };
127
+ }
128
+ if (deps["express"]) {
129
+ return { name: "express", version: deps["express"] };
130
+ }
120
131
  return void 0;
121
132
  } catch {
122
133
  return void 0;
@@ -125,12 +136,17 @@ function detectFramework(cwd) {
125
136
  function detectDatabase(cwd) {
126
137
  try {
127
138
  const pkgPath = (0, import_node_path.join)(cwd, "package.json");
128
- if (!(0, import_node_fs.existsSync)(pkgPath)) return void 0;
139
+ if (!(0, import_node_fs.existsSync)(pkgPath)) {
140
+ return void 0;
141
+ }
129
142
  const pkg = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
130
143
  const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
131
- if (deps["drizzle-orm"])
144
+ if (deps["drizzle-orm"]) {
132
145
  return { name: "drizzle", version: deps["drizzle-orm"] };
133
- if (deps["prisma"]) return { name: "prisma", version: deps["prisma"] };
146
+ }
147
+ if (deps["prisma"]) {
148
+ return { name: "prisma", version: deps["prisma"] };
149
+ }
134
150
  return void 0;
135
151
  } catch {
136
152
  return void 0;
@@ -151,31 +167,46 @@ function detectSystem() {
151
167
  }
152
168
  function detectPackageManager() {
153
169
  const ua = process.env.npm_config_user_agent;
154
- if (!ua || typeof ua !== "string") return void 0;
170
+ if (!ua || typeof ua !== "string") {
171
+ return void 0;
172
+ }
155
173
  const match = ua.match(/^(.+?)\/(\d+\.\d+\.\d+.*?)(?:\s|$)/);
156
174
  if (match) {
157
175
  const name = (match[1] ?? "unknown").toLowerCase();
158
176
  const version = match[2];
159
177
  return version ? { name, version } : { name };
160
178
  }
161
- if (ua.includes("pnpm")) return { name: "pnpm" };
162
- if (ua.includes("yarn")) return { name: "yarn" };
179
+ if (ua.includes("pnpm")) {
180
+ return { name: "pnpm" };
181
+ }
182
+ if (ua.includes("yarn")) {
183
+ return { name: "yarn" };
184
+ }
163
185
  return { name: "npm" };
164
186
  }
165
187
  function isTelemetryEnabled(options) {
166
- if (process.env.NODE_ENV === "test") return false;
188
+ if (process.env.NODE_ENV === "test") {
189
+ return false;
190
+ }
167
191
  const env = process.env.BETTER_TENANT_TELEMETRY;
168
- if (env === "0" || env?.toLowerCase() === "false") return false;
169
- if (env === "1" || env?.toLowerCase() === "true") return true;
192
+ if (env === "0" || env?.toLowerCase() === "false") {
193
+ return false;
194
+ }
195
+ if (env === "1" || env?.toLowerCase() === "true") {
196
+ return true;
197
+ }
170
198
  return options?.enabled !== false;
171
199
  }
172
200
  function isDebugMode(options) {
173
- if (process.env.BETTER_TENANT_TELEMETRY_DEBUG === "1") return true;
201
+ if (process.env.BETTER_TENANT_TELEMETRY_DEBUG === "1") {
202
+ return true;
203
+ }
174
204
  return options?.debug === true;
175
205
  }
176
206
  function sendTelemetry(type, payload, options) {
177
- if (!isTelemetryEnabled(options))
207
+ if (!isTelemetryEnabled(options)) {
178
208
  return options?.wait ? Promise.resolve() : void 0;
209
+ }
179
210
  const fullPayload = {
180
211
  library: LIBRARY_ID,
181
212
  type,
@@ -273,9 +304,10 @@ function getDatabase() {
273
304
  async function runWithTenantAndDatabase(tenantId, adapter, fn, options) {
274
305
  const result = await adapter.runWithTenant(tenantId, async (database) => {
275
306
  let context = { tenantId, database };
276
- if (options?.loadTenant && options.getTenantRepository && adapter.runAsSystem) {
307
+ const getTenantRepository = options?.getTenantRepository;
308
+ if (options?.loadTenant && getTenantRepository && adapter.runAsSystem) {
277
309
  const tenant = await adapter.runAsSystem(
278
- (systemDb) => options.getTenantRepository(systemDb).getById(tenantId)
310
+ (systemDb) => getTenantRepository(systemDb).getById(tenantId)
279
311
  );
280
312
  context = tenant != null ? { ...context, tenant } : context;
281
313
  }
@@ -340,17 +372,7 @@ function requireRunAsSystem(adapter) {
340
372
  }
341
373
  return adapter.runAsSystem;
342
374
  }
343
- function requireTenantRepository(getTenantRepository) {
344
- if (!getTenantRepository) {
345
- throw new Error(
346
- "better-tenant: tenant.api requires getTenantRepository in config (adapter provides CRUD for tenants table)"
347
- );
348
- }
349
- return getTenantRepository;
350
- }
351
375
  function createTenantApi(adapter, getTenantRepository) {
352
- const runAsSystem2 = requireRunAsSystem(adapter);
353
- const getRepository = requireTenantRepository(getTenantRepository);
354
376
  return {
355
377
  async createTenant(data) {
356
378
  if (!data.name?.trim()) {
@@ -359,8 +381,9 @@ function createTenantApi(adapter, getTenantRepository) {
359
381
  if (!data.slug?.trim()) {
360
382
  throw new Error("better-tenant: createTenant requires slug");
361
383
  }
384
+ const runAsSystem2 = requireRunAsSystem(adapter);
362
385
  return runAsSystem2(
363
- (database) => getRepository(database).create({
386
+ (database) => getTenantRepository(database).create({
364
387
  name: data.name.trim(),
365
388
  slug: data.slug.trim()
366
389
  })
@@ -370,8 +393,9 @@ function createTenantApi(adapter, getTenantRepository) {
370
393
  if (!tenantId?.trim()) {
371
394
  throw new Error("better-tenant: updateTenant requires tenantId");
372
395
  }
396
+ const runAsSystem2 = requireRunAsSystem(adapter);
373
397
  return runAsSystem2(
374
- (database) => getRepository(database).update(tenantId, {
398
+ (database) => getTenantRepository(database).update(tenantId, {
375
399
  ...data.name !== void 0 && { name: data.name },
376
400
  ...data.slug !== void 0 && { slug: data.slug }
377
401
  })
@@ -383,16 +407,18 @@ function createTenantApi(adapter, getTenantRepository) {
383
407
  MAX_LIST_LIMIT
384
408
  );
385
409
  const offset = Math.max(0, options.offset ?? 0);
410
+ const runAsSystem2 = requireRunAsSystem(adapter);
386
411
  return runAsSystem2(
387
- (database) => getRepository(database).list({ limit, offset })
412
+ (database) => getTenantRepository(database).list({ limit, offset })
388
413
  );
389
414
  },
390
415
  async deleteTenant(tenantId) {
391
416
  if (!tenantId?.trim()) {
392
417
  throw new Error("better-tenant: deleteTenant requires tenantId");
393
418
  }
419
+ const runAsSystem2 = requireRunAsSystem(adapter);
394
420
  return runAsSystem2(
395
- (database) => getRepository(database).delete(tenantId)
421
+ (database) => getTenantRepository(database).delete(tenantId)
396
422
  );
397
423
  }
398
424
  };
@@ -402,10 +428,7 @@ async function runAs(tenantId, adapter, fn) {
402
428
  }
403
429
  async function runAsSystem(adapter, fn) {
404
430
  const run = requireRunAsSystem(adapter);
405
- return runWithContext(
406
- { tenantId: "", isSystem: true },
407
- () => run(fn)
408
- );
431
+ return runWithContext({ isSystem: true }, () => run(fn));
409
432
  }
410
433
 
411
434
  // src/resolver.ts
@@ -416,17 +439,23 @@ function getHeader(headers, name) {
416
439
  return value2?.trim() || void 0;
417
440
  }
418
441
  const raw = headers[key] ?? headers[name];
419
- if (raw === void 0) return void 0;
442
+ if (raw === void 0) {
443
+ return void 0;
444
+ }
420
445
  const value = Array.isArray(raw) ? raw[0] : raw;
421
446
  return (typeof value === "string" ? value : "").trim() || void 0;
422
447
  }
423
448
  function resolveFromHeader(request, headerName) {
424
- if (!headerName) return void 0;
449
+ if (!headerName) {
450
+ return void 0;
451
+ }
425
452
  return getHeader(request.headers, headerName);
426
453
  }
427
454
  function resolveFromPath(request, pathConfig) {
428
455
  const pathOrUrl = request.path ?? request.url;
429
- if (!pathOrUrl) return void 0;
456
+ if (!pathOrUrl) {
457
+ return void 0;
458
+ }
430
459
  let path;
431
460
  try {
432
461
  path = pathOrUrl.startsWith("http") ? new URL(pathOrUrl).pathname : pathOrUrl;
@@ -446,11 +475,17 @@ function parseTenantSegmentIndex(pattern) {
446
475
  }
447
476
  function resolveFromSubdomain(request, config) {
448
477
  const host = request.host ?? (request.url ? new URL(request.url).host : "");
449
- if (!host) return void 0;
478
+ if (!host) {
479
+ return void 0;
480
+ }
450
481
  const hostname = host.split(":")[0];
451
- if (!hostname) return void 0;
482
+ if (!hostname) {
483
+ return void 0;
484
+ }
452
485
  const parts = hostname.split(".");
453
- if (parts.length <= 2) return void 0;
486
+ if (parts.length <= 2) {
487
+ return void 0;
488
+ }
454
489
  const index = config === true ? 0 : typeof config === "object" && config.segmentIndex !== void 0 ? config.segmentIndex : 0;
455
490
  const value = parts[index];
456
491
  return typeof value === "string" && value.length > 0 ? value : void 0;
@@ -458,125 +493,159 @@ function resolveFromSubdomain(request, config) {
458
493
  function decodeJwtPayload(token) {
459
494
  try {
460
495
  const parts = token.split(".");
461
- if (parts.length < 2) return null;
496
+ if (parts.length < 2) {
497
+ return null;
498
+ }
462
499
  const payload = parts[1];
463
- if (!payload) return null;
500
+ if (!payload) {
501
+ return null;
502
+ }
464
503
  const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
465
- return JSON.parse(decoded);
504
+ const parsed = JSON.parse(decoded);
505
+ if (typeof parsed !== "object" || parsed === null) {
506
+ return null;
507
+ }
508
+ return parsed;
466
509
  } catch {
467
510
  return null;
468
511
  }
469
512
  }
470
- function resolveFromJwt(request, config) {
471
- const getToken = request.getToken;
472
- if (!getToken) return void 0;
473
- const token = typeof getToken === "function" ? getToken() : getToken;
474
- const value = token instanceof Promise ? void 0 : token ?? void 0;
475
- const resolved = value ?? void 0;
476
- if (!resolved) return void 0;
477
- const claim = typeof config === "string" ? config : config.claim;
478
- if (!claim) return void 0;
479
- const payload = decodeJwtPayload(resolved);
480
- if (!payload) return void 0;
481
- const claimValue = payload[claim];
482
- return typeof claimValue === "string" && claimValue.length > 0 ? claimValue : void 0;
483
- }
484
- async function resolveFromJwtAsync(request, config) {
513
+ async function resolveFromJwt(request, config) {
485
514
  const getToken = request.getToken;
486
- if (!getToken) return void 0;
515
+ if (!getToken) {
516
+ return void 0;
517
+ }
487
518
  const token = typeof getToken === "function" ? getToken() : getToken;
488
519
  const value = token instanceof Promise ? await token : token;
489
520
  const resolved = value ?? void 0;
490
- if (!resolved) return void 0;
521
+ if (!resolved) {
522
+ return void 0;
523
+ }
491
524
  const claim = typeof config === "string" ? config : config.claim;
492
- if (!claim) return void 0;
493
- const payload = decodeJwtPayload(resolved);
494
- if (!payload) return void 0;
525
+ if (!claim) {
526
+ return void 0;
527
+ }
528
+ const verifyToken = typeof config === "object" ? config.verifyToken : void 0;
529
+ let payload;
530
+ if (verifyToken) {
531
+ payload = await verifyToken(resolved);
532
+ } else {
533
+ payload = decodeJwtPayload(resolved);
534
+ }
535
+ if (!payload) {
536
+ return void 0;
537
+ }
495
538
  const claimValue = payload[claim];
496
539
  return typeof claimValue === "string" && claimValue.length > 0 ? claimValue : void 0;
497
540
  }
498
- function resolveTenant(request, config) {
541
+ function describeStrategies(config) {
542
+ const strategies = [];
499
543
  if (config.header !== void 0) {
500
- const v = resolveFromHeader(request, config.header);
501
- if (v !== void 0) return v;
544
+ strategies.push(`header '${config.header}'`);
502
545
  }
503
546
  if (config.path !== void 0) {
504
- const v = resolveFromPath(request, config.path);
505
- if (v !== void 0) return v;
547
+ const pattern = typeof config.path === "string" ? config.path : config.path.pattern;
548
+ strategies.push(`path '${pattern}'`);
506
549
  }
507
550
  if (config.subdomain !== void 0 && config.subdomain !== false) {
508
- const v = resolveFromSubdomain(request, config.subdomain);
509
- if (v !== void 0) return v;
551
+ strategies.push("subdomain");
510
552
  }
511
553
  if (config.jwt !== void 0) {
512
- const v = resolveFromJwt(request, config.jwt);
513
- if (v !== void 0) return v;
554
+ const claim = typeof config.jwt === "string" ? config.jwt : config.jwt.claim;
555
+ strategies.push(`jwt claim '${claim}'`);
514
556
  }
515
557
  if (config.custom !== void 0) {
516
- const v = config.custom(request);
517
- if (typeof v === "string" && v.length > 0) return v;
558
+ strategies.push("custom resolver");
518
559
  }
519
- return void 0;
560
+ return strategies;
520
561
  }
521
- async function resolveTenantAsync(request, config) {
562
+ async function resolveTenant(request, config) {
522
563
  if (config.header !== void 0) {
523
564
  const v = resolveFromHeader(request, config.header);
524
- if (v !== void 0) return v;
565
+ if (v !== void 0) {
566
+ return v;
567
+ }
525
568
  }
526
569
  if (config.path !== void 0) {
527
570
  const v = resolveFromPath(request, config.path);
528
- if (v !== void 0) return v;
571
+ if (v !== void 0) {
572
+ return v;
573
+ }
529
574
  }
530
575
  if (config.subdomain !== void 0 && config.subdomain !== false) {
531
576
  const v = resolveFromSubdomain(request, config.subdomain);
532
- if (v !== void 0) return v;
577
+ if (v !== void 0) {
578
+ return v;
579
+ }
533
580
  }
534
581
  if (config.jwt !== void 0) {
535
- const v = await resolveFromJwtAsync(request, config.jwt);
536
- if (v !== void 0) return v;
582
+ const v = await resolveFromJwt(request, config.jwt);
583
+ if (v !== void 0) {
584
+ return v;
585
+ }
537
586
  }
538
587
  if (config.custom !== void 0) {
539
588
  const v = await Promise.resolve(config.custom(request));
540
- if (typeof v === "string" && v.length > 0) return v;
589
+ if (typeof v === "string" && v.length > 0) {
590
+ return v;
591
+ }
541
592
  }
542
593
  return void 0;
543
594
  }
544
595
 
545
596
  // src/better-tenant.ts
597
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
598
+ async function resolveIdentifierToId(identifier, resolverConfig, adapter, getTenantRepository) {
599
+ if (resolverConfig.resolveToId) {
600
+ return resolverConfig.resolveToId(identifier);
601
+ }
602
+ if (UUID_RE.test(identifier)) {
603
+ return identifier;
604
+ }
605
+ if (adapter.runAsSystem) {
606
+ const tenant = await adapter.runAsSystem(
607
+ (systemDb) => getTenantRepository(systemDb).getBySlug(identifier)
608
+ );
609
+ return tenant?.id;
610
+ }
611
+ return identifier;
612
+ }
546
613
  function betterTenant(config) {
547
- const { adapter, tenantResolver, getTenantRepository, loadTenant } = config;
614
+ const { database, tenantResolver, loadTenant } = config;
615
+ const { adapter, getTenantRepository } = database;
548
616
  sendInitTelemetry(config, config.telemetry);
549
- const api = getTenantRepository ? createTenantApi(adapter, getTenantRepository) : createStubTenantApi();
550
- const shouldLoadTenant = getTenantRepository != null && loadTenant !== false;
551
- const runWithTenantAndDatabaseOptions = shouldLoadTenant ? { loadTenant: true, getTenantRepository } : void 0;
617
+ const api = createTenantApi(adapter, getTenantRepository);
618
+ const runWithTenantAndDatabaseOptions = loadTenant !== false ? { loadTenant: true, getTenantRepository } : void 0;
619
+ const resolverStrategies = describeStrategies(tenantResolver);
620
+ async function resolveAndNormalize(request) {
621
+ const raw = await resolveTenant(request, tenantResolver);
622
+ if (!raw) return void 0;
623
+ return resolveIdentifierToId(
624
+ raw,
625
+ tenantResolver,
626
+ adapter,
627
+ getTenantRepository
628
+ );
629
+ }
552
630
  return {
553
631
  getContext,
554
- getDatabase,
632
+ getDatabase: () => getDatabase(),
555
633
  runWithTenant,
556
- runWithTenantAndDatabase: (tenantId, _adapter, fn) => runWithTenantAndDatabase(tenantId, adapter, fn, runWithTenantAndDatabaseOptions),
557
- runAs: (tenantId, _adapter, fn) => runAs(tenantId, adapter, fn),
634
+ runAs: (tenantId, fn) => runWithTenantAndDatabase(
635
+ tenantId,
636
+ adapter,
637
+ fn,
638
+ runWithTenantAndDatabaseOptions
639
+ ),
558
640
  runAsSystem: (fn) => runAsSystem(adapter, fn),
559
- resolveTenant: (request) => resolveTenant(request, tenantResolver),
560
- resolveTenantAsync: (request) => resolveTenantAsync(request, tenantResolver),
641
+ resolveTenant: resolveAndNormalize,
642
+ resolverStrategies,
561
643
  handleRequest: (request, next, options) => handleRequest(request, next, {
562
644
  ...options,
563
- resolveTenant: (input) => resolveTenantAsync(input, tenantResolver),
645
+ resolveTenant: resolveAndNormalize,
564
646
  adapter
565
647
  }),
566
- tenant: { api }
567
- };
568
- }
569
- function createStubTenantApi() {
570
- const err = () => {
571
- throw new Error(
572
- "better-tenant: tenant.api requires getTenantRepository in config"
573
- );
574
- };
575
- return {
576
- createTenant: () => err(),
577
- updateTenant: () => err(),
578
- listTenants: () => err(),
579
- deleteTenant: () => err()
648
+ api
580
649
  };
581
650
  }
582
651
 
@@ -585,12 +654,16 @@ function isFetchRequest(input) {
585
654
  return typeof Request !== "undefined" && input instanceof Request;
586
655
  }
587
656
  function normalizeHost(raw) {
588
- if (!raw) return void 0;
657
+ if (!raw) {
658
+ return void 0;
659
+ }
589
660
  const value = raw.split(":")[0]?.trim();
590
661
  return value || void 0;
591
662
  }
592
663
  function normalizeHeaders(headers) {
593
- if (!headers) return {};
664
+ if (!headers) {
665
+ return {};
666
+ }
594
667
  const normalized = {};
595
668
  for (const [key, value] of Object.entries(headers)) {
596
669
  const normalizedKey = key.toLowerCase();
@@ -607,7 +680,9 @@ function normalizeHeaders(headers) {
607
680
  return normalized;
608
681
  }
609
682
  function pathWithoutQuery(value) {
610
- if (!value) return void 0;
683
+ if (!value) {
684
+ return void 0;
685
+ }
611
686
  const [pathname] = value.split("?");
612
687
  return pathname || void 0;
613
688
  }
@@ -641,7 +716,9 @@ function toResolvableRequest(request) {
641
716
  const hostFromHeaders = headers.host;
642
717
  const hostValue = Array.isArray(hostFromHeaders) ? hostFromHeaders[0] : hostFromHeaders;
643
718
  const host = normalizeHost(request.hostname ?? request.host ?? hostValue);
644
- const path = pathWithoutQuery(request.path ?? request.originalUrl ?? request.url);
719
+ const path = pathWithoutQuery(
720
+ request.path ?? request.originalUrl ?? request.url
721
+ );
645
722
  const resolved = {
646
723
  headers
647
724
  };
@@ -662,15 +739,13 @@ function toResolvableRequest(request) {
662
739
  TenantNotResolvedError,
663
740
  betterTenant,
664
741
  createTenantApi,
742
+ describeStrategies,
665
743
  getContext,
666
- getDatabase,
667
744
  handleRequest,
668
745
  resolveTenant,
669
- resolveTenantAsync,
670
746
  runAs,
671
747
  runAsSystem,
672
748
  runWithTenant,
673
- runWithTenantAndDatabase,
674
749
  sendCliTelemetry,
675
750
  toResolvableRequest
676
751
  });