@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/README.md +33 -20
- package/dist/adapter.d.ts +3 -3
- package/dist/adapter.d.ts.map +1 -1
- package/dist/api.d.ts +6 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/better-tenant.d.ts +13 -18
- package/dist/better-tenant.d.ts.map +1 -1
- package/dist/index.cjs +197 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +196 -119
- package/dist/index.js.map +1 -1
- package/dist/request.d.ts.map +1 -1
- package/dist/resolver.d.ts +6 -5
- package/dist/resolver.d.ts.map +1 -1
- package/dist/telemetry.d.ts +6 -4
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/types.d.ts +35 -16
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,8 +15,7 @@ function getTelemetryTenantConfig(config) {
|
|
|
15
15
|
jwt: !!r.jwt,
|
|
16
16
|
custom: !!r.custom
|
|
17
17
|
},
|
|
18
|
-
tenantTablesCount:
|
|
19
|
-
hasGetTenantRepository: !!config.getTenantRepository,
|
|
18
|
+
tenantTablesCount: 0,
|
|
20
19
|
loadTenant: config.loadTenant,
|
|
21
20
|
basePathSet: !!config.basePath,
|
|
22
21
|
plugins: (config.plugins ?? []).map((p) => String(p.id))
|
|
@@ -32,7 +31,9 @@ function getTelemetryCliConfig(config) {
|
|
|
32
31
|
function getAnonymousId(cwd) {
|
|
33
32
|
try {
|
|
34
33
|
const pkgPath = join(cwd, "package.json");
|
|
35
|
-
if (!existsSync(pkgPath))
|
|
34
|
+
if (!existsSync(pkgPath)) {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
36
37
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
37
38
|
const name = typeof pkg?.name === "string" ? pkg.name : "";
|
|
38
39
|
const basePath = typeof pkg?.betterTenant?.basePath === "string" ? pkg.betterTenant.basePath : "";
|
|
@@ -61,22 +62,34 @@ function detectRuntime() {
|
|
|
61
62
|
}
|
|
62
63
|
function detectEnvironment() {
|
|
63
64
|
const env = process.env.NODE_ENV || "development";
|
|
64
|
-
if (env === "test")
|
|
65
|
+
if (env === "test") {
|
|
66
|
+
return "test";
|
|
67
|
+
}
|
|
65
68
|
if (process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true" || process.env.GITLAB_CI === "true" || process.env.CIRCLECI === "true") {
|
|
66
69
|
return "ci";
|
|
67
70
|
}
|
|
68
|
-
if (env === "production")
|
|
71
|
+
if (env === "production") {
|
|
72
|
+
return "production";
|
|
73
|
+
}
|
|
69
74
|
return "development";
|
|
70
75
|
}
|
|
71
76
|
function detectFramework(cwd) {
|
|
72
77
|
try {
|
|
73
78
|
const pkgPath = join(cwd, "package.json");
|
|
74
|
-
if (!existsSync(pkgPath))
|
|
79
|
+
if (!existsSync(pkgPath)) {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
75
82
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
76
83
|
const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
|
|
77
|
-
if (deps["next"])
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
if (deps["next"]) {
|
|
85
|
+
return { name: "next", version: deps["next"] };
|
|
86
|
+
}
|
|
87
|
+
if (deps["hono"]) {
|
|
88
|
+
return { name: "hono", version: deps["hono"] };
|
|
89
|
+
}
|
|
90
|
+
if (deps["express"]) {
|
|
91
|
+
return { name: "express", version: deps["express"] };
|
|
92
|
+
}
|
|
80
93
|
return void 0;
|
|
81
94
|
} catch {
|
|
82
95
|
return void 0;
|
|
@@ -85,12 +98,17 @@ function detectFramework(cwd) {
|
|
|
85
98
|
function detectDatabase(cwd) {
|
|
86
99
|
try {
|
|
87
100
|
const pkgPath = join(cwd, "package.json");
|
|
88
|
-
if (!existsSync(pkgPath))
|
|
101
|
+
if (!existsSync(pkgPath)) {
|
|
102
|
+
return void 0;
|
|
103
|
+
}
|
|
89
104
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
90
105
|
const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
|
|
91
|
-
if (deps["drizzle-orm"])
|
|
106
|
+
if (deps["drizzle-orm"]) {
|
|
92
107
|
return { name: "drizzle", version: deps["drizzle-orm"] };
|
|
93
|
-
|
|
108
|
+
}
|
|
109
|
+
if (deps["prisma"]) {
|
|
110
|
+
return { name: "prisma", version: deps["prisma"] };
|
|
111
|
+
}
|
|
94
112
|
return void 0;
|
|
95
113
|
} catch {
|
|
96
114
|
return void 0;
|
|
@@ -111,31 +129,46 @@ function detectSystem() {
|
|
|
111
129
|
}
|
|
112
130
|
function detectPackageManager() {
|
|
113
131
|
const ua = process.env.npm_config_user_agent;
|
|
114
|
-
if (!ua || typeof ua !== "string")
|
|
132
|
+
if (!ua || typeof ua !== "string") {
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
115
135
|
const match = ua.match(/^(.+?)\/(\d+\.\d+\.\d+.*?)(?:\s|$)/);
|
|
116
136
|
if (match) {
|
|
117
137
|
const name = (match[1] ?? "unknown").toLowerCase();
|
|
118
138
|
const version = match[2];
|
|
119
139
|
return version ? { name, version } : { name };
|
|
120
140
|
}
|
|
121
|
-
if (ua.includes("pnpm"))
|
|
122
|
-
|
|
141
|
+
if (ua.includes("pnpm")) {
|
|
142
|
+
return { name: "pnpm" };
|
|
143
|
+
}
|
|
144
|
+
if (ua.includes("yarn")) {
|
|
145
|
+
return { name: "yarn" };
|
|
146
|
+
}
|
|
123
147
|
return { name: "npm" };
|
|
124
148
|
}
|
|
125
149
|
function isTelemetryEnabled(options) {
|
|
126
|
-
if (process.env.NODE_ENV === "test")
|
|
150
|
+
if (process.env.NODE_ENV === "test") {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
127
153
|
const env = process.env.BETTER_TENANT_TELEMETRY;
|
|
128
|
-
if (env === "0" || env?.toLowerCase() === "false")
|
|
129
|
-
|
|
154
|
+
if (env === "0" || env?.toLowerCase() === "false") {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
if (env === "1" || env?.toLowerCase() === "true") {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
130
160
|
return options?.enabled !== false;
|
|
131
161
|
}
|
|
132
162
|
function isDebugMode(options) {
|
|
133
|
-
if (process.env.BETTER_TENANT_TELEMETRY_DEBUG === "1")
|
|
163
|
+
if (process.env.BETTER_TENANT_TELEMETRY_DEBUG === "1") {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
134
166
|
return options?.debug === true;
|
|
135
167
|
}
|
|
136
168
|
function sendTelemetry(type, payload, options) {
|
|
137
|
-
if (!isTelemetryEnabled(options))
|
|
169
|
+
if (!isTelemetryEnabled(options)) {
|
|
138
170
|
return options?.wait ? Promise.resolve() : void 0;
|
|
171
|
+
}
|
|
139
172
|
const fullPayload = {
|
|
140
173
|
library: LIBRARY_ID,
|
|
141
174
|
type,
|
|
@@ -233,9 +266,10 @@ function getDatabase() {
|
|
|
233
266
|
async function runWithTenantAndDatabase(tenantId, adapter, fn, options) {
|
|
234
267
|
const result = await adapter.runWithTenant(tenantId, async (database) => {
|
|
235
268
|
let context = { tenantId, database };
|
|
236
|
-
|
|
269
|
+
const getTenantRepository = options?.getTenantRepository;
|
|
270
|
+
if (options?.loadTenant && getTenantRepository && adapter.runAsSystem) {
|
|
237
271
|
const tenant = await adapter.runAsSystem(
|
|
238
|
-
(systemDb) =>
|
|
272
|
+
(systemDb) => getTenantRepository(systemDb).getById(tenantId)
|
|
239
273
|
);
|
|
240
274
|
context = tenant != null ? { ...context, tenant } : context;
|
|
241
275
|
}
|
|
@@ -300,17 +334,7 @@ function requireRunAsSystem(adapter) {
|
|
|
300
334
|
}
|
|
301
335
|
return adapter.runAsSystem;
|
|
302
336
|
}
|
|
303
|
-
function requireTenantRepository(getTenantRepository) {
|
|
304
|
-
if (!getTenantRepository) {
|
|
305
|
-
throw new Error(
|
|
306
|
-
"better-tenant: tenant.api requires getTenantRepository in config (adapter provides CRUD for tenants table)"
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
return getTenantRepository;
|
|
310
|
-
}
|
|
311
337
|
function createTenantApi(adapter, getTenantRepository) {
|
|
312
|
-
const runAsSystem2 = requireRunAsSystem(adapter);
|
|
313
|
-
const getRepository = requireTenantRepository(getTenantRepository);
|
|
314
338
|
return {
|
|
315
339
|
async createTenant(data) {
|
|
316
340
|
if (!data.name?.trim()) {
|
|
@@ -319,8 +343,9 @@ function createTenantApi(adapter, getTenantRepository) {
|
|
|
319
343
|
if (!data.slug?.trim()) {
|
|
320
344
|
throw new Error("better-tenant: createTenant requires slug");
|
|
321
345
|
}
|
|
346
|
+
const runAsSystem2 = requireRunAsSystem(adapter);
|
|
322
347
|
return runAsSystem2(
|
|
323
|
-
(database) =>
|
|
348
|
+
(database) => getTenantRepository(database).create({
|
|
324
349
|
name: data.name.trim(),
|
|
325
350
|
slug: data.slug.trim()
|
|
326
351
|
})
|
|
@@ -330,8 +355,9 @@ function createTenantApi(adapter, getTenantRepository) {
|
|
|
330
355
|
if (!tenantId?.trim()) {
|
|
331
356
|
throw new Error("better-tenant: updateTenant requires tenantId");
|
|
332
357
|
}
|
|
358
|
+
const runAsSystem2 = requireRunAsSystem(adapter);
|
|
333
359
|
return runAsSystem2(
|
|
334
|
-
(database) =>
|
|
360
|
+
(database) => getTenantRepository(database).update(tenantId, {
|
|
335
361
|
...data.name !== void 0 && { name: data.name },
|
|
336
362
|
...data.slug !== void 0 && { slug: data.slug }
|
|
337
363
|
})
|
|
@@ -343,16 +369,18 @@ function createTenantApi(adapter, getTenantRepository) {
|
|
|
343
369
|
MAX_LIST_LIMIT
|
|
344
370
|
);
|
|
345
371
|
const offset = Math.max(0, options.offset ?? 0);
|
|
372
|
+
const runAsSystem2 = requireRunAsSystem(adapter);
|
|
346
373
|
return runAsSystem2(
|
|
347
|
-
(database) =>
|
|
374
|
+
(database) => getTenantRepository(database).list({ limit, offset })
|
|
348
375
|
);
|
|
349
376
|
},
|
|
350
377
|
async deleteTenant(tenantId) {
|
|
351
378
|
if (!tenantId?.trim()) {
|
|
352
379
|
throw new Error("better-tenant: deleteTenant requires tenantId");
|
|
353
380
|
}
|
|
381
|
+
const runAsSystem2 = requireRunAsSystem(adapter);
|
|
354
382
|
return runAsSystem2(
|
|
355
|
-
(database) =>
|
|
383
|
+
(database) => getTenantRepository(database).delete(tenantId)
|
|
356
384
|
);
|
|
357
385
|
}
|
|
358
386
|
};
|
|
@@ -362,10 +390,7 @@ async function runAs(tenantId, adapter, fn) {
|
|
|
362
390
|
}
|
|
363
391
|
async function runAsSystem(adapter, fn) {
|
|
364
392
|
const run = requireRunAsSystem(adapter);
|
|
365
|
-
return runWithContext(
|
|
366
|
-
{ tenantId: "", isSystem: true },
|
|
367
|
-
() => run(fn)
|
|
368
|
-
);
|
|
393
|
+
return runWithContext({ isSystem: true }, () => run(fn));
|
|
369
394
|
}
|
|
370
395
|
|
|
371
396
|
// src/resolver.ts
|
|
@@ -376,17 +401,23 @@ function getHeader(headers, name) {
|
|
|
376
401
|
return value2?.trim() || void 0;
|
|
377
402
|
}
|
|
378
403
|
const raw = headers[key] ?? headers[name];
|
|
379
|
-
if (raw === void 0)
|
|
404
|
+
if (raw === void 0) {
|
|
405
|
+
return void 0;
|
|
406
|
+
}
|
|
380
407
|
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
381
408
|
return (typeof value === "string" ? value : "").trim() || void 0;
|
|
382
409
|
}
|
|
383
410
|
function resolveFromHeader(request, headerName) {
|
|
384
|
-
if (!headerName)
|
|
411
|
+
if (!headerName) {
|
|
412
|
+
return void 0;
|
|
413
|
+
}
|
|
385
414
|
return getHeader(request.headers, headerName);
|
|
386
415
|
}
|
|
387
416
|
function resolveFromPath(request, pathConfig) {
|
|
388
417
|
const pathOrUrl = request.path ?? request.url;
|
|
389
|
-
if (!pathOrUrl)
|
|
418
|
+
if (!pathOrUrl) {
|
|
419
|
+
return void 0;
|
|
420
|
+
}
|
|
390
421
|
let path;
|
|
391
422
|
try {
|
|
392
423
|
path = pathOrUrl.startsWith("http") ? new URL(pathOrUrl).pathname : pathOrUrl;
|
|
@@ -406,11 +437,17 @@ function parseTenantSegmentIndex(pattern) {
|
|
|
406
437
|
}
|
|
407
438
|
function resolveFromSubdomain(request, config) {
|
|
408
439
|
const host = request.host ?? (request.url ? new URL(request.url).host : "");
|
|
409
|
-
if (!host)
|
|
440
|
+
if (!host) {
|
|
441
|
+
return void 0;
|
|
442
|
+
}
|
|
410
443
|
const hostname = host.split(":")[0];
|
|
411
|
-
if (!hostname)
|
|
444
|
+
if (!hostname) {
|
|
445
|
+
return void 0;
|
|
446
|
+
}
|
|
412
447
|
const parts = hostname.split(".");
|
|
413
|
-
if (parts.length <= 2)
|
|
448
|
+
if (parts.length <= 2) {
|
|
449
|
+
return void 0;
|
|
450
|
+
}
|
|
414
451
|
const index = config === true ? 0 : typeof config === "object" && config.segmentIndex !== void 0 ? config.segmentIndex : 0;
|
|
415
452
|
const value = parts[index];
|
|
416
453
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -418,125 +455,159 @@ function resolveFromSubdomain(request, config) {
|
|
|
418
455
|
function decodeJwtPayload(token) {
|
|
419
456
|
try {
|
|
420
457
|
const parts = token.split(".");
|
|
421
|
-
if (parts.length < 2)
|
|
458
|
+
if (parts.length < 2) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
422
461
|
const payload = parts[1];
|
|
423
|
-
if (!payload)
|
|
462
|
+
if (!payload) {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
424
465
|
const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
|
|
425
|
-
|
|
466
|
+
const parsed = JSON.parse(decoded);
|
|
467
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
return parsed;
|
|
426
471
|
} catch {
|
|
427
472
|
return null;
|
|
428
473
|
}
|
|
429
474
|
}
|
|
430
|
-
function resolveFromJwt(request, config) {
|
|
431
|
-
const getToken = request.getToken;
|
|
432
|
-
if (!getToken) return void 0;
|
|
433
|
-
const token = typeof getToken === "function" ? getToken() : getToken;
|
|
434
|
-
const value = token instanceof Promise ? void 0 : token ?? void 0;
|
|
435
|
-
const resolved = value ?? void 0;
|
|
436
|
-
if (!resolved) return void 0;
|
|
437
|
-
const claim = typeof config === "string" ? config : config.claim;
|
|
438
|
-
if (!claim) return void 0;
|
|
439
|
-
const payload = decodeJwtPayload(resolved);
|
|
440
|
-
if (!payload) return void 0;
|
|
441
|
-
const claimValue = payload[claim];
|
|
442
|
-
return typeof claimValue === "string" && claimValue.length > 0 ? claimValue : void 0;
|
|
443
|
-
}
|
|
444
|
-
async function resolveFromJwtAsync(request, config) {
|
|
475
|
+
async function resolveFromJwt(request, config) {
|
|
445
476
|
const getToken = request.getToken;
|
|
446
|
-
if (!getToken)
|
|
477
|
+
if (!getToken) {
|
|
478
|
+
return void 0;
|
|
479
|
+
}
|
|
447
480
|
const token = typeof getToken === "function" ? getToken() : getToken;
|
|
448
481
|
const value = token instanceof Promise ? await token : token;
|
|
449
482
|
const resolved = value ?? void 0;
|
|
450
|
-
if (!resolved)
|
|
483
|
+
if (!resolved) {
|
|
484
|
+
return void 0;
|
|
485
|
+
}
|
|
451
486
|
const claim = typeof config === "string" ? config : config.claim;
|
|
452
|
-
if (!claim)
|
|
453
|
-
|
|
454
|
-
|
|
487
|
+
if (!claim) {
|
|
488
|
+
return void 0;
|
|
489
|
+
}
|
|
490
|
+
const verifyToken = typeof config === "object" ? config.verifyToken : void 0;
|
|
491
|
+
let payload;
|
|
492
|
+
if (verifyToken) {
|
|
493
|
+
payload = await verifyToken(resolved);
|
|
494
|
+
} else {
|
|
495
|
+
payload = decodeJwtPayload(resolved);
|
|
496
|
+
}
|
|
497
|
+
if (!payload) {
|
|
498
|
+
return void 0;
|
|
499
|
+
}
|
|
455
500
|
const claimValue = payload[claim];
|
|
456
501
|
return typeof claimValue === "string" && claimValue.length > 0 ? claimValue : void 0;
|
|
457
502
|
}
|
|
458
|
-
function
|
|
503
|
+
function describeStrategies(config) {
|
|
504
|
+
const strategies = [];
|
|
459
505
|
if (config.header !== void 0) {
|
|
460
|
-
|
|
461
|
-
if (v !== void 0) return v;
|
|
506
|
+
strategies.push(`header '${config.header}'`);
|
|
462
507
|
}
|
|
463
508
|
if (config.path !== void 0) {
|
|
464
|
-
const
|
|
465
|
-
|
|
509
|
+
const pattern = typeof config.path === "string" ? config.path : config.path.pattern;
|
|
510
|
+
strategies.push(`path '${pattern}'`);
|
|
466
511
|
}
|
|
467
512
|
if (config.subdomain !== void 0 && config.subdomain !== false) {
|
|
468
|
-
|
|
469
|
-
if (v !== void 0) return v;
|
|
513
|
+
strategies.push("subdomain");
|
|
470
514
|
}
|
|
471
515
|
if (config.jwt !== void 0) {
|
|
472
|
-
const
|
|
473
|
-
|
|
516
|
+
const claim = typeof config.jwt === "string" ? config.jwt : config.jwt.claim;
|
|
517
|
+
strategies.push(`jwt claim '${claim}'`);
|
|
474
518
|
}
|
|
475
519
|
if (config.custom !== void 0) {
|
|
476
|
-
|
|
477
|
-
if (typeof v === "string" && v.length > 0) return v;
|
|
520
|
+
strategies.push("custom resolver");
|
|
478
521
|
}
|
|
479
|
-
return
|
|
522
|
+
return strategies;
|
|
480
523
|
}
|
|
481
|
-
async function
|
|
524
|
+
async function resolveTenant(request, config) {
|
|
482
525
|
if (config.header !== void 0) {
|
|
483
526
|
const v = resolveFromHeader(request, config.header);
|
|
484
|
-
if (v !== void 0)
|
|
527
|
+
if (v !== void 0) {
|
|
528
|
+
return v;
|
|
529
|
+
}
|
|
485
530
|
}
|
|
486
531
|
if (config.path !== void 0) {
|
|
487
532
|
const v = resolveFromPath(request, config.path);
|
|
488
|
-
if (v !== void 0)
|
|
533
|
+
if (v !== void 0) {
|
|
534
|
+
return v;
|
|
535
|
+
}
|
|
489
536
|
}
|
|
490
537
|
if (config.subdomain !== void 0 && config.subdomain !== false) {
|
|
491
538
|
const v = resolveFromSubdomain(request, config.subdomain);
|
|
492
|
-
if (v !== void 0)
|
|
539
|
+
if (v !== void 0) {
|
|
540
|
+
return v;
|
|
541
|
+
}
|
|
493
542
|
}
|
|
494
543
|
if (config.jwt !== void 0) {
|
|
495
|
-
const v = await
|
|
496
|
-
if (v !== void 0)
|
|
544
|
+
const v = await resolveFromJwt(request, config.jwt);
|
|
545
|
+
if (v !== void 0) {
|
|
546
|
+
return v;
|
|
547
|
+
}
|
|
497
548
|
}
|
|
498
549
|
if (config.custom !== void 0) {
|
|
499
550
|
const v = await Promise.resolve(config.custom(request));
|
|
500
|
-
if (typeof v === "string" && v.length > 0)
|
|
551
|
+
if (typeof v === "string" && v.length > 0) {
|
|
552
|
+
return v;
|
|
553
|
+
}
|
|
501
554
|
}
|
|
502
555
|
return void 0;
|
|
503
556
|
}
|
|
504
557
|
|
|
505
558
|
// src/better-tenant.ts
|
|
559
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
560
|
+
async function resolveIdentifierToId(identifier, resolverConfig, adapter, getTenantRepository) {
|
|
561
|
+
if (resolverConfig.resolveToId) {
|
|
562
|
+
return resolverConfig.resolveToId(identifier);
|
|
563
|
+
}
|
|
564
|
+
if (UUID_RE.test(identifier)) {
|
|
565
|
+
return identifier;
|
|
566
|
+
}
|
|
567
|
+
if (adapter.runAsSystem) {
|
|
568
|
+
const tenant = await adapter.runAsSystem(
|
|
569
|
+
(systemDb) => getTenantRepository(systemDb).getBySlug(identifier)
|
|
570
|
+
);
|
|
571
|
+
return tenant?.id;
|
|
572
|
+
}
|
|
573
|
+
return identifier;
|
|
574
|
+
}
|
|
506
575
|
function betterTenant(config) {
|
|
507
|
-
const {
|
|
576
|
+
const { database, tenantResolver, loadTenant } = config;
|
|
577
|
+
const { adapter, getTenantRepository } = database;
|
|
508
578
|
sendInitTelemetry(config, config.telemetry);
|
|
509
|
-
const api =
|
|
510
|
-
const
|
|
511
|
-
const
|
|
579
|
+
const api = createTenantApi(adapter, getTenantRepository);
|
|
580
|
+
const runWithTenantAndDatabaseOptions = loadTenant !== false ? { loadTenant: true, getTenantRepository } : void 0;
|
|
581
|
+
const resolverStrategies = describeStrategies(tenantResolver);
|
|
582
|
+
async function resolveAndNormalize(request) {
|
|
583
|
+
const raw = await resolveTenant(request, tenantResolver);
|
|
584
|
+
if (!raw) return void 0;
|
|
585
|
+
return resolveIdentifierToId(
|
|
586
|
+
raw,
|
|
587
|
+
tenantResolver,
|
|
588
|
+
adapter,
|
|
589
|
+
getTenantRepository
|
|
590
|
+
);
|
|
591
|
+
}
|
|
512
592
|
return {
|
|
513
593
|
getContext,
|
|
514
|
-
getDatabase,
|
|
594
|
+
getDatabase: () => getDatabase(),
|
|
515
595
|
runWithTenant,
|
|
516
|
-
|
|
517
|
-
|
|
596
|
+
runAs: (tenantId, fn) => runWithTenantAndDatabase(
|
|
597
|
+
tenantId,
|
|
598
|
+
adapter,
|
|
599
|
+
fn,
|
|
600
|
+
runWithTenantAndDatabaseOptions
|
|
601
|
+
),
|
|
518
602
|
runAsSystem: (fn) => runAsSystem(adapter, fn),
|
|
519
|
-
resolveTenant:
|
|
520
|
-
|
|
603
|
+
resolveTenant: resolveAndNormalize,
|
|
604
|
+
resolverStrategies,
|
|
521
605
|
handleRequest: (request, next, options) => handleRequest(request, next, {
|
|
522
606
|
...options,
|
|
523
|
-
resolveTenant:
|
|
607
|
+
resolveTenant: resolveAndNormalize,
|
|
524
608
|
adapter
|
|
525
609
|
}),
|
|
526
|
-
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
function createStubTenantApi() {
|
|
530
|
-
const err = () => {
|
|
531
|
-
throw new Error(
|
|
532
|
-
"better-tenant: tenant.api requires getTenantRepository in config"
|
|
533
|
-
);
|
|
534
|
-
};
|
|
535
|
-
return {
|
|
536
|
-
createTenant: () => err(),
|
|
537
|
-
updateTenant: () => err(),
|
|
538
|
-
listTenants: () => err(),
|
|
539
|
-
deleteTenant: () => err()
|
|
610
|
+
api
|
|
540
611
|
};
|
|
541
612
|
}
|
|
542
613
|
|
|
@@ -545,12 +616,16 @@ function isFetchRequest(input) {
|
|
|
545
616
|
return typeof Request !== "undefined" && input instanceof Request;
|
|
546
617
|
}
|
|
547
618
|
function normalizeHost(raw) {
|
|
548
|
-
if (!raw)
|
|
619
|
+
if (!raw) {
|
|
620
|
+
return void 0;
|
|
621
|
+
}
|
|
549
622
|
const value = raw.split(":")[0]?.trim();
|
|
550
623
|
return value || void 0;
|
|
551
624
|
}
|
|
552
625
|
function normalizeHeaders(headers) {
|
|
553
|
-
if (!headers)
|
|
626
|
+
if (!headers) {
|
|
627
|
+
return {};
|
|
628
|
+
}
|
|
554
629
|
const normalized = {};
|
|
555
630
|
for (const [key, value] of Object.entries(headers)) {
|
|
556
631
|
const normalizedKey = key.toLowerCase();
|
|
@@ -567,7 +642,9 @@ function normalizeHeaders(headers) {
|
|
|
567
642
|
return normalized;
|
|
568
643
|
}
|
|
569
644
|
function pathWithoutQuery(value) {
|
|
570
|
-
if (!value)
|
|
645
|
+
if (!value) {
|
|
646
|
+
return void 0;
|
|
647
|
+
}
|
|
571
648
|
const [pathname] = value.split("?");
|
|
572
649
|
return pathname || void 0;
|
|
573
650
|
}
|
|
@@ -601,7 +678,9 @@ function toResolvableRequest(request) {
|
|
|
601
678
|
const hostFromHeaders = headers.host;
|
|
602
679
|
const hostValue = Array.isArray(hostFromHeaders) ? hostFromHeaders[0] : hostFromHeaders;
|
|
603
680
|
const host = normalizeHost(request.hostname ?? request.host ?? hostValue);
|
|
604
|
-
const path = pathWithoutQuery(
|
|
681
|
+
const path = pathWithoutQuery(
|
|
682
|
+
request.path ?? request.originalUrl ?? request.url
|
|
683
|
+
);
|
|
605
684
|
const resolved = {
|
|
606
685
|
headers
|
|
607
686
|
};
|
|
@@ -621,15 +700,13 @@ export {
|
|
|
621
700
|
TenantNotResolvedError,
|
|
622
701
|
betterTenant,
|
|
623
702
|
createTenantApi,
|
|
703
|
+
describeStrategies,
|
|
624
704
|
getContext,
|
|
625
|
-
getDatabase,
|
|
626
705
|
handleRequest,
|
|
627
706
|
resolveTenant,
|
|
628
|
-
resolveTenantAsync,
|
|
629
707
|
runAs,
|
|
630
708
|
runAsSystem,
|
|
631
709
|
runWithTenant,
|
|
632
|
-
runWithTenantAndDatabase,
|
|
633
710
|
sendCliTelemetry,
|
|
634
711
|
toResolvableRequest
|
|
635
712
|
};
|