@usebetterdev/tenant-core 0.1.0 → 0.2.0-beta.9
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 +7 -8
- package/dist/adapter.d.ts +3 -3
- package/dist/adapter.d.ts.map +1 -1
- package/dist/api.d.ts +4 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/better-tenant.d.ts +9 -11
- package/dist/better-tenant.d.ts.map +1 -1
- package/dist/index.cjs +171 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +171 -60
- package/dist/index.js.map +1 -1
- package/dist/request.d.ts.map +1 -1
- package/dist/resolver.d.ts.map +1 -1
- package/dist/telemetry.d.ts +8 -3
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/types.d.ts +25 -13
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ function getTelemetryTenantConfig(config) {
|
|
|
15
15
|
jwt: !!r.jwt,
|
|
16
16
|
custom: !!r.custom
|
|
17
17
|
},
|
|
18
|
-
tenantTablesCount:
|
|
18
|
+
tenantTablesCount: 0,
|
|
19
19
|
hasGetTenantRepository: !!config.getTenantRepository,
|
|
20
20
|
loadTenant: config.loadTenant,
|
|
21
21
|
basePathSet: !!config.basePath,
|
|
@@ -32,7 +32,9 @@ function getTelemetryCliConfig(config) {
|
|
|
32
32
|
function getAnonymousId(cwd) {
|
|
33
33
|
try {
|
|
34
34
|
const pkgPath = join(cwd, "package.json");
|
|
35
|
-
if (!existsSync(pkgPath))
|
|
35
|
+
if (!existsSync(pkgPath)) {
|
|
36
|
+
return void 0;
|
|
37
|
+
}
|
|
36
38
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
37
39
|
const name = typeof pkg?.name === "string" ? pkg.name : "";
|
|
38
40
|
const basePath = typeof pkg?.betterTenant?.basePath === "string" ? pkg.betterTenant.basePath : "";
|
|
@@ -61,22 +63,34 @@ function detectRuntime() {
|
|
|
61
63
|
}
|
|
62
64
|
function detectEnvironment() {
|
|
63
65
|
const env = process.env.NODE_ENV || "development";
|
|
64
|
-
if (env === "test")
|
|
66
|
+
if (env === "test") {
|
|
67
|
+
return "test";
|
|
68
|
+
}
|
|
65
69
|
if (process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true" || process.env.GITLAB_CI === "true" || process.env.CIRCLECI === "true") {
|
|
66
70
|
return "ci";
|
|
67
71
|
}
|
|
68
|
-
if (env === "production")
|
|
72
|
+
if (env === "production") {
|
|
73
|
+
return "production";
|
|
74
|
+
}
|
|
69
75
|
return "development";
|
|
70
76
|
}
|
|
71
77
|
function detectFramework(cwd) {
|
|
72
78
|
try {
|
|
73
79
|
const pkgPath = join(cwd, "package.json");
|
|
74
|
-
if (!existsSync(pkgPath))
|
|
80
|
+
if (!existsSync(pkgPath)) {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
75
83
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
76
84
|
const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
|
|
77
|
-
if (deps["next"])
|
|
78
|
-
|
|
79
|
-
|
|
85
|
+
if (deps["next"]) {
|
|
86
|
+
return { name: "next", version: deps["next"] };
|
|
87
|
+
}
|
|
88
|
+
if (deps["hono"]) {
|
|
89
|
+
return { name: "hono", version: deps["hono"] };
|
|
90
|
+
}
|
|
91
|
+
if (deps["express"]) {
|
|
92
|
+
return { name: "express", version: deps["express"] };
|
|
93
|
+
}
|
|
80
94
|
return void 0;
|
|
81
95
|
} catch {
|
|
82
96
|
return void 0;
|
|
@@ -85,12 +99,17 @@ function detectFramework(cwd) {
|
|
|
85
99
|
function detectDatabase(cwd) {
|
|
86
100
|
try {
|
|
87
101
|
const pkgPath = join(cwd, "package.json");
|
|
88
|
-
if (!existsSync(pkgPath))
|
|
102
|
+
if (!existsSync(pkgPath)) {
|
|
103
|
+
return void 0;
|
|
104
|
+
}
|
|
89
105
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
90
106
|
const deps = { ...pkg?.dependencies, ...pkg?.devDependencies };
|
|
91
|
-
if (deps["drizzle-orm"])
|
|
107
|
+
if (deps["drizzle-orm"]) {
|
|
92
108
|
return { name: "drizzle", version: deps["drizzle-orm"] };
|
|
93
|
-
|
|
109
|
+
}
|
|
110
|
+
if (deps["prisma"]) {
|
|
111
|
+
return { name: "prisma", version: deps["prisma"] };
|
|
112
|
+
}
|
|
94
113
|
return void 0;
|
|
95
114
|
} catch {
|
|
96
115
|
return void 0;
|
|
@@ -111,31 +130,46 @@ function detectSystem() {
|
|
|
111
130
|
}
|
|
112
131
|
function detectPackageManager() {
|
|
113
132
|
const ua = process.env.npm_config_user_agent;
|
|
114
|
-
if (!ua || typeof ua !== "string")
|
|
133
|
+
if (!ua || typeof ua !== "string") {
|
|
134
|
+
return void 0;
|
|
135
|
+
}
|
|
115
136
|
const match = ua.match(/^(.+?)\/(\d+\.\d+\.\d+.*?)(?:\s|$)/);
|
|
116
137
|
if (match) {
|
|
117
138
|
const name = (match[1] ?? "unknown").toLowerCase();
|
|
118
139
|
const version = match[2];
|
|
119
140
|
return version ? { name, version } : { name };
|
|
120
141
|
}
|
|
121
|
-
if (ua.includes("pnpm"))
|
|
122
|
-
|
|
142
|
+
if (ua.includes("pnpm")) {
|
|
143
|
+
return { name: "pnpm" };
|
|
144
|
+
}
|
|
145
|
+
if (ua.includes("yarn")) {
|
|
146
|
+
return { name: "yarn" };
|
|
147
|
+
}
|
|
123
148
|
return { name: "npm" };
|
|
124
149
|
}
|
|
125
150
|
function isTelemetryEnabled(options) {
|
|
126
|
-
if (process.env.NODE_ENV === "test")
|
|
151
|
+
if (process.env.NODE_ENV === "test") {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
127
154
|
const env = process.env.BETTER_TENANT_TELEMETRY;
|
|
128
|
-
if (env === "0" || env?.toLowerCase() === "false")
|
|
129
|
-
|
|
155
|
+
if (env === "0" || env?.toLowerCase() === "false") {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
if (env === "1" || env?.toLowerCase() === "true") {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
130
161
|
return options?.enabled !== false;
|
|
131
162
|
}
|
|
132
163
|
function isDebugMode(options) {
|
|
133
|
-
if (process.env.BETTER_TENANT_TELEMETRY_DEBUG === "1")
|
|
164
|
+
if (process.env.BETTER_TENANT_TELEMETRY_DEBUG === "1") {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
134
167
|
return options?.debug === true;
|
|
135
168
|
}
|
|
136
169
|
function sendTelemetry(type, payload, options) {
|
|
137
|
-
if (!isTelemetryEnabled(options))
|
|
170
|
+
if (!isTelemetryEnabled(options)) {
|
|
138
171
|
return options?.wait ? Promise.resolve() : void 0;
|
|
172
|
+
}
|
|
139
173
|
const fullPayload = {
|
|
140
174
|
library: LIBRARY_ID,
|
|
141
175
|
type,
|
|
@@ -233,9 +267,10 @@ function getDatabase() {
|
|
|
233
267
|
async function runWithTenantAndDatabase(tenantId, adapter, fn, options) {
|
|
234
268
|
const result = await adapter.runWithTenant(tenantId, async (database) => {
|
|
235
269
|
let context = { tenantId, database };
|
|
236
|
-
|
|
270
|
+
const getTenantRepository = options?.getTenantRepository;
|
|
271
|
+
if (options?.loadTenant && getTenantRepository && adapter.runAsSystem) {
|
|
237
272
|
const tenant = await adapter.runAsSystem(
|
|
238
|
-
(systemDb) =>
|
|
273
|
+
(systemDb) => getTenantRepository(systemDb).getById(tenantId)
|
|
239
274
|
);
|
|
240
275
|
context = tenant != null ? { ...context, tenant } : context;
|
|
241
276
|
}
|
|
@@ -362,10 +397,7 @@ async function runAs(tenantId, adapter, fn) {
|
|
|
362
397
|
}
|
|
363
398
|
async function runAsSystem(adapter, fn) {
|
|
364
399
|
const run = requireRunAsSystem(adapter);
|
|
365
|
-
return runWithContext(
|
|
366
|
-
{ tenantId: "", isSystem: true },
|
|
367
|
-
() => run(fn)
|
|
368
|
-
);
|
|
400
|
+
return runWithContext({ tenantId: "", isSystem: true }, () => run(fn));
|
|
369
401
|
}
|
|
370
402
|
|
|
371
403
|
// src/resolver.ts
|
|
@@ -376,17 +408,23 @@ function getHeader(headers, name) {
|
|
|
376
408
|
return value2?.trim() || void 0;
|
|
377
409
|
}
|
|
378
410
|
const raw = headers[key] ?? headers[name];
|
|
379
|
-
if (raw === void 0)
|
|
411
|
+
if (raw === void 0) {
|
|
412
|
+
return void 0;
|
|
413
|
+
}
|
|
380
414
|
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
381
415
|
return (typeof value === "string" ? value : "").trim() || void 0;
|
|
382
416
|
}
|
|
383
417
|
function resolveFromHeader(request, headerName) {
|
|
384
|
-
if (!headerName)
|
|
418
|
+
if (!headerName) {
|
|
419
|
+
return void 0;
|
|
420
|
+
}
|
|
385
421
|
return getHeader(request.headers, headerName);
|
|
386
422
|
}
|
|
387
423
|
function resolveFromPath(request, pathConfig) {
|
|
388
424
|
const pathOrUrl = request.path ?? request.url;
|
|
389
|
-
if (!pathOrUrl)
|
|
425
|
+
if (!pathOrUrl) {
|
|
426
|
+
return void 0;
|
|
427
|
+
}
|
|
390
428
|
let path;
|
|
391
429
|
try {
|
|
392
430
|
path = pathOrUrl.startsWith("http") ? new URL(pathOrUrl).pathname : pathOrUrl;
|
|
@@ -406,11 +444,17 @@ function parseTenantSegmentIndex(pattern) {
|
|
|
406
444
|
}
|
|
407
445
|
function resolveFromSubdomain(request, config) {
|
|
408
446
|
const host = request.host ?? (request.url ? new URL(request.url).host : "");
|
|
409
|
-
if (!host)
|
|
447
|
+
if (!host) {
|
|
448
|
+
return void 0;
|
|
449
|
+
}
|
|
410
450
|
const hostname = host.split(":")[0];
|
|
411
|
-
if (!hostname)
|
|
451
|
+
if (!hostname) {
|
|
452
|
+
return void 0;
|
|
453
|
+
}
|
|
412
454
|
const parts = hostname.split(".");
|
|
413
|
-
if (parts.length <= 2)
|
|
455
|
+
if (parts.length <= 2) {
|
|
456
|
+
return void 0;
|
|
457
|
+
}
|
|
414
458
|
const index = config === true ? 0 : typeof config === "object" && config.segmentIndex !== void 0 ? config.segmentIndex : 0;
|
|
415
459
|
const value = parts[index];
|
|
416
460
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -418,86 +462,146 @@ function resolveFromSubdomain(request, config) {
|
|
|
418
462
|
function decodeJwtPayload(token) {
|
|
419
463
|
try {
|
|
420
464
|
const parts = token.split(".");
|
|
421
|
-
if (parts.length < 2)
|
|
465
|
+
if (parts.length < 2) {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
422
468
|
const payload = parts[1];
|
|
423
|
-
if (!payload)
|
|
469
|
+
if (!payload) {
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
424
472
|
const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
|
|
425
|
-
|
|
473
|
+
const parsed = JSON.parse(decoded);
|
|
474
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
return parsed;
|
|
426
478
|
} catch {
|
|
427
479
|
return null;
|
|
428
480
|
}
|
|
429
481
|
}
|
|
430
482
|
function resolveFromJwt(request, config) {
|
|
431
483
|
const getToken = request.getToken;
|
|
432
|
-
if (!getToken)
|
|
484
|
+
if (!getToken) {
|
|
485
|
+
return void 0;
|
|
486
|
+
}
|
|
433
487
|
const token = typeof getToken === "function" ? getToken() : getToken;
|
|
434
488
|
const value = token instanceof Promise ? void 0 : token ?? void 0;
|
|
435
489
|
const resolved = value ?? void 0;
|
|
436
|
-
if (!resolved)
|
|
490
|
+
if (!resolved) {
|
|
491
|
+
return void 0;
|
|
492
|
+
}
|
|
437
493
|
const claim = typeof config === "string" ? config : config.claim;
|
|
438
|
-
if (!claim)
|
|
439
|
-
|
|
440
|
-
|
|
494
|
+
if (!claim) {
|
|
495
|
+
return void 0;
|
|
496
|
+
}
|
|
497
|
+
const verifyToken = typeof config === "object" ? config.verifyToken : void 0;
|
|
498
|
+
let payload;
|
|
499
|
+
if (verifyToken) {
|
|
500
|
+
const result = verifyToken(resolved);
|
|
501
|
+
if (result instanceof Promise) {
|
|
502
|
+
return void 0;
|
|
503
|
+
}
|
|
504
|
+
payload = result;
|
|
505
|
+
} else {
|
|
506
|
+
payload = decodeJwtPayload(resolved);
|
|
507
|
+
}
|
|
508
|
+
if (!payload) {
|
|
509
|
+
return void 0;
|
|
510
|
+
}
|
|
441
511
|
const claimValue = payload[claim];
|
|
442
512
|
return typeof claimValue === "string" && claimValue.length > 0 ? claimValue : void 0;
|
|
443
513
|
}
|
|
444
514
|
async function resolveFromJwtAsync(request, config) {
|
|
445
515
|
const getToken = request.getToken;
|
|
446
|
-
if (!getToken)
|
|
516
|
+
if (!getToken) {
|
|
517
|
+
return void 0;
|
|
518
|
+
}
|
|
447
519
|
const token = typeof getToken === "function" ? getToken() : getToken;
|
|
448
520
|
const value = token instanceof Promise ? await token : token;
|
|
449
521
|
const resolved = value ?? void 0;
|
|
450
|
-
if (!resolved)
|
|
522
|
+
if (!resolved) {
|
|
523
|
+
return void 0;
|
|
524
|
+
}
|
|
451
525
|
const claim = typeof config === "string" ? config : config.claim;
|
|
452
|
-
if (!claim)
|
|
453
|
-
|
|
454
|
-
|
|
526
|
+
if (!claim) {
|
|
527
|
+
return void 0;
|
|
528
|
+
}
|
|
529
|
+
const verifyToken = typeof config === "object" ? config.verifyToken : void 0;
|
|
530
|
+
let payload;
|
|
531
|
+
if (verifyToken) {
|
|
532
|
+
payload = await verifyToken(resolved);
|
|
533
|
+
} else {
|
|
534
|
+
payload = decodeJwtPayload(resolved);
|
|
535
|
+
}
|
|
536
|
+
if (!payload) {
|
|
537
|
+
return void 0;
|
|
538
|
+
}
|
|
455
539
|
const claimValue = payload[claim];
|
|
456
540
|
return typeof claimValue === "string" && claimValue.length > 0 ? claimValue : void 0;
|
|
457
541
|
}
|
|
458
542
|
function resolveTenant(request, config) {
|
|
459
543
|
if (config.header !== void 0) {
|
|
460
544
|
const v = resolveFromHeader(request, config.header);
|
|
461
|
-
if (v !== void 0)
|
|
545
|
+
if (v !== void 0) {
|
|
546
|
+
return v;
|
|
547
|
+
}
|
|
462
548
|
}
|
|
463
549
|
if (config.path !== void 0) {
|
|
464
550
|
const v = resolveFromPath(request, config.path);
|
|
465
|
-
if (v !== void 0)
|
|
551
|
+
if (v !== void 0) {
|
|
552
|
+
return v;
|
|
553
|
+
}
|
|
466
554
|
}
|
|
467
555
|
if (config.subdomain !== void 0 && config.subdomain !== false) {
|
|
468
556
|
const v = resolveFromSubdomain(request, config.subdomain);
|
|
469
|
-
if (v !== void 0)
|
|
557
|
+
if (v !== void 0) {
|
|
558
|
+
return v;
|
|
559
|
+
}
|
|
470
560
|
}
|
|
471
561
|
if (config.jwt !== void 0) {
|
|
472
562
|
const v = resolveFromJwt(request, config.jwt);
|
|
473
|
-
if (v !== void 0)
|
|
563
|
+
if (v !== void 0) {
|
|
564
|
+
return v;
|
|
565
|
+
}
|
|
474
566
|
}
|
|
475
567
|
if (config.custom !== void 0) {
|
|
476
568
|
const v = config.custom(request);
|
|
477
|
-
if (typeof v === "string" && v.length > 0)
|
|
569
|
+
if (typeof v === "string" && v.length > 0) {
|
|
570
|
+
return v;
|
|
571
|
+
}
|
|
478
572
|
}
|
|
479
573
|
return void 0;
|
|
480
574
|
}
|
|
481
575
|
async function resolveTenantAsync(request, config) {
|
|
482
576
|
if (config.header !== void 0) {
|
|
483
577
|
const v = resolveFromHeader(request, config.header);
|
|
484
|
-
if (v !== void 0)
|
|
578
|
+
if (v !== void 0) {
|
|
579
|
+
return v;
|
|
580
|
+
}
|
|
485
581
|
}
|
|
486
582
|
if (config.path !== void 0) {
|
|
487
583
|
const v = resolveFromPath(request, config.path);
|
|
488
|
-
if (v !== void 0)
|
|
584
|
+
if (v !== void 0) {
|
|
585
|
+
return v;
|
|
586
|
+
}
|
|
489
587
|
}
|
|
490
588
|
if (config.subdomain !== void 0 && config.subdomain !== false) {
|
|
491
589
|
const v = resolveFromSubdomain(request, config.subdomain);
|
|
492
|
-
if (v !== void 0)
|
|
590
|
+
if (v !== void 0) {
|
|
591
|
+
return v;
|
|
592
|
+
}
|
|
493
593
|
}
|
|
494
594
|
if (config.jwt !== void 0) {
|
|
495
595
|
const v = await resolveFromJwtAsync(request, config.jwt);
|
|
496
|
-
if (v !== void 0)
|
|
596
|
+
if (v !== void 0) {
|
|
597
|
+
return v;
|
|
598
|
+
}
|
|
497
599
|
}
|
|
498
600
|
if (config.custom !== void 0) {
|
|
499
601
|
const v = await Promise.resolve(config.custom(request));
|
|
500
|
-
if (typeof v === "string" && v.length > 0)
|
|
602
|
+
if (typeof v === "string" && v.length > 0) {
|
|
603
|
+
return v;
|
|
604
|
+
}
|
|
501
605
|
}
|
|
502
606
|
return void 0;
|
|
503
607
|
}
|
|
@@ -511,7 +615,7 @@ function betterTenant(config) {
|
|
|
511
615
|
const runWithTenantAndDatabaseOptions = shouldLoadTenant ? { loadTenant: true, getTenantRepository } : void 0;
|
|
512
616
|
return {
|
|
513
617
|
getContext,
|
|
514
|
-
getDatabase,
|
|
618
|
+
getDatabase: () => getDatabase(),
|
|
515
619
|
runWithTenant,
|
|
516
620
|
runWithTenantAndDatabase: (tenantId, _adapter, fn) => runWithTenantAndDatabase(tenantId, adapter, fn, runWithTenantAndDatabaseOptions),
|
|
517
621
|
runAs: (tenantId, _adapter, fn) => runAs(tenantId, adapter, fn),
|
|
@@ -545,12 +649,16 @@ function isFetchRequest(input) {
|
|
|
545
649
|
return typeof Request !== "undefined" && input instanceof Request;
|
|
546
650
|
}
|
|
547
651
|
function normalizeHost(raw) {
|
|
548
|
-
if (!raw)
|
|
652
|
+
if (!raw) {
|
|
653
|
+
return void 0;
|
|
654
|
+
}
|
|
549
655
|
const value = raw.split(":")[0]?.trim();
|
|
550
656
|
return value || void 0;
|
|
551
657
|
}
|
|
552
658
|
function normalizeHeaders(headers) {
|
|
553
|
-
if (!headers)
|
|
659
|
+
if (!headers) {
|
|
660
|
+
return {};
|
|
661
|
+
}
|
|
554
662
|
const normalized = {};
|
|
555
663
|
for (const [key, value] of Object.entries(headers)) {
|
|
556
664
|
const normalizedKey = key.toLowerCase();
|
|
@@ -567,7 +675,9 @@ function normalizeHeaders(headers) {
|
|
|
567
675
|
return normalized;
|
|
568
676
|
}
|
|
569
677
|
function pathWithoutQuery(value) {
|
|
570
|
-
if (!value)
|
|
678
|
+
if (!value) {
|
|
679
|
+
return void 0;
|
|
680
|
+
}
|
|
571
681
|
const [pathname] = value.split("?");
|
|
572
682
|
return pathname || void 0;
|
|
573
683
|
}
|
|
@@ -601,7 +711,9 @@ function toResolvableRequest(request) {
|
|
|
601
711
|
const hostFromHeaders = headers.host;
|
|
602
712
|
const hostValue = Array.isArray(hostFromHeaders) ? hostFromHeaders[0] : hostFromHeaders;
|
|
603
713
|
const host = normalizeHost(request.hostname ?? request.host ?? hostValue);
|
|
604
|
-
const path = pathWithoutQuery(
|
|
714
|
+
const path = pathWithoutQuery(
|
|
715
|
+
request.path ?? request.originalUrl ?? request.url
|
|
716
|
+
);
|
|
605
717
|
const resolved = {
|
|
606
718
|
headers
|
|
607
719
|
};
|
|
@@ -622,7 +734,6 @@ export {
|
|
|
622
734
|
betterTenant,
|
|
623
735
|
createTenantApi,
|
|
624
736
|
getContext,
|
|
625
|
-
getDatabase,
|
|
626
737
|
handleRequest,
|
|
627
738
|
resolveTenant,
|
|
628
739
|
resolveTenantAsync,
|